outlines review

Outlines 框架评测:保证 LLM 输出结构化

Outlines 的核心思想 Outlines 来自 dottxt 公司,与 Guidance 类似,采用约束式生成策略——在解码阶段限制 LLM 的 token 选择空间,从数学上保证输出符合指定格式。区别在于 Outlines 更聚焦于"结构"而非"模板",且在 CFG(上下文无关文法)支持上更加深入。 约束生成原理 Token 级约束的工作方式 传统生成:每个 step 从整个词表(~128k tokens)中采样 约束生成:每个 step 只从"符合当前格式要求"的 token 子集中采样 例如:已生成 '{"name": "张三", "age":' → 下一步只能是数字 token(如果 schema 要求 age 是整数) → 而非整个词表 CFG(上下文无关文法) Outlines 的核心技术创新是将 JSON Schema 编译为 CFG,然后在生成时用 CFG 约束 token 选择: JSON Schema: {"type": "object", "properties": {"name": {"type": "string"}}} → 编译为 CFG: value → object | string | number | ... object → "{" ws string ws ":" ws value ws "}" string → "\"" chars "\"" chars → char chars | ε ... → 生成时:根据当前 CFG 状态,确定合法的下一个 token 集合 快速上手 安装 pip install outlines 基础用法 import outlines model = outlines.models.transformers("meta-llama/Llama-3-8B-Instruct") # 直接定义输出类型 @outlines.generate.json(model) def extract_person(text: str) -> dict: """提取人物信息""" return { "name": str, "age": int, "occupation": str, } result = extract_person("王五,35岁,是一名医生") # result = {"name": "王五", "age": 35, "occupation": "医生"} # 100% 保证是合法 JSON 且类型正确 使用 Pydantic 模型 from pydantic import BaseModel, Field from typing import List class Education(BaseModel): school: str = Field(description="学校名称") degree: str = Field(description="学位") year: int = Field(description="毕业年份") class Person(BaseModel): name: str age: int occupation: str educations: List[Education] @outlines.generate.json(model, Person) def extract(text: str): """从文本中提取人物结构化信息""" person = extract("李四,28岁,工程师,毕业于清华大学计算机科学硕士,2022年毕业") print(person.name) # "李四" print(person.educations[0].school) # "清华大学" 正则约束 @outlines.generate.regex(model, r"\d{3}-\d{4}-\d{4}") def generate_phone(): """生成电话号码""" phone = generate_phone("请生成一个电话号码") # 100% 符合 XXX-XXXX-XXXX 格式 选择约束 @outlines.generate.choice(model, ["正面", "负面", "中性"]) def classify_sentiment(text: str): """情感分类""" result = classify_sentiment("这个产品太棒了!") # 只能是 "正面"、"负面" 或 "中性" 类型约束 # 整数约束 @outlines.generate.format(model, int) def generate_score(text: str): """生成评分""" # 布尔约束 @outlines.generate.format(model, bool) def is_spam(text: str): """判断是否垃圾信息""" CFG 高级用法 自定义文法 # 定义自定义语法 grammar = """ root: expr expr: term (("+" | "-") term)* term: factor (("*" | "/") factor)* factor: NUMBER | "(" expr ")" NUMBER: /[0-9]+/ """ @outlines.generate.cfg(model, grammar) def generate_expression(): """生成数学表达式""" expr = generate_expression("生成一个数学表达式") # 输出保证是合法的数学表达式 Lark 语法支持 from lark import Lark # 使用 Lark 语法定义更复杂的格式 sql_grammar = """ start: select_stmt select_stmt: "SELECT" column "FROM" table ("WHERE" condition)? column: NAME table: NAME condition: NAME OP VALUE OP: "=" | ">" | "<" | "!=" NAME: /[a-zA-Z_]+/ VALUE: /"[^"]*"/ | NUMBER NUMBER: /[0-9]+/ """ @outlines.generate.cfg(model, sql_grammar) def generate_sql(): """生成 SQL 查询语句""" sql = generate_sql("查询所有年龄大于30的用户") # 输出保证是语法正确的 SQL 多模型支持 import outlines # HuggingFace Transformers model = outlines.models.transformers("meta-llama/Llama-3-8B-Instruct") # llama.cpp (GGUF) model = outlines.models.llamacpp("models/Llama-3-8B-Instruct-Q4_K_M.gguf", n_gpu_layers=35) # vLLM (高吞吐) model = outlines.models.vllm("meta-llama/Llama-3-8B-Instruct") # mamba (SSM 架构) model = outlines.models.mamba("state-spaces/mamba-130m-hf") Outlines vs Function Calling vs Instructor vs Guidance 维度 Outlines Function Calling Instructor Guidance 格式保证 100%(CFG 约束) ~95%(API 约束) ~99%(重试) 100%(Token 约束) 模型要求 本地模型 API 模型 任意 本地模型优先 延迟开销 低(无重试) 中 中(可能重试) 低 Schema 支持 JSON Schema/Pydantic/正则/CFG JSON Schema Pydantic JSON Schema/正则/select 灵活性 高 中 高 很高 生产成熟度 高 高 高 中 可靠性对比 在 500 条信息抽取任务上的测试: ...

2026-06-24 · 4 min · 700 words · 硅基 AGI 探索者
鲁ICP备2026018361号