HanaokaYuzu/Gemini-API

GitHub: HanaokaYuzu/Gemini-API

逆向工程的异步 Python 库,通过浏览器 Cookie 免费调用 Google Gemini Web 应用,支持图像生成、Gems、扩展和多轮对话等功能。

Stars: 2398 | Forks: 362

Gemini Banner

PyPI Downloads Dependencies License Code style

GitHub stars GitHub issues CI

# Gemini Icon Gemini-API 一个针对 [Google Gemini](https://gemini.google.com) Web 应用(原名 Bard)的逆向工程异步 Python 封装库。 ## 功能特性 - **持久化 Cookies** - 在后台自动刷新 cookies。针对常驻服务进行了优化。 - **图像生成** - 原生支持使用自然语言生成和编辑图像。 - **系统提示词** - 支持通过 [Gemini Gems](https://gemini.google.com/gems/view) 自定义模型的系统提示词。 - **扩展支持** - 支持使用 [Gemini 扩展](https://gemini.google.com/extensions)(如 YouTube 和 Gmail)生成内容。 - **分类输出** - 将响应中的文本、思考过程、网络图像和 AI 生成图像进行分类。 - **流式模式** - 支持流式生成,在生成部分输出时即时产出。 - **官方风格** - 提供受 [Google Generative AI](https://ai.google.dev/tutorials/python_quickstart) 官方 API 启发的简洁优雅接口。 - **异步执行** - 利用 `asyncio` 高效运行生成任务并返回结果。 ## 目录 - [功能特性](#features) - [目录](#table-of-contents) - [安装](#installation) - [身份验证](#authentication) - [使用方法](#usage) - [初始化](#initialization) - [生成内容](#generate-content) - [生成带文件的内容](#generate-content-with-files) - [多轮对话](#conversations-across-multiple-turns) - [继续之前的对话](#continue-previous-conversations) - [读取对话历史](#read-conversation-history) - [从 Gemini 历史记录中删除之前的对话](#delete-previous-conversations-from-gemini-history) - [临时模式](#temporary-mode) - [流式模式](#streaming-mode) - [选择语言模型](#select-language-model) - [通过 Gemini Gems 应用系统提示词](#apply-system-prompt-with-gemini-gems) - [管理自定义 Gems](#manage-custom-gems) - [创建自定义 Gem](#create-a-custom-gem) - [更新现有 Gem](#update-an-existing-gem) - [删除自定义 Gem](#delete-a-custom-gem) - [获取模型的思考过程](#retrieve-models-thought-process) - [获取响应中的图像](#retrieve-images-in-response) - [生成和编辑图像](#generate-and-edit-images) - [使用 Gemini 扩展生成内容](#generate-content-with-gemini-extensions) - [检查并切换其他回复候选](#check-and-switch-to-other-reply-candidates) - [日志配置](#logging-configuration) - [参考](#references) - [Stargazers](#stargazers) ## 安装 使用 pip 安装或更新该包。 ``` pip install -U gemini_webapi ``` 可选地,该包提供了一种通过可选依赖项 `browser-cookie3` 从本地浏览器自动导入 cookies 的方法。要启用此功能,请改为安装 `gemini_webapi[browser]`。支持的平台和浏览器可以在[这里](https://github.com/borisbabic/browser_cookie3?tab=readme-ov-file#contribute)找到。 ``` pip install -U gemini_webapi[browser] ``` ## 身份验证 - 前往 并使用您的 Google 账号登录 - 按 F12 打开网页检查器,转到 `Network`(网络)标签页,并刷新页面 - 点击任意请求并复制 `__Secure-1PSID` 和 `__Secure-1PSIDTS` 的 cookie 值 ``` services: main: environment: GEMINI_COOKIE_PATH: /tmp/gemini_webapi volumes: - ./gemini_cookies:/tmp/gemini_webapi ``` ## 使用方法 ### 初始化 导入所需的包,并使用上一步获取的 cookies 初始化客户端。初始化成功后,只要进程处于活动状态,API 将在后台自动刷新 `__Secure-1PSIDTS`。 ``` import asyncio from gemini_webapi import GeminiClient # 将 "COOKIE VALUE HERE" 替换为您的实际 cookie 值。 # 如果您的账户没有 Secure_1PSIDTS,请将其留空。 Secure_1PSID = "COOKIE VALUE HERE" Secure_1PSIDTS = "COOKIE VALUE HERE" async def main(): # If browser-cookie3 is installed, simply use `client = GeminiClient()` client = GeminiClient(Secure_1PSID, Secure_1PSIDTS, proxy=None) await client.init(timeout=30, auto_close=False, close_delay=300, auto_refresh=True) asyncio.run(main()) ``` ### 生成内容 通过调用 `GeminiClient.generate_content` 提出单轮问题,它将返回一个 `gemini_webapi.ModelOutput` 对象,其中包含生成的文本、图像、思考过程和对话元数据。 ``` async def main(): response = await client.generate_content("Hello World!") print(response.text) asyncio.run(main()) ``` ### 生成带文件的内容 Gemini 支持文件输入,包括图像和文档。您可以选择将文件路径列表(以 `str` 或 `pathlib.Path` 形式)连同文本提示词一起传递给 `GeminiClient.generate_content`。 ``` async def main(): response = await client.generate_content( "Introduce the contents of these two files. Is there any connection between them?", files=["assets/sample.pdf", Path("assets/banner.png")], ) print(response.text) asyncio.run(main()) ``` ### 多轮对话 如果您想保持对话连续性,请使用 `GeminiClient.start_chat` 创建一个 `gemini_webapi.ChatSession` 对象并通过它发送消息。对话历史将被自动处理并在每一轮后更新。 ``` async def main(): chat = client.start_chat() response1 = await chat.send_message( "Introduce the contents of these two files. Is there any connection between them?", files=["assets/sample.pdf", Path("assets/banner.png")], ) print(response1.text) response2 = await chat.send_message( "Use image generation tool to modify the banner with another font and design." ) print(response2.text, response2.images, sep="\n\n----------------------------------\n\n") asyncio.run(main()) ``` ### 继续之前的对话 要手动检索之前的对话,您可以在创建新的 `ChatSession` 时将先前 `ChatSession` 的元数据传递给 `GeminiClient.start_chat`。或者,如果您需要在当前 Python 进程退出后访问它,可以将先前的元数据持久化到文件或数据库中。 ``` async def main(): # Start a new chat session chat = client.start_chat() response = await chat.send_message("Fine weather today") # Save chat's metadata previous_session = chat.metadata # Load the previous conversation previous_chat = client.start_chat(metadata=previous_session) response = await previous_chat.send_message("What was my previous message?") print(response) asyncio.run(main()) ``` ### 读取对话历史 您可以通过调用 `GeminiClient.read_chat` 并传入聊天 ID 来读取特定聊天的对话历史。 ``` async def main(): chat = client.start_chat() await chat.send_message("What is the capital of France?") # Read the chat history history = await client.read_chat(chat.cid) for turn in history: print( f"Input: {turn.user_prompt}\n" f"Output: {turn.assistant_response}" "\n\n----------------------------------\n\n" ) asyncio.run(main()) ``` ### 从 Gemini 历史记录中删除之前的对话 您可以通过调用 `GeminiClient.delete_chat` 并传入聊天 ID,从服务器上的 Gemini 历史记录中删除特定的聊天。 ``` async def main(): # Start a new chat session chat = client.start_chat() await chat.send_message("This is a temporary conversation.") # Delete the chat await client.delete_chat(chat.cid) print(f"Chat deleted: {chat.cid}") asyncio.run(main()) ``` ### 临时模式 您可以通过向 `GeminiClient.generate_content` 或 `ChatSession.send_message` 传递 `temporary=True` 来启动临时聊天。临时聊天不会保存在 Gemini 历史记录中。 ``` async def main(): response = await client.generate_content("Hello World!", temporary=True) print(response.text, "\n\n----------------------------------\n\n") chat = client.start_chat() await chat.send_message("Fine weather today", temporary=False) response2 = await chat.send_message("What's my last message?", temporary=True) print(response2.text) asyncio.run(main()) ``` ### 流式模式 对于较长的响应,您可以使用流式模式在生成部分输出时即时接收。这提供了更具响应性的用户体验,特别是对于像聊天机器人这样的实时应用程序。 `generate_content_stream` 方法产出 `ModelOutput` 对象,其中 `text_delta` 属性仅包含自上次产出以来接收到的 **新字符**,便于显示增量更新。 ``` async def main(): async for chunk in client.generate_content_stream( "What's the difference between 'await' and 'async for'?" ): print(chunk.text_delta, end="", flush=True) print() asyncio.run(main()) ``` ### 选择语言模型 您可以通过向 `GeminiClient.generate_content` 或 `GeminiClient.start_chat` 传递 `model` 参数来指定要使用的语言模型。默认值为 `unspecified`。 当前可用的模型(截至 2025 年 11 月 20 日): - `unspecified` - 默认模型 - `gemini-3.0-pro` - Gemini 3.0 Pro - `gemini-3.0-flash` - Gemini 3.0 Flash - `gemini-3.0-flash-thinking` - Gemini 3.0 Flash Thinking ``` from gemini_webapi.constants import Model async def main(): response1 = await client.generate_content( "What's your language model version? Reply with the version number only.", model=Model.G_3_0_FLASH, ) print(f"Model version ({Model.G_3_0_FLASH.model_name}): {response1.text}") chat = client.start_chat(model="gemini-2.5-pro") response2 = await chat.send_message("What's your language model version? Reply with the version number only.") print(f"Model version (gemini-2.5-pro): {response2.text}") asyncio.run(main()) ``` 您也可以直接传递自定义模型头字符串来访问未在上方列出的模型。 ``` # 必须包含 "model_name" 和 "model_header" 键 custom_model = { "model_name": "xxx", "model_header": { "x-goog-ext-525001261-jspb": "[1,null,null,null,'e6fa609c3fa255c0',null,null,null,[4]]" }, } response = await client.generate_content( "What's your model version?", model=custom_model ) ``` ### 通过 Gemini Gems 应用系统提示词 系统提示词可以通过 [Gemini Gems](https://gemini.google.com/gems/view) 应用于对话。要使用 gem,您可以将 `gem` 参数传递给 `GeminiClient.generate_content` 或 `GeminiClient.start_chat`。`gem` 可以是 gem ID 字符串或 `gemini_webapi.Gem` 对象。单个对话只能应用一个 gem。 ``` async def main(): # Fetch all gems for the current account, including both predefined and user-created ones await client.fetch_gems(include_hidden=False, language="en") # Once fetched, gems will be cached in `GeminiClient.gems` gems = client.gems # Get the gem you want to use system_gems = gems.filter(predefined=True) coding_partner = system_gems.get(id="coding-partner") response1 = await client.generate_content( "What's your system prompt?", model=Model.G_3_0_FLASH, gem=coding_partner, ) print(response1.text) # Another example with a user-created custom gem # Gem ids are consistent strings. Store them somewhere to avoid fetching gems every time your_gem = gems.get(name="Your Gem Name") your_gem_id = your_gem.id chat = client.start_chat(gem=your_gem_id) response2 = await chat.send_message("What's your system prompt?") print(response2) ``` ### 管理自定义 Gems 您可以使用 API 以编程方式创建、更新和删除您的自定义 gems。请注意,预定义的系统 gems 无法被修改或删除。 #### 创建自定义 Gem 使用名称、系统提示词(指令)和可选描述创建一个新的自定义 gem: ``` async def main(): # Create a new custom gem new_gem = await client.create_gem( name="Python Tutor", prompt="You are a helpful Python programming tutor.", description="A specialized gem for Python programming" ) print(f"Custom gem created: {new_gem}") # Use the newly created gem in a conversation response = await client.generate_content( "Explain how list comprehensions work in Python", gem=new_gem ) print(response.text) asyncio.run(main()) ``` #### 更新现有 Gem ``` async def main(): # Get a custom gem (assuming you have one named "Python Tutor") await client.fetch_gems() python_tutor = client.gems.get(name="Python Tutor") # Update the gem with new instructions updated_gem = await client.update_gem( gem=python_tutor, # Can also pass gem ID string name="Advanced Python Tutor", prompt="You are an expert Python programming tutor.", description="An advanced Python programming assistant" ) print(f"Custom gem updated: {updated_gem}") asyncio.run(main()) ``` #### 删除自定义 Gem ``` async def main(): # Get the gem to delete await client.fetch_gems() gem_to_delete = client.gems.get(name="Advanced Python Tutor") # Delete the gem await client.delete_gem(gem_to_delete) # Can also pass gem ID string print(f"Custom gem deleted: {gem_to_delete.name}") asyncio.run(main()) ``` ### 获取模型的思考过程 使用具有思考能力的模型时,模型的思考过程将填充在 `ModelOutput.thoughts` 中。 ``` async def main(): response = await client.generate_content( "What's 1+1?", model="gemini-2.5-pro" ) print(response.thoughts) print(response.text) asyncio.run(main()) ``` ### 获取响应中的图像 API 输出中的图像存储为 `gemini_webapi.Image` 对象列表。您可以通过分别调用 `Image.title`、`Image.url` 和 `Image.alt` 来访问图像标题、URL 和描述。 ``` async def main(): response = await client.generate_content("Send me some pictures of cats") for image in response.images: print(image, "\n\n----------------------------------\n\n") asyncio.run(main()) ``` ### 生成和编辑图像 您可以要求 Gemini 使用 Google 最新的图像模型 Nano Banana,通过自然语言生成和编辑图像。 您可以通过调用 `Image.save()` 将从 Gemini 返回的图像保存在本地。可选地,您可以通过向函数传递 `path` 和 `filename` 参数来指定文件路径和文件名,并通过传递 `skip_invalid_filename=True` 来跳过具有无效文件名的图像。这适用于 `WebImage` 和 `GeneratedImage`。 ``` async def main(): response = await client.generate_content("Generate some pictures of cats") for i, image in enumerate(response.images): await image.save(path="temp/", filename=f"cat_{i}.png", verbose=True) print(image, "\n\n----------------------------------\n\n") asyncio.run(main()) ``` ### 使用 Gemini 扩展生成内容 为您的账号激活扩展后,您可以在提示词中以自然语言访问它们,或者通过在提示词开头使用 "@" 后跟扩展关键字来访问。 ``` async def main(): response1 = await client.generate_content("@Gmail What's the latest message in my mailbox?") print(response1, "\n\n----------------------------------\n\n") response2 = await client.generate_content("@Youtube What's the latest activity of Taylor Swift?") print(response2, "\n\n----------------------------------\n\n") asyncio.run(main()) ``` ### 检查并切换其他回复候选 来自 Gemini 的响应有时包含多个具有不同生成内容的回复候选。您可以检查所有候选并选择一个来继续对话。默认情况下,选择第一个候选。 ``` async def main(): # Start a conversation and list all reply candidates chat = client.start_chat() response = await chat.send_message("Recommend a science fiction book for me.") for candidate in response.candidates: print(candidate, "\n\n----------------------------------\n\n") if len(response.candidates) > 1: # Control the ongoing conversation flow by choosing candidate manually new_candidate = chat.choose_candidate(index=1) # Choose the second candidate here followup_response = await chat.send_message("Tell me more about it.") # Will generate content based on the chosen candidate print(new_candidate, followup_response, sep="\n\n----------------------------------\n\n") else: print("Only one candidate available.") asyncio.run(main()) ``` ### 日志配置 该包使用 [loguru](https://loguru.readthedocs.io/en/stable/) 进行日志记录,并公开了一个 `set_log_level` 函数来控制日志级别。您可以将日志级别设置为以下值之一:`DEBUG`、`INFO`、`WARNING`、`ERROR` 和 `CRITICAL`。默认值为 `INFO`。 ``` from gemini_webapi import set_log_level set_log_level("DEBUG") ``` ## 参考 [Google AI Studio](https://ai.google.dev/tutorials/ai-studio_quickstart) [acheong08/Bard](https://github.com/acheong08/Bard) ## Stargazers

Star History Chart

标签:API 封装, Chatbot, DLL 劫持, PyPI, Python, Spyse API, Web Scraping, 云资产清单, 人工智能, 大语言模型, 开源情报, 异步编程, 无后门, 机器人, 用户模式Hook绕过, 网络调试, 自动化, 计算机取证, 逆向工具, 逆向工程