> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aihubmix.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Gemini 指南

> Gemini 漫游指南：关于本站的 Gemini 调用细节，在此汇总。

## Gemini 调用方式

对于 Gemini 系列，我们提供原生调用和 Openai 兼容这 2 种调用方式。\
使用前运行 `pip install google-genai` 或 `pip install -U google-genai`，安装（更新）原生依赖。

1️⃣ 对于原生调用，我们的 Gemini 调用支持 AI Studio 和 VertexAI 自动路由。转发方法主要是在内部传入 AIHubMix 密钥和请求链接。需要注意的是，这个链接和常规的 `base_url` 写法不同，请参考示例：

```py theme={null}
client = genai.Client(
    api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
    http_options={"base_url": "https://aihubmix.com/gemini"},
)
```

2️⃣ 对于 Openai 兼容格式，则维持通用的 `v1` 端点：

```py theme={null}
client = OpenAI(
    api_key="sk-***", # 换成你在 AiHubMix 生成的密钥
    base_url="https://aihubmix.com/v1",
)
```

3️⃣ 对于 2.5 系列，如果你需要显示推理过程，可以使用以下 2 种方式：

1. 原生调用：传入 `include_thoughts=True`
2. OpenAI 兼容方式：传入 `reasoning_effort`

相关的详细调用可以参考下文的代码示例。

## **Gemini 3 Pro** Image Preview 说明

Gemini 3 Pro Image Preview（Nano Banana Pro 预览版）专为专业素材资源制作和复杂指令而设计。该模型具有以下特点：

* 使用Google 搜索实时获取世界知识
* 默认“思考”过程（在生成之前优化构图）
* 能够生成分辨率高达 **4K** 的图像

<Tip>
  - 流式模式只返回推理过程，生成的图片不会在流式输出中出现。
  - 如需获取图片数据，请使用非流式请求。
</Tip>

**Python 调用参考如下：**

<CodeGroup>
  ```python 文生图 theme={null}
  import os
  from google import genai
  from google.genai import types

  API_KEY = "<YOUR AIHUBMIX API KEY>"  

  client = genai.Client(
      api_key=API_KEY,
      http_options={"base_url": "https://aihubmix.com/gemini"},  
  )

  prompt = (
      "Da Vinci style anatomical sketch of a dissected Monarch butterfly. "
      "Detailed drawings of the head, wings, and legs on textured parchment with notes in English."
  )

  # 可选参数
  aspect_ratio = "1:1"   # 支持: "1:1","2:3","3:2","3:4","4:3","4:5","5:4","9:16","16:9","21:9"
  resolution   = "4K"    # 默认1K，支持: "1K", "2K", "4K"，注意：必须是大写“K”

  response = client.models.generate_content(
      model="gemini-3-pro-image-preview",
      contents=prompt,   
      config=types.GenerateContentConfig(
          response_modalities=['TEXT', 'IMAGE'],
          image_config=types.ImageConfig(
              aspect_ratio=aspect_ratio,
              image_size=resolution,
          ),
      ),
  )

  # 保存图片 & 输出文本
  for part in response.parts:
      if part.text:
          print(part.text)  
      elif image := part.as_image():
          image.save("butterfly.png")
          print("Image saved: butterfly.png")
  ```

  ```python 图生图 theme={null}
  from google import genai
  from PIL import Image

  API_KEY = "<YOUR AIHUBMIX API KEY>"

  client = genai.Client(
      api_key=API_KEY,
      http_options={"base_url": "https://aihubmix.com/gemini"}
  )

  prompt = (
      "Create a picture of my cat eating a nano-banana "
      "in a fancy restaurant under the Gemini constellation."
  )

  image = Image.open("cat_image.jpg")

  response = client.models.generate_content(
      model="gemini-2.5-flash-image",
      contents=[prompt, image],
  )

  # 保存图片 & 输出文本
  for part in response.parts:
      if part.text is not None:
          print(part.text)
      elif part.inline_data is not None:
          image = part.as_image()
          image.save("generated_image.png")
  ```

  ```python 多图参考 theme={null}
  from google import genai
  from google.genai import types
  from PIL import Image

  API_KEY = "<YOUR AIHUBMIX_API_KEY>"

  prompt = "An office group photo of these people, they are making funny faces."
  aspect_ratio = "5:4"
  resolution = "2K"

  client = genai.Client(
      api_key=API_KEY,
      http_options={"base_url": "https://aihubmix.com/gemini"}
  )

  response = client.models.generate_content(
      model="gemini-3-pro-image-preview",
      contents=[
          prompt,
          Image.open('person1.png'),
          Image.open('person2.png'),
          Image.open('person3.png'),
          Image.open('person4.png'),
          Image.open('person5.png'),
      ],
      config=types.GenerateContentConfig(
          response_modalities=['TEXT', 'IMAGE'],
          image_config=types.ImageConfig(
              aspect_ratio=aspect_ratio,
              image_size=resolution,
          ),
      )
  )

  # 保存图片 & 输出文本
  for part in response.parts:
      if part.text is not None:
          print(part.text)
      elif image := part.as_image():
          image.save("office.png")
  ```

  ```python Google Search theme={null}
  from google import genai
  from google.genai import types

  API_KEY = "<YOUR AIHUBMIX API KEY>"

  prompt = (
      "Visualize the current weather forecast for the next 5 days in Shanghai "
      "as a clean, modern weather chart. Add a visual on what I should wear each day."
  ) # 将上海近五日天气以天气图表形式呈现出来

  aspect_ratio = "16:9"

  client = genai.Client(
      api_key=API_KEY,
      http_options={"base_url": "https://aihubmix.com/gemini"}
  )

  response = client.models.generate_content(
      model="gemini-3-pro-image-preview",
      contents=prompt,
      config=types.GenerateContentConfig(
          response_modalities=['TEXT', 'IMAGE'],
          image_config=types.ImageConfig(
              aspect_ratio=aspect_ratio,
          ),
          tools=[{"google_search": {}}]
      )
  )

  # 保存图片 & 输出文本
  for part in response.parts:
      if part.text is not None:
          print(part.text)
      elif image := part.as_image():
          image.save("weather.png")
  ```
