思考特征是模型内部思考过程的加密表示形式。思路签名可在多轮和多步骤对话期间保留 Gemini 的推理状态,这在使用函数调用时非常有用。回答可以在任何内容部分(例如,thought_signaturetext、functionCall)。
与之前的 Gemini 版本相比,Gemini 3 Pro 对思考签名执行更严格的验证,因为这有助于提高模型在函数调用方面的性能。为确保模型在多轮对话中保持完整上下文,您必须在后续请求中返回之前回答中的思考特征。
如果在使用 Gemini 3 Pro 时未返回必需的思维签名,模型会返回 400 错误。
Gemini 3 Pro Image 不会强制执行此验证。为确保模型在多轮对话中保持完整上下文,您必须在后续请求中返回之前回答中的思考特征。
如果未返回思路签名,Gemini 3 Pro Image 不会返回 400 错误。如需查看与使用 Gemini 3 Pro Image 进行多轮图片修改相关的代码示例,请参阅使用思维签名的多轮图片修改示例。
如果您使用的是官方 Google Gen AI SDK(Python、Node.js、Go 或 Java),并且使用标准对话历史记录功能或将完整的模型响应附加到历史记录中,系统会自动处理思路签名。
为什么这些指标很重要?
当思考模型调用外部工具时,它会暂停其内部推理过程。思路签名充当“保存状态”,让模型在您提供函数结果后能够无缝恢复其思维链。如果没有思路签名,模型会在工具执行阶段“忘记”其具体的推理步骤。传回签名可确保:
- 上下文连续性:模型会保留并可以检查证明调用工具合理的推理步骤。
- 复杂推理:支持多步任务,其中一个工具的输出会为下一个工具的推理提供信息。
回合和步数
在函数调用的上下文中,请务必了解轮次和步骤之间的区别:
- 一个轮次表示一次完整的对话交流,从用户提出提示开始,到模型针对该提示提供最终的非函数调用响应结束。
- 当模型调用函数并需要函数响应才能继续推理过程时,就会在一个对话轮次内发生步骤。如图所示,如果模型需要按顺序调用多个函数才能满足用户的请求,则单个对话轮次可能涉及多个步骤。
如何使用思路签名
处理思维签名的最简单方法是在发送新请求时,将对话历史记录中所有先前消息的所有 Part 都包含在内,就像模型返回的那样。
如果您未使用任何 Google Gen AI SDK,或者需要修改或截断对话历史记录,则必须确保保留并发送回模型中的思维签名。
使用 Google Gen AI SDK(推荐)
使用 SDK 的聊天记录功能或将上一个回答中的模型 content 对象附加到下一个请求的 contents 时,系统会自动处理签名。
以下 Python 示例展示了自动处理:
from google import genai
from google.genai.types import Content, FunctionDeclaration, GenerateContentConfig, Part, ThinkingConfig, Tool
client = genai.Client()
# 1. Define your tool
get_weather_declaration = FunctionDeclaration(
name="get_weather",
description="Gets the current weather temperature for a given location.",
parameters={
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"],
},
)
get_weather_tool = Tool(function_declarations=[get_weather_declaration])
# 2. Send a message that triggers the tool
prompt = "What's the weather like in London?"
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=prompt,
config=GenerateContentConfig(
tools=[get_weather_tool],
thinking_config=ThinkingConfig(include_thoughts=True)
),
)
# 3. Handle the function call
function_call = response.function_calls[0]
location = function_call.args["location"]
print(f"Model wants to call: {function_call.name}")
# Execute your tool (for example, call an API)
# (This is a mock response for the example)
print(f"Calling external tool for: {location}")
function_response_data = {
"location": location,
"temperature": "30C",
}
# 4. Send the tool's result back
# Append this turn's messages to history for a final response.
# The `content` object automatically attaches the required thought_signature behind the scenes.
history = [
Content(role="user", parts=[Part(text=prompt)]),
response.candidates[0].content, # Signature preserved here
Content(
role="tool",
parts=[
Part.from_function_response(
name=function_call.name,
response=function_response_data,
)
],
)
]
response_2 = client.models.generate_content(
model="gemini-2.5-flash",
contents=history,
config=GenerateContentConfig(
tools=[get_weather_tool],
thinking_config=ThinkingConfig(include_thoughts=True)
),
)
# 5. Get the final, natural-language answer
print(f"\nFinal model response: {response_2.text}")
使用 REST 或手动处理时
如果您直接与 API 交互,则必须根据以下 Gemini 3 Pro 规则实现签名处理:
- 函数调用:
- 如果模型响应包含一个或多个
functionCall部分,则需要thought_signature才能正确处理。 - 如果单个响应中存在并行函数调用,则只有第一个
functionCall部分会包含thought_signature。 - 如果在一轮对话中存在跨多个步骤的连续函数调用,则每个
functionCall部分都将包含thought_signature。 - 规则:构建下一个请求时,您必须包含
part,其中包含functionCall及其thought_signature,完全按照模型返回时的样子。对于顺序(多步)函数调用,系统会对当前回合中的所有步骤执行验证,如果当前回合中任何步骤的第一个functionCall部分省略了必需的thought_signature,则会导致400错误。对话轮次从不是functionResponse的最新用户消息开始。 - 如果模型返回并行函数调用(例如
FC1+signature、FC2),您的响应必须包含所有函数调用,然后是所有函数响应(FC1+signature、FC2、FR1、FR2)。交错响应(FC1+signature、FR1、FC2、FR2)会导致400错误。 - 在极少数情况下,您需要提供并非由 API 生成的
functionCall部分,因此这些部分没有关联的思路签名(例如,当从不包含思路签名的模型转移历史记录时)。您可以将thought_signature设置为skip_thought_signature_validator,但这应该是最后的手段,因为这会给模型性能带来负面影响。
- 如果模型响应包含一个或多个
- 非函数调用:
- 如果模型回答不包含
functionCall,则可能在回答的最后part(例如,最后一个text部分)中包含thought_signature。 - 规则:建议在下一个请求中包含此签名,以实现最佳性能,但省略此签名不会导致错误。在流式传输时,此签名可能会在文本内容为空的部分中返回,因此请务必解析所有部分,直到模型返回
finish_reason。
- 如果模型回答不包含
请遵循以下规则,确保模型的上下文得到保留:
- 始终将
thought_signature发送回原始Part内的模型。 - 请勿将包含签名的
Part与不包含签名的Part合并。这会破坏思路的位置背景。 - 请勿合并两个都包含签名的
Part,因为签名字符串无法合并。
顺序函数调用示例
以下示例展示了一个多步函数调用示例,其中用户要求“Check flight status for AA100 and book a taxi if delayed”(查看 AA100 航班的状态,如果航班延误则预订出租车),这需要执行多项任务。
REST
以下示例演示了如何使用 REST API 在顺序函数调用工作流的多个步骤中处理思路签名。
第 1 回合,第 1 步(用户请求)
{ "contents": [ { "role": "user", "parts": [ { "text": "Check flight status for AA100 and book a taxi 2 hours before if delayed." } ] } ], "tools": [ { "functionDeclarations": [ { "name": "check_flight", "description": "Gets the current status of a flight", "parameters": { "type": "object", "properties": { "flight": { "type": "string", "description": "The flight number to check" } }, "required": [ "flight" ] } }, { "name": "book_taxi", "description": "Book a taxi", "parameters": { "type": "object", "properties": { "time": { "type": "string", "description": "time to book the taxi" } }, "required": [ "time" ] } } ] } ] }
第 1 轮,第 1 步(模型回答)
{ "content": { "role": "model", "parts": [ { "functionCall": { "name": "check_flight", "args": { "flight": "AA100" } }, "thoughtSignature": "<SIGNATURE_A>" } ] } }
第 1 轮,第 2 步(用户回答 - 发送工具输出)
由于此用户回合仅包含 functionResponse(没有新文本),因此我们仍处于第 1 回合。您必须保留 <SIGNATURE_A>。
{ "role": "user", "parts": [ { "text": "Check flight status for AA100 and book a taxi 2 hours before if delayed." } ] }, { "role": "model", "parts": [ { "functionCall": { "name": "check_flight", "args": { "flight": "AA100" } }, "thoughtSignature": "<SIGNATURE_A>" } ] }, { "role": "user", "parts": [ { "functionResponse": { "name": "check_flight", "response": { "status": "delayed", "departure_time": "12 PM" } } } ] }
第 1 轮,第 2 步(模型回答)
模型现在会根据之前的工具输出决定是否预订出租车。
{ "content": { "role": "model", "parts": [ { "functionCall": { "name": "book_taxi", "args": { "time": "10 AM" } }, "thoughtSignature": "<SIGNATURE_B>" } ] } }
第 1 轮,第 3 步(用户回答 - 发送工具输出)
如需发送出租车预订确认信息,您必须在此循环中包含所有函数调用(<SIGNATURE_A> 和 <SIGNATURE_B>)的签名。
{ "role": "user", "parts": [ { "text": "Check flight status for AA100 and book a taxi 2 hours before if delayed." } ] }, { "role": "model", "parts": [ { "functionCall": { "name": "check_flight", "args": { "flight": "AA100" } }, "thoughtSignature": "<SIGNATURE_A>" } ] }, { "role": "user", "parts": [ { "functionResponse": { "name": "check_flight", "response": { "status": "delayed", "departure_time": "12 PM" } } } ] }, { "role": "model", "parts": [ { "functionCall": { "name": "book_taxi", "args": { "time": "10 AM" } }, "thoughtSignature": "<SIGNATURE_B>" } ] }, { "role": "user", "parts": [ { "functionResponse": { "name": "book_taxi", "response": { "booking_status": "success" } } } ] } }
聊天补全
以下示例演示了如何使用 Chat Completions API 在顺序函数调用工作流的多个步骤中处理思维签名。
第 1 回合,第 1 步(用户请求)
{ "model": "google/gemini-3-pro-preview", "messages": [ { "role": "user", "content": "Check flight status for AA100 and book a taxi 2 hours before if delayed." } ], "tools": [ { "type": "function", "function": { "name": "check_flight", "description": "Gets the current status of a flight", "parameters": { "type": "object", "properties": { "flight": { "type": "string", "description": "The flight number to check." } }, "required": [ "flight" ] } } }, { "type": "function", "function": { "name": "book_taxi", "description": "Book a taxi", "parameters": { "type": "object", "properties": { "time": { "type": "string", "description": "time to book the taxi" } }, "required": [ "time" ] } } } ] }
第 1 轮,第 1 步(模型回答)
{ "role": "model", "tool_calls": [ { "extra_content": { "google": { "thought_signature": "<SIGNATURE_A>" } }, "function": { "arguments": "{\"flight\":\"AA100\"}", "name": "check_flight" }, "id": "function-call-1", "type": "function" } ] }
第 1 轮,第 2 步(用户回答 - 发送工具输出)
由于此用户回合仅包含 functionResponse(没有新文本),因此我们仍处于第 1 回合。您必须保留 <SIGNATURE_A>。
"messages": [ { "role": "user", "content": "Check flight status for AA100 and book a taxi 2 hours before if delayed." }, { "role": "model", "tool_calls": [ { "extra_content": { "google": { "thought_signature": "<SIGNATURE_A>" } }, "function": { "arguments": "{\"flight\":\"AA100\"}", "name": "check_flight" }, "id": "function-call-1", "type": "function" } ] }, { "role": "tool", "name": "check_flight", "tool_call_id": "function-call-1", "content": "{\"status\":\"delayed\",\"departure_time\":\"12 PM\"}" } ]
第 1 轮,第 2 步(模型回答)
模型现在会根据之前的工具输出决定是否预订出租车。
{ "role": "model", "tool_calls": [ { "extra_content": { "google": { "thought_signature": "<SIGNATURE_B>" } }, "function": { "arguments": "{\"time\":\"10 AM\"}", "name": "book_taxi" }, "id": "function-call-2", "type": "function" } ] }
第 1 轮,第 3 步(用户回答 - 发送工具输出)
如需发送出租车预订确认信息,您必须在此循环中包含所有函数调用(<SIGNATURE_A> 和 <SIGNATURE_B>)的签名。
"messages": [ { "role": "user", "content": "Check flight status for AA100 and book a taxi 2 hours before if delayed." }, { "role": "model", "tool_calls": [ { "extra_content": { "google": { "thought_signature": "<SIGNATURE_A>" } }, "function": { "arguments": "{\"flight\":\"AA100\"}", "name": "check_flight" }, "id": "function-call-1d6a1a61-6f4f-4029-80ce-61586bd86da5", "type": "function" } ] }, { "role": "tool", "name": "check_flight", "tool_call_id": "function-call-1d6a1a61-6f4f-4029-80ce-61586bd86da5", "content": "{\"status\":\"delayed\",\"departure_time\":\"12 PM\"}" }, { "role": "model", "tool_calls": [ { "extra_content": { "google": { "thought_signature": "<SIGNATURE_B>" } }, "function": { "arguments": "{\"time\":\"10 AM\"}", "name": "book_taxi" }, "id": "function-call-65b325ba-9b40-4003-9535-8c7137b35634", "type": "function" } ] }, { "role": "tool", "name": "book_taxi", "tool_call_id": "function-call-65b325ba-9b40-4003-9535-8c7137b35634", "content": "{\"booking_status\":\"success\"}" } ]
并行函数调用示例
以下示例展示了一个并行函数调用示例,其中用户询问“Check weather in Paris and London”(查看巴黎和伦敦的天气)。
REST
以下示例演示了如何使用 REST API 在并行函数调用工作流中处理思路签名。
第 1 回合,第 1 步(用户请求)
{ "contents": [ { "role": "user", "parts": [ { "text": "Check the weather in Paris and London." } ] } ], "tools": [ { "functionDeclarations": [ { "name": "get_current_temperature", "description": "Gets the current temperature for a given location.", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city name, e.g. San Francisco" } }, "required": [ "location" ] } } ] } ] }
第 1 轮,第 1 步(模型回答)
{ "content": { "parts": [ { "functionCall": { "name": "get_current_temperature", "args": { "location": "Paris" } }, "thoughtSignature": "<SIGNATURE_A>" }, { "functionCall": { "name": "get_current_temperature", "args": { "location": "London" } } } ] } }
第 1 轮,第 2 步(用户回答 - 发送工具输出)
您必须按原样保留第一部分中的 <SIGNATURE_A>。
[ { "role": "user", "parts": [ { "text": "Check the weather in Paris and London." } ] }, { "role": "model", "parts": [ { "functionCall": { "name": "get_current_temperature", "args": { "city": "Paris" } }, "thought_signature": "<SIGNATURE_A>" }, { "functionCall": { "name": "get_current_temperature", "args": { "city": "London" } } } ] }, { "role": "user", "parts": [ { "functionResponse": { "name": "get_current_temperature", "response": { "temp": "15C" } } }, { "functionResponse": { "name": "get_current_temperature", "response": { "temp": "12C" } } } ] } ]
聊天补全
以下示例演示了如何使用 Chat Completions API 在并行函数调用工作流中处理思维签名。
第 1 回合,第 1 步(用户请求)
{ "contents": [ { "role": "user", "parts": [ { "text": "Check the weather in Paris and London." } ] } ], "tools": [ { "functionDeclarations": [ { "name": "get_current_temperature", "description": "Gets the current temperature for a given location.", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city name, e.g. San Francisco" } }, "required": [ "location" ] } } ] } ] }
第 1 轮,第 1 步(模型回答)
{ "role": "assistant", "tool_calls": [ { "extra_content": { "google": { "thought_signature": "<SIGNATURE_A>" } }, "function": { "arguments": "{\"location\":\"Paris\"}", "name": "get_current_temperature" }, "id": "function-call-f3b9ecb3-d55f-4076-98c8-b13e9d1c0e01", "type": "function" }, { "function": { "arguments": "{\"location\":\"London\"}", "name": "get_current_temperature" }, "id": "function-call-335673ad-913e-42d1-bbf5-387c8ab80f44", "type": "function" } ] }
第 1 轮,第 2 步(用户回答 - 发送工具输出)
您必须按原样保留第一部分中的 <SIGNATURE_A>。
"messages": [ { "role": "user", "content": "Check the weather in Paris and London." }, { "role": "assistant", "tool_calls": [ { "extra_content": { "google": { "thought_signature": "<SIGNATURE_A>" } }, "function": { "arguments": "{\"location\":\"Paris\"}", "name": "get_current_temperature" }, "id": "function-call-f3b9ecb3-d55f-4076-98c8-b13e9d1c0e01", "type": "function" }, { "function": { "arguments": "{\"location\":\"London\"}", "name": "get_current_temperature" }, "id": "function-call-335673ad-913e-42d1-bbf5-387c8ab80f44", "type": "function" } ] }, { "role":"tool", "name": "get_current_temperature", "tool_call_id": "function-call-f3b9ecb3-d55f-4076-98c8-b13e9d1c0e01", "content": "{\"temp\":\"15C\"}" }, { "role":"tool", "name": "get_current_temperature", "tool_call_id": "function-call-335673ad-913e-42d1-bbf5-387c8ab80f44", "content": "{\"temp\":\"12C\"}" } ]
非 functionCall Part 中的签名
即使没有函数调用,Gemini 也可能会在响应的最终 Part 中返回 thought_signature。
- 行为:模型返回的最终内容
Part(text、inlineData等)可能包含thought_signature。 - 要求:建议返回此签名,以确保模型保持高质量的推理能力,尤其是在复杂的指令遵循或模拟的智能体工作流程方面。
- 验证:对于非
functionCall部分中的签名,该 API 不会严格强制执行验证。如果您省略这些参数,系统不会显示阻塞性错误,但性能可能会下降。
文本部分包含签名的模型回答示例:
以下示例展示了模型响应(其中 thought_signature 包含在非 functionCall Part 中)以及如何在后续请求中处理该响应。
第 1 轮,第 1 步(模型回答)
{ "role": "model", "parts": [ { "text": "I need to calculate the risk. Let me think step-by-step...", "thought_signature": "<SIGNATURE_C>" // OPTIONAL (Recommended) } ] }
第 2 回合,第 1 步(用户)
[ { "role": "user", "parts": [{ "text": "What is the risk?" }] }, { "role": "model", "parts": [ { "text": "I need to calculate the risk. Let me think step-by-step...", // If you omit <SIGNATURE_C> here, no error will occur. } ] }, { "role": "user", "parts": [{ "text": "Summarize it." }] } ]
使用思路签名的多轮图片修改示例
以下示例说明了如何在 Gemini 3 Pro Image 的多轮图片创建和编辑过程中检索和传递思维签名。
第 1 轮:获取回答并保存包含思路签名的相关数据
chat = client.chats.create( model="gemini-3-pro-image-preview", config=types.GenerateContentConfig( response_modalities=['TEXT', 'IMAGE'] ) ) message = "Create an image of a clear perfume bottle sitting on a vanity." response = chat.send_message(message) data = b'' for part in response.candidates[0].content.parts: if part.text: display(Markdown(part.text)) if part.inline_data: data = part.inline_data.data display(Image(data=data, width=500))
第 2 轮:传递包含意念签名的相关数据
response = chat.send_message( message=[ types.Part.from_bytes( data=data, mime_type="image/png", ), "Make the perfume bottle purple and add a vase of hydrangeas next to the bottle.", ], ) for part in response.candidates[0].content.parts: if part.text: display(Markdown(part.text)) if part.inline_data: display(Image(data=part.inline_data.data, width=500))