Вызов инструментов
Опишите функции, которые умеет выполнять ваш собственный код; модель решает, когда запросить одну из них, а ваш код решает, стоит ли и как именно её на самом деле выполнить. tAI никогда не выполняет инструмент от вашего имени.
tAI возвращает один ход модели за раз и на этом останавливается. Он никогда не вызывает инструмент самостоятельно, никогда не зацикливается и никогда не видит результат вызова инструмента, если вы не отправите его обратно в последующем запросе. Весь цикл выполнения принадлежит вашему собственному коду: решение, действительно ли запускать то, что запросила модель, запуск этого и продолжение диалога с результатом.
Определение инструментов
Передайте в запросе массив tools, используя тот же формат, что и API function calling от OpenAI:
{
"model": "tai-4.1",
"messages": [{"role": "user", "content": "Ankara'da hava nasıl?"}],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}
]
}
description важнее, чем может показаться: это единственная информация, которой располагает модель о том, что делает инструмент и когда уместно к нему обращаться. Расплывчатое или отсутствующее описание приводит к тому, что инструмент вызывается не в те моменты или не вызывается тогда, когда следовало бы. parameters — это объект JSON Schema, описывающий аргументы, которые принимает инструмент; собственные аргументы модели в вызове инструмента генерируются в соответствии с этой схемой.
Получение вызова инструмента
Когда модель решает вызвать инструмент вместо прямого ответа, finish_reason в ответе становится "tool_calls", а message.tool_calls заполняется вместо message.content (или наряду с ним):
{
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_a1b2c3",
"type": "function",
"function": {"name": "get_weather", "arguments": "{\"city\": \"Ankara\"}"}
}]
},
"finish_reason": "tool_calls"
}]
}
function.arguments — это строка в формате JSON, а не вложенный объект; разберите её перед использованием. Модель может запросить более одного вызова инструмента за один и тот же ход, если в запросе определено несколько инструментов и задача этого требует, поэтому tool_calls всегда массив, даже когда в нём ровно одна запись.
В потоковом режиме та же информация приходит в виде чанка delta.tool_calls, за которым следует финальный чанк с "finish_reason": "tool_calls"; общий формат чанков, на котором это строится, см. в разделе Потоковая передача.
Выполнение и продолжение диалога
Что происходит дальше — полностью на усмотрение вашего кода. Решите, готовы ли вы выполнить запрошенный вызов (это как раз тот момент, в котором приложение обычно применяет собственную модель разрешений, песочницу или подтверждение пользователя, прежде чем что-либо выполнять). Если вы его выполняете, отправьте результат обратно как новое сообщение с role: "tool", ссылаясь на исходный вызов по его id:
{
"model": "tai-4.1",
"messages": [
{"role": "user", "content": "Ankara'da hava nasıl?"},
{"role": "assistant", "content": null, "tool_calls": [{"id": "call_a1b2c3", "type": "function", "function": {"name": "get_weather", "arguments": "{\"city\": \"Ankara\"}"}}]},
{"role": "tool", "tool_call_id": "call_a1b2c3", "content": "18°C, parçalı bulutlu"}
],
"tools": [/* тот же массив tools, что и раньше */]
}
Затем модель продолжает с этого места, как правило отвечая на исходный вопрос с использованием результата инструмента, хотя может и запросить ещё один вызов инструмента, если этого требует задача. Отправляйте один и тот же массив tools в каждом запросе диалога, а не только в первом; модель не помнит, какие инструменты были доступны на предыдущем ходу, — только то, что есть в текущем запросе.
Отказ от выполнения вызова
Ничто не обязывает вас на самом деле выполнять то, что запросила модель. Если вы решаете этого не делать (запрос выходит за рамки допустимого, требует подтверждения, которого у вас ещё нет, или просто не поддерживается вашим приложением), отправьте сообщение tool, объясняющее это, вместо реального результата, и модель учтёт это в своём следующем ответе, как правило объяснив ограничение пользователю, а не предположив, что действие было выполнено.
Почему устроено именно так
Некоторые агентные фреймворки встраивают выполнение инструментов прямо в сам вызов API: вы регистрируете инструмент один раз, а инфраструктура самого провайдера выполняет его внутренне, зацикливаясь, пока не будет готов финальный ответ. tAI намеренно этого не делает для ваших собственных инструментов. Ваши инструменты — это то, что умеет запускать только ваш код, зачастую затрагивающий вашу собственную инфраструктуру, ваши собственные учётные данные, вашу собственную файловую систему; у tAI нет способа безопасно их выполнить, даже если бы он захотел. Вместо этого tAI предоставляет ровно одну вещь: решение о том, когда следует вызвать инструмент и с какими аргументами, полученное за один ход модели. Всё, что происходит после, — выполнение, зацикливание, защита от неконтролируемой последовательности вызовов, — целиком ответственность вашего приложения, с той степенью осторожности и ограничений, которая уместна для того, что ваши инструменты действительно могут делать.