mcpField
G
guidance

guidance

github.com/davila7Agent 工作流33.0k343 次安装今天更新
代码仓库

关于 guidance

Guidance 是 Microsoft Research 推出的 Python 库,可用正则表达式、语法和选项约束控制大模型生成。它支持 API 与本地模型后端,并以 Python 风格构建结构化输出和多步工作流。

主要功能

  1. 01正则表达式与语法约束
  2. 02使用 select() 限定选项
  3. 03提示词边界的 Token 修复
  4. 04Python 风格的上下文管理器与函数
  5. 05支持 API 和本地模型

适用场景

  1. 01生成结构化 JSON 或代码
  2. 02按固定格式提取实体
  3. 03将文本分类到预设类别
  4. 04构建多步生成工作流

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/davila7/claude-code-templates --skill guidance

安装后在 Claude Code 中输入/guidance确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
backends.md
constraints.md
examples.md

详细介绍

指南:受约束的大模型生成

何时使用此技能

在以下情况下使用 Guidance:

  • 通过正则表达式或语法控制大模型输出语法
  • 确保生成有效的 JSON/XML/代码
  • 与传统提示词方法相比降低延迟
  • 强制采用结构化格式(日期、电子邮件、ID 等)
  • 使用 Python 风格的控制流构建多步骤工作流
  • 通过语法约束防止无效输出

GitHub Stars:18,000+ | 来自:Microsoft Research

安装

# Base installation
pip install guidance

# With specific backends
pip install guidance[transformers]  # Hugging Face models
pip install guidance[llama_cpp]     # llama.cpp models

快速入门

基本示例:结构化生成
from guidance import models, gen

# Load model (supports OpenAI, Transformers, llama.cpp)
lm = models.OpenAI("gpt-4")

# Generate with constraints
result = lm + "The capital of France is " + gen("capital", max_tokens=5)

print(result["capital"])  # "Paris"
使用 Anthropic Claude
from guidance import models, gen, system, user, assistant

# Configure Claude
lm = models.Anthropic("claude-sonnet-4-5-20250929")

# Use context managers for chat format
with system():
    lm += "You are a helpful assistant."

with user():
    lm += "What is the capital of France?"

with assistant():
    lm += gen(max_tokens=20)

核心概念

1. 上下文管理器

Guidance 使用 Python 风格的上下文管理器进行聊天式交互。

from guidance import system, user, assistant, gen

lm = models.Anthropic("claude-sonnet-4-5-20250929")

# System message
with system():
    lm += "You are a JSON generation expert."

# User message
with user():
    lm += "Generate a person object with name and age."

# Assistant response
with assistant():
    lm += gen("response", max_tokens=100)

print(lm["response"])

优点:

  • 自然的聊天流程
  • 清晰的角色区分
  • 易于阅读和维护
2. 受约束的生成

Guidance 使用正则表达式或语法确保输出符合指定模式。

正则表达式约束
from guidance import models, gen

lm = models.Anthropic("claude-sonnet-4-5-20250929")

