Детальный вызов инструментов (Fine-Grained Tool Calling)
Когда вы используете инструменты Claude в сочетании со стримингом (потоковой передачей данных), вы получаете обновления в реальном времени по мере того, как AI генерирует аргументы для этих инструментов. Это значительно улучшает пользовательский опыт, делая взаимодействие более отзывчивым. Однако за кулисами этого процесса скрываются важные детали, которые стоит понять, чтобы максимально эффективно использовать возможности Claude API.
Основы потоковой передачи данных при использовании инструментов
При включенном стриминге Claude отправляет различные типы событий по мере обработки вашего запроса. Вы, вероятно, уже знакомы с событием ContentBlockDelta, которое используется для обычной генерации текста. Однако для работы с инструментами появляется новый тип событий, который содержит два ключевых свойства:
partial_json: фрагмент JSON, представляющий часть аргументов инструмента.snapshot: кумулятивный JSON, собранный из всех полученных фрагментов на данный момент.
Эти свойства позволяют вам отслеживать процесс формирования аргументов инструмента в реальном времени. Например, в вашем коде вы можете обрабатывать эти события следующим образом:
for chunk in stream:
if chunk.type == "tool_input_chunk": # Пример названия типа события
# Обработка частичного фрагмента JSON
print(chunk.partial_json)
# Или использование полного снимка на данный момент
current_args = chunk.snapshot
Как работает валидация JSON по умолчанию
Именно здесь кроется важная особенность стандартного поведения API. API Anthropic не отправляет каждый фрагмент сразу же, как только Claude его генерирует. Вместо этого он буферизует фрагменты и сначала проверяет их. API ждет, пока будут сформированы полные пары ключ-значение верхнего уровня, прежде чем что-либо отправить.
Например, если ваш инструмент ожидает следующую структуру:
{
"action": "save_article",
"parameters": {
"url": "...",
"word_count": "..."
}
}
API будет ждать, пока значение для ключа url не будет полностью сформировано и проверено по вашей схеме. Только после этого будут отправлены все буферизованные фрагменты, относящиеся к этому ключу. Затем процесс повторяется для следующего ключа, например, word_count. Этот процесс валидации объясняет, почему вы можете наблюдать задержки, за которыми следуют всплески текста, даже при включенном стриминге. Фрагменты удерживаются до тех пор, пока не будет готова полная и валидная пара ключ-значение верхнего уровня.
Детальный вызов инструментов (Fine-Grained Tool Calling)
Если вам требуется более быстрая и детальная потоковая передача данных – возможно, для того чтобы показывать пользователям немедленные обновления или быстро начинать обработку частичных результатов – вы можете включить функцию, называемую Fine-Grained Tool Calling (детальный вызов инструментов).
Основное отличие Fine-Grained Tool Calling заключается в том, что он отключает валидацию JSON на стороне API. Это означает, что:
- Вы получаете фрагменты данных сразу же, как только Claude их генерирует.
- Отсутствуют задержки буферизации между ключами верхнего уровня.
- Поведение становится более похожим на традиционный стриминг, где данные поступают непрерывным потоком.
- Валидация JSON отключена – ваш код должен самостоятельно обрабатывать невалидный JSON.
Чтобы активировать эту функцию, достаточно добавить параметр fine_grained=True в ваш вызов API:
run_conversation(
messages,
tools=[save_article_schema],
fine_grained=True
)
С включенным Fine-Grained Tool Calling вы можете получить значение, например, для url, значительно раньше в потоке, не дожидаясь завершения всего объекта parameters.
Обработка невалидного JSON
Когда вы используете Fine-Grained Tool Calling, Claude может генерировать невалидный JSON. Например, вместо корректного числа для word_count вы можете получить "word_count": undefined. Ваше приложение должно корректно обрабатывать такие случаи, чтобы избежать сбоев.
Пример обработки невалидного JSON:
import json
# ... в вашем цикле обработки стрима ...
try:
parsed_args = json.loads(chunk.snapshot)
# Дальнейшая обработка валидных аргументов
except json.JSONDecodeError:
# Обработка невалидного JSON
print("Получен невалидный JSON, продолжаем...")
# Здесь можно реализовать логику пропуска, логирования или повторной попытки
Без Fine-Grained Tool Calling валидация на стороне API перехватила бы эту ошибку и, возможно, обернула бы проблемные значения в строки, что, однако, могло бы не соответствовать вашей ожидаемой схеме.
Когда использовать Fine-Grained Tool Calling?
Рассмотрите возможность включения Fine-Grained Tool Calling в следующих случаях:
- Вам нужно показывать пользователям прогресс генерации аргументов инструмента в реальном времени.
- Вы хотите начать обработку частичных результатов инструмента как можно быстрее.
- Задержки, вызванные буферизацией, негативно сказываются на пользовательском опыте.
- Вы готовы реализовать надежную обработку ошибок JSON в своем коде.
Для большинства приложений поведение по умолчанию с валидацией API вполне адекватно и обеспечивает стабильность, поскольку API гарантирует корректность получаемых данных. Но когда вам нужна эта дополнительная отзывчивость и максимальный контроль над потоком данных, Fine-Grained Tool Calling дает вам возможность получать фрагменты данных так быстро, как Claude может их генерировать, перекладывая ответственность за валидацию на ваше приложение.