</CodeGroup>

## Gemini 2.5 系列的「推理」说明

1. 2.5 系列都是推理模型。
2. 2.5 flash 是混合模型，类似 claude sonnet 3.7，可以通过用 `thinking_budget` 控制推理预算来达到最佳效果。
3. 2.5 pro 是纯粹的推理模型，因此不能关闭 thinking、也不显式传递推理预算。
4. 温度值支持范围 0 \<= `temprature` \<= 2

**Python 调用参考如下：**

<CodeGroup>
  ```py 普通非流式 theme={null}
  from google import genai
  from google.genai import types

  def generate():
      client = genai.Client(
          api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
          http_options={"base_url": "https://aihubmix.com/gemini"},
      )

      model = "gemini-2.0-flash"
      contents = [
          types.Content(
              role="user",
              parts=[
                  types.Part.from_text(text="""For the average stock investor, if analyzing financial reports works, why is luck still needed?"""),
              ],
          ),
      ]

      print(client.models.generate_content(
          model=model,
          contents=contents,
      ))

  if __name__ == "__main__":
      generate()
  ```

  ```py 2.0 系列-流式 theme={null}
  from google import genai
  from google.genai import types

  def generate():
      client = genai.Client(
          api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
          http_options={"base_url": "https://aihubmix.com/gemini"},
      )

      model = "gemini-2.0-flash"
      contents = [
          types.Content(
              role="user",
              parts=[
                  types.Part.from_text(text="""For the average stock investor, if analyzing financial reports works, why is luck still needed?"""),
              ],
          ),
      ]
      generate_content_config = types.GenerateContentConfig(
          response_mime_type="text/plain",
      )

      for chunk in client.models.generate_content_stream(
          model=model,
          contents=contents,
          config=generate_content_config,
      ):
          print(chunk.text, end="")

  if __name__ == "__main__":
      generate()
  ```

  ```py 2.5 Flash-流式 theme={null}
  from google import genai
  from google.genai import types

  def generate():
      client = genai.Client(
          api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
          http_options={"base_url": "https://aihubmix.com/gemini"},
      )

      model = "gemini-2.5-flash-preview-04-17" #gemini-2.5-pro-preview-03-25、gemini-2.5-flash-preview-04-17
      contents = [
          types.Content(
              role="user",
              parts=[
                  types.Part.from_text(text="""For the average stock investor, if analyzing financial reports works, why is luck still needed?"""),
              ],
          ),
      ]
      generate_content_config = types.GenerateContentConfig(
          thinking_config = types.ThinkingConfig(
              thinking_budget=2048, #范围 0-16384。默认 1024，最佳边际效果 16000
          ),
          response_mime_type="text/plain",
      )

      for chunk in client.models.generate_content_stream(
          model=model,
          contents=contents,
          config=generate_content_config,
      ):
          print(chunk.text, end="")

  if __name__ == "__main__":
      generate()
  ```

  ```py 2.5 Pro-流式 theme={null}
  from google import genai
  from google.genai import types

  def generate():
      client = genai.Client(
          api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
          http_options={"base_url": "https://aihubmix.com/gemini"},
      )

      model = "gemini-2.5-pro-preview-03-25"
      contents = [
          types.Content(
              role="user",
              parts=[
                  types.Part.from_text(text="""How do I know I'm not just wasting my time?"""),
              ],
          ),
      ]
      generate_content_config = types.GenerateContentConfig(
          response_mime_type="text/plain",
      )

      for chunk in client.models.generate_content_stream(
          model=model,
          contents=contents,
          config=generate_content_config,
      ):
          print(chunk.text, end="")

  if __name__ == "__main__":
      generate()
  ```

  ```py 显示推理内容 theme={null}
  from google import genai
  from google.genai import types

  def generate():
      client = genai.Client(
          api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
          http_options={"base_url": "https://aihubmix.com/gemini"},
      )

      model = "gemini-2.5-pro-preview-05-06"
      contents = [
          types.Content(
              role="user",
              parts=[
                  types.Part.from_text(text="""How is the Rule of 72 in finance derived?"""),
              ],
          ),
      ]
      generate_content_config = types.GenerateContentConfig(
          response_mime_type="text/plain",
          thinking_config=types.ThinkingConfig(
              include_thoughts=True  # 🧠 启用思考过程输出
          ),
      )

      # 用于存储最后一个 chunk 的 usage_metadata
      final_usage_metadata = None
      
      for chunk in client.models.generate_content_stream(
          model=model,
          contents=contents,
          config=generate_content_config,
      ):
          # 检查是否有内容部分
          if chunk.candidates and len(chunk.candidates) > 0:
              for part in chunk.candidates[0].content.parts:
                  if part.text:
                      if part.thought:
                          # 思考过程内容
                          print(part.text, end="")
                      else:
                          # 最终答案内容
                          print(part.text, end="")
          
          # 保存最新的 usage_metadata，只有最后一个 chunk 会包含完整信息
          if chunk.usage_metadata:
              final_usage_metadata = chunk.usage_metadata
      
      # 在所有 chunk 处理完后，打印完整的 token 使用情况
      if final_usage_metadata:
          print(f"\n\n📊 Token 使用情况:")
          print(f"思考 tokens: {getattr(final_usage_metadata, 'thoughts_token_count', '不可用')}")
          print(f"输出 tokens: {getattr(final_usage_metadata, 'candidates_token_count', '不可用')}")
          print(f"总计: {final_usage_metadata}")

  if __name__ == "__main__":
      generate()
  ```
