目录
  1. 1. 目录
  2. 2. 项目速览
  3. 3. 功能概述
    1. 3.1. Handlebars 风格的角色模板
    2. 3.2. 正则表达式约束生成
    3. 3.3. JSON Schema 约束生成(gen_json)
    4. 3.4. 选项列表约束(select)
    5. 3.5. @guidance 装饰器 — 可组合语法函数
    6. 3.6. 上下文无关文法(CFG)约束
    7. 3.7. Token Fast-Forwarding
    8. 3.8. Mock 模型 — 离线语法验证
  4. 4. 适用场景
  5. 5. 快速上手
    1. 5.1. 安装
    2. 5.2. 最小示例
    3. 5.3. 核心 API 速查
  6. 6. 源码架构
  7. 7. 实操 Demo
    1. 7.1. Demo 1:医疗数据结构化提取
    2. 7.2. Demo 2:受控多步推理链
    3. 7.3. Demo 3:正则约束批量分类
  8. 8. 同类对比
  9. 9. 参考资源
Guidance — 受控生成与结构化输出编程范式

GitHub: guidance-ai/guidance
Stars: 21,500+ | Language: Python (2.9%) + Jupyter Notebook (94%) | License: MIT
最新版本: v0.3.2(2026 年 3 月)

目录

  1. 项目速览
  2. 功能概述
  3. 适用场景
  4. 快速上手
  5. 源码架构
  6. 实操 Demo
  7. 同类对比
  8. 参考资源

项目速览

Guidance 是一种高效的受控生成(Constrained Generation)编程范式,由 guidance-ai 团队开发和维护。它的核心设计理念是”在生成过程中插入控制”——与传统 Prompt 工程先生成后解析不同,Guidance 在模型生成每一个 Token 时就能强制执行格式约束,从而杜绝输出格式错误。

传统做法的痛点是”先生成,后校验”:你要求模型输出 JSON,但它可能多了一个逗号、少了一个引号;你要求模型从 A/B/C/D 中选择,但它可能输出”答案是 C”而不是单个字母。Guidance 通过 Token 级别的约束彻底解决了这个问题——当语法规则已经确定了下一个 Token 时,Guidance 直接跳过模型推理,插入该 Token(称为 Token Fast-Forwarding),既保证了格式正确,又降低了延迟和成本。

Guidance 支持多种约束后端:正则表达式(regex)、上下文无关文法(CFG)、JSON Schema(通过 gen_json)、以及选项列表(select)。它还支持模板化的角色对话、多步推理链、工具调用和可组合的语法函数(通过 @guidance 装饰器)。项目主要由 Jupyter Notebook 形式的示例驱动开发,截至 2026 年 6 月已获得 21,500+ Star,发布了 47 个版本。

功能概述

Handlebars 风格的角色模板

Guidance 使用与 Handlebars 类似的模板语法,通过 system()user()assistant() 等上下文管理器构建结构化的对话模板。每个角色块中的内容会按正确的消息格式序列化发送给模型:

from guidance import system, user, assistant, gen
from guidance.models import Transformers

phi_lm = Transformers("microsoft/Phi-4-mini-instruct")
lm = phi_lm

with system():
lm += "You are a helpful assistant"
with user():
lm += "Hello. What is your name?"
with assistant():
lm += gen(name="lm_response", max_tokens=20)

print(f"{lm['lm_response']=}")

gen() 是 Guidance 的核心生成函数,通过 name 参数将生成的文本绑定到变量上,后续可通过 lm['variable_name'] 访问。

正则表达式约束生成

通过 regex 参数,可以强制生成内容匹配指定的正则表达式。模型在生成每个 Token 时,Guidance 会建立一个 Token 映射,只允许符合正则规则的 Token 通过,将不符合的 Token 的 logit 设为负无穷:

lm = phi_lm
with system():
lm += "You are a teenager"
with user():
lm += "How old are you?"
with assistant():
lm += gen("lm_age", regex=r"\d+", temperature=0.8)

print(f"The language model is {lm['lm_age']} years old")

这种约束是精确的——无论温度设置多高,输出一定匹配 \d+(一个或多个数字)。

JSON Schema 约束生成(gen_json)

gen_json 是 Guidance 最强大的约束生成功能。它接受一个 Pydantic 模型或 JSON Schema 定义,确保 LLM 输出严格符合指定的 JSON 结构。底层通过编译 JSON Schema 为令牌级别的语法约束来实现:

import json
from pydantic import BaseModel, Field
from guidance import json as gen_json

class BloodPressure(BaseModel):
systolic: int = Field(gt=300, le=400)
diastolic: int = Field(gt=0, le=20)
location: str = Field(max_length=50)
model_config = dict(extra="forbid")

