探索LLM推理全阶段的JSON格式输出限制方法

简介: 文章详细讨论了如何确保大型语言模型(LLMs)输出结构化的JSON格式,这对于提高数据处理的自动化程度和系统的互操作性至关重要。

一、引言


1.1 JSON结构化输出的意义

对于基于大型语言模型(LLMs)的应用而言,确保输出能直接以结构化的JSON格式呈现,对于提升数据处理的自动化程度、增强系统的互操作性具有重要意义。例如,客户需要对LLM的输出进行信息提取时,若输出是一个JSON格式则会大大方便工程链路上的后处理;例如,LLM在调用工具(或其它智能体)时,需要按照工具要求传入正确的参数,若能保证LLM的输出是结构化的JSON,则能保证传参正确,从而正确调用工具。


然而,在实践中,即使我们在提示词中反复告诉模型要输出JSON结构,LLM还是偶尔出错。虽然“偶尔”出错的概率很低,但对于工程链路的设计来说,是致命且麻烦的。


1.2 LLM为何不能严格输出JSON

LLM在推理时,基于已经输出的句子,从词汇表中预测下一个词。预测时,为词汇表中的每个词分配一个概率,通过采样得到预测输出,如图1所示。例如,模型在输出"My name is"后,仅有0.62的概率输出自己的名字"Tang",即使我们在提示词中告诉了模型自己的名字是"Tang",模型也有0.38的概率输出别的名字。

image.png

因此,这个依概率采样的推理过程决定了LLM不可能100%按要求输出JSON格式。错误的JSON输出导致了我们在工程链路上无法作后续的解析,因此,能100%严格限制JSON格式输出的方法非常重要。


1.3 友商方案

  • OpenAI JSON Mode


推出于2023年12月份,基于提示词优化,用户仍需要在提示词中给出JSON示例,不能保证严格100%输出JSON。


  • Kimi JSON Mode


近期推出。类似OpenAI的 JSON Mode,用户仍需要在提示词中给出JSON示例,不能保证严格100%输出JSON。


  • OpenAI Structured Outputs


推出于2024年8月份,根据用户给出的JSON示例,严格保证100%输出JSON格式。

https://openai.com/index/introducing-structured-outputs-in-the-api/

image.png

二、前中后三阶段的优化策略

Motivation: 在一个基于通义千问的AI教评项目场景中,JSON格式输出对客户十分重要。因此,我们在该项目实践中由浅入深,从LLM推理的前、中、后三个阶段探索了限制输出JSON格式的方法。其中,“推理前”和“推理后”这两个阶段的方法用在了项目实践中,大大提高了AI教评任务中JSON格式的输出概率。为了进一步研究如何100%输出JSON格式,我们借他山之石,研究了OpenAI的Structured Outputs方法,在“推理中”这一阶段探索并验证了基于动态限制解码的100%输出JSON格式方法。


在分析相关工作基础上,我们将深入讨论每阶段的方法、优劣及其实现方式,以期帮助读者掌握提升JSON输出概率的办法,并应用在实践中。


2.1 推理“前”:Prompt Engineering

(以下提示词来自大量项目实践验证)


在提示词中加入这句话“The JSON object:json”可提高JSON输出概率。(别问,问就是大量实践总结的经验~)


在提示词中给出"##输出格式规范",并给出JSON示例```json ... ```

## 输出格式规范:
```json
[{
  "name":"<评价维度>",
  "mentions":"< 提及次数 >",
  "references":[{
    "time":"<发言时间>",
    "text":"<原文内容>"}]}]
```

The JSON object:json

【实践】

在利用Qwen-long作AI教评的一个项目中,我们需要从教师的课堂录音文本中提取结构化的教学维度信息。采用本节中的prompt加上2.3中的JSON后处理方法后,输出样本基本是符合预期的结构化JSON。JSON正确概率从50%左右上升到了95%。可见仅靠prompt和后处理,已经能以很高的概率使得大模型按照JSON格式输出。然而,在一些需要严谨输出JSON格式的场景,100%严格输出JSON格式的方法仍值得研究。