</CodeGroup>

## Gemini 2.5 Flash 支持

Openai 兼容方式调用参考如下：

<CodeGroup>
  ```py Python 用于快速任务时，关闭思考 theme={null}
  from openai import OpenAI

  client = OpenAI(
      api_key="sk-***", # 换成你在 AiHubMix 生成的密钥
      base_url="https://aihubmix.com/v1",
  )

  completion = client.chat.completions.create(
      model="gemini-2.5-flash-preview-04-17-nothink",
      messages=[
          {
              "role": "user",
              "content": "Explain the Occam's Razor concept and provide everyday examples of it"
          }
      ]
  )

  print(completion.choices[0].message.content)
  ```

  ```py Python 控制预算 theme={null}
  from openai import OpenAI

  client = OpenAI(
      api_key="sk-***", # 换成你在 AiHubMix 生成的密钥
      base_url="https://aihubmix.com/v1",
  )

  completion = client.chat.completions.create(
      model="gemini-2.5-flash-preview-04-17",
      reasoning_effort="low", # 可选 "low", "medium" 和 "high", 分别对应 1024, 8192 和 16384 推理预算
      messages=[
          {
              "role": "user",
              "content": "Explain the Occam's Razor concept and provide everyday examples of it"
          }
      ]
  )

  print(completion.choices[0].message.content)
  ```

  ```shell Curl-基础调用 theme={null}
  curl -X POST https://aihubmix.com/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer sk-***" \
    -d '{
      "model": "gemini-2.5-flash-preview-04-17-nothink",
      "messages": [
        {
          "role": "user",
          "content": "Explain the Occam'\''s Razor concept and provide an everyday example of it."
        }
      ]
    }'
  ```

  ```shell Curl-Thinking 显示 theme={null}
  curl https://aihubmix.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-***" \
  -d '{
    "model": "gemini-2.5-pro-preview-05-06",
    "messages": [
      {
        "role": "user",
        "content": "Explain the Occam'\''s Razor concept and provide an everyday example of it."
      }
    ],
    "reasoning_effort": "low"
  }'
  ```