lm = phi_lm
with system():
lm += "You are a doctor taking a patient's blood pressure taken from their arm"
with user():
lm += "Report the blood pressure"
with assistant():
lm += gen_json(name="bp", schema=BloodPressure)

result = BloodPressure.model_validate_json(lm["bp"])
print(result.model_dump_json(indent=8))

这里的关键是 model_config = dict(extra="forbid") — 结合 Pydantic 的严格模式和 Guidance 的语法约束,生成的 JSON 不仅结构正确,而且字段值还满足 gt/le/max_length 等验证条件。

选项列表约束(select)

对于多选题、分类任务等场景,select() 函数将生成严格约束到给定的选项列表中:

from guidance import select

lm = phi_lm
with system():
lm += "You are a geography expert"
with user():
lm += """What is the capital of Sweden? Answer with the correct letter.
A) Helsinki
B) Reykjavik
C) Stockholm
D) Oslo
"""
with assistant():
lm += select(["A", "B", "C", "D"], name="model_selection")

print(f"The model selected {lm['model_selection']}")

模型只能输出 A/B/C/D 之一,绝不会生成多余的文字。这在批量评估和下游自动处理中极其重要。

@guidance 装饰器 — 可组合语法函数

Guidance 支持通过 @guidance 装饰器将受控生成逻辑封装为可复用的函数。stateless=True 参数表示该函数不依赖外部状态,可以安全地嵌套组合:

import guidance
from guidance.models import Model

ASCII_OFFSET = ord("a")

@guidance
def zero_shot_multiple_choice(
language_model: Model,
question: str,
choices: list[str],
):
with user():
language_model += question + "\n"
for i, choice in enumerate(choices):
language_model += f"{chr(i+ASCII_OFFSET)} : {choice}\n"

with assistant():
language_model += select(
[chr(i + ASCII_OFFSET) for i in range(len(choices))],
name="string_choice"
)

return language_model

上下文无关文法(CFG)约束

Guidance 支持完整的上下文无关文法约束,允许生成任意递归结构的数据。以下示例展示生成合规 HTML 页面的组合式语法函数:

from guidance.library import one_or_more, capture, with_temperature

@guidance(stateless=True)
def _gen_text(lm: Model):
return lm + gen(regex="[^<>]+")

@guidance(stateless=True)
def _gen_text_in_tag(lm: Model, tag: str):
lm += f"<{tag}>"
lm += _gen_text()
lm += f"</{tag}>"
return lm

@guidance(stateless=True)
def _gen_body(lm: Model):
lm += "<body>\n"
lm += one_or_more(
select(options=[_gen_heading(), one_or_more(_gen_para())])
)
lm += "</body>\n"
return lm

@guidance(stateless=True)
def make_html(lm, name: str | None = None, *, temperature: float = 0.0):
return lm + capture(
with_temperature(_gen_html(), temperature=temperature),
name=name,
)

这种组合式方法让复杂格式(JSON、XML、HTML、YAML 等)的受控生成变得模块化且可测试。

Token Fast-Forwarding

