awesome-everything EN
↑ Обратно к восхождению

AI / LLM

Tool calls: чтение кода и схем

Суть Читай реальные сниппеты tool calling — JSON schema tool, диспетчер parallel-вызовов, цикл с timeout/обработкой ошибок и валидатор аргументов — и выбирай фикс с наибольшим рычагом.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 14 min

Баги tool calling живут в схеме, диспетчере и цикле — не в модели. Читай каждый сниппет так, как читал бы на ревью, и выбирай фикс, который senior сделал бы первым.

Цель

Отработай петлю диагностики, которую ты запускаешь на каждом агенте: читай tool schema и код цикла, предскажи, как поведут себя модель и твой handler, и тянись к фиксу, который закрывает границу доверия или останавливает runaway.

Сниппет 1 — JSON schema tool

{
  "name": "cancel_order",
  "description": "Cancel an order.",
  "input_schema": {
    "type": "object",
    "properties": {
      "order_id": { "type": "string" },
      "reason":   { "type": "string" }
    }
  }
}
Викторина

Мутирующий tool cancel_order выходит с этой схемой. В чём главная слабость и фикс с наибольшим рычагом?

Сниппет 2 — диспетчер parallel-вызовов

results = []
for block in response.tool_use_blocks:          # их может быть несколько за ход
    output = TOOLS[block.name](**block.input)    # исполняем последовательно
    results.append(tool_result(block.id, output))
send(messages + results)
Викторина

Когда модель эмитит три независимых tool_use-блока за один ход, что этот диспетчер делает верно и что оставляет на столе?

Сниппет 3 — цикл без защиты

while True:
    resp = model.create(messages=messages, tools=TOOLS)
    if resp.stop_reason != "tool_use":
        break
    for b in resp.tool_use_blocks:
        out = run_tool(b.name, b.input)          # может бросить / зависнуть
        messages.append(tool_result(b.id, out))
    messages.append(resp.message)
Викторина

Этот цикл работает в проде против client tools. Какие два дефекта укусят первыми при сбое и как их чинить?

Сниппет 4 — валидатор

def handle(block):
    args = block.input
    try:
        validated = ToolArgs.model_validate(args)   # pydantic: форма + типы
    except ValidationError as e:
        return tool_result(block.id, f"invalid arguments: {e}", is_error=True)
    return tool_result(block.id, run(validated))
Викторина

Этот handler валидирует по схеме через Pydantic и возвращает ошибки как tool_result. Для мутирующего tool против multi-tenant БД чего всё ещё не хватает?

Итог

Каждый баг tool calling читается в схеме, диспетчере, цикле или валидаторе. Слабая схема (нет required, нет enum, пустой description) даёт модели угадывать и не даёт тебе что валидировать. Последовательный диспетчер корректен, но теряет выигрыш по латентности от parallel-вызовов для независимых tools. while True без per-tool timeout — это runaway и зависание, ждущие случиться: ограничь итерации и тайм-боксь каждый tool. А валидация формы через Pydantic необходима, но недостаточна для мутирующего вызова: добавь проверку авторизации и существования и возвращай каждый отказ как tool_result, чтобы модель само-исправлялась.

Продолжить восхождение ↑Tool calls: построй устойчивый цикл tool calling
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.