思考簽章是模型內部思考過程的加密表示法。在多輪和多步驟對話中,思維簽章會保留 Gemini 的推論狀態,這在使用函式呼叫時非常實用。回覆可在任何內容部分 (例如 text、functionCall) 包含 thought_signature 欄位。
Gemini 3 模型對思考簽章的驗證比先前的 Gemini 版本更嚴格,因為這能提升函式呼叫的模型效能。為確保模型在多輪對話中維持完整脈絡,您必須在後續要求中傳回先前回覆的思維簽章,即使使用 MINIMAL 思維層級也一樣。使用 Gemini 3 模型時,如果未傳回必要的思考簽章,模型會傳回 400 錯誤。
雖然 Gemini 3 Pro Image 不會強制執行這項驗證,但為確保模型在多輪對話中能完整掌握上下文,您仍須在後續要求中傳回先前回應的思考簽章。如果系統未傳回想法簽章,Gemini 3 Pro Image 不會傳回 400 錯誤。如需使用 Gemini 3 Pro Image 進行多輪圖像編輯的程式碼範例,請參閱「使用思想特徵進行多輪圖像編輯的範例」。
如果您使用官方 Google Gen AI SDK (Python、Node.js、Go 或 Java),並使用標準對話記錄功能,或將完整模型回覆附加至記錄,系統會自動處理思考簽章。
為什麼這些原則很重要?
當思考型模型呼叫外部工具時,會暫停內部推理程序。思考簽章就像是「儲存狀態」,可讓模型在您提供函式結果後,順暢地繼續思考。如果沒有思考簽章,模型在工具執行階段會「忘記」特定的推論步驟。傳回簽名可確保:
- 情境延續性:模型會保留並檢查呼叫工具的推論步驟。
- 複雜推論:可執行多步驟工作,其中一項工具的輸出內容會做為下一項工具的推論依據。
保留想法
如果是 Gemini 3.5 Flash 和更新的模型,系統預設會保留先前對話的思考過程。這項服務會將對話脈絡中的思考歷程記錄傳遞給模型。
傳送對話記錄時,請與先前的對話保持一致:加入完整脈絡 (思考內容、函式呼叫和回覆),或完全省略。提供部分背景資訊可能會降低模型效能。
其他模型的想法簽名
Flash-Lite 模型無法讀取非 Flash-Lite 模型產生的想法。如果向 Flash-Lite 模型提出的要求包含非 Flash-Lite 模型生成的思考簽章,要求不會失敗。而是會從模型的脈絡中捨棄這些想法。舉例來說,如果傳送要求給 Flash-Lite 模型,但要求中包含 Gemini Flash 或 Pro 模型的記錄,就會發生這種情況。
轉彎和步數
在函式呼叫的脈絡中,請務必瞭解「回合」和「步驟」之間的差異:
- 輪次代表完整的對話互動,從使用者提示開始,到模型針對該提示提供最終回覆 (非函式呼叫) 為止。
- 當模型叫用函式並需要函式回應才能繼續推論程序時,就會在單一回合中發生「步驟」。如圖所示,如果模型需要依序呼叫多個函式,才能滿足使用者要求,則單一回合可能包含多個步驟。
如何使用想法簽章
處理思考簽章最簡單的方法,是在傳送新要求時,將對話記錄中所有先前訊息的所有 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-3.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-3.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。 - 規則:建構下一個要求時,您必須加入包含
functionCall及其thought_signature的part,且完全與模型傳回的內容相同。如果是循序 (多步驟) 函式呼叫,系統會驗證目前回合中的所有步驟,且如果省略任何步驟中第一個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中包含thought_signature(例如最後一個text部分)。 - 規則:建議在下一個要求中加入這個簽章,以獲得最佳效能,但省略簽章不會導致錯誤。串流時,這個簽章可能會在文字內容空白的部分傳回,因此請務必剖析所有部分,直到模型傳回
finish_reason為止。
- 如果模型回應不含
請遵守下列規則,確保模型保留情境:
- 請務必將
thought_signature傳回原始Part內的模型。 - 請勿將含有簽章的
Part與不含簽章的合併。這會中斷想法的位置脈絡。 - 請勿合併兩個都含有簽章的
Part,因為簽章字串無法合併。
依序呼叫函式範例
以下範例說明多步驟函式呼叫,使用者要求「查看 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
以下範例說明如何使用 Chat Completions API,在依序呼叫函式的工作流程中,處理多個步驟的思考簽章。
第 1 回合,步驟 1 (使用者要求)
{ "model": "google/gemini-3.1-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\"}" } ]
平行函式呼叫範例
以下範例說明平行函式呼叫,使用者要求「查看巴黎和倫敦的天氣」。
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": { "functionResponse": { "name": "get_current_temperature", "response": { "temp": "12C" } } } ] } ]
Chat Completions
以下範例說明如何使用 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。 - 必要條件:建議傳回這個簽章,確保模型維持高品質的推理能力,特別是針對複雜的指令遵循或模擬代理式工作流程。
- 驗證:API「不會」嚴格強制驗證非
functionCall部分的簽章。如果省略這些屬性,系統不會顯示封鎖錯誤,但效能可能會降低。
模型回覆範例 (文字部分包含簽名):
以下範例顯示模型回覆,其中 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 圖像模型,在多輪圖像建立和編輯過程中擷取及傳遞思想特徵。
第 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))