Gemini Live API 的最佳实践

为了从 Gemini Live API 获得更好的结果,请重点关注以下最佳实践:

设计清晰的系统指令

为了充分发挥 Gemini Live API 的性能,建议您有一套清晰定义的系统指令 (SI),按照智能体角色、对话规则和保护措施的顺序进行定义。

为获得最佳结果,请将每个智能体分离到不同的 SI 中。

  1. 指定智能体的角色设定:详细说明智能体的名称、角色和任何偏好特征。如果您想指定口音,请务必同时指定首选输出语言(例如,针对说英语的人指定英式口音)。

  2. 指定对话规则:按您希望模型遵循的顺序放置这些规则。划分对话中一次性元素和对话循环之间的界限。例如:

    • 一次性元素:一次性收集客户的详细信息(例如姓名、位置、会员卡号)。
    • 对话循环:用户可以讨论建议、价格、退货和配送,并可能希望在不同主题之间切换。让模型知道,只要用户愿意,就可以一直进行这种对话循环。
  3. 在流程中以单独的句子指定工具调用:例如,如果收集客户详细信息的一次性步骤需要调用一个 get_user_info 函数,您可以这样说:第一步是收集用户信息。首先,要求用户提供其姓名、位置信息和会员卡号。然后,使用这些详细信息调用 get_user_info。

  4. 添加任何必要的保护措施:提供您不希望模型执行的任何通用对话保护措施。您可以随意提供具体示例,例如,说明如果发生 x,您希望模型执行 y。如果您仍未获得所需的精确度,请使用“毫无疑问”一词来引导模型提高精确度。

精确定义工具

将工具与 Gemini Live API 搭配使用时,工具定义应具体明确。 务必告知 Gemini 在什么条件下应调用工具。如需了解详情,请参阅工具定义。

撰写有效的提示

  • 使用清晰的提示:在提示中提供模型应该和不应该做什么的示例,并尽量限制每个提示只针对一个角色或身份。考虑使用提示链代替冗长的多页提示。模型在涉及单一函数调用的任务上表现最佳。

    # Prompt chaining example.
    chainable_long_prompt = """
    You need to perform a sequence of tasks.
    First, you should do task1; after that, task2; later, task3; and finally, task4.
    """
    
    # New initial prompt
    """
    You need to perform a sequence of tasks. Once you finish the current task, call
    the `get_next_prompt` function to get instructions for the next task.
    """
    
    PROMPT_LIST = ["Now, do task1", "Now, do task2", "Now, do task3", "Now, do task 4", "all tasks done"]
    def get_next_prompt():
      # Provide this function as a tool to the model.
      for prompt in PROMPT_LIST:
        yield prompt
    
    # Catch and execute tool call `get_next_prompt` and send the new prompt back to the model.
    
  • 提供起始命令和信息:Gemini Live API 在响应前需要用户输入。如要让 Gemini Live API 发起对话,请添加一个要求它向用户问好或开始对话的提示。添加有关用户的信息,以便 Gemini Live API 对问候语进行个性化设置。

会话恢复

  1. 使用透明会话恢复:在 genai.types.LiveConnectConfig 中使用 SessionResumptionConfig(transparent=True) 配置连接。这表示客户端打算无缝处理会话恢复,从而支持在重新连接时重放未使用的消息等功能。
from google.genai import types

session_handle: str | None = None

live_config = types.LiveConnectConfig(
  session_resumption=types.SessionResumptionConfig(
      handle=session_handle,
      transparent=True,
  ),
)
  1. 维护和更新会话句柄:监听来自服务器的 session_resumption_update 消息。如果 resumable 为 true 且提供了 new_handle,则存储此句柄。如果发生断开连接,此句柄对于重新连接到同一会话状态至关重要。

  2. 缓冲已发送的消息并删除已确认的消息:为确保在断开连接期间不会丢失任何客户端消息,请维护一个发送到 Gemini Live API 的消息缓冲区。启用透明会话恢复后,session_resumption_update 消息将包含 last_consumed_client_message_index,表示服务器处理的最后一条消息。使用此索引从缓冲区中移除已确认的消息。为了正确跟踪消息,用户管理的索引必须从 1 开始,因为索引 0 表示 the session is not resumable。发送给模型的每条后续消息都应将此索引递增 1。每次会话恢复时,请确保将使用新连接传输的初始消息的索引重置为 1。

  3. 妥善处理断开连接的情况:

    • GoAway 信号:服务器在预期断开连接(例如超时)之前发送 go_away 消息。管理器应监听此事件,然后使用最新句柄主动重新连接。
    • API 错误:网络问题可能会导致 genai_errors.APIError(例如,WebSocket 错误的代码 1000 或 1006)。管理器应在发送和接收循环中捕获这些错误,并触发会话更新或重新连接过程。
  4. 实现消息重放重新连接:发生断开连接时,使用 client.aio.live.connect 和最新会话句柄创建新会话。建立新连接后,重新发送缓冲区中在断开连接之前未被服务器确认的所有消息。在缓冲区中发送的第一条消息应标记为新连接的索引 1。

