释放LLM潜力:软件应用的结构化输出之道

Towardsdatascience

虽然ChatGPT和Gemini等大型语言模型(LLM)通过直观的聊天界面彻底改变了人类与AI的互动方式,但它们的用途远不止于日常对话。对于软件应用程序而言,这些强大的模型拥有庞大且不断增长的用户群,而典型的聊天界面产生的自由形式、非结构化文本输出则带来了重大挑战。与人类不同,软件程序需要数据遵循特定格式或模式才能有效处理。这种根本性差异使得我们必须采用技术来强制LLM生成结构化输出,从而释放它们在自动化任务中的潜力。

结构化输出生成涉及引导LLM生成符合预定义格式的数据,最常见的是JSON或正则表达式(RegEx)。例如,JSON模式可以指定预期的键及其关联的数据类型(如字符串、整数),确保LLM提供完美格式化的对象。这种能力对于从大量文本甚至图像(使用多模态LLM)中提取精确信息至关重要,例如从数字收据中提取购买日期、总价和商店名称。为满足这一需求,工程师们开发了几种流行的方法。

一种直接的方法是依赖提供内置结构化输出功能的LLM API提供商。OpenAI和Google Gemini等公司的服务允许开发者定义输出模式,通常使用Pydantic等Python类,并将其直接传递给API端点。这种方法的主要吸引力在于其简单性;提供商处理底层复杂性,让开发者专注于定义数据结构。然而,这种便利性也伴随着显著的缺点。它引入了厂商锁定,将项目限制在特定提供商,并可能排除对更广泛模型生态系统(包括许多强大的开源替代方案)的访问。此外,它使应用程序面临潜在的价格波动,并模糊了其背后的技术机制,从而阻碍了调试和深入理解。

第二种常用策略是采用提示词工程和重复提示技术。这涉及明确指示LLM(通常在系统提示中)遵循特定结构,并常辅以示例来加强。在LLM生成响应后,解析器会尝试根据所需模式验证输出。如果解析成功,则过程完成。然而,仅仅依靠提示词固有的不可靠性意味着LLM可能会偏离指令,添加无关文本、省略字段或使用不正确的数据类型。当解析失败时,系统必须启动错误恢复过程,通常通过向LLM“重复提示”并提供反馈来纠正其输出。虽然解析器可以提供特定错误的详细信息,但重复提示的需求引入了显著的成本因素。LLM的使用通常按令牌计费,这意味着每次重试都会使该次交互的成本翻倍。采用此方法的开发者必须实施保障措施,例如对重试次数设置硬编码限制,以防止意外高额账单。尽管存在这些挑战,但像instructor这样的库已经出现,简化了这种方法,自动化了模式定义、与各种LLM提供商的集成以及自动重试。

最健壮且通常首选的方法是受限解码。与提示词工程不同,该技术保证了有效且符合模式的输出,无需昂贵的重试。它利用计算语言学和对LLM如何逐令牌生成文本的理解。LLM是自回归的,这意味着它们根据所有前面的令牌来预测下一个令牌。LLM的最后一层计算其词汇表中每个可能令牌的概率。受限解码在此阶段进行干预,通过限制每个生成步骤中可用的令牌。

这首先通过使用正则表达式(RegEx)定义所需的输出结构来实现。然后,此RegEx模式被编译成确定性有限自动机(DFA),本质上是一个状态机,可以验证文本序列是否符合该模式。DFA提供了一种精确的机制,可以在任何给定点确定哪些令牌在遵循当前序列的同时符合模式。当LLM计算令牌概率时,DFA不允许的所有令牌的logits(softmax前的值)都会被有效地归零。这迫使模型只能从有效集中进行选择,从而保证生成的输出严格遵循所需的结构。至关重要的是,一旦DFA建立,此过程不会产生额外的计算成本。像Outlines这样的库简化了受限解码的实现,允许开发者使用Pydantic类或直接RegEx定义模式,并与众多LLM提供商无缝集成。

总之,从LLM生成结构化输出是一项关键能力,它将LLM的应用范围远远扩展到以人类为中心的聊天之外。虽然依赖API提供商提供了最初的简单性,并且带有错误恢复的提示词工程提供了灵活性,但受限解码作为最强大且最具成本效益的方法脱颖而出。通过从根本上引导LLM的令牌生成过程,它确保了可靠、符合模式的输出,使其成为将LLM集成到复杂软件系统中的首选方法。