☰
【Agent】LLM格式化输出(二)
2026/10/6 2:25:50 网站建设 项目流程

作为上一篇文章引导解码的补充,我们进一步介绍vLLM的引导解码。

注意,本篇文章基于vllm 0.16.0。vllm的语法变更频繁,请以最新的文档为准。

输出数组

我们以一个最简单的例子,让LLM只输出数组:

# 2. 定义 JSON Schema 约束 (强制输出整数数组)json_schema={"type":"array","items":{"type":"integer"},"minItems":3,"maxItems":10}# 3. 构造请求 Payloadpayload={"model":MODEL_NAME,"messages":[{"role":"system","content":"你是一个严格遵循格式要求的助手。"},{"role":"user","content":"请列出前 5 个质数。必须严格以 JSON 数组格式输出,不要包含任何 Markdown 标记(如 ```json)或其他解释文字。"}],"temperature":0.7,"max_tokens":100,# 核心:在顶层传入 guided_json 参数{"structured_outputs":{"json":json_schema}}}

还是同样的道理,如果不使用 openai 后端,只是在代码里调用 LLM,还可以用

fromvllmimportLLM,SamplingParamsfromvllm.sampling_paramsimportStructuredOutputsParams llm=LLM(model="HuggingFaceTB/SmolLM2-1.7B-Instruct")# 2. 定义 JSON Schema 约束# 这里的 Schema 规定:输出必须是一个数组,且数组内的元素必须是整数guided_json_schema={"type":"array","items":{"type":"integer"},# 可选:限制数组长度,防止模型输出过长或过短"minItems":3,"maxItems":10}structured_outputs_params=StructuredOutputsParams(json=guided_json_schema)sampling_params=SamplingParams(structured_outputs=structured_outputs_params)outputs=llm.generate(prompts="请列出前 5 个质数。必须严格以 JSON 数组格式输出,不要包含任何 Markdown 标记(如 ```json)或其他解释文字。",sampling_params=sampling_params,)print(outputs[0].outputs[0].text)

和上一篇文章所介绍的一样,如果需要LLM格式化输出,需要保证两点:

  1. 提示词需要写明格式化输出
  2. 需要启用引导解码

EBNF 驱动下更复杂的输出

扩展巴科斯-瑙尔范式(Extended Backus–Naur Form,EBNF)是一种用于描述计算机编程语言等正式语言的与上下文无关语法的元语法(metasyntax)符号表示法。简而言之,它是一种描述语言的语言。它是基本巴科斯范式(BNF)元语法符号表示法的一种扩展。

当然,我是不会写 EBNF 范式的,这不影响使用,可以找模型来生成。
要生成一个合法的 JSON 整数数组(如 [1, -2, 34]),我们需要定义数组结构、元素、整数以及允许的空格。

root ::="["ws elements ws"]"elements ::=element(","ws element)* element ::=integer integer ::="-"?[0-9]+ ws ::=[\t\n]*

文法解析:
root: 定义整体必须是以 [ 开始,] 结束,中间是 elements,且允许首尾有空格 (ws)。
elements: 定义元素列表,至少一个 element,后面可以跟 0 个或多个由 , 和空格隔开的 element。
integer: 定义整数,可选的负号 - 加上一个或多个数字 [0-9]+。
ws: 定义空白字符(空格、制表符、换行符),用于提高模型生成的容错率。

使用 openai 后端的服务下,我们可以如下编写代码:

grammar_str=r""" root ::= "[" ws elements ws "]" elements ::= element ("," ws element)* element ::= integer integer ::= "-"? [0-9]+ ws ::= [ \t\n]* """# 3. 构造请求 Payloadpayload={"model":MODEL_NAME,"messages":[{"role":"system","content":"你是一个严格遵循格式要求的助手。"},{"role":"user","content":"请列出前 5 个质数。必须严格以 JSON 数组格式输出,不要包含任何 Markdown 标记(如 ```json)或其他解释文字。"}],"temperature":0.7,"max_tokens":100,# 核心:在顶层传入 guided_json 参数{"structured_outputs":{"grammar":grammar_str}}}

当然,既然有EBNF,就可以实现更加复杂的表达式。LLM只能生成数组吗?如果让LLM生成可执行的代码,是否就能拿来执行了呢?

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询