Подписи мыслей

«Сигнатуры мыслей» — это зашифрованные представления внутреннего мыслительного процесса модели, используемые для сохранения контекста рассуждений при многоэтапном взаимодействии. При использовании моделей мышления (таких как серии Gemini 3 и 2.5) API может возвращать поле thoughtSignature в частях содержимого ответа (например, text или частях functionCall ).

Как правило, если вы получили сигнатуру мысли в ответе модели, вы должны передать её обратно точно в том виде, в котором она была получена, при отправке истории разговора в следующем ходу. При использовании моделей Gemini 3 необходимо передавать сигнатуры мысли обратно во время вызова функции, иначе вы получите ошибку проверки (код состояния 4xx). Это относится и к случаям использования minimal уровня мышления для Gemini 3 Flash.

Как это работает

Приведенная ниже диаграмма наглядно демонстрирует значение терминов «turn» и «step» в контексте вызова функций в API Gemini. «Turn» — это отдельный, завершенный обмен репликами в диалоге между пользователем и моделью. «Step» — это более детальное действие или операция, выполняемая моделью, часто как часть более крупного процесса для завершения «turn».

Диаграмма вызовов и шагов функций

Данный документ посвящен обработке вызовов функций для моделей Gemini 3. Информация о несоответствиях с версией 2.5 приведена в разделе, посвященном поведению моделей .

Gemini 3 возвращает сигнатуры мыслей для всех ответов модели (ответов от API) при вызове функции. Сигнатуры мыслей отображаются в следующих случаях:

  • При параллельном вызове функций первая часть вызова функции, возвращаемая ответом модели, будет иметь сигнатуру thought.
  • При последовательных вызовах функций (многошаговом выполнении) каждый вызов функции будет иметь свою сигнатуру, и необходимо передать все сигнатуры обратно.
  • В ответах модели, не содержащих вызов функции, в последней части, возвращаемой моделью, будет содержаться сигнатура мысли.

В следующей таблице представлена ​​визуализация многошаговых вызовов функций, объединяющая определения поворотов и шагов с концепцией сигнатур, представленной выше:

Повернуть

Шаг

Запрос пользователя

Ответ модели

ФункцияОтвет

1

1

request1 = user_prompt FC1 + signature FR1

1

2

request2 = request1 + (FC1 + signature) + FR1 FC2 + signature FR2

1

3

request3 = request2 + (FC2 + signature) + FR2 text_output

(без FC)

Никто

Сигнатуры в частях вызова функции

Когда Gemini генерирует functionCall , он полагается на thought_signature для корректной обработки выходных данных инструмента в следующем ходе.

  • Поведение :
    • Вызов одной функции : часть functionCall будет содержать thought_signature .
    • Параллельные вызовы функций : Если модель генерирует параллельные вызовы функций в ответе, thought_signature добавляется только к первой части functionCall . Последующие части functionCall в том же ответе не будут содержать сигнатуру.
  • Требование : Вы должны вернуть эту подпись в том же самом месте, где она была получена при отправке истории переписки.
  • Проверка : Строгая проверка применяется ко всем вызовам функций в текущем ходу. (Требуется проверка только текущего хода; предыдущие ходы не проверяются).
    • API обращается к истории (от самых новых к самым старым), чтобы найти самое последнее сообщение пользователя , содержащее стандартный контент (например, text ) (который будет началом текущего хода). Это не будет functionResponse .
    • Все вызовы functionCall модели, происходящие после конкретного сообщения об использовании, считаются частью вызова.
    • Первая часть functionCall на каждом шаге текущего хода должна включать свою thought_signature .
    • Если в первом functionCall на любом этапе текущего хода опустить параметр thought_signature , запрос завершится ошибкой 400.
  • Если корректные подписи не возвращаются, вы получите ошибку следующим образом.
    • gemini-3-pro-preview и gemini-3-flash-preview : Отсутствие подписей приведет к ошибке 400. Текст сообщения будет иметь следующий вид:
      • В блоке содержимого <index of contents array> отсутствует thought_signature при вызове функции <Function Call> . Например, в блоке содержимого 1. отсутствует thought_signature при вызове функции FC1 .