启用上下文窗口压缩

对于长时间会话,请使用 ContextWindowCompressionConfig 配置会话的上下文窗口,因为实时音频 token 会快速累积(每秒音频大约 25 个 token)。

警告:上下文压缩会导致对话记录丢失。

from google.genai import types

live_config = types.LiveConnectConfig(
  context_window_compression=types.ContextWindowCompressionConfig(
    trigger_tokens=100_000, # For better clarity
    sliding_window=types.SlidingWindow(target_tokens=4_000),
  ),
)

token 用量计算

价格页面详细介绍了 Gemini Live API 结算结构。 在每个轮次中,API 会针对所有上下文词元计费,其中包括对话记录和用户提供的系统指令。开发者可以通过提取模型响应中提供的 usage_metadata 字段来监控和计算这些费用。

# Example code to get token usage
from google.genai import live

session: live.AsyncSession
async for response in session.receive():
  if response.usage_metadata is not None:
    print("Token usage:", response.usage_metadata)

语音活动检测 (VAD)

默认情况下,Gemini Live API 使用 Gemini 提供的 VAD。

使用 Gemini Live API VAD 时,您可以将模型配置为显式返回 VAD 事件。通过在配置中启用 explicit_vad_signal,您可以直接从模型的回答中监控和捕获这些事件。

from google.genai import types
from google.genai import live

live_config = types.LiveConnectConfig(
  explicit_vad_signal=True
)

session: live.AsyncSession
# In receive loop
async for response in session.receive():
  if response.voice_activity is not None:
    print("Get VAD event", response.voice_activity)

如果您希望使用自定义活动检测系统,则必须停用默认的语音活动检测 (VAD),并手动向 Gemini 模型发出用户轮次信号。这是通过传输 ActivityStart 或 ActivityEnd 事件来定义互动边界来实现的。

from google.genai import live
from google.genai import types

# Disable VAD in config
live_config = types.LiveConnectConfig(
  realtime_input_config=types.RealtimeInputConfig(
    automatic_activity_detection=types.AutomaticActivityDetection(
        disabled=True
    ),
  ),
)

session: live.AsyncSession
await session.send_realtime_input( # Send activity start
    activity_start=types.ActivityStart()
)
for audio_bytes in bytes_to_send_queue: # Send user data
    await session.send_realtime_input(
        audio=types.Blob(
            data=audio_bytes,
            mime_type=f"audio/pcm;rate=16000",
        )
    )
await session.send_realtime_input(activity_end=types.ActivityEnd()) # Send activity end

设置音频语言代码

建议在配置中明确设置语言和语音代码,以保持一致性;如果没有此定义,Gemini 可能会根据提供的上下文更改对话语言。

from google.genai import types

config = types.LiveConnectConfig(
  speech_config=types.SpeechConfig(
    language_code="en-US",
  ),
)

此外,还请在系统指令中提及以下内容:

RESPOND IN {OUTPUT_LANGUAGE}. YOU MUST RESPOND UNMISTAKABLY IN {OUTPUT_LANGUAGE}.

对于 gemini-3.8-live 等实时音频模型,您可以在会话配置中提供语言提示,从而提高多语言自动语音识别 (ASR) 的转写质量。如需了解详情,请参阅为会话启用音频转写功能。

使用参考语音控制语速

在 Gemini 3.8 Live 等实时音频模型上,要求模型加快或减慢语速的系统指令提示无法可靠地更改合成语速。如需控制语速,请在 replicated_voice_config 字段中配置自定义语音,并提供加速或减速的参考音频样本。合成的回答会沿用您在 voice_sample_audio 字段中传递的样本的语速和节奏。

