真正做过 LLM 开发的都知道,虽然理论上 LLM 可以生成结构化的数据,但是真正生成的时候经常出错。怎么稳定的让 LLM 返回结构化的数据?
LinkedIn 的做法如下:
https://www.linkedin.com/blog/engineering/generative-ai/musings-on-building-a-generative-ai-product
YAML 和 JSON 是两种常用的数据序列化格式,它们各有优势和用途。大多数 LLM 在训练中都使用了 YAML 和 JSON 来进行结构化输出。
LinkedIn 选择了 YAML,因为它比 JSON 更简洁,因此消耗的 Token 更少。
使用 YAML 而不是 JSON
选择 YAML 作为数据交换格式相对于 JSON 的一个主要优势在于它的人类可读性和灵活性,这些特性使得 YAML 在某些方面具有更高的容错率。
以下是几个关键点来解释为什么在某些情况下 YAML 可能比 JSON 更容错:
1、注释支持
YAML 支持在文件中直接添加注释,这有助于开发人员解释或标记代码,增加了代码的可读性和维护性。
这种可注释的特性使得开发者可以在配置文件中留下有用的说明,有助于避免错误的配置和理解配置的意图。
YAML
YAML 除了注释行,还允许在同一行中加注释和在冒号后直接跟值,使得配置更加简洁;
JSON
对比说明: YAML 允许在文件中直接添加注释,方便开发者记录重要信息或者暂时禁用某个配置项。而JSON格式不支持注释,试图添加注释会导致解析错误。
让LLM生成指定格式内容时,可以给出示例,YAML格式的示例中有注释,更不容易产生歧义。
2、不严格的语法
YAML 不要求所有数据结构元素(如列表和映射)强制使用逗号和括号分隔。
这种灵活性意味着在编写或编辑数据时,遗漏或错误添加分隔符不会立即导致解析错误,从而提高了容错能力。
YAML
JSON
对比说明: YAML 中列表项前只需要一个短横线和一个空格,没有严格的逗号分隔;而JSON中的数组元素必须使用逗号分隔,漏写或多写逗号都会导致错误。
3、数据类型检测
YAML 自动检测数据类型,如整数、浮点数、字符串等。这意味着不需要显式声明类型,简化了数据的书写和阅读过程。
例如,你不需要用引号包围字符串,除非它包含可能会被解析为其他类型的字符。
YAML
YAML 自动推断数据类型,整数和浮点数不需要引号。
在 YAML 中,字符串常常不需要转义字符(除非包含特定的符号),这简化了复杂字符串的表示,减少了因转义错误导致的问题。
unquoted_string
中的文本不需要引号,除非像 quoted_string
那样要强制为字符串类型。
JSON
JSON 中所有的字符串都必须用引号包围,无论内容。布尔值和数值不需要引号,但对于想要表示为字符串的数字,如 quoted_string
,也必须用引号。
4、复杂结构的表示
YAML 通过缩进来表示层级结构,而不是使用大括号和方括号。这种基于缩进的结构通常更易于阅读和编辑,减少了因括号匹配错误导致的问题。
YAML
JSON
对比说明: YAML 使用缩进来表达层级关系,更易读;JSON 使用花括号和逗号,层次复杂时容易出错,尤其是在括号匹配上。
上面这些例子可以看出:YAML在某些方面相对于JSON的高容错性和灵活性。
解决生成的 YAML 也不规范问题
尽管选用了YAML作为LLM结构化数据输出格式,也有成功率的挑战:
LinkedIn 统计:尽管大约 90% 的时间里 LLM 的响应包含了正确格式的参数,但仍有约 10% 的时间 LLM 会出错,常常输出不符合提供的架构,甚至不是有效的 YAML。
虽然这些错误对于人类来说很容易发现,但却会导致解析代码出错。10% 的错误率足够高,不能轻易忽视,针对这个问题,LinkedIn的解决方案是编写了一个内部防御性 YAML 解析器:
1、YAML 解析器
用日志记录常见的 YAML 错误,优化自己的 YAML 解析器,可以解析 LLM 返回的不规范的 YAML;
下面是一个python版本的yaml格式修正代码,可以根据自己实际的yaml错误做优化改进。
2、修复解析错误的Prompt
如果还是无法解析则将错误信息交给 LLM 修复,并且不断优化提示词,提升 LLM 修复的成功率;
下面是一个修复解析错误的Prompt示例:
你可以根据实际情况,不断迭代优化这个Prompt。
通过上面步骤的努力,LinkedIn 最终结构化数据的错误率从 10% 下降到 0.01%。
总结
在开发过程中,使用LLM生成结构化数据时,经常会出现格式错误。
为了提高生成数据的准确性和稳定性,LinkedIn选择了YAML作为数据序列化格式,主要因为其简洁性和较低的Token消耗。YAML的优点包括较高的人类可读性、灵活性和容错性。它支持在文件中添加注释,不严格要求数据结构元素使用逗号和括号分隔,自动检测数据类型,且通过缩进来表示层级结构,这些特点使其在某些情况下比JSON更容错。
尽管如此,LLM生成的YAML有时仍然存在约10%的错误率。为应对此问题,LinkedIn开发了一个内部防御性YAML解析器,通过记录常见错误、优化解析器和不断调整提示词,将错误率显著降低至0.01%。