name: outlines description: 在生成过程中保证JSON/XML/代码结构的有效性,使用Pydantic模型进行类型安全输出,支持本地模型(Transformers、vLLM),并通过Outlines - dottxt.ai的结构化生成库最大化推理速度。 version: 1.0.0 author: Orchestra Research license: MIT tags: [提示工程, Outlines, 结构化生成, JSON模式, Pydantic, 本地模型, 基于语法的生成, vLLM, Transformers, 类型安全] dependencies: [outlines, transformers, vllm, pydantic]
Outlines:结构化文本生成
何时使用此技能
当您需要时使用Outlines:
- 保证有效的JSON/XML/代码结构在生成过程中
- 使用Pydantic模型进行类型安全输出
- 支持本地模型(Transformers、llama.cpp、vLLM)
- 最大化推理速度,通过零开销结构化生成
- 自动针对JSON模式生成
- 在语法级别控制令牌采样
GitHub星标:8,000+ | 来自:dottxt.ai(原.txt)
安装
# 基础安装
pip install outlines
# 使用特定后端
pip install outlines transformers # Hugging Face模型
pip install outlines llama-cpp-python # llama.cpp
pip install outlines vllm # vLLM用于高吞吐量
快速开始
基础示例:分类
import outlines
from typing import Literal
# 加载模型
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
# 使用类型约束生成
prompt = "情感分析:'这个产品太棒了!': "
generator = outlines.generate.choice(model, ["positive", "negative", "neutral"])
sentiment = generator(prompt)
print(sentiment) # "positive"(保证是其中之一)
使用Pydantic模型
from pydantic import BaseModel
import outlines
class User(BaseModel):
name: str
age: int
email: str
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
# 生成结构化输出
prompt = "提取用户:John Doe,30岁,john@example.com"
generator = outlines.generate.json(model, User)
user = generator(prompt)
print(user.name) # "John Doe"
print(user.age) # 30
print(user.email) # "john@example.com"
核心概念
1. 约束令牌采样
Outlines使用有限状态机(FSM)在日志级别约束令牌生成。
工作原理:
- 将模式(JSON/Pydantic/正则表达式)转换为上下文无关文法(CFG)
- 将CFG转换为有限状态机(FSM)
- 在生成过程中每个步骤过滤无效令牌
- 当只有一个有效令牌时快速跳过
优势:
- 零开销:过滤在令牌级别进行
- 速度提升:跳过确定性路径
- 保证有效性:无效输出不可能
import outlines
# Pydantic模型 -> JSON模式 -> CFG -> FSM
class Person(BaseModel):
name: str
age: int
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
# 幕后:
# 1. Person -> JSON模式
# 2. JSON模式 -> CFG
# 3. CFG -> FSM
# 4. FSM在生成过程中过滤令牌
generator = outlines.generate.json(model, Person)
result = generator("生成人员:Alice,25")
2. 结构化生成器
Outlines提供针对不同输出类型的专门生成器。
选择生成器
# 多项选择
generator = outlines.generate.choice(
model,
["positive", "negative", "neutral"]
)
sentiment = generator("评论:这太棒了!")
# 结果:三个选择之一
JSON生成器
from pydantic import BaseModel
class Product(BaseModel):
name: str
price: float
in_stock: bool
# 生成符合模式的有效JSON
generator = outlines.generate.json(model, Product)
product = generator("提取:iPhone 15,$999,有货")
# 保证有效的Product实例
print(type(product)) # <class '__main__.Product'>
正则表达式生成器
# 生成匹配正则表达式的文本
generator = outlines.generate.regex(
model,
r"[0-9]{3}-[0-9]{3}-[0-9]{4}" # 电话号码模式
)
phone = generator("生成电话号码:")
# 结果:"555-123-4567"(保证匹配模式)
整数/浮点数生成器
# 生成特定数字类型
int_generator = outlines.generate.integer(model)
age = int_generator("人员年龄:") # 保证整数
float_generator = outlines.generate.float(model)
price = float_generator("产品价格:") # 保证浮点数
3. 模型后端
Outlines支持多个本地和基于API的后端。
Transformers(Hugging Face)
import outlines
# 从Hugging Face加载
model = outlines.models.transformers(
"microsoft/Phi-3-mini-4k-instruct",
device="cuda" # 或 "cpu"
)
# 与任何生成器一起使用
generator = outlines.generate.json(model, YourModel)
llama.cpp
# 加载GGUF模型
model = outlines.models.llamacpp(
"./models/llama-3.1-8b-instruct.Q4_K_M.gguf",
n_gpu_layers=35
)
generator = outlines.generate.json(model, YourModel)
vLLM(高吞吐量)
# 用于生产部署
model = outlines.models.vllm(
"meta-llama/Llama-3.1-8B-Instruct",
tensor_parallel_size=2 # 多GPU
)
generator = outlines.generate.json(model, YourModel)
OpenAI(有限支持)
# 基础OpenAI支持
model = outlines.models.openai(
"gpt-4o-mini",
api_key="your-api-key"
)
# 注意:API模型有些功能有限
generator = outlines.generate.json(model, YourModel)
4. Pydantic集成
Outlines具有一流的Pydantic支持,带有自动模式转换。
基础模型
from pydantic import BaseModel, Field
class Article(BaseModel):
title: str = Field(description="文章标题")
author: str = Field(description="作者姓名")
word_count: int = Field(description="字数", gt=0)
tags: list[str] = Field(description="标签列表")
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
generator = outlines.generate.json(model, Article)
article = generator("生成关于AI的文章")
print(article.title)
print(article.word_count) # 保证 > 0
嵌套模型
class Address(BaseModel):
street: str
city: str
country: str
class Person(BaseModel):
name: str
age: int
address: Address # 嵌套模型
generator = outlines.generate.json(model, Person)
person = generator("生成在纽约的人员")
print(person.address.city) # "New York"
枚举和字面量
from enum import Enum
from typing import Literal
class Status(str, Enum):
PENDING = "pending"
APPROVED = "approved"
REJECTED = "rejected"
class Application(BaseModel):
applicant: str
status: Status # 必须是枚举值之一
priority: Literal["low", "medium", "high"] # 必须是字面量之一
generator = outlines.generate.json(model, Application)
app = generator("生成申请")
print(app.status) # Status.PENDING(或APPROVED/REJECTED)
常见模式
模式1:数据提取
from pydantic import BaseModel
import outlines
class CompanyInfo(BaseModel):
name: str
founded_year: int
industry: str
employees: int
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
generator = outlines.generate.json(model, CompanyInfo)
text = """
Apple Inc. 成立于1976年,属于科技行业。
该公司在全球雇佣约164,000人。
"""
prompt = f"提取公司信息:
{text}
公司:"
company = generator(prompt)
print(f"名称:{company.name}")
print(f"成立年份:{company.founded_year}")
print(f"行业:{company.industry}")
print(f"员工数:{company.employees}")
模式2:分类
from typing import Literal
import outlines
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
# 二分类
generator = outlines.generate.choice(model, ["spam", "not_spam"])
result = generator("邮件:现在购买!50%折扣!")
# 多类分类
categories = ["technology", "business", "sports", "entertainment"]
category_gen = outlines.generate.choice(model, categories)
category = category_gen("文章:Apple宣布新iPhone...")
# 带置信度
class Classification(BaseModel):
label: Literal["positive", "negative", "neutral"]
confidence: float
classifier = outlines.generate.json(model, Classification)
result = classifier("评论:这个产品还行,没什么特别的")
模式3:结构化表单
class UserProfile(BaseModel):
full_name: str
age: int
email: str
phone: str
country: str
interests: list[str]
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
generator = outlines.generate.json(model, UserProfile)
prompt = """
从以下提取用户档案:
姓名:Alice Johnson
年龄:28
邮箱:alice@example.com
电话:555-0123
国家:USA
兴趣:徒步、摄影、烹饪
"""
profile = generator(prompt)
print(profile.full_name)
print(profile.interests) # ["徒步", "摄影", "烹饪"]
模式4:多实体提取
class Entity(BaseModel):
name: str
type: Literal["PERSON", "ORGANIZATION", "LOCATION"]
class DocumentEntities(BaseModel):
entities: list[Entity]
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
generator = outlines.generate.json(model, DocumentEntities)
text = "Tim Cook 在Redmond的Microsoft总部会见了Satya Nadella。"
prompt = f"从以下提取实体:{text}"
result = generator(prompt)
for entity in result.entities:
print(f"{entity.name} ({entity.type})")
模式5:代码生成
class PythonFunction(BaseModel):
function_name: str
parameters: list[str]
docstring: str
body: str
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
generator = outlines.generate.json(model, PythonFunction)
prompt = "生成一个Python函数来计算阶乘"
func = generator(prompt)
print(f"def {func.function_name}({', '.join(func.parameters)}):")
print(f' """{func.docstring}"""')
print(f" {func.body}")
模式6:批处理
def batch_extract(texts: list[str], schema: type[BaseModel]):
"""从多个文本中提取结构化数据。"""
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
generator = outlines.generate.json(model, schema)
results = []
for text in texts:
result = generator(f"从以下提取:{text}")
results.append(result)
return results
class Person(BaseModel):
name: str
age: int
texts = [
"John 30岁",
"Alice 25岁",
"Bob 40岁"
]
people = batch_extract(texts, Person)
for person in people:
print(f"{person.name}: {person.age}")
后端配置
Transformers
import outlines
# 基础用法
model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct")
# GPU配置
model = outlines.models.transformers(
"microsoft/Phi-3-mini-4k-instruct",
device="cuda",
model_kwargs={"torch_dtype": "float16"}
)
# 流行模型
model = outlines.models.transformers("meta-llama/Llama-3.1-8B-Instruct")
model = outlines.models.transformers("mistralai/Mistral-7B-Instruct-v0.3")
model = outlines.models.transformers("Qwen/Qwen2.5-7B-Instruct")
llama.cpp
# 加载GGUF模型
model = outlines.models.llamacpp(
"./models/llama-3.1-8b.Q4_K_M.gguf",
n_ctx=4096, # 上下文窗口
n_gpu_layers=35, # GPU层
n_threads=8 # CPU线程
)
# 完全GPU卸载
model = outlines.models.llamacpp(
"./models/model.gguf",
n_gpu_layers=-1 # 所有层在GPU上
)
vLLM(生产)
# 单GPU
model = outlines.models.vllm("meta-llama/Llama-3.1-8B-Instruct")
# 多GPU
model = outlines.models.vllm(
"meta-llama/Llama-3.1-70B-Instruct",
tensor_parallel_size=4 # 4 GPUs
)
# 带量化
model = outlines.models.vllm(
"meta-llama/Llama-3.1-8B-Instruct",
quantization="awq" # 或 "gptq"
)
最佳实践
1. 使用特定类型
# ✅ 好:特定类型
class Product(BaseModel):
name: str
price: float # 不是 str
quantity: int # 不是 str
in_stock: bool # 不是 str
# ❌ 坏:一切都作为字符串
class Product(BaseModel):
name: str
price: str # 应该是 float
quantity: str # 应该是 int
2. 添加约束
from pydantic import Field
# ✅ 好:带约束
class User(BaseModel):
name: str = Field(min_length=1, max_length=100)
age: int = Field(ge=0, le=120)
email: str = Field(pattern=r"^[\w\.-]+@[\w\.-]+\.\w+$")
# ❌ 坏:无约束
class User(BaseModel):
name: str
age: int
email: str
3. 使用枚举进行分类
# ✅ 好:枚举用于固定集合
class Priority(str, Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
class Task(BaseModel):
title: str
priority: Priority
# ❌ 坏:自由形式字符串
class Task(BaseModel):
title: str
priority: str # 可以是任何内容
4. 在提示中提供上下文
# ✅ 好:清晰上下文
prompt = """
从以下文本中提取产品信息。
文本:iPhone 15 Pro 售价$999,目前有货。
产品:
"""
# ❌ 坏:最小上下文
prompt = "iPhone 15 Pro 售价$999,目前有货。"
5. 处理可选字段
from typing import Optional
# ✅ 好:可选字段用于不完整数据
class Article(BaseModel):
title: str # 必需
author: Optional[str] = None # 可选
date: Optional[str] = None # 可选
tags: list[str] = [] # 默认空列表
# 即使作者/日期缺失也能成功
与替代方案比较
| 功能 | Outlines | Instructor | Guidance | LMQL |
|---|---|---|---|---|
| Pydantic 支持 | ✅ 原生 | ✅ 原生 | ❌ 无 | ❌ 无 |
| JSON 模式 | ✅ 是 | ✅ 是 | ⚠️ 有限 | ✅ 是 |
| 正则表达式约束 | ✅ 是 | ❌ 无 | ✅ 是 | ✅ 是 |
| 本地模型 | ✅ 完整 | ⚠️ 有限 | ✅ 完整 | ✅ 完整 |
| API 模型 | ⚠️ 有限 | ✅ 完整 | ✅ 完整 | ✅ 完整 |
| 零开销 | ✅ 是 | ❌ 无 | ⚠️ 部分 | ✅ 是 |
| 自动重试 | ❌ 无 | ✅ 是 | ❌ 无 | ❌ 无 |
| 学习曲线 | 低 | 低 | 低 | 高 |
何时选择 Outlines:
- 使用本地模型(Transformers、llama.cpp、vLLM)
- 需要最大推理速度
- 想要Pydantic模型支持
- 需要零开销结构化生成
- 控制令牌采样过程
何时选择替代方案:
- Instructor:需要API模型并自动重试
- Guidance:需要令牌修复和复杂工作流
- LMQL:偏好声明式查询语法
性能特征
速度:
- 零开销:结构化生成与无约束一样快
- 快速跳过优化:跳过确定性令牌
- 比后生成验证方法快1.2-2倍
内存:
- FSM 每个模式编译一次(缓存)
- 最小运行时开销
- 高效使用vLLM进行高吞吐量
准确性:
- 100% 有效输出(由FSM保证)
- 无需重试循环
- 确定性令牌过滤
资源
- 文档:https://outlines-dev.github.io/outlines
- GitHub:https://github.com/outlines-dev/outlines (8k+ 星)
- Discord:https://discord.gg/R9DSu34mGd
- 博客:https://blog.dottxt.co
另请参阅
references/json_generation.md- 全面的JSON和Pydantic模式references/backends.md- 后端特定配置references/examples.md- 生产就绪示例