SKILL.md
SKILL.mdBrowse 4 files
4,478 tokens
17,327 bytes
Token encoding: o200k_base
Snapshot 24fd22b
1---2name: outlines3description: "Outlines: structured JSON/regex/Pydantic LLM generation."4version: 1.0.15author: Orchestra Research6license: MIT7dependencies: [outlines, transformers, vllm, pydantic]8platforms: [linux, macos, windows]9metadata:10 hermes:11 tags: [Prompt Engineering, Outlines, Structured Generation, JSON Schema, Pydantic, Local Models, Grammar-Based Generation, vLLM, Transformers, Type Safety]12 13---14 15# Outlines: Structured Text Generation16 17## When to Use This Skill18 19Use Outlines when you need to:20- **Guarantee valid JSON/XML/code** structure during generation21- **Use Pydantic models** for type-safe outputs22- **Support local models** (Transformers, llama.cpp, vLLM)23- **Maximize inference speed** with zero-overhead structured generation24- **Generate against JSON schemas** automatically25- **Control token sampling** at the grammar level26 27**GitHub Stars**: 12,000+ | **From**: dottxt.ai (formerly .txt)28 29> **API note (Outlines 1.x):** This skill targets the current v1 API.30> The pre-1.0 helpers (`outlines.models.transformers(...)`,31> `outlines.generate.json/choice/regex/...`) have been **removed**. In v1 you32> create a model with `outlines.from_transformers(...)` (or `from_vllm`,33> `from_llamacpp`, `from_openai`) and then **call the model directly** with an34> output type: `model(prompt, output_type)`. JSON/Pydantic outputs are returned35> as a **JSON string** — validate with `YourModel.model_validate_json(result)`.36 37## Installation38 39```bash40# Base installation41pip install outlines42 43# With specific backends44pip install outlines transformers # Hugging Face models45pip install outlines llama-cpp-python # llama.cpp46pip install outlines vllm # vLLM for high-throughput47```48 49## Quick Start50 51### Basic Example: Classification52 53```python54import outlines55from typing import Literal56from transformers import AutoModelForCausalLM, AutoTokenizer57 58MODEL_NAME = "microsoft/Phi-3-mini-4k-instruct"59 60# v1: wrap a Transformers model + tokenizer61model = outlines.from_transformers(62 AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="auto"),63 AutoTokenizer.from_pretrained(MODEL_NAME),64)65 66# Call the model directly with an output type67prompt = "Sentiment of 'This product is amazing!': "68sentiment = model(prompt, Literal["positive", "negative", "neutral"])69 70print(sentiment) # "positive" (guaranteed one of these)71```72 73### With Pydantic Models74 75```python76from pydantic import BaseModel77import outlines78from transformers import AutoModelForCausalLM, AutoTokenizer79 80class User(BaseModel):81 name: str82 age: int83 email: str84 85MODEL_NAME = "microsoft/Phi-3-mini-4k-instruct"86model = outlines.from_transformers(87 AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="auto"),88 AutoTokenizer.from_pretrained(MODEL_NAME),89)90 91# Generate structured output (returns a JSON string)92prompt = "Extract user: John Doe, 30 years old, john@example.com"93result = model(prompt, User, max_new_tokens=200)94 95user = User.model_validate_json(result) # parse into the Pydantic model96print(user.name) # "John Doe"97print(user.age) # 3098print(user.email) # "john@example.com"99```100 101## Core Concepts102 103### 1. Constrained Token Sampling104 105Outlines constrains token generation at the logit level using a compiled106automaton derived from your output type.107 108**How it works:**1091. Convert the output type (JSON/Pydantic/regex/`Literal`) to a schema/grammar1102. Compile the grammar into a token-level automaton1113. Filter invalid tokens at each step during generation1124. Fast-forward when only one valid token exists113 114**Benefits:**115- **Zero overhead**: Filtering happens at token level116- **Speed improvement**: Fast-forward through deterministic paths117- **Guaranteed validity**: Invalid outputs impossible118 119```python120import outlines121from pydantic import BaseModel122from transformers import AutoModelForCausalLM, AutoTokenizer123 124class Person(BaseModel):125 name: str126 age: int127 128model = outlines.from_transformers(129 AutoModelForCausalLM.from_pretrained("microsoft/Phi-3-mini-4k-instruct", device_map="auto"),130 AutoTokenizer.from_pretrained("microsoft/Phi-3-mini-4k-instruct"),131)132 133result = model("Generate person: Alice, 25", Person)134person = Person.model_validate_json(result)135```136 137### 2. Output Types138 139In v1 you pass the desired **output type** directly as the second argument.140 141#### Multiple choice (`Literal`)142 143```python144from typing import Literal145 146sentiment = model("Review: This is great!", Literal["positive", "negative", "neutral"])147# Result: one of the three choices148```149 150#### JSON via Pydantic151 152```python153from pydantic import BaseModel154 155class Product(BaseModel):156 name: str157 price: float158 in_stock: bool159 160result = model("Extract: iPhone 15, $999, available", Product)161product = Product.model_validate_json(result) # valid Product instance162```163 164#### Regex (pass a regex string)165 166```python167# Generate text matching a regex pattern168phone = model("Generate phone number:", r"[0-9]{3}-[0-9]{3}-[0-9]{4}")169# Result: "555-123-4567" (guaranteed to match the pattern)170```171 172#### Numeric types173 174```python175# Pass the Python type directly176age = model("Person's age:", int) # guaranteed integer177price = model("Product price:", float) # guaranteed float178```179 180### 3. Model Backends181 182Outlines supports multiple local and API-based backends via `from_*` factories.183 184#### Transformers (Hugging Face)185 186```python187import outlines188from transformers import AutoModelForCausalLM, AutoTokenizer189 190model = outlines.from_transformers(191 AutoModelForCausalLM.from_pretrained("microsoft/Phi-3-mini-4k-instruct", device_map="auto"),192 AutoTokenizer.from_pretrained("microsoft/Phi-3-mini-4k-instruct"),193)194 195result = model(prompt, YourModel)196```197 198#### llama.cpp199 200```python201import outlines202from llama_cpp import Llama203 204llm = Llama("./models/llama-3.1-8b-instruct.Q4_K_M.gguf", n_gpu_layers=35, n_ctx=4096)205model = outlines.from_llamacpp(llm)206 207result = model(prompt, YourModel)208```209 210#### vLLM (High Throughput)211 212```python213import outlines214from vllm import LLM215 216llm = LLM("meta-llama/Llama-3.1-8B-Instruct", tensor_parallel_size=2)217model = outlines.from_vllm(llm)218 219result = model(prompt, YourModel)220```221 222#### OpenAI (server-side constrained JSON)223 224```python225import outlines226from openai import OpenAI227 228client = OpenAI()229model = outlines.from_openai(client, "gpt-4o-mini")230 231# API backends support JSON-schema style structured output232result = model(prompt, YourModel)233```234 235### 4. Pydantic Integration236 237Outlines has first-class Pydantic support with automatic schema translation.238Generation returns a JSON string; call `model_validate_json` to get an instance.239 240#### Basic Models241 242```python243from pydantic import BaseModel, Field244 245class Article(BaseModel):246 title: str = Field(description="Article title")247 author: str = Field(description="Author name")248 word_count: int = Field(description="Number of words", gt=0)249 tags: list[str] = Field(description="List of tags")250 251result = model("Generate article about AI", Article, max_new_tokens=300)252article = Article.model_validate_json(result)253print(article.title)254print(article.word_count) # Guaranteed > 0255```256 257#### Nested Models258 259```python260class Address(BaseModel):261 street: str262 city: str263 country: str264 265class Person(BaseModel):266 name: str267 age: int268 address: Address # Nested model269 270result = model("Generate person in New York", Person)271person = Person.model_validate_json(result)272print(person.address.city) # "New York"273```274 275#### Enums and Literals276 277```python278from enum import Enum279from typing import Literal280 281class Status(str, Enum):282 PENDING = "pending"283 APPROVED = "approved"284 REJECTED = "rejected"285 286class Application(BaseModel):287 applicant: str288 status: Status # Must be one of enum values289 priority: Literal["low", "medium", "high"] # Must be one of literals290 291result = model("Generate application", Application)292app = Application.model_validate_json(result)293print(app.status) # Status.PENDING (or APPROVED/REJECTED)294```295 296## Common Patterns297 298### Pattern 1: Data Extraction299 300```python301from pydantic import BaseModel302import outlines303from transformers import AutoModelForCausalLM, AutoTokenizer304 305class CompanyInfo(BaseModel):306 name: str307 founded_year: int308 industry: str309 employees: int310 311model = outlines.from_transformers(312 AutoModelForCausalLM.from_pretrained("microsoft/Phi-3-mini-4k-instruct", device_map="auto"),313 AutoTokenizer.from_pretrained("microsoft/Phi-3-mini-4k-instruct"),314)315 316text = """317Apple Inc. was founded in 1976 in the technology industry.318The company employs approximately 164,000 people worldwide.319"""320 321prompt = f"Extract company information:\n{text}\n\nCompany:"322company = CompanyInfo.model_validate_json(model(prompt, CompanyInfo, max_new_tokens=200))323 324print(f"Name: {company.name}")325print(f"Founded: {company.founded_year}")326print(f"Industry: {company.industry}")327print(f"Employees: {company.employees}")328```329 330### Pattern 2: Classification331 332```python333from typing import Literal334from pydantic import BaseModel335 336# Binary classification337result = model("Email: Buy now! 50% off!", Literal["spam", "not_spam"])338 339# Multi-class classification340category = model(341 "Article: Apple announces new iPhone...",342 Literal["technology", "business", "sports", "entertainment"],343)344 345# With confidence346class Classification(BaseModel):347 label: Literal["positive", "negative", "neutral"]348 confidence: float349 350out = model("Review: This product is okay, nothing special", Classification)351result = Classification.model_validate_json(out)352```353 354### Pattern 3: Structured Forms355 356```python357class UserProfile(BaseModel):358 full_name: str359 age: int360 email: str361 phone: str362 country: str363 interests: list[str]364 365prompt = """366Extract user profile from:367Name: Alice Johnson368Age: 28369Email: alice@example.com370Phone: 555-0123371Country: USA372Interests: hiking, photography, cooking373"""374 375profile = UserProfile.model_validate_json(model(prompt, UserProfile, max_new_tokens=250))376print(profile.full_name)377print(profile.interests) # ["hiking", "photography", "cooking"]378```379 380### Pattern 4: Multi-Entity Extraction381 382```python383from typing import Literal384 385class Entity(BaseModel):386 name: str387 type: Literal["PERSON", "ORGANIZATION", "LOCATION"]388 389class DocumentEntities(BaseModel):390 entities: list[Entity]391 392text = "Tim Cook met with Satya Nadella at Microsoft headquarters in Redmond."393prompt = f"Extract entities from: {text}"394 395result = DocumentEntities.model_validate_json(model(prompt, DocumentEntities, max_new_tokens=300))396for entity in result.entities:397 print(f"{entity.name} ({entity.type})")398```399 400### Pattern 5: Code Generation401 402```python403class PythonFunction(BaseModel):404 function_name: str405 parameters: list[str]406 docstring: str407 body: str408 409prompt = "Generate a Python function to calculate factorial"410func = PythonFunction.model_validate_json(model(prompt, PythonFunction, max_new_tokens=300))411 412print(f"def {func.function_name}({', '.join(func.parameters)}):")413print(f' """{func.docstring}"""')414print(f" {func.body}")415```416 417### Pattern 6: Batch Processing418 419```python420import outlines421from transformers import AutoModelForCausalLM, AutoTokenizer422from pydantic import BaseModel423 424class Person(BaseModel):425 name: str426 age: int427 428model = outlines.from_transformers(429 AutoModelForCausalLM.from_pretrained("microsoft/Phi-3-mini-4k-instruct", device_map="auto"),430 AutoTokenizer.from_pretrained("microsoft/Phi-3-mini-4k-instruct"),431)432 433texts = [434 "John is 30 years old",435 "Alice is 25 years old",436 "Bob is 40 years old",437]438 439# v1 accepts a list of prompts for batched generation440prompts = [f"Extract from: {t}" for t in texts]441outputs = model(prompts, Person, max_new_tokens=100)442people = [Person.model_validate_json(o) for o in outputs]443for person in people:444 print(f"{person.name}: {person.age}")445```446 447## Backend Configuration448 449### Transformers450 451```python452import outlines453from transformers import AutoModelForCausalLM, AutoTokenizer454 455MODEL_NAME = "microsoft/Phi-3-mini-4k-instruct"456 457# Basic usage458model = outlines.from_transformers(459 AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="auto"),460 AutoTokenizer.from_pretrained(MODEL_NAME),461)462 463# GPU + dtype configuration is set on the HF model itself464import torch465model = outlines.from_transformers(466 AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="cuda", torch_dtype=torch.float16),467 AutoTokenizer.from_pretrained(MODEL_NAME),468)469 470# Popular models471for name in [472 "meta-llama/Llama-3.1-8B-Instruct",473 "mistralai/Mistral-7B-Instruct-v0.3",474 "Qwen/Qwen2.5-7B-Instruct",475]:476 model = outlines.from_transformers(477 AutoModelForCausalLM.from_pretrained(name, device_map="auto"),478 AutoTokenizer.from_pretrained(name),479 )480```481 482### llama.cpp483 484```python485import outlines486from llama_cpp import Llama487 488# Load GGUF model489llm = Llama(490 "./models/llama-3.1-8b.Q4_K_M.gguf",491 n_ctx=4096, # Context window492 n_gpu_layers=35, # GPU layers493 n_threads=8, # CPU threads494)495model = outlines.from_llamacpp(llm)496 497# Full GPU offload: set n_gpu_layers=-1 on the Llama object498```499 500### vLLM (Production)501 502```python503import outlines504from vllm import LLM505 506# Single GPU507model = outlines.from_vllm(LLM("meta-llama/Llama-3.1-8B-Instruct"))508 509# Multi-GPU510model = outlines.from_vllm(LLM("meta-llama/Llama-3.1-70B-Instruct", tensor_parallel_size=4))511 512# With quantization513model = outlines.from_vllm(LLM("meta-llama/Llama-3.1-8B-Instruct", quantization="awq"))514```515 516## Best Practices517 518### 1. Use Specific Types519 520```python521# ✅ Good: Specific types522class Product(BaseModel):523 name: str524 price: float # Not str525 quantity: int # Not str526 in_stock: bool # Not str527 528# ❌ Bad: Everything as string529class Product(BaseModel):530 name: str531 price: str # Should be float532 quantity: str # Should be int533```534 535### 2. Add Constraints536 537```python538from pydantic import Field539 540# ✅ Good: With constraints541class User(BaseModel):542 name: str = Field(min_length=1, max_length=100)543 age: int = Field(ge=0, le=120)544 email: str = Field(pattern=r"^[\w\.-]+@[\w\.-]+\.\w+$")545 546# ❌ Bad: No constraints547class User(BaseModel):548 name: str549 age: int550 email: str551```552 553### 3. Use Enums for Categories554 555```python556# ✅ Good: Enum for fixed set557class Priority(str, Enum):558 LOW = "low"559 MEDIUM = "medium"560 HIGH = "high"561 562class Task(BaseModel):563 title: str564 priority: Priority565 566# ❌ Bad: Free-form string567class Task(BaseModel):568 title: str569 priority: str # Can be anything570```571 572### 4. Provide Context in Prompts573 574```python575# ✅ Good: Clear context576prompt = """577Extract product information from the following text.578Text: iPhone 15 Pro costs $999 and is currently in stock.579Product:580"""581 582# ❌ Bad: Minimal context583prompt = "iPhone 15 Pro costs $999 and is currently in stock."584```585 586### 5. Handle Optional Fields587 588```python589from typing import Optional590 591# ✅ Good: Optional fields for incomplete data592class Article(BaseModel):593 title: str # Required594 author: Optional[str] = None # Optional595 date: Optional[str] = None # Optional596 tags: list[str] = [] # Default empty list597 598# Can succeed even if author/date missing599```600 601### 6. Always Validate JSON Output602 603```python604# v1 returns a JSON string for Pydantic/JSON output types.605result = model(prompt, Article) # str606article = Article.model_validate_json(result) # Article instance607```608 609## Comparison to Alternatives610 611| Feature | Outlines | Instructor | Guidance | LMQL |612|---------|----------|------------|----------|------|613| Pydantic Support | ✅ Native | ✅ Native | ✅ Yes | ❌ No |614| JSON Schema | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |615| Regex Constraints | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |616| Local Models | ✅ Full | ⚠️ Limited | ✅ Full | ✅ Full |617| API Models | ✅ Yes | ✅ Full | ✅ Yes | ✅ Full |618| Zero Overhead | ✅ Yes | ❌ No | ⚠️ Partial | ✅ Yes |619| Automatic Retrying | ❌ No | ✅ Yes | ❌ No | ❌ No |620| Learning Curve | Low | Low | Low | High |621 622**When to choose Outlines:**623- Using local models (Transformers, llama.cpp, vLLM)624- Need maximum inference speed625- Want Pydantic model support626- Require zero-overhead structured generation627- Control token sampling process628 629**When to choose alternatives:**630- Instructor: Need API models with automatic retrying631- Guidance: Need token healing and complex workflows632- LMQL: Prefer declarative query syntax633 634## Performance Characteristics635 636**Speed:**637- **Zero overhead**: Structured generation as fast as unconstrained638- **Fast-forward optimization**: Skips deterministic tokens639- **1.2-2x faster** than post-generation validation approaches640 641**Memory:**642- Automaton compiled once per output type (cached)643- Minimal runtime overhead644- Efficient with vLLM for high throughput645 646**Accuracy:**647- **100% valid outputs** (guaranteed by the constrained automaton)648- No retry loops needed649- Deterministic token filtering650 651## Resources652 653- **Documentation**: https://dottxt-ai.github.io/outlines/654- **GitHub**: https://github.com/dottxt-ai/outlines (12k+ stars)655- **Discord**: https://discord.gg/R9DSu34mGd656- **Blog**: https://blog.dottxt.co657 658## See Also659 660- `references/json_generation.md` - Comprehensive JSON and Pydantic patterns661- `references/backends.md` - Backend-specific configuration662- `references/examples.md` - Production-ready examples663 Discovery context
Discovered by repository scan. No exact path reference found in the snapshot’s root AGENTS.md.