如需使用参考语音调整语速,请完成以下步骤:

  1. 获取目标声音的 10-20 秒清晰音频样本。您可以使用不含语速指令的中性系统指令,录制自己的语音样本或捕获预构建语音的回答。如需了解录制指南,请参阅使用自定义语音。

  2. 应用保调时间拉伸来加快或减慢样本速度,并将结果导出为 24 kHz、16 位有符号小端序单声道 WAV 文件。使用保留音高的滤镜(例如 ffmpeg atempo 滤镜),并将倍数设置为 0.8 到 1.5 之间,这样可以在不改变声音音高或音色的情况下改变语速。小于 1.0 的值会减慢语速,大于 1.0 的值会加快语速。

    例如,以下 ffmpeg 命令可将参考录音的速度提高到 1.25 倍,同时保持音高不变,并将输出格式设置为 24 kHz、16 位单声道 WAV 文件:

    ffmpeg -i INPUT_WAV \
      -filter:a "atempo=1.25" -ar 24000 -ac 1 -sample_fmt s16 \
      PACED_WAV
    

    替换以下内容:

    • INPUT_WAV:原始语音样本的路径。
    • PACED_WAV:时间缩放的 24 kHz 单声道 WAV 文件的输出路径。
  3. 读取时间缩放的 WAV 文件,并将其字节传递给 LiveConnectConfig 中的 ReplicatedVoiceConfig:

    from google.genai import types
    
    with open("PACED_WAV", "rb") as f:
      voice_sample_bytes = f.read()
    
    config = types.LiveConnectConfig(
        response_modalities=[types.Modality.AUDIO],
        speech_config=types.SpeechConfig(
            voice_config=types.VoiceConfig(
                replicated_voice_config=types.ReplicatedVoiceConfig(
                    mime_type="audio/wav",
                    voice_sample_audio=voice_sample_bytes,
                ),
            ),
        ),
    )
    

    将 PACED_WAV 替换为时间缩放的 24 kHz 单声道 WAV 文件的路径。

设置转写语言代码

使用 BCP-47 语言代码格式指定转写语言代码,以提高转写准确率。

注意:启用转写功能会增加 token 数量。

from google.genai import types

config = types.LiveConnectConfig(
  input_audio_transcription=types.AudioTranscriptionConfig(
      language_codes=['en-US']  # This supports multiple language codes.
  ),
  output_audio_transcription=types.AudioTranscriptionConfig(
      language_codes=['en-US']
  ),
)

使用自定义词汇表提高转录准确率

语音识别模型的默认词汇表中通常不包含商品名称、内部代号、药物名称和风格化标识符,因此模型会转写最接近的常用字词。在 input_audio_transcription 的 custom_vocabulary 字段中列出这些字词,以便让识别结果偏向用户实际说出的字词。

from google.genai import types

config = types.LiveConnectConfig(
  input_audio_transcription=types.AudioTranscriptionConfig(
      language_codes=['en-US'],
      custom_vocabulary=['QwikPay', 'Xylotek', 'Traefik', 'oatmilk'],
  ),
)

上述配置会针对同一音频产生以下转写差异:

语音指令 未设置custom_vocabulary 借助custom_vocabulary
QwikPay QuickPay QwikPay
Xylotek Xilotech Xylotek
Traefik Trafic Traefik
oatmilk 燕麦奶 oatmilk

当您将转写内容传递给工具、搜索查询或客户记录时,拼写准确性至关重要,因为像 QuickPay 这样的近似拼写无法匹配任何内容。

在系统指令中列出自定义词汇表不会产生相同的结果。使用 custom_vocabulary 会在语音识别器处理音频时对其产生偏向,而系统指令只有在音频转写完成后才会到达模型。

确保列表中的字词针对的是特定网域术语、品牌名称和专有名词,而不是常见的日常用语。您最多可以提供 1,000 个字词。

客户端缓冲

在发送之前,请勿对输入音频进行大量缓冲(例如 1 秒)。 发送小块(20 毫秒到 40 毫秒之间)以最大限度地减少延迟时间。

重新采样

确保您的客户端应用在传输之前将麦克风输入(通常为 44.1 kHz 或 48 kHz)重新采样为 16 kHz。

示例

此示例结合了最佳实践和系统指令设计指南,旨在引导模型发挥职业规划师的作用。

**Persona:**
You are Laura, a career coach from Brooklyn, NY. You specialize in providing
data-driven advice to give your clients a fresh perspective on the career
questions they're navigating. Your special sauce is providing quantitative,
data-driven insights to help clients think about their issues in a different
way. You leverage statistics, research, and psychology as much as possible.
You only speak to your clients in English, no matter what language they speak
to you in.

**Conversational Rules:**

1. **Introduce yourself:** Warmly greet the client.

2. **Intake:** Ask for your client's full name, date of birth, and state they're
calling in from. Call `create_client_profile` to create a new patient profile.

3. **Discuss the client's issue:** Get a sense of what the client wants to
cover in the session. DO NOT repeat what the client is saying back to them in
your response. Don't ask more than a few questions here.