【优势】

实施简便,无需模型架构调整,可以大幅提高输出JSON的概率。


【不足】

高度依赖于人工设计的prompt,灵活性受限。不能100%输出JSON


2.2 推理“中”:基于动态限制解码实现100%输出JSON

【原理】

LLM依据已输出的词,从词汇表中预测下一个词,可以在词汇表中将不符合JSON规范的词概率置零,从而防止输出不符合JSON规范。(原理偏复杂,可跳过本节直接看结论)。假设我们想让LLM的输出为一个城市的如下信息:

city_info_schema=[{
  "name":"城市名",
  "country":"城市所属国家",
  "latitude":"城市纬度",
  "population":"城市人口(千万)",
  "top 3 landmarks":["知名景点1","知名景点2","知名景点3"]
}]

如上代码块所示,在内存中定义JSON输出的模式city_info_schema。LLM每轮逐个单词输出"response",对于JSON的"key"值,如"name",我们直接从内存拼接到输出字符串"response_str"中;对于JSON的"value",则让LLM通过推理产生。当用户提出问题“请填写杭州的城市信息”后,动态限制解码流程如下:


image.png

上图展示了动态限制解码的工作流程,每一轮推理过程我们给定了JSON的“键”,仅让模型推理“值”。可以进一步用正则式(Python re库)限制我们想要的输出格式:

city_regex = (
    r"""\{\n"""
    + r"""  "name": "[\w\d\s]{1,16}",\n"""
    + r"""  "country": "[\w\d\s]{1,16}",\n"""
    + r"""  "latitude": [-+]?[0-9]*\.?[0-9]{0,2},\n"""
    + r"""  "population": [-+]?[0-9]{1,9},\n"""
    + r"""  "top 3 landmarks": \["[\w\d\s]{1,16}", "[\w\d\s]{1,16}", "[\w\d\s]{1,16}"\]\n"""
    + r"""\}"""
)

在推理过程中,根据正则式限制输出格式的流程如下:

image.png

如第一个键"key"对应的"name",我们用正则式限制其必须输出16个字以内的英文,则"杭"的概率由于不符合正则式要求,预测概率置零,模型一定会按照我们的要求输出。


由于动态限制解码技术需要我们有冻结模型解码过程、改变词汇表采样概率、改变模型输入的权限,目前在线的API接口。


不支持编写动态限制解码算法。但是可以在本地部署模型以实现动态限制解码。


【实践】


在PAI平台的免费体验DSW(NVIDIA A10)上本地部署Qwen2-7B-Instruct实现动态限制解码。基于开源的sglang库,可快速部署动态限制解码算法。

pip install --upgrade pip
pip install "sglang[all]"
# Install FlashInfer CUDA kernels
wget "https://modelscope.oss-cn-beijing.aliyuncs.com/resource/flashinfer-0.1.2%2Bcu121torch2.3-cp310-cp310-linux_x86_64.whl"
pip install flashinfer-0.1.2+cu121torch2.3-cp310-cp310-linux_x86_64.whl
modelscope download --model=qwen/Qwen2-7B-Instruct --local_dir ./Qwen2-7B-Instruct
python3 -m sglang.launch_server --model-path Qwen2-7B-Instruct --port 30000

image.png

显示上图即部署成功。

###导入库
import json
import time
from sglang import set_default_backend, RuntimeEndpoint
import sglang as sgl
from sglang.test.test_utils import (
    add_common_sglang_args_and_parse,
    select_sglang_backend,
)
from sglang.utils import dump_state_text, read_jsonl
##定义“限制模型输出的正则式”
city_regex = (
    r"""\{\n"""
    + r"""  "name": "[\w\d\s]{1,16}",\n"""
    + r"""  "country": "[\w\d\s]{1,16}",\n"""
    + r"""  "latitude": [-+]?[0-9]*\.?[0-9]{0,2},\n"""
    + r"""  "population": [-+]?[0-9]{1,9},\n"""
    + r"""  "top 3 landmarks": \["[\w\d\s]{1,16}", "[\w\d\s]{1,16}", "[\w\d\s]{1,16}"\]\n"""
    + r"""\}"""
)
## 将正则式应用在输出范式中
@sgl.function
def chat_example(s,question):
    s += sgl.system("You are a helpful assistant.")
    # Same as: s += s.system("You are a helpful assistant.")

    with s.user():
        s += question

    s += sgl.assistant_begin()
    s += "Answer: " + sgl.gen("json_output", max_tokens=256, regex=city_regex)
    s += sgl.assistant_end()