Пример последовательного вызова функции

В этом разделе приведен пример множественных вызовов функций, в которых пользователь задает сложный вопрос, требующий выполнения нескольких задач.

Рассмотрим пример вызова функции в несколько этапов, где пользователь задает сложный вопрос, требующий выполнения нескольких задач: "Check flight status for AA100 and book a taxi if delayed" .

Повернуть

Шаг

Запрос пользователя

Ответ модели

ФункцияОтвет

1

1

request1="Check flight status for AA100 and book a taxi 2 hours before if delayed." FC1 ("check_flight") + signature FR1

1

2

request2 = request1 + FC1 ("check_flight") + signature + FR1 FC2("book_taxi") + signature FR2

1

3

request3 = request2 + FC2 ("book_taxi") + signature + FR2 text_output

(без FC)

None

Приведенный ниже код иллюстрирует последовательность действий, представленную в таблице выше.

Шаг 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>" //Required and Validated
          }
        ]
      },
      {
        "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>" //Required and Validated
          }
        ]
      },
      {
        "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>" //Required and Validated
          }
        ]
      },
      {
        "role": "user",
        "parts": [
          {
            "functionResponse": {
              "name": "book_taxi",
              "response": {
                "booking_status": "success"
              }
              }
            }
        ]
    }
}

Пример параллельного вызова функции

Давайте рассмотрим пример параллельного вызова функции, где пользователь задает вопрос "Check weather in Paris and London" чтобы увидеть, где модель выполняет проверку.

Повернуть

Шаг

Запрос пользователя

Ответ модели

ФункцияОтвет

1

1

request1="Проверьте погоду в Париже и Лондоне"

ФК1 ("Париж") + подпись

ФК2 («Лондон»)

FR1

1

2

Запрос 2 = Запрос 1 + FC1 ("Париж") + подпись + FC2 ("Лондон")

текстовый вывод

(без FC)

Никто

Приведенный ниже код иллюстрирует последовательность действий, представленную в таблице выше.

Шаг 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>"// INCLUDED on First FC
      },
      {
        "functionCall": {
          "name": "get_current_temperature",
          "args": {
            "location": "London"
          }// NO signature on subsequent parallel FCs
        }
      }
    ]
  }
}

Шаг 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>" // MUST BE INCLUDED
      },
      {
        "functionCall": {
          "name": "get_current_temperature",
          "args": {
            "city": "London"
          }
        }
      } // NO SIGNATURE FIELD
    ]
  },
  {
    "role": "user",
    "parts": [
      {
        "functionResponse": {
          "name": "get_current_temperature",
          "response": {
            "temp": "15C"
          }
        }
      },
      {
        "functionResponse": {
          "name": "get_current_temperature",
          "response": {
            "temp": "12C"
          }
        }
      }
    ]
  }
]

Подписи в частях, не относящихся functionCall

Gemini также может возвращать thought_signatures в заключительной части ответа, если речь не идёт о вызове функции.

  • Поведение : Финальная часть содержимого ( text, inlineData… ), возвращаемая моделью, может содержать thought_signature .
  • Рекомендация : Рекомендуется возвращать эти подписи, чтобы обеспечить высокое качество рассуждений модели, особенно при выполнении сложных инструкций или моделировании рабочих процессов агентов.
  • Валидация : API не предъявляет строгих требований к валидации. Если вы их пропустите, вы не получите блокирующей ошибки, хотя производительность может снизиться.

Рассуждения на основе текста/контекста (без проверки достоверности)

Шаг 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." }] }
]

Подписи для совместимости с OpenAI

В следующих примерах показано, как обрабатывать сигнатуры мыслей для API автозавершения чата с использованием совместимости с OpenAI .

Пример последовательного вызова функции

Это пример вызова нескольких функций, когда пользователь задает сложный вопрос, требующий выполнения нескольких задач.

Давайте рассмотрим пример вызова функции, выполняющей несколько операций в цикле, где пользователь спрашивает: Check flight status for AA100 and book a taxi if delayed Вы увидите, что происходит, когда пользователь задает сложный вопрос, требующий выполнения нескольких задач.