</CodeGroup>

<Tip>
  1. 用于复杂任务时，只需要将模型 id 设置为默认开启思考的 `gemini-2.5-flash-preview-04-17` 即可。
  2. Gemini 2.5 Flash 通过 `budget`（思考预算）来控制思考的深度，范围 0-16K，目前转发采用的是默认预算 1024，最佳边际效果为 16K。
</Tip>

## 多媒体文件

* 对于 **20MB** 以下的多媒体文件（图片、音频、视频），用 `inline_data` 上传。
* 当多媒体文件大于 20M 时，需要用 Files API。

### 20M 以下文件

<Tip>
  你可以增加 `EDIARESOLUTION_MEDIUM` 参数来约束图片的精度，从而大幅节省输入的费用以及减少大图报错的可能性。

  **支持的媒体分辨率参数值:**

  | 参数名                            | 备注                                               |
  | ------------------------------ | ------------------------------------------------ |
  | MEDIA\_RESOLUTION\_UNSPECIFIED | 媒体分辨率未指定                                         |
  | MEDIA\_RESOLUTION\_LOW         | 媒体分辨率设为 low (64 tokens).                         |
  | MEDIA\_RESOLUTION\_MEDIUM      | 媒体分辨率设为 medium (256 tokens).                     |
  | MEDIA\_RESOLUTION\_HIGH        | 媒体分辨率设为 high (zoomed reframing with 256 tokens). |
</Tip>

**调用参考：**

<CodeGroup>
  ```py 图片 theme={null}
  from google import genai
  from google.genai import types

  # 读取文件为二进制数据
  file_path = "yourpath/file.jpeg"
  with open(file_path, "rb") as f:
      file_bytes = f.read()

  client = genai.Client(
      api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
      http_options={"base_url": "https://aihubmix.com/gemini"}
  )

  response = client.models.generate_content(
      model="gemini-2.5-flash",
      contents=types.Content(
          parts=[
              types.Part(
                  inline_data=types.Blob(
                      data=file_bytes,
                      mime_type="image/jpeg"
                  )
              ),
              types.Part(
                  text="Describe the image."
              )
          ]
      ),
      config=types.GenerateContentConfig(
          system_instruction="You are a helpful assistant that can describe images.",
          max_output_tokens=768,
          temperature=0.1,
          thinking_config=types.ThinkingConfig(
              thinking_budget=0, include_thoughts=False
          ),
          media_resolution=types.MediaResolution.MEDIA_RESOLUTION_MEDIUM # 256 tokens
      )
  )

  print(response.text)
  print(response.usage_metadata) # 输出 token 花费细节
  ```

  ```py 音频 theme={null}
  from google import genai
  from google.genai import types

  # 读取文件为二进制数据
  file_path = "yourpath/file.m4a"
  with open(file_path, "rb") as f:
      file_bytes = f.read()

  client = genai.Client(
      api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
      http_options={"base_url": "https://aihubmix.com/gemini"}
  )

  response = client.models.generate_content(
      model="gemini-2.0-flash",
      contents=types.Content(
          parts=[
              types.Part(
                  inline_data=types.Blob(
                      data=file_bytes,
                      mime_type="audio/m4a"
                  )
              ),
              types.Part(
                  text="Transcribe the audio to text."
              )
          ]
      )
  )

  print(response.text)
  ```

  ```py 视频 theme={null}
  from google import genai
  from google.genai import types

  # 读取文件为二进制数据
  file_path = "yourpath/file.mp4"
  with open(file_path, "rb") as f:
      file_bytes = f.read()

  client = genai.Client(
      api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
      http_options={"base_url": "https://aihubmix.com/gemini"}
  )

  response = client.models.generate_content(
      model="gemini-2.0-flash",
      contents=types.Content(
          parts=[
              types.Part(
                  inline_data=types.Blob(
                      data=file_bytes,
                      mime_type="video/mp4"
                  )
              ),
              types.Part(
                  text="Summarize this video. Then create a quiz with an answer key based on the information in this video."
              )
          ]
      )
  )

  print(response.text)
  ```

  ```py Youtube 链接 theme={null}
  from google import genai
  from google.genai import types

  client = genai.Client(
      api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
      http_options={"base_url": "https://aihubmix.com/gemini"}
  )

  response = client.models.generate_content(
      model="gemini-2.0-flash",
      contents=types.Content(
          parts=[
              types.Part(
                  file_data=types.FileData(
                      file_uri="https://www.youtube.com/watch?v=OoU7PwNyYUw"
                  )
              ),
              types.Part(
                  text="Please summarize the video in 3 sentences."
              )
          ]
      )
  )

  print(response.text)
  ```
