Skip to main content

instructor

Structured LLM outputs validated with Pydantic.

跳到安装

来源信息

仓库
NousResearch/hermes-agent
最近来源活动
2026年7月24日 04:07
检测到的 SKILL.md 语言
英语
星标
246,398
分支
51,557

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
4 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
instructor
description
Structured LLM outputs validated with Pydantic.
version
1.0.0
author
Orchestra Research
license
MIT
dependencies
["instructor","pydantic","openai","anthropic"]
platforms
["linux","macos","windows"]
metadata
{"hermes":{"tags":["Prompt Engineering","Instructor","Structured Output","Pydantic","Data Extraction","JSON Parsing","Type Safety","Validation","Streaming","OpenAI","Anthropic"]}}
# Instructor: Structured LLM Outputs ## When to Use This Skill Use Instructor when you need to: - **Extract structured data** from LLM responses reliably - **Validate outputs** against Pydantic schemas automatically - **Retry failed extractions** with automatic error handling - **Parse complex JSON** with type safety and validation - **Stream partial results** for real-time processing - **Support multiple LLM providers** with consistent API **GitHub Stars**: 15,000+ | **Battle-tested**: 100,000+ developers ## Installation ```bash # 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 ``` ## Quick Start ### Basic Example: Extract User Data ```python 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 john@example.com" }], response_model=User ) print(user.name) # "John Doe" print(user.age) # 30 print(user.email) # "john@example.com" ``` ### With OpenAI ```python 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, alice@email.com"}] ) ``` ## Core Concepts ### 1. Response Models (Pydantic) Response models define the structure and validation rules for LLM outputs. #### Basic Model ```python 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 ) ``` **Benefits:** - Type safety with Python type hints - Automatic validation (word_count > 0) - Self-documenting with Field descriptions - IDE autocomplete support #### Nested Models ```python 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" ``` #### Optional Fields ```python 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 ``` #### Enums for Constraints ```python 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. Validation Pydantic validates LLM outputs automatically. If validation fails, Instructor retries. #### Built-in Validators ```python 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 ``` #### Custom Validators ```python 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 ``` #### Model-Level Validation ```python 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. Automatic Retrying Instructor retries automatically when validation fails, providing error feedback to the LLM. ```python # 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 ``` **How it works:** 1. LLM generates output 2. Pydantic validates 3. If invalid: Error message sent back to LLM 4. LLM tries again with error feedback 5. Repeats up to max_retries ### 4. Streaming Stream partial results for real-time processing. #### Streaming Partial Objects ```python 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 ``` #### Streaming Iterables ```python 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 ``` ## Provider Configuration ### Anthropic Claude ```python import instructor from anthropic import Anthropic client = instructor.from_anthropic( Anthropic(api_key="your-api-key") ) # Use with Claude models response = client.messages.create( model="claude-sonnet-4-5-20250929", max_tokens=1024, messages=[...], response_model=YourModel ) ``` ### OpenAI ```python from openai import OpenAI client = instructor.from_openai( OpenAI(api_key="your-api-key") ) response = client.chat.completions.create( model="gpt-4o-mini", response_model=YourModel, messages=[...] ) ``` ### Local Models (Ollama) ```python from openai import OpenAI # Point to local Ollama server client = instructor.from_openai( OpenAI( base_url="http://localhost:11434/v1", api_key="ollama" # Required but ignored ), mode=instructor.Mode.JSON ) response = client.chat.completions.create( model="llama3.1", response_model=YourModel, messages=[...] ) ``` ## Common Patterns ### Pattern 1: Data Extraction from Text ```python class CompanyInfo(BaseModel): name: str founded_year: int industry: str employees: int headquarters: str text = """ Tesla, Inc. was founded in 2003. It operates in the automotive and energy industry with approximately 140,000 employees. The company is headquartered in Austin, Texas. """ company = client.messages.create( model="claude-sonnet-4-5-20250929", max_tokens=1024, messages=[{ "role": "user", "content": f"Extract company information from: {text}" }], response_model=CompanyInfo ) ``` ### Pattern 2: Classification ```python class Category(str, Enum): TECHNOLOGY = "technology" FINANCE = "finance" HEALTHCARE = "healthcare" EDUCATION = "education" OTHER = "other" class ArticleClassification(BaseModel): category: Category confidence: float = Field(ge=0.0, le=1.0) keywords: list[str] classification = client.messages.create( model="claude-sonnet-4-5-20250929", max_tokens=1024, messages=[{ "role": "user", "content": "Classify this article: [article text]" }], response_model=ArticleClassification ) ``` ### Pattern 3: Multi-Entity Extraction ```python class Person(BaseModel): name: str role: str class Organization(BaseModel): name: str industry: str class Entities(BaseModel): people: list[Person] organizations: list[Organization] locations: list[str] text = "Tim Cook, CEO of Apple, announced at the event in Cupertino..." entities = client.messages.create( model="claude-sonnet-4-5-20250929", max_tokens=1024, messages=[{ "role": "user", "content": f"Extract all entities from: {text}" }], response_model=Entities ) for person in entities.people: print(f"{person.name} - {person.role}") ``` ### Pattern 4: Structured Analysis ```python class SentimentAnalysis(BaseModel): overall_sentiment: Sentiment positive_aspects: list[str] negative_aspects: list[str] suggestions: list[str] score: float = Field(ge=-1.0, le=1.0) review = "The product works well but setup was confusing..." analysis = client.messages.create( model="claude-sonnet-4-5-20250929", max_tokens=1024, messages=[{ "role": "user", "content": f"Analyze this review: {review}" }], response_model=SentimentAnalysis ) ``` ### Pattern 5: Batch Processing ```python def extract_person(text: str) -> Person: return client.messages.create( model="claude-sonnet-4-5-20250929", max_tokens=1024, messages=[{ "role": "user", "content": f"Extract person from: {text}" }], response_model=Person ) texts = [ "John Doe is a 30-year-old engineer", "Jane Smith, 25, works in marketing", "Bob Johnson, age 40, software developer" ] people = [extract_person(text) for text in texts] ```
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看