JSON 是全球使用最广泛的数据交换格式之一,支持我们的所有需求。 在构建人工智能驱动的应用程序时,工程师不可避免地需要将大型语言模型(LLM)的输出集成到他们的代码库中。
通过指示 LLM 使用特定的语法或模式,然后输出应用程序所需的生成结果,我们可以使应用程序的行为更加可预测。 简而言之,JSON 的互操作性使其成为数据交换的首选。
NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包
1、为什么让LLM 输出JSON数据如此困难?
语言模型擅长预测下一个标记并生成文本,但它们在产生文本之外的精确输出方面可能具有挑战性,因为它们并不总是精确地遵循指令
例如:对于 OpenAI,我希望 GPT-3.5-turbo 始终以以下形式响应
(message_type) {message_content}
然而,它可能会以略微不同的方式响应:
message_type:message_content
message_type:"message_content"
。(message_type): "message_content"
2、使用提示工程
Please provide the response in the form of a Python list. It should begin with “[“ and end with “]”.
Chatgpt (gpt4) 支持提示系统/用户 (gpt4 api) 将数据格式化为 csv。 通常工作完美。 虽然 gpt4 非常适合制作演示原型,但它相当昂贵,因此本地解决方案将是完美的。
有许多提示工程框架可以限制 json 格式的输出,请参阅此处的一个用于 LLM 输出的严格 JSON 框架。
## simple example provided by the author
res = strict_output(system_prompt = 'You are a classifier',
user_prompt = 'It is a beautiful day',
output_format = {"Sentiment": "Type of Sentiment",
"Tense": "Type of Tense"})
print(res)
## output
{'Sentiment': 'Positive', 'Tense': 'Present'}
虽然提示工程对于某些用例可能是有效的,但它有一个局限性—LLM所做的任何内部更改都可能导致意外的输出。 众所周知,这会在生产环境中引起问题,正如在线故事中所见,依赖 ChatGPT API 的 AI 应用程序由于不断的后台更新而失败。
3、约束LLM输出
这一领域已经有大量的创新工作,我有机会探索三个框架,它们都从不同的角度解决了这个问题。 尽管使用不同的方法,但每个框架如何达到相似的结果给我留下了深刻的印象。
- GRAMMAR — 约束模型输出的语法。 例如,你可以强制模型仅输出 JSON:
- KOR — 这是一个半成品原型,可以“帮助”你使用LLM从文本中提取结构化数据
- LM-Format-Enforcer — 强制语言模型的输出格式(JSON Schema、Regex 等)
- Finetune LLM 模型 — 教导模型根据输入数据输出 JSON
3.1 使用语法规则强制模型仅输出 JSON
在这种方法中,你需要使用 Llama.cpp 来运行模型并创建语法文件。 GBNF (GGML BNF) 是一种用于定义形式语法以约束 llama.cpp 中模型输出的格式。
这是我为基本测试创建的一个简单语法文件:
root ::= answer
answer ::= "{" ws "\"id\":" ws number "," ws "\"name\":" ws string "}"
answerlist ::= "[]" | "[" ws answer ("," ws answer)* "]"
string ::= "\"" ([^"]*) "\""
boolean ::= "true" | "false"
ws ::= [ \t\n]*
number ::= [0-9]+ "."? [0-9]*
stringlist ::= "[" ws "]" | "[" ws string ("," ws string)* ws "]"
numberlist ::= "[" ws "]" | "[" ws string ("," ws number)* ws "]"
它更难理解,但是,可以从更容易理解的模式定义开始。 如下所示:
interface answer {
id: number;
name: string;
}
接下来将模式粘贴到这个在线工具以自动生成语法文件 - 省去很多麻烦。
现在,我们有了一个语法文件并准备好插入 Llama.cpp。 有关在你的计算机上本地运行的设置的更多详细信息,请参阅存储库。
## start with a prompt
./main -m ./models/Mistral-7B-Instruct-v0.1-Q8.gguf -n 256 — grammar-file grammars/answer.gbnf -p ‘Q: Name the planets in the solar system? A:’
...................................................................................................
llama_new_context_with_model: n_ctx = 512
llama_new_