Повернуть

Шаг

Запрос пользователя

Ответ модели

ФункцияОтвет

1

1

request1="Check the weather in Paris and London" FC1 ("Paris") + signature

ФК2 («Лондон»)

FR1

1

2

request 2 = request1 + FC1 ("Paris") + signature + FC2 ("London") text_output

(без FC)

None

Следующий код проходит по заданной последовательности.

Этап 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>" //Required and Validated
              }
            },
            "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>" //Required and Validated
              }
            },
            "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>" //Required and Validated
              }
            },
            "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" , и вы увидите, где модель выполняет проверку.

Повернуть

Шаг

Запрос пользователя

Ответ модели

ФункцияОтвет

1

1

request1="Check the weather in Paris and London" FC1 ("Paris") + signature

ФК2 («Лондон»)

FR1

1

2

request 2 = request1 + FC1 ("Paris") + signature + FC2 ("London") text_output

(без FC)

None

Вот код для пошагового выполнения заданной последовательности.

Этап 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>" //Signature returned
              }
            },
            "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" // No signature on Parallel FC
          }
        ]
}

Шаг 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>" //Required
              }
            },
            "function": {
              "arguments": "{\"location\":\"Paris\"}",
              "name": "get_current_temperature"
            },
            "id": "function-call-f3b9ecb3-d55f-4076-98c8-b13e9d1c0e01",
            "type": "function"
          },
          {
            "function": { //No Signature
              "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\"}"
    }
  ]

Часто задаваемые вопросы

  1. Как перенести историю из другой модели в Gemini 3, используя часть вызова функции в текущем повороте и шаге? Мне нужно предоставить части вызова функции, которые не были сгенерированы API и, следовательно, не имеют связанной сигнатуры мысли?

    Хотя внедрение блоков вызова пользовательских функций в запрос крайне нежелательно, в случаях, когда этого нельзя избежать, например, при предоставлении модели информации о вызовах функций и ответах, которые были детерминированно выполнены клиентом, или при передаче трассировки из другой модели, которая не включает сигнатуры мыслей, вы можете установить следующие фиктивные сигнатуры: "context_engineering_is_the_way_to_go" или "skip_thought_signature_validator" в поле сигнатуры мысли, чтобы пропустить проверку.

  2. Я отправляю чередующиеся вызовы функций и ответы, и API возвращает ошибку 400. Почему?

    Когда API возвращает параллельные вызовы функций "FC1 + signature, FC2", ожидается ответ пользователя "FC1 + signature, FC2, FR1, FR2". Если они чередуются в виде "FC1 + signature, FR1, FC2, FR2", API вернет ошибку 400.

  3. Когда модель работает в потоковом режиме и не возвращает вызов функции, я не могу найти сигнатуру мысли.

    В случае, если ответ модели не содержит FC с потоковым запросом, модель может вернуть сигнатуру мысли в части с пустым текстовым содержимым. Рекомендуется анализировать весь запрос до тех пор, пока модель не вернет finish_reason .

Мыслительные подписи для разных моделей

Модели Gemini 3 Pro и Flash, Gemini 3 Pro Image и Gemini 2.5 по-разному реагируют на сигнатуры мыслей. Для Gemini 3 Pro Image см. раздел «Процесс мышления» в руководстве по созданию изображений .

Модели Gemini 3 и Gemini 2.5 по-разному реагируют на сигнатуры мыслей при вызове функций:

  • Если в ответе содержатся вызовы функций,
    • В Gemini 3 сигнатура всегда будет находиться в первой части вызова функции. Возвращать эту часть обязательно .
    • В Gemini 2.5 подпись будет в первой части (независимо от типа). Возврат этой части необязателен .
  • Если в ответе нет вызовов функций,
    • Подпись Gemini 3 появится в последней части, если модель сгенерирует мысль.
    • В модели Gemini 2.5 не будет никаких отличительных черт.

Информацию о особенностях мышления моделей Gemini 2.5 см. на странице «Мышление» .