当语法约束已经确定下一个 Token 时(例如 JSON 对象的 {": 分隔符),Guidance 直接插入该 Token 而无需模型推理,大幅降低推理延迟和 API 成本。对于高度结构化的输出(如嵌套 JSON),Token Fast-Forwarding 可节省 30%-50% 的生成 Token 量。

Mock 模型 — 离线语法验证

Guidance 内置了 Mock 模型,可以在不调用任何 LLM API 的情况下验证语法规则的正确性:

from guidance import gen
from guidance.models import Mock

grammar = "expr=" + gen(regex=r"\d+([+*]\d+)*", name="expr")

# 直接验证字符串是否匹配语法
assert grammar.match("expr=12+7*3") is not None
assert grammar.match("expr=12+*3") is None

# 使用 Mock 模型运行
lm = Mock(b"<s>expr=12+7*3")
lm += grammar
print(lm["expr"]) # 12+7*3

这非常适合 CI/CD 流程中的语法单元测试——在部署前确保约束规则的行为符合预期。

适用场景

  1. 结构化数据提取:从非结构化文本中提取 JSON 结构,确保字段类型和约束完全正确(如提取病历、发票、合同信息)
  2. 多选题自动评测:用 select() 确保模型只输出选项字母,消除后处理解析的脆弱性
  3. 代码生成:用 CFG 约束确保生成代码语法正确,消除括号不匹配、缩进错误等问题
  4. 合规内容生成:通过 regex 约束过滤敏感词、固定格式要求(如身份证号、电话号码格式)
  5. Agent 工具调用:用 JSON Schema 约束确保工具调用参数结构正确,减少无效调用
  6. 多步推理链:用 @guidance 函数组合多个推理步骤,每步的输出作为下一步的输入
  7. 批量结构化生成:在数据标注、测试数据生成等场景中确保输出一致性和正确性

快速上手

安装

pip install guidance

支持 Transformers、llama.cpp、OpenAI API 等后端。

最小示例

from guidance import system, user, assistant, gen
from guidance.models import Transformers

lm = Transformers("microsoft/Phi-4-mini-instruct")

with system():
lm += "You are a helpful assistant"
with user():
lm += "List three colors, one per line:"
with assistant():
lm += gen(name="colors", max_tokens=50)

print(lm["colors"])

核心 API 速查

函数/类 用途 示例
gen(name=..., max_tokens=...) 基本生成 gen("answer", max_tokens=100)
gen(name, regex=r"...") 正则约束 gen("age", regex=r"\d+")
gen_json(name, schema=Model) JSON Schema 约束 gen_json("bp", schema=BloodPressure)
select(options, name) 选项约束 select(["A","B","C"], name="choice")
@guidance 可组合函数 @guidance \ndef my_fn(lm): ...
@guidance(stateless=True) 无状态语法函数 用于 CFG 组合
capture(content, name) 命名捕获 capture(gen(), name="out")
one_or_more(content) 一次或多次重复 用于列表/段落等重复结构
with_temperature(content, t) 局部温度控制 with_temperature(gen(), t=0.9)
system() / user() / assistant() 角色上下文 with system(): lm += "..."
Mock(bytes) 离线模拟 Mock(b"<s>expr=12+3")

源码架构

Guidance 的仓库以 Jupyter Notebook 为主要代码承载形式(94%),核心 Python 库位于 guidance/ 目录:

guidance/
├── models/ # 模型后端(Transformers、llama.cpp、OpenAI 等)
├── _grammar.py # 语法约束核心(Token 级别约束引擎)
├── _parser.py # 约束解析器(regex/CFG → Token 映射)
├── _server.py # 本地模型推理服务器
├── _utils.py # 工具函数
├── library/ # 语法组合子库(one_or_more、capture、select 等)
├── ext/ # 扩展接口
├── resources/ # 内置资源
└── utils/ # 工具类

核心设计模式:

  1. Token-Mask 约束:在模型每次生成 Token 前,Guidance 计算当前状态下允许的 Token 集合,将其余 Token 的 logit 设为负无穷,从而保证约束不被违反
  2. 语法编译:regex/JSON Schema/CFG 在首次使用时被编译为确定有限状态自动机(DFA),生成过程中根据自动机状态决定 Token Mask
  3. Token Fast-Forward:当 DFA 的当前状态只有一个出边时(如 JSON 的结构字符),跳过模型调用直接插入
  4. Immutable LM Chain:每次 lm += ... 操作创建新的不可变状态,支持分支和回溯

实操 Demo

以下演示 Guidance 三个核心场景:JSON Schema 约束生成、多步推理链、以及正则约束分类。

Demo 1:医疗数据结构化提取

import json
from pydantic import BaseModel, Field
from guidance import system, user, assistant
from guidance import json as gen_json
from guidance.models import Transformers

lm = Transformers("microsoft/Phi-4-mini-instruct")

# 定义期望的 JSON 结构
class PatientVitals(BaseModel):
heart_rate: int = Field(gt=40, le=200, description="Heart rate in bpm")
systolic_bp: int = Field(gt=70, le=250, description="Systolic blood pressure")
diastolic_bp: int = Field(gt=40, le=150, description="Diastolic blood pressure")
temperature: float = Field(gt=35.0, le=42.0, description="Body temperature in Celsius")
model_config = dict(extra="forbid")

clinical_note = """
Patient presents with HR 78, BP 128/82, temp 36.8C.
No complaints of chest pain or shortness of breath.
"""

with system():
lm += "You are a medical scribe. Extract vital signs from clinical notes into structured JSON."

with user():
lm += f"Extract vitals from this note:\n{clinical_note}"

with assistant():
lm += gen_json(name="vitals", schema=PatientVitals)

# 生成的结果一定符合 schema
print(json.dumps(json.loads(lm["vitals"]), indent=2))

# 直接反序列化为 Pydantic 对象
vitals = PatientVitals.model_validate_json(lm["vitals"])
print(f"Heart rate: {vitals.heart_rate} bpm")
print(f"Blood pressure: {vitals.systolic_bp}/{vitals.diastolic_bp}")

Demo 2:受控多步推理链

此 Demo 展示 Guidance 的独特能力:在每个推理步骤中施加精确约束,确保推理格式可控。

from guidance import system, user, assistant, gen, select
from guidance import guidance
from guidance.models import Model

@guidance
def constrained_math_solver(lm: Model, problem: str):
"""多步数学推理:先分析、再计算、最后选择答案"""
with user():
lm += f"Problem: {problem}\n"
lm += "Step 1 - Identify the operation needed: "
with assistant():
lm += gen(name="step1_analysis", max_tokens=60)

with user():
lm += "Step 2 - Show your calculation: "
with assistant():
lm += gen(name="step2_calculation", max_tokens=100)

with user():
lm += "Step 3 - Select the final answer: "
with assistant():
lm += select(
["A) 9", "B) 12", "C) 24", "D) 36"],
name="final_answer"
)
return lm

lm = Transformers("microsoft/Phi-4-mini-instruct")
with system():
lm += "You are a careful math tutor. Think step by step."

result = constrained_math_solver(
lm, "If a train travels at 60 mph for 2.5 hours, how far does it go?"
)
print(f"Analysis: {result['step1_analysis']}")
print(f"Calculation: {result['step2_calculation']}")
print(f"Final answer: {result['final_answer']}")

Demo 3:正则约束批量分类

from guidance import system, user, assistant, gen

lm = Transformers("microsoft/Phi-4-mini-instruct")

sentiments = []
reviews = [
"This product is amazing, exceeded all my expectations!",
"Terrible quality, broke after two days of use.",
"It's okay, does the job but nothing special.",
"The customer service was outstanding and resolved my issue quickly.",
"Waste of money, do not buy this.",
]

for review in reviews:
lm_session = lm
with system():
lm_session += "You are a sentiment classifier."
with user():
lm_session += (
f"Classify this review as POSITIVE, NEGATIVE, or NEUTRAL.\n"
f"Review: {review}\n"
f"Output ONLY one word: "
)
with assistant():
lm_session += gen(
name="sentiment",
regex=r"POSITIVE|NEGATIVE|NEUTRAL",
max_tokens=10
)
sentiments.append(lm_session["sentiment"])

for review, sentiment in zip(reviews, sentiments):
print(f"[{sentiment}] {review}")

同类对比

维度 Guidance DSPy Outlines LangChain Output Parser
核心理念 Token 级受控生成 自动优化 Prompt 基于 FSMs 的结构化生成 先生成后解析
约束方式 regex、CFG、JSON Schema Signature OutputField 描述 regex、JSON Schema、Pydantic Pydantic、JSON parser
约束时机 生成时实时约束(Token 级) 编译时优化,生成时不约束 生成时实时约束(Token 级) 生成后解析校验
格式保证 100% 保证(数学级别) 不保证(统计优化) 100% 保证(数学级别) 不保证(可能解析失败)
多步推理 原生支持(模板链式调用) 通过 Module 组合 有限支持 通过 Chain 组合
工具调用 支持(interleaved control) 支持(ReAct/Tool) 不直接支持 通过 Agent 框架
性能优化 Token Fast-Forwarding 减少调用 编译缓存 Logit 掩码 无特殊优化
学习曲线 低,模板语法直观 中等 中等

Guidance 与 DSPy 的关系是互补的:DSPy 在”策略层面”自动找到最优 Prompt,Guidance 在”执行层面”保证输出格式正确。两者结合使用非常强大——先用 DSPy 编译出最优的 Prompt 指令和 Few-shot 示例,然后在推理时使用 Guidance 强制执行输出约束。

与 Outlines 的对比:两者都在 Token 级别实现约束,但 Guidance 的 Handlebars 模板语法和 @guidance 可组合函数使得复杂链式推理更容易表达;Outlines 更偏学术研究,API 相对底层。

参考资源

  • 官方文档: https://guidance.readthedocs.io
  • GitHub 仓库: https://github.com/guidance-ai/guidance
  • 示例 Notebook: 仓库 notebooks/ 目录包含完整的使用示例
  • Phi-4 模型: microsoft/Phi-4-mini-instruct — Guidance 推荐的高效本地模型
  • 相关论文: “Guidance: A Guidance Language for Controlling Large Language Models” — 项目设计理念的学术表达
  • 对比阅读: 本文与《SKILL-DSPy》和《SKILL-Outlines》形成 Prompt 工程的完整技术拼图
文章作者: Leo·Cheung
文章链接: http://tufusi.com/2026/06/15/SKILL-Guidance/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ONE·PIECE
打赏
  • 微信
  • 支付宝

评论