mcpField
I
instructor

instructor

github.com/kalarislabs数据与数据库7746 次安装4 天前更新
代码仓库

关于 instructor

此技能介绍如何用 Instructor 将大模型响应转为类型明确、经过验证的结构化数据。开发者可定义 Pydantic 模式、重试无效输出、流式接收部分结果,并通过统一 API 使用不同提供方。

主要功能

  1. 01Pydantic 模式验证
  2. 02无效输出自动重试
  3. 03部分结果流式传输
  4. 04嵌套及可选字段类型支持
  5. 05跨提供方统一 API

适用场景

  1. 01从文本中提取记录
  2. 02按模式验证生成的 JSON
  3. 03实时流式接收结构化结果
  4. 04处理无效的提取响应

安装

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

$npx skills add https://github.com/kalarislabs/research-agent-skills --skill instructor

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

包含的文件

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

references/
advanced-features.md
common-patterns.md
error-handling.md
examples.md
provider-configuration.md
providers.md
validation.md

详细介绍

Instructor:结构化 LLM 输出

何时使用此技能

在以下情况下使用 Instructor:

  • 从 LLM 响应中可靠地提取结构化数据
  • 根据 Pydantic schema 自动验证输出
  • 自动处理错误并重试提取失败的操作
  • 以类型安全和验证机制解析复杂 JSON
  • 流式传输部分结果,以便实时处理
  • 通过一致的 API 支持多个 LLM 提供商

安装

# Base installation
pip install instructor

# With specific providers
pip install "instructor[anthropic]"  # Anthropic Claude
pip install "instructor[openai]"     # OpenAI
pip install "instructor[all]"        # All providers

快速入门

基本示例:提取用户数据
import instructor
from pydantic import BaseModel
from anthropic import Anthropic

# Define output structure
class User(BaseModel):
    name: str
    age: int
    email: str

# Create instructor client
client = instructor.from_anthropic(Anthropic())

# Extract structured data
user = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "John Doe is 30 years old. His email is [email protected]"
    }],
    response_model=User
)

print(user.name)   # "John Doe"
print(user.age)    # 30
print(user.email)  # "[email protected]"
使用 OpenAI
from openai import OpenAI

client = instructor.from_openai(OpenAI())

user = client.chat.completions.create(
    model="gpt-4o-mini",
    response_model=User,
    messages=[{"role": "user", "content": "Extract: Alice, 25, [email protected]"}]
)

核心概念

1. 响应模型(Pydantic)

响应模型定义 LLM 输出的结构和验证规则。

基本模型
from pydantic import BaseModel, Field

class Article(BaseModel):
    title: str = Field(description="Article title")
    author: str = Field(description="Author name")
    word_count: int = Field(description="Number of words", gt=0)
    tags: list[str] = Field(description="List of relevant tags")

article = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "Analyze this article: [article text]"
    }],
    response_model=Article
)

优点:

  • 使用 Python 类型提示确保类型安全
  • 自动验证(word_count > 0)
  • 使用 Field 描述实现自文档化
  • 支持 IDE 自动补全
嵌套模型
class Address(BaseModel):
    street: str
    city: str
    country: str

class Person(BaseModel):
    name: str
    age: int
    address: Address  # Nested model

person = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "John lives at 123 Main St, Boston, USA"
    }],
    response_model=Person
)

print(person.address.city)  # "Boston"
可选字段
from typing import Optional

class Product(BaseModel):
    name: str
    price: float
    discount: Optional[float] = None  # Optional
    description: str = Field(default="No description")  # Default value

# LLM doesn't need to provide discount or description
使用枚举设置约束
from enum import Enum

class Sentiment(str, Enum):
    POSITIVE = "positive"
    NEGATIVE = "negative"
    NEUTRAL = "neutral"

class Review(BaseModel):
    text: str
    sentiment: Sentiment  # Only these 3 values allowed

review = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "This product is amazing!"
    }],
    response_model=Review
)

print(review.sentiment)  # Sentiment.POSITIVE
2. 验证

Pydantic 会自动验证 LLM 输出。如果验证失败,Instructor 会重试。

内置验证器
from pydantic import Field, EmailStr, HttpUrl

class Contact(BaseModel):
    name: str = Field(min_length=2, max_length=100)
    age: int = Field(ge=0, le=120)  # 0 <= age <= 120
    email: EmailStr  # Validates email format
    website: HttpUrl  # Validates URL format

# If LLM provides invalid data, Instructor retries automatically
自定义验证器
from pydantic import field_validator

class Event(BaseModel):
    name: str
    date: str
    attendees: int

    @field_validator('date')
    def validate_date(cls, v):
        """Ensure date is in YYYY-MM-DD format."""
        import re
        if not re.match(r'\d{4}-\d{2}-\d{2}', v):
            raise ValueError('Date must be YYYY-MM-DD format')
        return v

    @field_validator('attendees')
    def validate_attendees(cls, v):
        """Ensure positive attendees."""
        if v < 1:
            raise ValueError('Must have at least 1 attendee')
        return v
模型级验证
from pydantic import model_validator

class DateRange(BaseModel):
    start_date: str
    end_date: str

    @model_validator(mode='after')
    def check_dates(self):
        """Ensure end_date is after start_date."""
        from datetime import datetime
        start = datetime.strptime(self.start_date, '%Y-%m-%d')
        end = datetime.strptime(self.end_date, '%Y-%m-%d')

        if end < start:
            raise ValueError('end_date must be after start_date')
        return self