4. **Reframe the client's issue with real data:** NO PLATITUDES. Start providing
data-driven insights for the client, but embed these as general facts within
conversation. This is what they're coming to you for: your unique thinking on
the subjects that are stressing them out. Show them a new way of thinking about
something. Let this step go on for as long as the client wants. As part of this,
if the client mentions wanting to take any actions, update
`add_action_items_to_profile` to remind the client later.

5. **Next appointment:** Call `get_next_appointment` to see if another
appointment has already been scheduled for the client. If so, then share the
date and time with the client and confirm if they'll be able to attend. If
there is no appointment, then call `get_available_appointments` to see openings.
Share the list of openings with the client and ask what they would prefer. Save
their preference with `schedule_appointment`. If the client prefers to schedule
offline, then let them know that's perfectly fine and to use the patient portal.

**General Guidelines:** You're meant to be a witty, snappy conversational
partner. Keep your responses short and progressively disclose more information
if the client requests it. Don't repeat what the client says back to them.
Each of your responses should add to the conversation, not just recap what
the client said. Be relatable by bringing in your own background
growing up professionally in Brooklyn, NY. If a client tries to get you off
track, gently bring them back to the workflow articulated above.

**Guardrails:** If the client is being hard on themselves, never encourage that.
Remember that your ultimate goal is to create a supportive environment for your
clients to thrive.

工具定义

此 JSON 定义了职业规划师示例中调用的相关函数。 为获得最佳效果,请在定义函数时添加其名称、说明、参数和调用条件。

[
 {
   "name": "create_client_profile",
   "description": "Creates a new client profile with their personal details. Returns a unique client ID. \n**Invocation Condition:** Invoke this tool *only after* the client has provided their full name, date of birth, AND state. This should only be called once at the beginning of the 'Intake' step.",
   "parameters": {
     "type": "object",
     "properties": {
       "full_name": {
         "type": "string",
         "description": "The client's full name."
       },
       "date_of_birth": {
         "type": "string",
         "description": "The client's date of birth in YYYY-MM-DD format."
       },
       "state": {
         "type": "string",
         "description": "The 2-letter postal abbreviation for the client's state (e.g., 'NY', 'CA')."
       }
     },
     "required": ["full_name", "date_of_birth", "state"]
   }
 },
 {
   "name": "add_action_items_to_profile",
   "description": "Adds a list of actionable next steps to a client's profile using their client ID. \n**Invocation Condition:** Invoke this tool *only after* a list of actionable next steps has been discussed and agreed upon with the client during the 'Actions' step. Requires the `client_id` obtained from the start of the session.",
   "parameters": {
     "type": "object",
     "properties": {
       "client_id": {
         "type": "string",
         "description": "The unique ID of the client, obtained from create_client_profile."
       },
       "action_items": {
         "type": "array",
         "items": {
           "type": "string"
         },
         "description": "A list of action items for the client (e.g., ['Update resume', 'Research three companies'])."
       }
     },
     "required": ["client_id", "action_items"]
   }
 },
 {
   "name": "get_next_appointment",
   "description": "Checks if a client has a future appointment already scheduled using their client ID. Returns the appointment details or null. \n**Invocation Condition:** Invoke this tool at the *start* of the 'Next Appointment' workflow step, immediately after the 'Actions' step is complete. This is used to check if an appointment *already exists*.",
   "parameters": {
     "type": "object",
     "properties": {
       "client_id": {
         "type": "string",
         "description": "The unique ID of the client."
       }
     },
     "required": ["client_id"]
   }
 },
 {
   "name": "get_available_appointments",
   "description": "Fetches a list of the next available appointment slots. \n**Invocation Condition:** Invoke this tool *only if* the `get_next_appointment` tool was called and it returned `null` (or an empty response), indicating no future appointment is scheduled.",
   "parameters": {
     "type": "object",
     "properties": {}
   }
 },
 {
   "name": "schedule_appointment",
   "description": "Books a new appointment for a client at a specific date and time. \n**Invocation Condition:** Invoke this tool *only after* `get_available_appointments` has been called, a list of openings has been presented to the client, and the client has *explicitly confirmed* which specific date and time they want to book.",
   "parameters": {
     "type": "object",
     "properties": {
       "client_id": {
         "type": "string",
         "description": "The unique ID of the client."
       },
       "appointment_datetime": {
         "type": "string",
         "description": "The chosen appointment slot in ISO 8601 format (e.g., '2025-10-30T14:30:00')."
       }
     },
     "required": ["client_id", "appointment_datetime"]
   }
 }
]

更多信息

如需详细了解如何使用 Gemini Live API,请参阅: