跳到正文
Hacker News (official RSS)(ubicloud.com)·· 3 小時前精選AI 評分73

vLLM 加入 constrained decoding,工具呼叫準確率提升至 100%

Fixing Tool-Call Accuracy in vLLM

AI 導讀

vLLM 在 0.31 版正式支援 constrained decoding,透過 XGrammar 進行結構化生成,確保工具呼叫符合 JSON schema,將 Kimi K2.6 的工具呼叫準確率由 92% 提升至 100%。

推薦理由

本博文說明瞭如何利用 vLLM 的 constrained decoding 功能提升工具呼叫準確率,對需要高質量多輪對話的應用有直接參考價值。

正文 · AI 翻譯

所有部落格文章

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 呼叫外部工具:(1) 告知 AI 模型有可用的外部工具呼叫;(2) 提供模型如何輸出結構化工具呼叫的指示。例如,將 OpenCode 連線至 Kimi 時,OpenCode 會傳送一個 JSON 陣列描述可用工具。此清單中的一項工具為 webfetch,負責抓取網頁內容:

[{
  "type": "function",
  "function": {
    "name": "webfetch",
    "description": "- Fetches content from a specified URL\n- Takes a URL and optional format as input\n- Fetches the URL content, converts to requested format (markdown by default)\n- Returns the content in the specified format\n- Use this tool when you need to retrieve and analyze web content\n\nUsage notes:\n  [content redacted for brevity]\n",
    "parameters": {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "url": {
          "type": "string",
          "description": "The URL to fetch content from"
        },
        "format": {
          "type": "string",
          "enum": [
            "text",
            "markdown",
            "html"
          ],
          "description": "The format to return the content in (text, markdown, or html). Defaults to markdown.",
          "default": "markdown"
        },
        "timeout": {
          "type": "number",
          "description": "Optional timeout in seconds (max 120)"
        }
      },
      "required": [
        "url"
      ]
    }
  }
}, ...]

推理引擎接著將此 JSON 描述包裝於 LLM 專用的 token 內,再傳入 LLM,以符合 LLM 訓練時識別工具宣告的方式。提供 Kimi 時,情況大致如下:

<|im_system|>tool_declare<|im_middle|>[{"type":"function","function":{...}, ...]<|im_end|>

上述 JSON 中描述工具(或 function)的物件包含工具的引數、型別、哪些引數為必填等資訊。這被稱為工具的 結構。為使代理工具(例如 OpenCode)能成功執行 LLM 產生的工具呼叫,呼叫必須遵循其結構中規定的規則。

接著,當使用者透過其代理工具請求抓取網頁時,LLM 可能輸出以下 token:

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|>

這些 token 由推理伺服器的解析器解析,抽取 LLM 專用 token,並將呼叫轉換為類似的 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,並將輸出回傳給模型。

結構準確性的重點

為使工具呼叫成功,呼叫必須遵循工具的結構。

簡單的工具呼叫方式是允許模型自由產生工具呼叫,並信任模型的訓練足以產生正確呼叫。這類似於我們信任模型能生成語法正確的文字。

簡單方法大多時有效,因為現代模型擅長遵循結構化模式。但「大多時」的成功意味著許多工具呼叫仍可能失敗,導致因錯誤訊息而汙染上下文視窗、降低模型效能,以及因代理需重試一次或多次而增加成本。

為避免在使用 Kimi 時遇到類似經驗,Moonshot AI 發布了 K2VV ToolCall 基準測試。此基準測試允許供應商驗證其提供的 Kimi 服務與原始服務保持相同品質,包括僅產生有效工具呼叫的預設行為。

K2VV ToolCall 的工作量包含 2000 個請求,旨在評估 LLM 何時產生工具呼叫,以及產生的工具呼叫是否語法正確(即符合所提供的 schema)。此基準測試透過量化兩項指標:trigger similarity 與 schema accuracy 來分析模型品質。Trigger similarity 會考量服務何時觸發工具呼叫,以及其決策與 Moonshot AI 自身服務的相似度。Schema accuracy 量化符合工具 schema 的呼叫比例,從而可成功執行。例如,若工具呼叫準確率為 50%,則模型產生的工具呼叫中有一半為格式錯誤。

Schema accuracy 通常不足,因為語言模型本質上是機率性的。模型根據機率產生 token,並非執行編譯器或型別檢查器。即使提示清晰,也可能產生格式錯誤的工具呼叫。這可能由於模型訓練資料與目前推論環境不一致。例如,模型在訓練期間見過的工具或欄位名稱,卻在實際環境中不存在。舉例來說,模型可能產生 search_web 而可用工具為 web_search,或使用 city_name 而活躍 schema 期望 location。

受限解碼

LLM 會為每個 token 計算其為序列中下一個 token 的機率。接著透過加權抽樣選擇下一個 token。受限解碼透過阻止模型抽樣會導致語法不合法的工具呼叫 token,從而避免格式錯誤的工具呼叫。使用受限解碼時,推論引擎不再讓模型自由抽樣並在後續驗證結果,而是逐步引導生成。在每一步,僅允許合法 token。

允許的 token 由所提供的工具 schema 決定。vLLM 透過 structural tags 從 XGrammar library 實現此功能。以下片段展示了 XGrammar 在 Kimi K2.6 中實作受限解碼的範例。它定義了工具呼叫的有效結構,包括呼叫起始位置、索引位置、引數起始位置,以及必須生成符合 schema 限制的 JSON 的位置。

# Kimi K2.6 tool call syntax:
# <|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,
)

完整實作可於此處找到。

根據此定義,生成必須遵循有效路徑:

開始工具呼叫 → 工具名稱 → 工具呼叫索引 → 開始引數 → 受 Schema 限制的 JSON → 結束工具呼叫

生成過程中無效路徑會被阻止。例如,當生成到達工具呼叫索引階段時,引擎會將取樣限制為整數 token 並遮蔽其他所有內容。下圖(摘自 XGrammar 文章)很好地展示了無效 token 的遮蔽方式。

來源:Dong, Yixin 等人. "XGrammar: Flexible and efficient structured generation engine for large language models." Proceedings of Machine Learning and Systems 7 (2025). [連結]

這改變了模式準確度,從最佳努力的方式轉為執行時的保證。模型仍然決定要生成哪個 token,但現在 token 是從受限制且語法正確的集合中選擇的。

值得注意的是,這種執行時強制執行幾乎不增加效能開銷。透過為每個階段預先計算 token 掩碼,並在 GPU 生成時高效應用,XGrammar 確保正確的工具呼叫,而不犧牲顯著效能。

受限解碼行為的差異

Moonshot AI recommends constrained decoding to be turned on 其自己的 API 亦如此運作。因此,我們最初在我們的 vLLM 分支中加入了受限解碼。在 vLLM 在 v0.25 加入此功能後,我們改為使用上游的此功能來支援 Kimi 與 DeepSeek。不幸的是,沒過多久我們發現工具呼叫準確率又降回 91%!

經過問題分析,我們確認 vLLM 的受限解碼實作仍然正確。相反,我們發現 vLLM 改變了對未明確開啟受限解碼的請求的預設行為。這主要是因為 vLLM 設計為支援廣泛模型。支援受限解碼是每個模型的任務,問題可分為三類:

  • General model issues: 對於某些模型,其非受限輸出與工具的 schema 或模型的工具呼叫格式差異顯著。這迫使模型選擇本不會選擇的 token,導致偏離預期 [1]。例如,gpt-oss-20b、Qwen 3.6 與 GLM 5.1 的使用者在預設啟用此功能後報告問題。
  • Grammar translation bugs: vLLM 可能在將模型的工具 schema 或工具呼叫格式轉譯為模型特定語法時出現錯誤。這可能導致問題,包括無效的工具呼叫、請求失敗、靜默放棄受限解碼,以及較低的工具呼叫準確率 [1, 2]。
  • Feature interaction bugs: 受限解碼與其他服務引擎功能之間的互動存在錯誤。例如,受限解碼與投機解碼之間互動的錯誤可能導致投機 token 被語法錯誤地拒絕,進而導致請求失敗 [1, 2]。

由於這些問題,vLLM 維護者在啟用受限解碼後報告多個模型出現問題。這使得在像 vLLM 這樣的模型無關服務引擎中,預設關閉受限解碼成為更安全的選擇。後來,vLLM 添加了 --tool-strict-level 旗標,讓使用者能為其部署啟用工具呼叫嚴格模式。

Ubicloud 的重點與 vLLM 不同。然而,我們專注於以使用者期望的第一方供應商品質提供 Kimi 與 DeepSeek 模型。基於此,我們啟用了受限解碼並重新執行 K2VV ToolCall 基準測試。確認所有已服務模型版本的工具呼叫 schema 準確率為 100% 後,我們將更改部署到生產環境。接著撰寫此部落格文章分享我們的經驗。

結論

在使用 LLM 時,觀察到的品質並非僅取決於模型本身。推理引擎也扮演重要角色。更改推理引擎及其設定,即可改變模型的輸出品質。

在部署 Kimi K2.6 與 DeepSeek V4 Flash 時,我們發現由於工具呼叫 schema 不準確,品質明顯下降。我們先自行 fork vLLM,接著啟用 vLLM 的新受限解碼功能,進而將 K2VV ToolCall benchmark 的工具呼叫準確率從 92% 提升至 100%。

在這篇部落格文章中,我們分享了工具呼叫與受限解碼的經驗。如果這讓您感興趣,或想分享關於模型服務的實戰故事,請透過我們的 支援信箱 聯絡我們。