Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Guarantee valid JSON/XML/code structure during generation, use Pydantic models for type-safe outputs, support local models (Transformers, vLLM), and maximize inference speed with Outlines - dottxt.ai's structured generation library
.claude/skills/graniet-outlines/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-09 | ✗→✓ | ▲ Improved | 225% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 242% | 0% |
| case-20 | ✓→✓ | = Same ✓ | 113% | 0% |
| case-18 | ✓→✓ | = Same ✓ | 150% | 0% |
| case-19 | ✓→✓ | = Same ✓ | 176% | 0% |
This skill is repo-local and stays inactive until explicitly activated.
When the original instructions refer to legacy tool names, use these Kheish mappings:
terminal => bashweb_extract => web_fetch, plus web_search when discovery is neededsearch_files => grep_search and glob_searchbrowser_* tools require a browser-capable surfaced tool or MCP; if none is available, use the closest available surface and say so explicitlyWhen the instructions mention local helper files, resolve them from ${KHEISH_SKILL_DIR}.
Use Outlines when you need to:
GitHub Stars: 8,000+ | From: dottxt.ai (formerly .txt)
bash# Base installation pip install outlines # With specific backends pip install outlines transformers # Hugging Face models pip install outlines llama-cpp-python # llama.cpp pip install outlines vllm # vLLM for high-throughput
pythonimport outlines from typing import Literal # Load model model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") # Generate with type constraint prompt = "Sentiment of 'This product is amazing!': " generator = outlines.generate.choice(model, ["positive", "negative", "neutral"]) sentiment = generator(prompt) print(sentiment) # "positive" (guaranteed one of these)
pythonfrom pydantic import BaseModel import outlines class User(BaseModel): name: str age: int email: str model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") # Generate structured output prompt = "Extract user: John Doe, 30 years old, john@example.com" generator = outlines.generate.json(model, User) user = generator(prompt) print(user.name) # "John Doe" print(user.age) # 30 print(user.email) # "john@example.com"
Outlines uses Finite State Machines (FSM) to constrain token generation at the logit level.
How it works:
Benefits:
pythonimport outlines # Pydantic model -> JSON schema -> CFG -> FSM class Person(BaseModel): name: str age: int model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") # Behind the scenes: # 1. Person -> JSON schema # 2. JSON schema -> CFG # 3. CFG -> FSM # 4. FSM filters tokens during generation generator = outlines.generate.json(model, Person) result = generator("Generate person: Alice, 25")
Outlines provides specialized generators for different output types.
python# Multiple choice selection generator = outlines.generate.choice( model, ["positive", "negative", "neutral"] ) sentiment = generator("Review: This is great!") # Result: One of the three choices
pythonfrom pydantic import BaseModel class Product(BaseModel): name: str price: float in_stock: bool # Generate valid JSON matching schema generator = outlines.generate.json(model, Product) product = generator("Extract: iPhone 15, $999, available") # Guaranteed valid Product instance print(type(product)) # <class '__main__.Product'>
python# Generate text matching regex generator = outlines.generate.regex( model, r"[0-9]{3}-[0-9]{3}-[0-9]{4}" # Phone number pattern ) phone = generator("Generate phone number:") # Result: "555-123-4567" (guaranteed to match pattern)
python# Generate specific numeric types int_generator = outlines.generate.integer(model) age = int_generator("Person's age:") # Guaranteed integer float_generator = outlines.generate.float(model) price = float_generator("Product price:") # Guaranteed float
Outlines supports multiple local and API-based backends.
pythonimport outlines # Load from Hugging Face model = outlines.models.transformers( "microsoft/Phi-3-mini-4k-instruct", device="cuda" # Or "cpu" ) # Use with any generator generator = outlines.generate.json(model, YourModel)
python# Load GGUF model model = outlines.models.llamacpp( "./models/llama-3.1-8b-instruct.Q4_K_M.gguf", n_gpu_layers=35 ) generator = outlines.generate.json(model, YourModel)
python# For production deployments model = outlines.models.vllm( "meta-llama/Llama-3.1-8B-Instruct", tensor_parallel_size=2 # Multi-GPU ) generator = outlines.generate.json(model, YourModel)
python# Basic OpenAI support model = outlines.models.openai( "gpt-4o-mini", api_key="your-api-key" ) # Note: Some features limited with API models generator = outlines.generate.json(model, YourModel)
Outlines has first-class Pydantic support with automatic schema translation.
pythonfrom 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 tags") model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") generator = outlines.generate.json(model, Article) article = generator("Generate article about AI") print(article.title) print(article.word_count) # Guaranteed > 0
pythonclass Address(BaseModel): street: str city: str country: str class Person(BaseModel): name: str age: int address: Address # Nested model generator = outlines.generate.json(model, Person) person = generator("Generate person in New York") print(person.address.city) # "New York"
pythonfrom enum import Enum from typing import Literal class Status(str, Enum): PENDING = "pending" APPROVED = "approved" REJECTED = "rejected" class Application(BaseModel): applicant: str status: Status # Must be one of enum values priority: Literal["low", "medium", "high"] # Must be one of literals generator = outlines.generate.json(model, Application) app = generator("Generate application") print(app.status) # Status.PENDING (or APPROVED/REJECTED)
pythonfrom pydantic import BaseModel import outlines class CompanyInfo(BaseModel): name: str founded_year: int industry: str employees: int model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") generator = outlines.generate.json(model, CompanyInfo) text = """ Apple Inc. was founded in 1976 in the technology industry. The company employs approximately 164,000 people worldwide. """ prompt = f"Extract company information:\n{text}\n\nCompany:" company = generator(prompt) print(f"Name: {company.name}") print(f"Founded: {company.founded_year}") print(f"Industry: {company.industry}") print(f"Employees: {company.employees}")
pythonfrom typing import Literal import outlines model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") # Binary classification generator = outlines.generate.choice(model, ["spam", "not_spam"]) result = generator("Email: Buy now! 50% off!") # Multi-class classification categories = ["technology", "business", "sports", "entertainment"] category_gen = outlines.generate.choice(model, categories) category = category_gen("Article: Apple announces new iPhone...") # With confidence class Classification(BaseModel): label: Literal["positive", "negative", "neutral"] confidence: float classifier = outlines.generate.json(model, Classification) result = classifier("Review: This product is okay, nothing special")
pythonclass UserProfile(BaseModel): full_name: str age: int email: str phone: str country: str interests: list[str] model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") generator = outlines.generate.json(model, UserProfile) prompt = """ Extract user profile from: Name: Alice Johnson Age: 28 Email: alice@example.com Phone: 555-0123 Country: USA Interests: hiking, photography, cooking """ profile = generator(prompt) print(profile.full_name) print(profile.interests) # ["hiking", "photography", "cooking"]
pythonclass Entity(BaseModel): name: str type: Literal["PERSON", "ORGANIZATION", "LOCATION"] class DocumentEntities(BaseModel): entities: list[Entity] model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") generator = outlines.generate.json(model, DocumentEntities) text = "Tim Cook met with Satya Nadella at Microsoft headquarters in Redmond." prompt = f"Extract entities from: {text}" result = generator(prompt) for entity in result.entities: print(f"{entity.name} ({entity.type})")
pythonclass PythonFunction(BaseModel): function_name: str parameters: list[str] docstring: str body: str model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") generator = outlines.generate.json(model, PythonFunction) prompt = "Generate a Python function to calculate factorial" func = generator(prompt) print(f"def {func.function_name}({', '.join(func.parameters)}):") print(f' """{func.docstring}"""') print(f" {func.body}")
pythondef batch_extract(texts: list[str], schema: type[BaseModel]): """Extract structured data from multiple texts.""" model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") generator = outlines.generate.json(model, schema) results = [] for text in texts: result = generator(f"Extract from: {text}") results.append(result) return results class Person(BaseModel): name: str age: int texts = [ "John is 30 years old", "Alice is 25 years old", "Bob is 40 years old" ] people = batch_extract(texts, Person) for person in people: print(f"{person.name}: {person.age}")
pythonimport outlines # Basic usage model = outlines.models.transformers("microsoft/Phi-3-mini-4k-instruct") # GPU configuration model = outlines.models.transformers( "microsoft/Phi-3-mini-4k-instruct", device="cuda", model_kwargs={"torch_dtype": "float16"} ) # Popular models model = outlines.models.transformers("meta-llama/Llama-3.1-8B-Instruct") model = outlines.models.transformers("mistralai/Mistral-7B-Instruct-v0.3") model = outlines.models.transformers("Qwen/Qwen2.5-7B-Instruct")
python# Load GGUF model model = outlines.models.llamacpp( "./models/llama-3.1-8b.Q4_K_M.gguf", n_ctx=4096, # Context window n_gpu_layers=35, # GPU layers n_threads=8 # CPU threads ) # Full GPU offload model = outlines.models.llamacpp( "./models/model.gguf", n_gpu_layers=-1 # All layers on GPU )
python# Single GPU model = outlines.models.vllm("meta-llama/Llama-3.1-8B-Instruct") # Multi-GPU model = outlines.models.vllm( "meta-llama/Llama-3.1-70B-Instruct", tensor_parallel_size=4 # 4 GPUs ) # With quantization model = outlines.models.vllm( "meta-llama/Llama-3.1-8B-Instruct", quantization="awq" # Or "gptq" )
python# ✅ Good: Specific types class Product(BaseModel): name: str price: float # Not str quantity: int # Not str in_stock: bool # Not str # ❌ Bad: Everything as string class Product(BaseModel): name: str price: str # Should be float quantity: str # Should be int
pythonfrom pydantic import Field # ✅ Good: With constraints class User(BaseModel): name: str = Field(min_length=1, max_length=100) age: int = Field(ge=0, le=120) email: str = Field(pattern=r"^[\w\.-]+@[\w\.-]+\.\w+$") # ❌ Bad: No constraints class User(BaseModel): name: str age: int email: str
python# ✅ Good: Enum for fixed set class Priority(str, Enum): LOW = "low" MEDIUM = "medium" HIGH = "high" class Task(BaseModel): title: str priority: Priority # ❌ Bad: Free-form string class Task(BaseModel): title: str priority: str # Can be anything
python# ✅ Good: Clear context prompt = """ Extract product information from the following text. Text: iPhone 15 Pro costs $999 and is currently in stock. Product: """ # ❌ Bad: Minimal context prompt = "iPhone 15 Pro costs $999 and is currently in stock."
pythonfrom typing import Optional # ✅ Good: Optional fields for incomplete data class Article(BaseModel): title: str # Required author: Optional[str] = None # Optional date: Optional[str] = None # Optional tags: list[str] = [] # Default empty list # Can succeed even if author/date missing
| Feature | Outlines | Instructor | Guidance | LMQL | |---------|----------|------------|----------|------| | Pydantic Support | ✅ Native | ✅ Native | ❌ No | ❌ No | | JSON Schema | ✅ Yes | ✅ Yes | ⚠️ Limited | ✅ Yes | | Regex Constraints | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes | | Local Models | ✅ Full | ⚠️ Limited | ✅ Full | ✅ Full | | API Models | ⚠️ Limited | ✅ Full | ✅ Full | ✅ Full | | Zero Overhead | ✅ Yes | ❌ No | ⚠️ Partial | ✅ Yes | | Automatic Retrying | ❌ No | ✅ Yes | ❌ No | ❌ No | | Learning Curve | Low | Low | Low | High |
When to choose Outlines:
When to choose alternatives:
Speed:
Memory:
Accuracy:
references/json_generation.md - Comprehensive JSON and Pydantic patternsreferences/backends.md - Backend-specific configurationreferences/examples.md - Production-ready examples| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-20 | pass→pass | 12,905 | 4,964 | -62% | 1 | 1 | 0% | 2,584 | 5,513 | +113% | 0 | 0 | — |
case-18 | pass→pass | 13,971 | 6,979 | -50% | 1 | 1 | 0% | 2,290 | 5,726 | +150% | 0 | 0 | — |
case-19 | pass→pass | 13,553 | 7,916 | -42% | 1 | 1 | 0% | 2,108 | 5,821 | +176% | 0 | 0 | — |
case-01 | pass→pass | 8,452 | 8,549 | +1% | 1 | 1 | 0% | 1,432 | 5,300 | +270% | 0 | 0 | — |
case-02 | pass→pass | 17,967 | 7,644 | -57% | 1 | 1 | 0% | 2,853 | 5,685 | +99% | 0 | 0 | — |
case-03 | pass→pass | 11,480 | 7,342 | -36% | 1 | 1 | 0% | 2,011 | 5,740 | +185% | 0 | 0 | — |
case-04 | pass→pass | 12,396 | 8,223 | -34% | 1 | 1 | 0% | 2,251 | 5,882 | +161% | 0 | 0 | — |
case-05 | pass→pass | 8,661 | 4,888 | -44% | 1 | 1 | 0% | 1,564 | 5,551 | +255% | 0 | 0 | — |
case-06 | pass→pass | 6,670 | 3,379 | -49% | 1 | 1 | 0% | 1,251 | 5,136 | +311% | 0 | 0 | — |
case-07 | pass→pass | 12,388 | 9,331 | -25% | 1 | 1 | 0% | 2,421 | 6,400 | +164% | 0 | 0 | — |
case-08 | pass→pass | 6,800 | 5,249 | -23% | 1 | 1 | 0% | 1,240 | 5,525 | +346% | 0 | 0 | — |
case-09 | fail→pass | 10,361 | 6,485 | -37% | 1 | 1 | 0% | 1,779 | 5,782 | +225% | 0 | 0 | — |
case-10 | pass→pass | 9,642 | 3,518 | -64% | 1 | 1 | 0% | 1,777 | 5,200 | +193% | 0 | 0 | — |
case-11 | pass→pass | 7,763 | 4,978 | -36% | 1 | 1 | 0% | 1,512 | 5,469 | +262% | 0 | 0 | — |
case-12 | pass→pass | 16,777 | 9,211 | -45% | 1 | 1 | 0% | 3,087 | 6,319 | +105% | 0 | 0 | — |
case-13 | pass→pass | 10,007 | 5,633 | -44% | 1 | 1 | 0% | 2,005 | 5,563 | +177% | 0 | 0 | — |
case-14 | fail→pass | 8,215 | 4,809 | -41% | 1 | 1 | 0% | 1,598 | 5,460 | +242% | 0 | 0 | — |
case-15 | pass→pass | 3,737 | 2,434 | -35% | 1 | 1 | 0% | 666 | 4,973 | +647% | 0 | 0 | — |
case-16 | pass→pass | 10,427 | 7,131 | -32% | 1 | 1 | 0% | 1,972 | 5,955 | +202% | 0 | 0 | — |
case-17 | pass→pass | 8,843 | 4,700 | -47% | 1 | 1 | 0% | 1,733 | 5,298 | +206% | 0 | 0 | — |
case-21 | pass→pass | 7,144 | 5,749 | -20% | 1 | 1 | 0% | 1,397 | 5,682 | +307% | 0 | 0 | — |
case-22 | pass→pass | 8,953 | 3,998 | -55% | 1 | 1 | 0% | 1,503 | 5,348 | +256% | 0 | 0 | — |
case-23 | pass→pass | 11,998 | 6,551 | -45% | 1 | 1 | 0% | 1,994 | 5,614 | +182% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +9 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.