10.1k高星 GitHub 庫(kù):告別JSON錯(cuò)誤:Outlines如何提升大模型的結(jié)構(gòu)化輸出
在人工智能和大語(yǔ)言模型(LLM)的應(yīng)用中,如何高效、可靠地從模型輸出中提取結(jié)構(gòu)化數(shù)據(jù),成為了一個(gè)至關(guān)重要的課題。本篇文章將介紹 GitHub 高星開源庫(kù) Outlines,并分析它如何幫助開發(fā)者解決大模型在生成結(jié)構(gòu)化數(shù)據(jù)時(shí)面臨的挑戰(zhàn)。我們將探討大模型的非結(jié)構(gòu)化輸出給 AI 應(yīng)用帶來(lái)的問(wèn)題、結(jié)構(gòu)化輸出的好處,以及 Outlines 如何有效地提升模型的可靠性和性能。
在這里插入圖片描述
1. 大模型的非結(jié)構(gòu)化輸出帶來(lái)的問(wèn)題
1.1 問(wèn)題
大語(yǔ)言模型(LLM)具有強(qiáng)大的文本生成能力,但在生成結(jié)構(gòu)化數(shù)據(jù)時(shí)表現(xiàn)不夠可靠。這對(duì)以 Agent 為核心的 AI 應(yīng)用造成了嚴(yán)重的困擾。
核心問(wèn)題
- 輸出不一致性:當(dāng)從郵件中提取航班信息時(shí),理想情況是輸出一致的 JSON 對(duì)象,但 LLM 往往失敗,導(dǎo)致諸如 "JSON decode errors" 的問(wèn)題。
- 缺乏可靠性:這種不可預(yù)測(cè)性使得基于 LLM 構(gòu)建復(fù)雜模塊化系統(tǒng)變得困難。
影響
沒(méi)有可靠的結(jié)構(gòu)化輸出,開發(fā)者需要通過(guò)繁瑣的后處理(如正則表達(dá)式)提取信息,導(dǎo)致開發(fā)效率低下且易出錯(cuò)。
1.2 結(jié)構(gòu)化輸出的好處
數(shù)據(jù)的普遍結(jié)構(gòu)性
即使是看似無(wú)結(jié)構(gòu)的數(shù)據(jù)(如 GSM 數(shù)據(jù)集),也常常有內(nèi)在的結(jié)構(gòu)可利用。
保證輸出格式
通過(guò)定義特定的結(jié)構(gòu)(如 JSON 或正則表達(dá)式),可以保證輸出的有效性,避免繁瑣的后處理。
提升性能與效率
- 提升 JSON 有效率:使用結(jié)構(gòu)化生成后,JSON 有效率從 17.7% 提升至 99.9%。
- 減少示例需求:在 GSM8K 基準(zhǔn)測(cè)試中,一次性結(jié)構(gòu)化生成的性能幾乎與八次非結(jié)構(gòu)化生成相當(dāng)。
- 提升開放模型性能:在函數(shù)調(diào)用基準(zhǔn)測(cè)試中,性能從 86% 提升至 96.5%,甚至超越 GPT-4。
1.3 結(jié)構(gòu)化輸出與非結(jié)構(gòu)化輸出的對(duì)比
為了更好地理解結(jié)構(gòu)化輸出的優(yōu)勢(shì),我們可以通過(guò)以下例子來(lái)對(duì)比結(jié)構(gòu)化與非結(jié)構(gòu)化輸出的差異。
假設(shè)我們需要從一封電子郵件中提取航班信息:
非結(jié)構(gòu)化輸出
當(dāng)大模型生成的輸出沒(méi)有嚴(yán)格的格式時(shí),可能會(huì)得到如下文本:
飛往巴黎的航班在下周二,可能是早上10點(diǎn),飛機(jī)是法國(guó)航空。
這個(gè)輸出雖然包含了我們需要的信息(目的地、日期、時(shí)間、航空公司等),但它并沒(méi)有明確的結(jié)構(gòu)。要從中提取這些信息,開發(fā)者需要使用正則表達(dá)式或其他文本處理方法來(lái)解析每個(gè)字段,這既繁瑣又容易出錯(cuò)。例如,模型有可能在不同的輸入中給出不同格式的輸出,導(dǎo)致系統(tǒng)處理時(shí)出錯(cuò)或出現(xiàn)“JSON decode errors”。
結(jié)構(gòu)化輸出
如果使用結(jié)構(gòu)化生成,模型將返回符合預(yù)定義格式的數(shù)據(jù),例如:
{
"destination": "巴黎",
"departure_date": "2024-11-25",
"time": "10:00",
"airline": "法國(guó)航空"
}
在這種情況下,輸出是統(tǒng)一的、標(biāo)準(zhǔn)化的。開發(fā)者不再需要額外處理或解析信息,因?yàn)樗嘘P(guān)鍵字段都已經(jīng)按預(yù)期格式返回。這不僅節(jié)省了開發(fā)時(shí)間,還大大減少了出錯(cuò)的概率。
通過(guò)這個(gè)對(duì)比,我們可以清楚地看到,結(jié)構(gòu)化輸出不僅可以保證數(shù)據(jù)的一致性和可靠性,而且能顯著提高處理效率,特別是在需要從大模型中提取和處理大量信息時(shí)。
2. 解決方案:使用 Outlines 庫(kù)輸出結(jié)構(gòu)化數(shù)據(jù)
2.1 Outlines 簡(jiǎn)介
Outlines 是一個(gè)開源的 Python 庫(kù),專為提升大模型生成結(jié)構(gòu)化數(shù)據(jù)的能力而設(shè)計(jì)。
核心功能
- 結(jié)構(gòu)化生成:引導(dǎo)模型返回 JSON、正則表達(dá)式或上下文無(wú)關(guān)文法等特定格式的數(shù)據(jù)。
- 高度集成:可與現(xiàn)有工作流無(wú)縫整合,而不是強(qiáng)加框架。
- 開放模型支持:支持 Transformers、Llama CPP 等多種開源模型。
廣泛應(yīng)用
Outlines 已被主流推理框架(如 VLLM、TGI)用于函數(shù)調(diào)用。
2.2 Outlines 支持豐富的結(jié)構(gòu)化數(shù)據(jù)類型
超越基本結(jié)構(gòu)
- 上下文無(wú)關(guān)文法:支持定義復(fù)雜結(jié)構(gòu),如代碼、蛋白質(zhì)結(jié)構(gòu)甚至算術(shù)運(yùn)算。
- 語(yǔ)義約束:如 SQL 生成時(shí)保證表/列名的合法性。
- 嵌入計(jì)算:將計(jì)算邏輯嵌入生成過(guò)程中,提升效率。
3. 使用 Outlines 會(huì)給大模型帶來(lái)性能問(wèn)題嗎?
3.1 Outlines 是如何工作的?
基本原理
- Logit 處理:模型生成 logits 后,Outlines 會(huì)檢查每個(gè)可能的下一個(gè) token,屏蔽那些違反定義結(jié)構(gòu)的 token。
- 效率優(yōu)化:通過(guò)高效的屏蔽實(shí)現(xiàn)極低的額外開銷。
示例
"如果生成的 token 會(huì)破壞結(jié)構(gòu),則立即屏蔽,確保生成過(guò)程嚴(yán)格遵循預(yù)定義結(jié)構(gòu)。"
3.2 結(jié)構(gòu)化輸出會(huì)減慢輸出速度嗎?
不會(huì)。相反,結(jié)構(gòu)化生成通常加速生成過(guò)程:
- 減少無(wú)用 token:通過(guò)提前定義結(jié)構(gòu),避免生成多余的字段名或括號(hào)。
- 減少生成長(zhǎng)度:結(jié)構(gòu)化輸出的 token 數(shù)通常更少,速度更快,且更清晰。
3.3 Outlines 與其他結(jié)構(gòu)化生成庫(kù)的對(duì)比
- 與 Guidance 比較:Outlines 在推理階段的開銷幾乎為零,而 Guidance 在生成大量 token 時(shí)可能顯著減慢。
- 與 LMQL 比較:Outlines 的核心優(yōu)勢(shì)在于其輕量化設(shè)計(jì)和效率。
4. 代碼示例
以下是使用 Outlines 生成結(jié)構(gòu)化事件數(shù)據(jù)的示例:
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 定義事件結(jié)構(gòu)
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"
)
# 獲取當(dāng)前時(shí)間
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 ?? """
# 創(chuàng)建生成器
generator = generate.json(model, Event)
# 提取事件信息
event = generator(prompt + message)
# 輸出結(jié)果
print(f"Today: {now}")
print(event.json())
生成的事件信息如下:
{
"title": "Math Review",
"location": "3 avenue des tanneurs",
"start": "2024-11-22T14:00:00Z"
}
5. 結(jié)論與展望
結(jié)構(gòu)化生成不再只是一個(gè)利基功能,而是大模型應(yīng)用的未來(lái):
- 更高的可靠性與效率:通過(guò)結(jié)構(gòu)化生成,LLM 的性能得到了顯著提升。
- 開源的潛力:Outlines 的成功證明了開源模型在與專有模型競(jìng)爭(zhēng)中的潛力。
未來(lái),隨著結(jié)構(gòu)化生成的普及,Outlines 有望成為開發(fā)者工具箱中的關(guān)鍵組件。
本文轉(zhuǎn)載自??非架構(gòu)??,作者: 非架構(gòu) ????
