10.1k高星 GitHub 库:告别JSON错误:Outlines如何提升大模型的结构化输出
在人工智能和大语言模型(LLM)的应用中,如何高效、可靠地从模型输出中提取结构化数据,成为了一个至关重要的课题。本篇文章将介绍 GitHub 高星开源库 Outlines,并分析它如何帮助开发者解决大模型在生成结构化数据时面临的挑战。我们将探讨大模型的非结构化输出给 AI 应用带来的问题、结构化输出的好处,以及 Outlines 如何有效地提升模型的可靠性和性能。
在这里插入图片描述
1. 大模型的非结构化输出带来的问题
1.1 问题
大语言模型(LLM)具有强大的文本生成能力,但在生成结构化数据时表现不够可靠。这对以 Agent 为核心的 AI 应用造成了严重的困扰。
核心问题
- 输出不一致性:当从邮件中提取航班信息时,理想情况是输出一致的 JSON 对象,但 LLM 往往失败,导致诸如 "JSON decode errors" 的问题。
- 缺乏可靠性:这种不可预测性使得基于 LLM 构建复杂模块化系统变得困难。
影响
没有可靠的结构化输出,开发者需要通过繁琐的后处理(如正则表达式)提取信息,导致开发效率低下且易出错。
1.2 结构化输出的好处
数据的普遍结构性
即使是看似无结构的数据(如 GSM 数据集),也常常有内在的结构可利用。
保证输出格式
通过定义特定的结构(如 JSON 或正则表达式),可以保证输出的有效性,避免繁琐的后处理。
提升性能与效率
- 提升 JSON 有效率:使用结构化生成后,JSON 有效率从 17.7% 提升至 99.9%。
- 减少示例需求:在 GSM8K 基准测试中,一次性结构化生成的性能几乎与八次非结构化生成相当。
- 提升开放模型性能:在函数调用基准测试中,性能从 86% 提升至 96.5%,甚至超越 GPT-4。
1.3 结构化输出与非结构化输出的对比
为了更好地理解结构化输出的优势,我们可以通过以下例子来对比结构化与非结构化输出的差异。
假设我们需要从一封电子邮件中提取航班信息:
非结构化输出
当大模型生成的输出没有严格的格式时,可能会得到如下文本:
飞往巴黎的航班在下周二,可能是早上10点,飞机是法国航空。
这个输出虽然包含了我们需要的信息(目的地、日期、时间、航空公司等),但它并没有明确的结构。要从中提取这些信息,开发者需要使用正则表达式或其他文本处理方法来解析每个字段,这既繁琐又容易出错。例如,模型有可能在不同的输入中给出不同格式的输出,导致系统处理时出错或出现“JSON decode errors”。
结构化输出
如果使用结构化生成,模型将返回符合预定义格式的数据,例如:
{
"destination": "巴黎",
"departure_date": "2024-11-25",
"time": "10:00",
"airline": "法国航空"
}
在这种情况下,输出是统一的、标准化的。开发者不再需要额外处理或解析信息,因为所有关键字段都已经按预期格式返回。这不仅节省了开发时间,还大大减少了出错的概率。
通过这个对比,我们可以清楚地看到,结构化输出不仅可以保证数据的一致性和可靠性,而且能显著提高处理效率,特别是在需要从大模型中提取和处理大量信息时。
2. 解决方案:使用 Outlines 库输出结构化数据
2.1 Outlines 简介
Outlines 是一个开源的 Python 库,专为提升大模型生成结构化数据的能力而设计。
核心功能
- 结构化生成:引导模型返回 JSON、正则表达式或上下文无关文法等特定格式的数据。
- 高度集成:可与现有工作流无缝整合,而不是强加框架。
- 开放模型支持:支持 Transformers、Llama CPP 等多种开源模型。
广泛应用
Outlines 已被主流推理框架(如 VLLM、TGI)用于函数调用。
2.2 Outlines 支持丰富的结构化数据类型
超越基本结构
- 上下文无关文法:支持定义复杂结构,如代码、蛋白质结构甚至算术运算。
- 语义约束:如 SQL 生成时保证表/列名的合法性。
- 嵌入计算:将计算逻辑嵌入生成过程中,提升效率。
3. 使用 Outlines 会给大模型带来性能问题吗?
3.1 Outlines 是如何工作的?
基本原理
- Logit 处理:模型生成 logits 后,Outlines 会检查每个可能的下一个 token,屏蔽那些违反定义结构的 token。
- 效率优化:通过高效的屏蔽实现极低的额外开销。
示例
"如果生成的 token 会破坏结构,则立即屏蔽,确保生成过程严格遵循预定义结构。"
3.2 结构化输出会减慢输出速度吗?
不会。相反,结构化生成通常加速生成过程:
- 减少无用 token:通过提前定义结构,避免生成多余的字段名或括号。
- 减少生成长度:结构化输出的 token 数通常更少,速度更快,且更清晰。
3.3 Outlines 与其他结构化生成库的对比
- 与 Guidance 比较:Outlines 在推理阶段的开销几乎为零,而 Guidance 在生成大量 token 时可能显著减慢。
- 与 LMQL 比较:Outlines 的核心优势在于其轻量化设计和效率。
4. 代码示例
以下是使用 Outlines 生成结构化事件数据的示例:
from datetime import datetime
from pydantic import BaseModel, Field
from outlines import generate, models
# 加载模型
model = models.mlxlm("mlx-community/Hermes-3-Llama-3.1-8B-8bit")
# 使用 Pydantic 定义事件结构
class Event(BaseModel):
title: str = Field(descriptinotallow="title of the event")
location: str
start: datetime = Field(
default=None, descriptinotallow="date of the event if available in iso format"
)
# 获取当前时间
now = datetime.now().strftime("%A %d %B %Y and it's %H:%M")
# 定义提示
prompt = f"""
Today's date and time are {now}
Given a user message, extract information of the event like date and time in iso format, location and title.
If the given date is relative, think step by step to find the right date.
Here is the message:
"""
# 示例消息
message = """Hello Kitty, my grandmother will be here , I think it's better to postpone our
appointment to review math lessons to next Friday at 2pm at the same place, 3 avenue des tanneurs, I think that one hour will be enough
see you 😘 """
# 创建生成器
generator = generate.json(model, Event)
# 提取事件信息
event = generator(prompt + message)
# 输出结果
print(f"Today: {now}")
print(event.json())
生成的事件信息如下:
{
"title": "Math Review",
"location": "3 avenue des tanneurs",
"start": "2024-11-22T14:00:00Z"
}
5. 结论与展望
结构化生成不再只是一个利基功能,而是大模型应用的未来:
- 更高的可靠性与效率:通过结构化生成,LLM 的性能得到了显著提升。
- 开源的潜力:Outlines 的成功证明了开源模型在与专有模型竞争中的潜力。
未来,随着结构化生成的普及,Outlines 有望成为开发者工具箱中的关键组件。