3. 自动重试

验证失败时,Instructor 会自动重试,并向 LLM 提供错误反馈。

# Retries up to 3 times if validation fails
user = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "Extract user from: John, age unknown"
    }],
    response_model=User,
    max_retries=3  # Default is 3
)

# If age can't be extracted, Instructor tells the LLM:
# "Validation error: age - field required"
# LLM tries again with better extraction

工作原理:

  1. LLM 生成输出
  2. Pydantic 执行验证
  3. 如果无效:将错误消息发送回 LLM
  4. LLM 根据错误反馈重试
  5. 重复上述过程,最多达到 max_retries
4. 流式传输

流式传输部分结果,以便实时处理。

流式传输部分对象
from instructor import Partial

class Story(BaseModel):
    title: str
    content: str
    tags: list[str]

# Stream partial updates as LLM generates
for partial_story in client.messages.create_partial(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "Write a short sci-fi story"
    }],
    response_model=Story
):
    print(f"Title: {partial_story.title}")
    print(f"Content so far: {partial_story.content[:100]}...")
    # Update UI in real-time
流式传输可迭代对象
class Task(BaseModel):
    title: str
    priority: str

# Stream list items as they're generated
tasks = client.messages.create_iterable(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "Generate 10 project tasks"
    }],
    response_model=Task
)

for task in tasks:
    print(f"- {task.title} ({task.priority})")
    # Process each task as it arrives

提供商配置

详细信息、代码示例和参数表:references/provider-configuration.md。适用此步骤时请阅读。

常见模式

详细信息、代码示例和参数表:references/common-patterns.md。适用此步骤时请阅读。

高级功能

详细信息、代码示例和参数表:references/advanced-features.md。适用此步骤时请阅读。

错误处理

详细信息、代码示例和参数表:references/error-handling.md。适用此步骤时请阅读。

最佳实践

1. 清晰的字段描述
# ❌ Bad: Vague
class Product(BaseModel):
    name: str
    price: float

# ✅ Good: Descriptive
class Product(BaseModel):
    name: str = Field(description="Product name from the text")
    price: float = Field(description="Price in USD, without currency symbol")
2. 使用恰当的验证
# ✅ Good: Constrain values
class Rating(BaseModel):
    score: int = Field(ge=1, le=5, description="Rating from 1 to 5 stars")
    review: str = Field(min_length=10, description="Review text, at least 10 chars")
3. 在提示词中提供示例
messages = [{
    "role": "user",
    "content": """Extract person info from: "John, 30, engineer"

Example format:
{
  "name": "John Doe",
  "age": 30,
  "occupation": "engineer"
}"""
}]
4. 对固定类别使用枚举
# ✅ Good: Enum ensures valid values
class Status(str, Enum):
    PENDING = "pending"
    APPROVED = "approved"
    REJECTED = "rejected"

class Application(BaseModel):
    status: Status  # LLM must choose from enum
5. 妥善处理缺失数据
class PartialData(BaseModel):
    required_field: str
    optional_field: Optional[str] = None
    default_field: str = "default_value"

# LLM only needs to provide required_field

与其他方案的比较

功能Instructor手动 JSONLangChainDSPy
类型安全✅ 是❌ 否⚠️ 部分支持✅ 是
自动验证✅ 是❌ 否❌ 否⚠️ 有限支持
自动重试✅ 是❌ 否❌ 否✅ 是
流式传输✅ 是❌ 否✅ 是❌ 否
多提供商支持✅ 是⚠️ 手动处理✅ 是✅ 是
学习曲线低低中高

适合选择 Instructor 的情况:

  • 需要结构化且经过验证的输出
  • 希望获得类型安全和 IDE 支持
  • 需要自动重试
  • 正在构建数据提取系统

适合选择其他方案的情况:

  • DSPy:需要优化提示词
  • LangChain:正在构建复杂链
  • 手动处理:简单的一次性提取

资源

另请参阅

  • references/validation.md - 高级验证模式
  • references/providers.md - 提供商专属配置
  • references/examples.md - 实际应用案例

Agent 操作流程

  1. 检查环境。 确认框架版本、模型提供商、API 密钥和速率限制。
  2. 明确输入。 根据数据或用户确认格式、标识符和参数。任何会影响结果的值都不要猜测,应先询问。
  3. 先运行小规模版本。 使用已知输入测试单次调用或调用链,并检查原始输出。
  4. 使用以上说明和参考资料执行完整任务。
  5. 验证结果。 在小型标注数据集上评估;根据架构检查结构化输出;记录提示词和响应。
  6. 报告。 说明运行了什么(版本、命令、参数)、检查了什么,以及还有哪些不确定之处。
如果发生这种情况请这样做
输出与预期架构不符添加验证和重试机制,收紧架构,或简化提示词。
已安装版本中缺少这些说明提到的函数、标志或端点查阅已安装版本的文档(help()、--help、官方文档),进行调整并告知用户。切勿臆造 API。
必需的输入、标识符或参数含义不明确询问用户,或在运行前明确说明所采用的假设。

诚信守则

  • 切勿伪造结果、参数、标识符、引用或统计数据。若无法运行或验证某项内容,请如实说明。
  • 未经用户同意,切勿将私人或敏感数据发送到外部 API。
  • 此处与版本相关的细节可能已经过时:请根据已安装版本的官方文档进行确认。
  • 对于需要付费、消耗共享 GPU 或云配额、涉及个人或患者数据,或无法撤销的操作,请先征求同意。

评论

支持 Markdown