Перейти к основному содержимому

Для чистого Markdown-содержимого этой страницы добавьте .md к этому URL. Полный индекс документации см. в https://docs.nvidia.com/dynamo/llms.txt. Полное содержимое, включая API reference и примеры SDK, см. в https://docs.nvidia.com/dynamo/llms-full.txt.

Устранение неполадок с вызовами инструментов

Если вызов инструмента возвращается неверно (tool_calls равно null, аргументы выглядят повреждёнными, в message.content появляются сырые маркеры <tool_call>, или finish_reason равно "stop" там, где вы ожидали "tool_calls"), по одному запросу и ответу обычно нельзя понять, где именно ошибка. С точки зрения ответа сбой у модели и сбой у парсера выглядят одинаково.

Если добавить "logprobs": true в один воспроизводящий запрос, в ответе станет виден сырой токенный вывод движка. Этого достаточно, чтобы сотрудник команды Dynamo определил, проблема в модели, в конфигурации парсера или в самом парсере. На этой странице показано, какое поле нужно добавить и как будет выглядеть ответ, чтобы можно было собрать и передать полезную диагностическую информацию.

Рецепт применим к нестриминговым запросам к OpenAI-совместимому эндпоинту Dynamo /v1/chat/completions. Для многоканальных reasoning-моделей (harmony, kimi_k2, kimi_k25, gemma4) этот рецепт восстанавливает только канал содержимого ассистента; reasoning-канал не попадает в logprobs.content.

Если worker использует backend SGLang, logprobs: true по умолчанию отклоняется, потому что менеджер tokenizer'а в SGLang последовательно детокенизирует top-k токены, что ухудшает задержку. Запустите worker с DYN_SGL_ALLOW_TOP_LOGPROBS=1 в окружении, чтобы включить это только на время воспроизводящего запроса, а затем снимите переменную. Отслеживается в sgl-project/sglang#24447.

Запрос

Добавьте "logprobs": true в проблемный запрос:

curl -s http://localhost:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "Qwen/Qwen2.5-7B-Instruct",
"messages": [
{"role": "user", "content": "What is the weather in NYC?"}
],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"},
"unit": {"enum": ["celsius", "fahrenheit"]}
},
"required": ["location"]
}
}
}],
"tool_choice": "auto",
"temperature": 0.0,
"logprobs": true
}'

Ответ

Вы получите обычные поля (message.tool_calls, message.content, finish_reason) плюс новое поле choices[0].logprobs.content, в котором содержится сырой поток токенов движка:

{
"choices": [{
"finish_reason": "tool_calls",
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\":\"New York, NY\",\"unit\":\"fahrenheit\"}"
}
}]
},
"logprobs": {
"content": [
{"token": "<tool_call>", "bytes": [60, 116, 111, 111, 108, 95, 99, 97, 108, 108, 62]},
{"token": "\n", "bytes": [10]},
{"token": "{\"", "bytes": [123, 34]},
{"token": "name", "bytes": [110, 97, 109, 101]},
"...",
{"token": "</tool_call>", "bytes": [60, 47, 116, 111, 111, 108, 95, 99, 97, 108, 108, 62]}
]
}
}]
}

Каждая запись в logprobs.content соответствует одному сгенерированному токену с его точными байтами UTF-8 в поле bytes. Если сложить эти байты по порядку, получится сырой вывод модели до того, как к нему прикоснулся какой-либо parser tool-calls. Это ключевой артефакт для разбора: он показывает, что именно сгенерировала модель, отдельно от того, что из этого сделал parser.

Что включить в отчёт

Передайте в баг-репорте или в треде issue эти четыре вещи:

  1. Полное тело запроса: имя модели, сообщения, инструменты, параметры семплирования и logprobs: true.
  2. Полное тело ответа. Не обрезайте logprobs.content -- именно построчные записи имеют значение.
  3. Версию Dynamo и backend (vLLM, SGLang, TRT-LLM, включая версии, если они известны).
  4. Команду запуска worker'а, особенно значение --dyn-tool-call-parser, если оно задано.

Имея эти четыре части, команда Dynamo обычно может локализовать ошибку без поднятия вашей модели. Команда восстановит сырой поток из массивов bytes и сравнит его с message.content и message.tool_calls, чтобы понять, проблема в выводе модели, в конфигурации parser'а или в его логике.

См. также