</CodeGroup>

### Files API

Gemini 可以同时处理各种类型的输入数据，包括文本、图片和音频。当总请求大小（包括文件、文本提示、系统指令等）超过 **20 MB** 时，请务必使用 Files API。

<Tip>
  * 不支持列出已上传的文件
  * 文件会在 48 小时后自动删除，也可以手动删除已上传的文件
</Tip>

**调用参考**

<CodeGroup>
  ```python 上传文件 theme={null}
  from google import genai

  client = genai.Client(
      api_key="sk-****",   
      http_options={"base_url": "https://aihubmix.com/gemini"},
  )

  myfile = client.files.upload(file="path/to/sample.mp3")

  response = client.models.generate_content(
      model="gemini-2.5-flash", contents=["Describe this audio clip", myfile]
  )

  print(response.text)
  ```

  ```python 获取文件的元数据 theme={null}
  from google import genai

  client = genai.Client(
      api_key="sk-****",   
      http_options={"base_url": "https://aihubmix.com/gemini"},
  )

  myfile = client.files.upload(file='path/to/sample.mp3')
  file_name = myfile.name
  myfile = client.files.get(name=file_name)
  print(myfile)
  ```

  ```python 删除已上传的文件 theme={null}
  from google import genai

  client = genai.Client()

  myfile = client.files.upload(file='path/to/sample.mp3')
  client.files.delete(name=myfile.name)
  ```
</CodeGroup>

## Code Execution

自动代码解析器用例参考：

```py Python theme={null}
from google import genai
from google.genai import types

# 读取文件为二进制数据
file_path = "yourpath/file.csv"
with open(file_path, "rb") as f:
    file_bytes = f.read()

client = genai.Client(
    api_key="sk-***", # 🔑 换成你在 AiHubMix 生成的密钥
    http_options={"base_url": "https://aihubmix.com/gemini"}
)

response = client.models.generate_content(
    model="gemini-2.0-flash",
    contents=types.Content(
        parts=[
            types.Part(
                inline_data=types.Blob(
                    data=file_bytes,
                    mime_type="text/csv"
                )
            ),
            types.Part(
                text="Please analyze this CSV and summarize the key statistics. Use code execution if needed."
            )
        ]
    ),
    config=types.GenerateContentConfig(
        tools=[types.Tool(
            code_execution=types.ToolCodeExecution
        )]
    )
)

for part in response.candidates[0].content.parts:
    if part.text is not None:
        print(part.text)
    if getattr(part, "executable_code", None) is not None:
        print("Generated code:\n", part.executable_code.code)
    if getattr(part, "code_execution_result", None) is not None:
        print("Execution result:\n", part.code_execution_result.output)
```

## Interactions API

Interactions 是 Gemini 新一代推理接口，返回结构化的 `Interaction` 对象，支持文本生成、原生图像生成（Nano Banana）及多步推理。目前已支持**同步模式**（`interactions.create()`）；异步模式（Background Interactions）敬请期待。

<Warning>
  SDK 版本要求：`@google/genai` **>= 2.0.0**（JS/TS）或 `google-genai` **>= 2.0.0**（Python）。低版本 SDK 调用 Interactions 会被 Google 后端拒绝（`legacy Interactions schema no longer supported`）。
