Fixing Tool-Call Accuracy in vLLM
Fixing Tool-Call Accuracy in vLLM (ubicloud.com)
要約
この記事では、大規模言語モデル(LLM)におけるツール呼び出しの精度問題と、vLLMでの解決策について解説しています。特に、エージェント型ワークロードにおいて、ツール呼び出しのスキーマ精度が低いと、モデルの出力品質が低下する問題に焦点を当てています。vLLM 0.31で導入された制約付きデコーディング機能により、KimiやDeepSeekモデルで100%のスキーマ精度を達成する方法が紹介されています。
全文翻訳
vLLMにおけるツール呼び出し精度の修正
[画像](https://www.ubicloud.com/)
すべてのブログ記事
[画像](https://www.ubicloud.com/rss/rss.xml)
2026年10月20日 · 8分で読めます
[画像: Burak Yucesoy]
Jesse Donkervliet および Junhao Li
シニアソフトウェアエンジニア
オープンウェイトモデルを使用すると、品質ベンチマークが示す値とはかけ離れた結果が得られることがあります。
今日、AIモデルを扱うソフトウェア開発者
ツール呼び出しの精度は、オープンウェイトモデルを提供する上で重要な要素です。ツール呼び出しが正確でないと、モデルは無意味なコンテキストを積み重ねてしまい、特にマルチターンのセッションが一般的なエージェント型ワークロードでは、低品質な結果につながります。
残念ながら、多くのプロバイダーや広く使用されている推論エンジンは、ツール呼び出し精度のテストに完全には合格していません。例えば、vLLMバージョン0.28でKimi K2.6を提供した際、期待されるツール呼び出しスキーマが得られたのは92%の時間でした。つまり、試行されたツール呼び出しの25回に2回は失敗していたことになります。
幸いなことに、vLLMは最近、スキーマへの準拠を保証する技術である「制約付きデコーディング」のサポートを追加しました。この機能は、vLLM 0.31でサーバーサイドフラグとしてリリースされました。これを有効にすることで、新しいKimiおよびDeepSeekモデルで100%のスキーマ精度を達成できます。
この記事では、まずツール呼び出しスキーマ精度とその重要性について説明し、次に制約付きデコーディングとそれがスキーマ精度問題をどのように解決するかについて説明します。
ツール呼び出しスキーマ
LLMに外部ツールを呼び出させるには、2つのステップがあります。(1) AIモデルに外部で利用可能なツール呼び出しの存在を知らせ、(2) モデルに構造化されたツール呼び出しを出力する方法を指示します。例えば、OpenCodeをKimiに接続する際、OpenCodeは利用可能なツールのJSON配列をKimiに送信します。このリストのツールの一つがwebfetchで、Webページのコンテンツを取得します。
[
{
"type": "function",
"function": {
"name": "webfetch",
"description": "- 指定されたURLからコンテンツを取得します\n- URLとオプションのフォーマットを入力として受け取ります\n- URLコンテンツを取得し、要求されたフォーマット(デフォルトはmarkdown)に変換します\n- コンテンツを指定されたフォーマットで返します\n- Webコンテンツを取得して分析する必要がある場合に使用します\n\n使用上の注意:\n [コンテンツは簡潔にするために省略]
",
"parameters": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "コンテンツを取得するURL"
},
"format": {
"type": "string",
"enum": [
"text",
"markdown",
"html"
],
"description": "コンテンツを返すフォーマット(text、markdown、またはhtml)。デフォルトはmarkdownです。",
"default": "markdown"
},
"timeout": {
"type": "number",
"description": "オプションのタイムアウト(秒単位、最大120)"
}
},
"required": [
"url"
]
}
}
},
...
]
推論エンジンは、このJSON記述をLLM固有のトークンでラップし、LLMに渡して、ツール宣言を認識するようにトレーニングされた方法に合わせます。Kimiを提供する場合、これは次のようなものになります。
<|im_system|>tool_declare<|im_middle|>[{"type":"function","function":{...}, ...]<|im_end|>
ツール(上記のJSONではfunction)を記述するJSONオブジェクトには、ツールのパラメータ、その型、どのパラメータが必須かなどが含まれます。これはツールのスキーマとして知られています。エージェントハーネス(例: OpenCode)がLLMによって生成されたツール呼び出しを正常に実行するには、その呼び出しがスキーマで指定されたルールに従う必要があります。
次に、ユーザーがエージェントハーネス経由でWebページをフェッチするように要求すると、LLMは次のようなトークンを出力する可能性があります。
I'll fetch that page. <|tool_calls_section_begin|><|tool_call_begin|>functions.webfetch:0<|tool_call_argument_begin|>{"url": "https://ubicloud.com", "format": "markdown"}<|tool_call_end|><|tool_calls_section_end|>
これらのトークンは、推論サーバーのパーサーによって解析され、LLM固有のトークンが抽出され、呼び出しが次のようなJSONオブジェクトに変換されます。
{
"role": "assistant",
"content": "I'll fetch that page.",
"tool_calls": [
{
"id": "functions.webfetch:0",
"type": "function",
"function": {
"name": "webfetch",
"arguments": "{\"url\": \"https://example.com\", \"format\": \"markdown\"}"
}
}
]
}
これはハーネス(例ではOpenCode)に送り返され、webfetchツールを実行し、その出力をモデルに送り返します。
スキーマ精度の重要性
ツール呼び出しを成功させるには、呼び出しがツールのスキーマに準拠する必要があります。
ツール呼び出しの単純なアプローチは、モデルにツール呼び出しを自由に生成させ、モデルのトレーニングが正しい呼び出しを生成するのに十分であると信頼することです。これは、モデルが構文的に正しい文章を生成すると信頼するのと似ています。
この単純なアプローチは、ほとんどの場合うまくいきます。なぜなら、最新のモデルは構造化されたパターンに従うのが得意だからです。しかし、「ほとんどの場合」の成功は、多くのツール呼び出しが依然として失敗する可能性があることを意味し、エラーメッセージによるコンテキストウィンドウの汚染、モデルパフォーマンスの低下、およびエージェントが呼び出しを1回以上再試行する必要があることによるコストの増加につながります。
Kimiを使用する際にこのような経験を避けるため、Moonshot AIはK2VV ToolCallベンチマークを公開しました。このベンチマークにより、プロバイダーは、オリジナルのKimiと同じ品質で、特に有効なツール呼び出しのみを生成するというデフォルトの動作を含めて、Kimiを提供していることを検証できます。
K2VV ToolCallのワークロードは、LLMがツール呼び出しを生成するタイミングと、生成されたツール呼び出しが構文的に正しいか(つまり、提供されたスキーマに準拠しているか)を評価するために選択された2000件のリクエストで構成されています。このベンチマークでは、トリガーの類似性とスキーマ精度の2つのメトリックを定量化することで、モデルの品質を分析できます。トリガーの類似性は、サービスがツール呼び出しをトリガーすると決定するタイミングと、その決定がMoonshot AI自身のサービスとどれだけ似ているかを考慮します。スキーマ精度は、ツール呼び出しのスキーマに準拠し、したがって正常に呼び出すことができるツール呼び出しの割合を定量化します。例えば、ツール呼び出し精度が50%の場合、モデルによって生成されたツール呼び出しの半分は不正な形式です。
スキーマ精度は通常、言語モデルの確率的な性質により不足します。モデルは尤度に基づいてトークンを生成します。コンパイラや型チェッカーを実行しているわけではありません。明確なプロンプトであっても、不正な形式のツール呼び出しを生成する可能性があります。これは、例えば、モデルのトレーニングデータと現在の推論ハーネスとの間の不一致によって引き起こされる可能性があります。モデルは多くのツール呼び出しデータセットでトレーニングされており、それぞれに独自のツール、スキーマ、および規約があります。その結果、モデルは、現在の本番環境に存在しない場合でも、トレーニング中に見たツールまたはフィールド名を生成する可能性があります。例えば、利用可能なツールがweb_searchである場合にsearch_webを生成したり、アクティブなスキーマがlocationを期待している場合にcity_nameを使用したりすることがあります。
制約付きデコーディング
LLMは、各トークンに対して、それがシーケンスの次のトークンである確率を計算します。次に、重み付きサンプリングを実行して次のトークンを選択します。制約付きデコーディングは、モデルが構文的に無効なツール呼び出しにつながるトークンをサンプリングするのを防ぐことにより、不正な形式のツール呼び出しを回避します。制約付きデコーディングを使用する場合、モデルにトークンを自由にサンプリングさせてから結果を検証するのではなく、推論エンジンがステップバイステップで生成をガイドします。各ステップで、有効なトークンのみが許可されます。
どのトークンが許可されるかは、提供されたツールスキーマによって決定されます。vLLMは、XGrammarライブラリの構造タグを使用してこれを実装しています。以下のスニペットは、XGrammarがKimi K2.6で制約付きデコーディングをどのように実装しているかの抜粋です。これは、呼び出しの開始場所、インデックスの場所、引数の開始場所、スキーマ制約付きJSONが生成される場所など、ツール呼び出しの有効な構造を定義します。
# Kimi K2.6 ツール呼び出し構文:
# <|tool_call_begin|>{function.name}:{index}
# <|tool_call_argument_begin|>{arguments}
# <|tool_call_end|>
TagFormat(
begin=f"{TOOL_CALL_BEGIN_PREFIX}{name}{TOOL_CALL_SUFFIX}",
content=SequenceFormat(
elements=[
RegexFormat(pattern=r"\d+"),
ConstStringFormat(value=TOOL_CALL_ARGUMENT_BEGIN),
JSONSchemaFormat(
json_schema=parameters,
any_order=any_order,
max_whitespace_cnt=max_whitespace_cnt,
),
]
),
end=TOOL_CALL_END,
)
完全な実装はこちらで見つけることができます。
この定義により、生成は有効なパスに従う必要があります。
ツール呼び出しを開始 → ツール名 → ツール呼び出しインデックス → 引数を開始 → スキーマ制約付きJSON → ツール呼び出しを終了
無効なパスは生成中にブロックされます。例えば、生成がツール呼び出しインデックスフェーズに達すると、エンジンは整数トークンへのサンプリングを制限し、それ以外のすべてをマスクします。以下の図は、XGrammarの記事から転載されたもので、無効なトークンがどのようにマスクされるかを視覚的に示しています。
[画像]
出典: Dong, Yixin, et al. "XGrammar: Flexible and efficient structured generation engine for large language models." Proceedings of Machine Learning and Systems 7 (2025).
リンク
これにより、スキーマ精度はベストエフォートのアプローチから実行時保証に変わります。モデルは依然としてどのトークンを生成するかを決定しますが、そのトークンは制限された構文的に正しいセットから選択されます。
注目すべきは、この実行時強制はほとんどパフォーマンスのオーバーヘッドを追加しないことです。各フェーズのトークンマスクを事前に計算し、生成中にGPUで効率的に適用することにより、XGrammarは大幅なパフォーマンスのトレードオフなしに正しいツール呼び出しを保証します。
制約付きデコーディングの動作の違い
Moonshot AIは制約付きデコーディングをオンにすることを推奨しており、独自のAPIもそのように動作します。そのため、当初はvLLMのフォークに制約付きデコーディングを追加しました。vLLMがv0.25でこの機能を追加した後、KimiとDeepSeekのためにアップストリームのこの機能を使用するように切り替えました。しかし、間もなく、ツール呼び出し精度スコアが91%に低下したことが判明しました!
問題を分析した後、vLLMの実装は依然として正しいことを確認しました。代わりに、vLLMが制約付きデコーディングを明示的にオンにしないリクエストのデフォルト動作を変更したことが判明しました。これは主に、vLLMが幅広いモデルをサポートするように設計されているためです。制約付きデコーディングのサポートはモデルごとのタスクであり、問題は3つのキャンプに分類されます。
- 一般的なモデルの問題: 一部のモデルでは、その制約のない出力がツールスキーマやモデルのツール呼び出し形式から大きく逸脱します。これにより、モデルは通常とは異なるトークンを選択せざるを得なくなり、コースから外れてしまいます。
1
例えば、gpt-oss-20b、Qwen 3.6、GLM 5.1のユーザーは、この機能がデフォルトで有効になった後に問題が報告されています。 - 文法翻訳バグ: vLLMは、モデルのツールスキーマまたはツール呼び出し形式をモデル固有の文法に翻訳する際にバグがある可能性があります。これにより、無効なツール呼び出し、リクエストの失敗、制約付きデコーディングのサイレントドロップ、およびツール呼び出し精度の低下などの問題が発生する可能性があります。
1, 2 - 機能連携バグ: 制約付きデコーディングと他のサービングエンジンの機能との連携にバグがあります。例えば、制約付きデコーディングと投機的デコーディングとの相互作用におけるバグにより、投機的トークンが文法によって誤って拒否され、リクエストの失敗につながる可能性があります。
1, 2
これらの問題により、vLLMのメンテナーは、制約付きデコーディングが有効になった後、いくつかのモデルで問題が発生していると報告しています。これにより、モデルに依存しないサービングエンジンであるvLLMにとって、制約付きデコーディングをデフォルトで無効にすることがより安全な選択肢となりました。その後、vLLMは --tool-strict-level フラグを追加し、ユーザーがデプロイメントでツール呼び出しの厳密性を有効にできるようにしました。
しかし、Ubicloudの焦点はvLLMとは異なります。私たちはKimiとDeepSeekモデルを、ユーザーがファーストパーティプロバイダーに期待する品質で提供することに注力しています。このため、制約付きデコーディングを有効にし、K2VV ToolCallベンチマークを再実行しました。すべての提供モデルバージョンで100%のツール呼び出しスキーマ精度を確認した後、変更を本番環境にデプロイしました。その後、このブログ記事を執筆し、私たちの学びを共有しました。
結論
LLMを使用する際、観測される品質はモデルだけに基づいているわけではありません。推論エンジンも重要な役割を果たします。推論エンジンとその設定を変更すれば、モデルの出力品質も変わります。
Kimi K2.6とDeepSeek V4 Flashを提供した際、ツール呼び出しスキーマの不正確さにより、目に見える品質の低下を観測しました。この問題は、まずvLLMのフォークを維持し、次にvLLMの新しい制約付きデコーディング機能を有効にすることで解決しました。これにより、K2VV ToolCallベンチマークにおけるツール呼び出し精度が92%から100%に向上しました。
この記事では、ツール呼び出しと制約付きデコーディングに関する経験を共有しました。これが興味深い、またはモデル提供に関する苦労話(war stories)を共有したい場合は、サポートメールまでご連絡ください。