# Constrain to valid email format
lm += "Email: " + gen("email", regex=r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")

# Constrain to date format (YYYY-MM-DD)
lm += "Date: " + gen("date", regex=r"\d{4}-\d{2}-\d{2}")

# Constrain to phone number
lm += "Phone: " + gen("phone", regex=r"\d{3}-\d{3}-\d{4}")

print(lm["email"])  # Guaranteed valid email
print(lm["date"])   # Guaranteed YYYY-MM-DD format

工作原理:

  • 将正则表达式转换为 token 级别的语法
  • 在生成过程中筛除无效 token
  • 模型只能生成符合模式的输出
选项约束
from guidance import models, gen, select

lm = models.Anthropic("claude-sonnet-4-5-20250929")

# Constrain to specific choices
lm += "Sentiment: " + select(["positive", "negative", "neutral"], name="sentiment")

# Multiple-choice selection
lm += "Best answer: " + select(
    ["A) Paris", "B) London", "C) Berlin", "D) Madrid"],
    name="answer"
)

print(lm["sentiment"])  # One of: positive, negative, neutral
print(lm["answer"])     # One of: A, B, C, or D
3. Token 修复

Guidance 会自动“修复”提示词与生成内容之间的 token 边界。

**问题:**分词会产生不自然的边界。

# Without token healing
prompt = "The capital of France is "
# Last token: " is "
# First generated token might be " Par" (with leading space)
# Result: "The capital of France is  Paris" (double space!)

**解决方案:**Guidance 回退一个 token 并重新生成。

from guidance import models, gen

lm = models.Anthropic("claude-sonnet-4-5-20250929")

# Token healing enabled by default
lm += "The capital of France is " + gen("capital", max_tokens=5)
# Result: "The capital of France is Paris" (correct spacing)

优点:

  • 自然的文本边界
  • 没有别扭的空格问题
  • 模型性能更好(能看到自然的 token 序列)
4. 基于语法的生成

使用上下文无关语法定义复杂结构。

from guidance import models, gen

lm = models.Anthropic("claude-sonnet-4-5-20250929")

# JSON grammar (simplified)
json_grammar = """
{
    "name": <gen name regex="[A-Za-z ]+" max_tokens=20>,
    "age": <gen age regex="[0-9]+" max_tokens=3>,
    "email": <gen email regex="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}" max_tokens=50>
}
"""

# Generate valid JSON
lm += gen("person", grammar=json_grammar)

print(lm["person"])  # Guaranteed valid JSON structure

使用场景:

  • 复杂的结构化输出
  • 嵌套数据结构
  • 编程语言语法
  • 特定领域语言
5. Guidance 函数

使用 @guidance 装饰器创建可复用的生成模式。

from guidance import guidance, gen, models

@guidance
def generate_person(lm):
    """Generate a person with name and age."""
    lm += "Name: " + gen("name", max_tokens=20, stop="\n")
    lm += "\nAge: " + gen("age", regex=r"[0-9]+", max_tokens=3)
    return lm

# Use the function
lm = models.Anthropic("claude-sonnet-4-5-20250929")
lm = generate_person(lm)

print(lm["name"])
print(lm["age"])

有状态函数:

@guidance(stateless=False)
def react_agent(lm, question, tools, max_rounds=5):
    """ReAct agent with tool use."""
    lm += f"Question: {question}\n\n"

    for i in range(max_rounds):
        # Thought
        lm += f"Thought {i+1}: " + gen("thought", stop="\n")

        # Action
        lm += "\nAction: " + select(list(tools.keys()), name="action")

        # Execute tool
        tool_result = tools[lm["action"]]()
        lm += f"\nObservation: {tool_result}\n\n"

        # Check if done
        lm += "Done? " + select(["Yes", "No"], name="done")
        if lm["done"] == "Yes":
            break

    # Final answer
    lm += "\nFinal Answer: " + gen("answer", max_tokens=100)
    return lm

后端配置

Anthropic Claude
from guidance import models

lm = models.Anthropic(
    model="claude-sonnet-4-5-20250929",
    api_key="your-api-key"  # Or set ANTHROPIC_API_KEY env var
)
OpenAI
lm = models.OpenAI(
    model="gpt-4o-mini",
    api_key="your-api-key"  # Or set OPENAI_API_KEY env var
)
本地模型(Transformers)
from guidance.models import Transformers

lm = Transformers(
    "microsoft/Phi-4-mini-instruct",
    device="cuda"  # Or "cpu"
)
本地模型(llama.cpp)
from guidance.models import LlamaCpp

lm = LlamaCpp(
    model_path="/path/to/model.gguf",
    n_ctx=4096,
    n_gpu_layers=35
)

常见模式

模式 1:JSON 生成
from guidance import models, gen, system, user, assistant

lm = models.Anthropic("claude-sonnet-4-5-20250929")

with system():
    lm += "You generate valid JSON."

with user():
    lm += "Generate a user profile with name, age, and email."

with assistant():
    lm += """{
    "name": """ + gen("name", regex=r'"[A-Za-z ]+"', max_tokens=30) + """,
    "age": """ + gen("age", regex=r"[0-9]+", max_tokens=3) + """,
    "email": """ + gen("email", regex=r'"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"', max_tokens=50) + """
}"""

print(lm)  # Valid JSON guaranteed
模式 2:分类
from guidance import models, gen, select

lm = models.Anthropic("claude-sonnet-4-5-20250929")

text = "This product is amazing! I love it."

lm += f"Text: {text}\n"
lm += "Sentiment: " + select(["positive", "negative", "neutral"], name="sentiment")
lm += "\nConfidence: " + gen("confidence", regex=r"[0-9]+", max_tokens=3) + "%"

print(f"Sentiment: {lm['sentiment']}")
print(f"Confidence: {lm['confidence']}%")
模式 3:多步骤推理
from guidance import models, gen, guidance

@guidance
def chain_of_thought(lm, question):
    """Generate answer with step-by-step reasoning."""
    lm += f"Question: {question}\n\n"

    # Generate multiple reasoning steps
    for i in range(3):
        lm += f"Step {i+1}: " + gen(f"step_{i+1}", stop="\n", max_tokens=100) + "\n"

    # Final answer
    lm += "\nTherefore, the answer is: " + gen("answer", max_tokens=50)

    return lm

lm = models.Anthropic("claude-sonnet-4-5-20250929")
lm = chain_of_thought(lm, "What is 15% of 200?")

print(lm["answer"])
模式 4:ReAct Agent
from guidance import models, gen, select, guidance

@guidance(stateless=False)
def react_agent(lm, question):
    """ReAct agent with tool use."""
    tools = {
        "calculator": lambda expr: eval(expr),
        "search": lambda query: f"Search results for: {query}",
    }

    lm += f"Question: {question}\n\n"

    for round in range(5):
        # Thought
        lm += f"Thought: " + gen("thought", stop="\n") + "\n"

        # Action selection
        lm += "Action: " + select(["calculator", "search", "answer"], name="action")

        if lm["action"] == "answer":
            lm += "\nFinal Answer: " + gen("answer", max_tokens=100)
            break

        # Action input
        lm += "\nAction Input: " + gen("action_input", stop="\n") + "\n"

        # Execute tool
        if lm["action"] in tools:
            result = tools[lm["action"]](lm["action_input"])
            lm += f"Observation: {result}\n\n"

    return lm

lm = models.Anthropic("claude-sonnet-4-5-20250929")
lm = react_agent(lm, "What is 25 * 4 + 10?")
print(lm["answer"])
模式 5:数据提取
from guidance import models, gen, guidance

@guidance
def extract_entities(lm, text):
    """Extract structured entities from text."""
    lm += f"Text: {text}\n\n"

    # Extract person
    lm += "Person: " + gen("person", stop="\n", max_tokens=30) + "\n"

    # Extract organization
    lm += "Organization: " + gen("organization", stop="\n", max_tokens=30) + "\n"

    # Extract date
    lm += "Date: " + gen("date", regex=r"\d{4}-\d{2}-\d{2}", max_tokens=10) + "\n"

    # Extract location
    lm += "Location: " + gen("location", stop="\n", max_tokens=30) + "\n"

    return lm

text = "Tim Cook announced at Apple Park on 2024-09-15 in Cupertino."

lm = models.Anthropic("claude-sonnet-4-5-20250929")
lm = extract_entities(lm, text)

print(f"Person: {lm['person']}")
print(f"Organization: {lm['organization']}")
print(f"Date: {lm['date']}")
print(f"Location: {lm['location']}")

最佳实践

1. 使用正则表达式验证格式
# ✅ Good: Regex ensures valid format
lm += "Email: " + gen("email", regex=r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")

# ❌ Bad: Free generation may produce invalid emails
lm += "Email: " + gen("email", max_tokens=50)
2. 对固定类别使用 select()
# ✅ Good: Guaranteed valid category
lm += "Status: " + select(["pending", "approved", "rejected"], name="status")

# ❌ Bad: May generate typos or invalid values
lm += "Status: " + gen("status", max_tokens=20)
3. 利用 Token 修复
# Token healing is enabled by default
# No special action needed - just concatenate naturally
lm += "The capital is " + gen("capital")  # Automatic healing
4. 使用 stop 序列
# ✅ Good: Stop at newline for single-line outputs
lm += "Name: " + gen("name", stop="\n")

# ❌ Bad: May generate multiple lines
lm += "Name: " + gen("name", max_tokens=50)
5. 创建可复用函数
# ✅ Good: Reusable pattern
@guidance
def generate_person(lm):
    lm += "Name: " + gen("name", stop="\n")
    lm += "\nAge: " + gen("age", regex=r"[0-9]+")
    return lm

# Use multiple times
lm = generate_person(lm)
lm += "\n\n"
lm = generate_person(lm)
6. 平衡约束
# ✅ Good: Reasonable constraints
lm += gen("name", regex=r"[A-Za-z ]+", max_tokens=30)

# ❌ Too strict: May fail or be very slow
lm += gen("name", regex=r"^(John|Jane)$", max_tokens=10)

与其他方案的比较

特性GuidanceInstructorOutlinesLMQL
正则表达式约束✅ 是❌ 否✅ 是✅ 是
语法支持✅ CFG❌ 否✅ CFG✅ CFG
Pydantic 验证❌ 否✅ 是✅ 是❌ 否
Token 修复✅ 是❌ 否✅ 是❌ 否
本地模型✅ 是⚠️ 有限✅ 是✅ 是
API 模型✅ 是✅ 是⚠️ 有限✅ 是
Python 风格语法✅ 是✅ 是✅ 是❌ 类 SQL
学习曲线低低中高

选择 Guidance 的情况:

  • 需要正则表达式/语法约束
  • 希望使用 token 修复
  • 通过控制流构建复杂工作流
  • 使用本地模型(Transformers、llama.cpp)
  • 偏好 Python 风格语法

选择其他方案的情况:

  • Instructor:需要 Pydantic 验证和自动重试
  • Outlines:需要 JSON Schema 验证
  • LMQL:偏好声明式查询语法

性能特征

延迟降低:

  • 对于受约束的输出,速度比传统提示词方式快 30-50%
  • Token 修复可减少不必要的重新生成
  • 语法约束可防止生成无效 Token

内存使用:

  • 相比不受约束的生成,仅有极少额外开销
  • 语法编译后会缓存,供后续使用
  • 推理时可高效筛选 Token

Token 效率:

  • 防止为无效输出浪费 Token
  • 无需重试循环
  • 直接生成有效输出

资源

另请参阅

  • references/constraints.md - 全面的正则表达式和语法模式
  • references/backends.md - 特定后端的配置
  • references/examples.md - 可用于生产环境的示例

评论

支持 Markdown