</Warning>

### 文本生成

调用 `interactions.create()` 发起推理，返回的 `Interaction` 对象提供 `output_text` 便捷属性。

<CodeGroup>
  ```js JavaScript theme={null}
  import { GoogleGenAI } from "@google/genai";

  const ai = new GoogleGenAI({
    apiKey: "sk-***", // 替换为你在 AIHubMix 生成的 API Key
    httpOptions: { baseUrl: "https://aihubmix.com/gemini" },
  });

  const interaction = await ai.interactions.create({
    model: "gemini-3.5-flash",
    input: "Explain quantum computing in one sentence",
  });

  console.log(interaction.output_text);
  console.log(interaction.usage);
  // { total_tokens, total_input_tokens, total_output_tokens, ... }
  ```

  ```py Python theme={null}
  from google import genai

  client = genai.Client(
      api_key="sk-***",  # 替换为你在 AIHubMix 生成的 API Key
      http_options={"base_url": "https://aihubmix.com/gemini"},
  )

  interaction = client.interactions.create(
      model="gemini-3.5-flash",
      input="Explain quantum computing in one sentence",
  )

  print(interaction.output_text)
  ```
</CodeGroup>

### 原生图像生成

通过 `response_format` 配置输出模态为图像，返回的 `Interaction` 对象提供 `output_image` 便捷属性。

<Tip>
  * 推荐模型 `gemini-3.1-flash-image`（Nano Banana 2，通用生图模型）。
  * `response_modalities` 值必须为**小写** `['text', 'image']`；大写为 `generateContent` API 的写法，在 Interactions API 中会返回 `400`。
  * 勿传 `delivery: 'inline'`（`400 Image delivery mode is not supported`），结果默认即以 inline 方式返回。
</Tip>

<CodeGroup>
  ```js JavaScript theme={null}
  import { GoogleGenAI } from "@google/genai";
  import fs from "node:fs";

  const ai = new GoogleGenAI({
    apiKey: "sk-***", // 替换为你在 AIHubMix 生成的 API Key
    httpOptions: { baseUrl: "https://aihubmix.com/gemini" },
  });

  const interaction = await ai.interactions.create({
    model: "gemini-3.1-flash-image",
    input: "A translucent banana-shaped glass lamp on a white desk, soft studio lighting.",
    response_modalities: ["text", "image"],
    response_format: { type: "image", aspect_ratio: "1:1", image_size: "1K" },
  });

  // output_image 便捷属性（取最后一张生成图像）
  if (interaction.output_image?.data) {
    fs.writeFileSync("output.png", Buffer.from(interaction.output_image.data, "base64"));
  }
  ```

  ```py Python theme={null}
  import base64
  from google import genai

  client = genai.Client(
      api_key="sk-***",  # 替换为你在 AIHubMix 生成的 API Key
      http_options={"base_url": "https://aihubmix.com/gemini"},
  )

  interaction = client.interactions.create(
      model="gemini-3.1-flash-image",
      input="A translucent banana-shaped glass lamp on a white desk, soft studio lighting.",
      response_format={
          "type": "image",
          "aspect_ratio": "1:1",
          "image_size": "1K",
      },
  )

  if interaction.output_image:
      with open("output.png", "wb") as f:
          f.write(base64.b64decode(interaction.output_image.data))
  ```
</CodeGroup>

### 流式输出

传入 `stream: true` 启用 SSE 流式传输。增量文本通过 `event.delta.text` 获取。

```js JavaScript theme={null}
const stream = await ai.interactions.create({
  model: "gemini-3.5-flash",
  input: "Write a haiku about the moon",
  stream: true,
});

for await (const event of stream) {
  if (event.event_type === "step.delta" && event.delta?.type === "text") {
    process.stdout.write(event.delta.text);
  }
  if (event.event_type === "interaction.completed") {
    console.log("\nUsage:", JSON.stringify(event.interaction?.usage));
  }
}
```

> 完整的 SDK 接入指南（含 Embeddings、显式缓存 CRUD、能力矩阵等）请参考 [Gemini 原生 SDK 接入](/cn/api/Gemini-SDK)。

## 上下文缓存