## 设置Qwen2的本地通信端口,上图设置为port30000
set_default_backend(RuntimeEndpoint("http://localhost:30000"))
## 捕捉用户输入
state = chat_example.run(
    question=input("请输入城市名:"),
    # temperature=0.1,
    stream=True
)
## 打印必然的JSON输出结果
for out in state.text_iter():
    print(out, end="", flush=True)

运行效果:试输入“杭州”和“纽约”两个城市。输出严格按照了正则式的限制。

image.png

image.png

【优势】

  • 100%严格输出JSON格式,甚至是任意正则式可以定义的格式。


  • 在输出的JSON中,节省了输出"key"值的token:因为"key"值是内存中定义好的,不需要由LLM推理而得。因此,相对于prompt的方式让模型输出全JSON的方式,节省了输出的token数量。(这也是为什么OpenAI的JSON 模式每token价格有30%的折扣的原因)


【不足】

  • 必须本地部署LLM。


2.3 推理“后”:JSON数据后处理

在模型返回response后,也可以利用后处理的技术,校正JSON结构以提高JSON输出的概率。


  • JSON Repair库


Python 的json_repair库,可以解决一部分模型输出JSON格式不规范的问题。

from json_repair import loads #pip install json_repair
import json

if __name__ == '__main__':
    
    bad_string= '''
[
            {
                "foo": "Foo bar baz",
                "tag": "foo-bar-baz"
            },
            {
                "中文": "foo bar foobar foo bar baz.",
                "标签": "foo-bar-foobar"
            }
        ]
'''
    
    parsed_json = loads(bad_string)
    json_str = json.dumps(parsed_json,ensure_ascii=False)
    print(json_str)

经实践验证,json_repair可以解决输出的JSON中缺少"},],"的问题。


  • 随机种子控制:可改变LLM推理的seed, 在不同的seed下输出以减少出错概率。


三、总结与展望

以上介绍的三种类型的方法,可以同时使用,但需要注意不同的场景限制:

【前、中、后三阶段方法总结】

image.png


【彩蛋】

qwen-max-0919、qwen-max-latest、qwen-plus、qwen-plus-0919、qwen-plus-latest、qwen-turbo-0919、qwen-turbo-latest以及qwen2.5系列模型已支持结构化输出JSON。(设置response_format = { "type": "json_object" } )






来源  |  阿里云开发者公众号
作者  
|  唐殊

