ChatGPT 人工智能 GPT4 伦理 生成式 医疗 监管 安全 机器学习 深度学习 神经网络 计算机视觉 强化学习 模型 算法 应用 开发 研究 工具 平台 框架 数据集 训练 部署 安全 合规 培训 投资 LLM,llm AI,ai,Ai 大模型 大语言模型 制图 生图 绘图 文生图 文生视频 生成式AI AGI 世界模型 sora chatGPT,chatgpt,ChatGpt claude openai Llama deepseek midjourney 红熊猫模型 Red panda,panda Stable Diffusion,StableDiffusion,stable DALL- E 3 DALL E DALL Flux,flux 扩散模型 混元大模型 文心一言 通义千问 可灵 Pika PixelDance 豆包 月之暗面 零一万物 阶跃星辰 搜索增强 MiniMax Talkie Agent prompt fastai LangChain TTS 微调 提示词 知识库 智能体
# 热门搜索 #
搜索
探索LLM推理全阶段的JSON格式输出限制方法
8867点击    2024-10-31 10:14

文章详细讨论了如何确保大型语言模型(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的概率输出别的名字。


图1. LLM推理的预测概率示意


因此,这个依概率采样的推理过程决定了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/


图2. OpenAI输出JSON格式的方法,橙、黄、绿分别代表提示词优化、微调、动态限制解码法的JSON输出准确率


(动态限制解码法准确率为100%)


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


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通过推理产生。当用户提出问题“请填写杭州的城市信息”后,动态限制解码流程如下:


图3. 动态限制解码法示意图。其中只有绿色词是LLM的推理产生。


上图展示了动态限制解码的工作流程,每一轮推理过程我们给定了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"""\}"""

)


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


图4. 动态限制解码法的”推理-限制-采样-拼接”流程


如第一个键"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


图5. sglang框架下的千问模型本地部署成功示意图


显示上图即部署成功。


###导入库

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)


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



图6. 基于动态限制解码的JSON格式输出结果。


【优势】


  • 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下输出以减少出错概率。


三、总结与展望


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


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



【彩蛋】


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" } )


文章来自于“AI小智”,作者“唐殊”。


关键词: AI , LLMs , 模型训练 , 人工智能
AITNT资源拓展
根据文章内容,系统为您匹配了更有价值的资源信息。内容由AI生成,仅供参考
1
AI工作流

【开源免费】n8n是一个可以自定义工作流的AI项目,它提供了200个工作节点来帮助用户实现工作流的编排。

项目地址:https://github.com/n8n-io/n8n

在线使用:https://n8n.io/(付费)


【开源免费】DB-GPT是一个AI原生数据应用开发框架,它提供开发多模型管理(SMMF)、Text2SQL效果优化、RAG框架以及优化、Multi-Agents框架协作、AWEL(智能体工作流编排)等多种技术能力,让围绕数据库构建大模型应用更简单、更方便。

项目地址:https://github.com/eosphoros-ai/DB-GPT?tab=readme-ov-file



【开源免费】VectorVein是一个不需要任何编程基础,任何人都能用的AI工作流编辑工具。你可以将复杂的工作分解成多个步骤,并通过VectorVein固定并让AI依次完成。VectorVein是字节coze的平替产品。

项目地址:https://github.com/AndersonBY/vector-vein?tab=readme-ov-file

在线使用:https://vectorvein.ai/(付费)

2
智能体

【开源免费】AutoGPT是一个允许用户创建和运行智能体的(AI Agents)项目。用户创建的智能体能够自动执行各种任务,从而让AI有步骤的去解决实际问题。

项目地址:https://github.com/Significant-Gravitas/AutoGPT


【开源免费】MetaGPT是一个“软件开发公司”的智能体项目,只需要输入一句话的老板需求,MetaGPT即可输出用户故事 / 竞品分析 / 需求 / 数据结构 / APIs / 文件等软件开发的相关内容。MetaGPT内置了各种AI角色,包括产品经理 / 架构师 / 项目经理 / 工程师,MetaGPT提供了一个精心调配的软件公司研发全过程的SOP。

项目地址:https://github.com/geekan/MetaGPT/blob/main/docs/README_CN.md

3
微调

【开源免费】XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。它帮助开发者提供一个简单易用的平台,可以对大语言模型(LLM)和多模态图文模型(VLM)进行预训练和轻量级微调。XTuner 支持多种微调算法,如 QLoRA、LoRA 和全量参数微调。

项目地址:https://github.com/InternLM/xtuner

4
prompt

【开源免费】LangGPT 是一个通过结构化和模板化的方法,编写高质量的AI提示词的开源项目。它可以让任何非专业的用户轻松创建高水平的提示词,进而高质量的帮助用户通过AI解决问题。

项目地址:https://github.com/langgptai/LangGPT/blob/main/README_zh.md

在线使用:https://kimi.moonshot.cn/kimiplus/conpg00t7lagbbsfqkq0