Gemini 在原生 API 下默认启用了**隐式上下文缓存**，无需开发者手动操作。每一次 `generate_content` 请求，系统会自动为输入内容建立缓存。当后续请求与此前内容完全一致时，将直接命中缓存，返回上一次的推理结果，大幅提升响应速度并有机会节省 token 消耗。

* **缓存自动生效，无需手动配置。**
* 缓存仅在内容、模型、参数完全一致时生效；任何字段不同都会视为新请求，不命中缓存。
* 缓存有效期（TTL）由开发者设定，也可以不设置。如果未指定，默认为 1 小时。无最小或最大时长限制，费用取决于缓存 token 数与缓存时间。
  * 虽然 Google 官方对 TTL 不设上下限，但由于我们作为转发平台，**仅支持有限的 TTL 配置范围，不保证永久有效**。

### 注意事项

* **无成本节省保证**：缓存 token 的计费为输入原价的 25%，理论上输入部分可最多节省 75% 成本，[**但 Google 官方并未承诺必然节省**](https://ai.google.dev/gemini-api/docs/caching?lang=python)，实际账单还需结合缓存命中率、token 类型与存储时长共同评估。
* **缓存命中条件**：建议将重复的上下文放在请求前部，将易变内容（如用户输入）置于后部，以提高缓存命中率。
* **缓存命中反馈**：如果响应结果命中缓存，在 `response.usage_metadata` 中会包含 `cache_tokens_details` 字段，并有 `cached_content_token_count`，开发者可以据此判断本次请求是否命中缓存。\
  示例响应字段（命中缓存时）：

  ```
  cache_tokens_details=[ModalityTokenCount(modality=<MediaModality.TEXT: 'TEXT'>, token_count=2003)]
  cached_content_token_count=2003
  ```

**代码示例：**

```python theme={null}
from google import genai

client = genai.Client(
    http_options={"base_url": "https://aihubmix.com/gemini"},
    api_key="sk-***", # 换成你在 AiHubMix 生成的密钥
)

prompt = """
Call me Ishmael. Some years ago—never mind how long precisely—having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off—then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me. There now is your insular city of the Manhattoes, belted round by wharves as Indian isles by coral reefs—commerce surrounds it with her surf. Right and left, the streets take you waterward.
"""

def generate_content_sync():
    response = client.models.generate_content(
        model="gemini-2.5-flash-preview-05-20",
        contents=prompt + "How many sentences are in this passage? ",
    )
    print(response.usage_metadata)  # 命中缓存时会显示 cache_tokens_details 和 cached_content_token_count 字段
    return response

generate_content_sync()
```

> 命中缓存时，`response.usage_metadata` 会包含如下结构：
>
> ```
> cache_tokens_details=[ModalityTokenCount(modality=<MediaModality.TEXT: 'TEXT'>, token_count=2003)]
> cached_content_token_count=2003
> ```

**核心结论**：隐式缓存支持自动命中与命中反馈。开发者可以通过 usage\_metadata 判断命中情况。成本节省非保证，实际效果因请求结构和使用场景而异。

## Function calling

使用 openai 兼容方式调用 Gemini 的 function calling 功能时，需要在请求体内部传入`tool_choice="auto"`，否则会报错。

<CodeGroup>
  ```py Python theme={null}
  from openai import OpenAI

  # Define the function declaration for the model
  schedule_meeting_function = {
      "name": "schedule_meeting",
      "description": "Schedules a meeting with specified attendees at a given time and date.",
      "parameters": {
          "type": "object",
          "properties": {
              "attendees": {
                  "type": "array",
                  "items": {"type": "string"},
                  "description": "List of people attending the meeting.",
              },
              "date": {
                  "type": "string",
                  "description": "Date of the meeting (e.g., '2024-07-29')",
              },
              "time": {
                  "type": "string",
                  "description": "Time of the meeting (e.g., '15:00')",
              },
              "topic": {
                  "type": "string",
                  "description": "The subject or topic of the meeting.",
              },
          },
          "required": ["attendees", "date", "time", "topic"],
      },
  }

  # Configure the client
  client = OpenAI(
      api_key="sk-***", # 换成你在 AiHubMix 生成的密钥
      base_url="https://aihubmix.com/v1",
  )

  # Send request with function declarations using OpenAI compatible format
  response = client.chat.completions.create(
      model="gemini-2.0-flash",
      messages=[
          {"role": "user", "content": "Schedule a meeting with Bob and Alice for 03/14/2025 at 10:00 AM about the Q3 planning."}
      ],
      tools=[{"type": "function", "function": schedule_meeting_function}],
      tool_choice="auto" ## 📍 此处追加了 Aihubmix 兼容，更稳定的请求方式
  )

  # Check for a function call
  if response.choices[0].message.tool_calls:
      tool_call = response.choices[0].message.tool_calls[0]
      function_call = tool_call.function
      print(f"Function to call: {function_call.name}")
      print(f"Arguments: {function_call.arguments}")
      print(response.usage)
      #  In a real app, you would call your function here:
      #  result = schedule_meeting(**json.loads(function_call.arguments))
  else:
      print("No function call found in the response.")
      print(response.choices[0].message.content)
  ```
</CodeGroup>

**输出结果示例：**

```bash theme={null}
Function to call: schedule_meeting
Arguments: {"attendees":["Bob","Alice"],"date":"2025-03-14","time":"10:00","topic":"Q3 planning"}
CompletionUsage(completion_tokens=28, prompt_tokens=111, total_tokens=139, completion_tokens_details=None, prompt_tokens_details=None)
```

## Tokens 用量追踪

1. Gemini 原生采用 `usage_metadata` 来[追踪使用的 token](https://ai.google.dev/gemini-api/docs/tokens?lang=python)，其中的字段对应如下：

* prompt\_token\_count: 输入 token 数
* candidates\_token\_count: 输出 token 数
* thoughts\_token\_count: 推理使用的 token 数，性质上也是输出 token
* total\_token\_count: 总 token 使用量（输入+输出）

2. 对于 OpenAI 兼容格式，则采用 `.usage` 来追踪，字段对应如下：

* usage.completion\_tokens: 输入 token 数
* usage.prompt\_tokens: 输出 token 数（包含推理使用的 token 数）
* usage.total\_tokens:总 token 使用量

**使用方法如下:**

<CodeGroup>
  ```py Gemini 原生 theme={null}
  from google import genai
  from google.genai import types
  import time

  def generate():
      client = genai.Client(
          api_key="sk-***", # 换成你在 AiHubMix 生成的密钥
          http_options={"base_url": "https://aihubmix.com/gemini"},
      )

      model = "gemini-2.5-pro-preview-03-25"
      contents = [
          types.Content(
              role="user",
              parts=[
                  types.Part.from_text(text="""How is the Rule of 72 in finance derived?"""),
              ],
          ),
      ]
      generate_content_config = types.GenerateContentConfig(
          response_mime_type="text/plain",
      )

      final_usage_metadata = None
      
      for chunk in client.models.generate_content_stream(
          model=model,
          contents=contents,
          config=generate_content_config,
      ):
          print(chunk.text, end="")
          if chunk.usage_metadata:
              final_usage_metadata = chunk.usage_metadata
      
      # 在所有 chunk 处理完后，打印完整的 token 使用情况
      if final_usage_metadata:
          print(f"\nUsage: {final_usage_metadata}")

  if __name__ == "__main__":
      generate()
  ```

  ```py OpenAI 兼容 theme={null}
  from openai import OpenAI

  client = OpenAI(
      api_key="sk-***", # 换成你在 AiHubMix 生成的密钥
      base_url="https://aihubmix.com/v1",
  )

  completion = client.chat.completions.create(
      model="gemini-2.5-flash-preview-04-17",
      reasoning_effort="low", #"low", "medium", and "high", which behind the scenes we map to 1K, 8K, and 24K thinking token budgets. If you want to disable thinking, you can set the reasoning effort to "none".
      messages=[
          {
              "role": "user",
              "content": "How is the Rule of 72 in finance derived?"
          }
      ],
      stream=True
  )

  #print(completion.choices[0].message.content)

  for chunk in completion:
      print(chunk.choices[0].delta)
      # 只在最后一个 chunk（包含完整 usage 数据）时打印 usage 信息
      if chunk.usage and chunk.usage.completion_tokens > 0:
          print(f"输出 tokens: {chunk.usage.completion_tokens}")
          print(f"输入 tokens: {chunk.usage.prompt_tokens}")
          print(f"总 tokens: {chunk.usage.total_tokens}")
  ```
</CodeGroup>

***

更新时间：2026-07-07