相关文章
|
8天前
|
机器学习/深度学习 自然语言处理 测试技术
CoT神话破灭,并非LLM标配!三大学府机构联手证实,CoT仅在数学符号推理有用
【10月更文挑战第17天】链式思维(CoT)曾被认为是大型语言模型(LLM)激发推理能力的关键方法,但最新研究显示,CoT仅在数学和符号推理任务中有效,其他任务中效果不明显。加州大学伯克利分校、斯坦福大学和卡内基梅隆大学的联合研究打破了CoT作为LLM标配的神话,为重新评估LLM的推理能力提供了新视角。
17 1
|
12天前
|
自然语言处理 数据中心
Scaling LLM Test-Time Compute Optimally: 一种更有效的方法
【10月更文挑战第14天】本文探讨了大型语言模型(LLMs)在测试时通过增加计算资源来提升性能的可能性。研究发现,通过优化测试时计算的分配,特别是采用基于过程的验证器搜索和自适应更新响应分布的方法,LLM可以显著提高对复杂问题的应对能力,甚至在某些情况下超越更大规模的模型。论文提出了“计算最优”策略,旨在根据问题难度自适应调整计算资源,以最大化性能提升。未来工作将聚焦于增强测试时计算缩放、快速评估问题难度及实现自我改进循环。
22 6
|
10天前
|
机器学习/深度学习 自然语言处理 测试技术
CoT神话破灭,并非LLM标配!三大学府机构联手证实,CoT仅在数学符号推理有用
【10月更文挑战第16天】近期,加州大学伯克利分校、斯坦福大学和卡内基梅隆大学联合研究发现,链式思维(CoT)方法在数学和符号推理任务中表现优异,但在其他类型任务中效果不明显。这一研究打破了CoT作为大型语言模型(LLM)标配的神话,为重新审视LLM的推理能力提供了新视角。
18 2
|
14天前
|
JSON API 数据格式
商品详情数据JSON格式示例参考(api接口)
JSON数据格式的商品详情数据通常包含商品的多个层级信息,以下是一个综合多个来源信息的JSON数据格式的商品详情数据示例参考:
|
23天前
|
机器学习/深度学习 JSON JavaScript
LangChain-21 Text Splitters 内容切分器 支持多种格式 HTML JSON md Code(JS/Py/TS/etc) 进行切分并输出 方便将数据进行结构化后检索
LangChain-21 Text Splitters 内容切分器 支持多种格式 HTML JSON md Code(JS/Py/TS/etc) 进行切分并输出 方便将数据进行结构化后检索
20 0
|
14天前
|
前端开发 机器人 API
前端大模型入门(一):用 js+langchain 构建基于 LLM 的应用
本文介绍了大语言模型(LLM)的HTTP API流式调用机制及其在前端的实现方法。通过流式调用,服务器可以逐步发送生成的文本内容,前端则实时处理并展示这些数据块,从而提升用户体验和实时性。文章详细讲解了如何使用`fetch`发起流式请求、处理响应流数据、逐步更新界面、处理中断和错误,以及优化用户交互。流式调用特别适用于聊天机器人、搜索建议等应用场景,能够显著减少用户的等待时间,增强交互性。
108 2
|
8天前
|
机器学习/深度学习 人工智能 运维
企业内训|LLM大模型在服务器和IT网络运维中的应用-某日企IT运维部门
本课程是为某在华日资企业集团的IT运维部门专门定制开发的企业培训课程,本课程旨在深入探讨大型语言模型(LLM)在服务器及IT网络运维中的应用,结合当前技术趋势与行业需求,帮助学员掌握LLM如何为运维工作赋能。通过系统的理论讲解与实践操作,学员将了解LLM的基本知识、模型架构及其在实际运维场景中的应用,如日志分析、故障诊断、网络安全与性能优化等。
28 2
|
11天前
|
机器学习/深度学习 数据采集 人工智能
文档智能 & RAG 让AI大模型更懂业务 —— 阿里云LLM知识库解决方案评测
随着数字化转型的深入,企业对文档管理和知识提取的需求日益增长。阿里云推出的文档智能 & RAG(Retrieval-Augmented Generation)解决方案,通过高效的内容清洗、向量化处理、精准的问答召回和灵活的Prompt设计,帮助企业构建强大的LLM知识库,显著提升企业级文档管理的效率和准确性。
|
13天前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。
|
12天前
|
人工智能 前端开发
大模型体验体验报告:OpenAI-O1内置思维链和多个llm组合出的COT有啥区别?传统道家理论+中学生物理奥赛题测试,名不虚传还是名副其实?
一个月前,o1发布时,虽然让人提前体验,但自己并未进行测试。近期终于有机会使用,却仍忘记第一时间测试。本文通过两个测试案例展示了o1的强大能力:一是关于丹田及练气的详细解答,二是解决一道复杂的中学生物理奥赛题。o1的知识面广泛、推理迅速,令人印象深刻。未来,或许可以通过赋予o1更多能力,使其在更多领域发挥作用。如果你有好的测试题,欢迎留言,一起探索o1的潜力。