SKILL.md
SKILL.mdBrowse 4 files
4,094 tokens
15,280 bytes
Token encoding: o200k_base
Snapshot 24fd22b
1---2name: guidance3description: Constrain LLM output with grammars; guarantee valid JSON.4version: 1.0.15author: Orchestra Research6license: MIT7dependencies: [guidance, transformers]8platforms: [linux, macos, windows]9metadata:10 hermes:11 tags: [Prompt Engineering, Guidance, Constrained Generation, Structured Output, JSON Validation, Grammar, Microsoft Research, Format Enforcement, Multi-Step Workflows]12 13---14 15# Guidance: Constrained LLM Generation16 17## When to Use This Skill18 19Use Guidance when you need to:20- **Control LLM output syntax** with regex or grammars21- **Guarantee valid JSON/XML/code** generation22- **Reduce latency** vs traditional prompting approaches23- **Enforce structured formats** (dates, emails, IDs, etc.)24- **Build multi-step workflows** with Pythonic control flow25- **Prevent invalid outputs** through grammatical constraints26 27**GitHub Stars**: 18,000+ | **From**: Microsoft Research28 29## Installation30 31```bash32# Base installation33pip install guidance34 35# With specific backends36pip install guidance[transformers] # Hugging Face models37pip install guidance[llama_cpp] # llama.cpp models38```39 40## Quick Start41 42### Basic Example: Structured Generation43 44```python45from guidance import models, gen46 47# Load model (supports OpenAI, Transformers, llama.cpp)48lm = models.OpenAI("gpt-4")49 50# Generate with constraints51result = lm + "The capital of France is " + gen("capital", max_tokens=5)52 53print(result["capital"]) # "Paris"54```55 56### Chat format with a local model57 58> **Constraint support requires local logit access.** Regex, `select()`, and59> grammar-based constrained generation only work with local backends60> (`Transformers`, `LlamaCpp`). Remote API backends (`OpenAI`, and Azure61> variants) support unconstrained `gen()` / chat only — they cannot enforce62> token-level constraints. guidance 0.3.x has no `models.Anthropic` class.63 64```python65from guidance import models, gen, system, user, assistant66 67# Local model (supports constrained generation)68lm = models.Transformers("microsoft/Phi-4-mini-instruct")69 70# Use context managers for chat format71with system():72 lm += "You are a helpful assistant."73 74with user():75 lm += "What is the capital of France?"76 77with assistant():78 lm += gen(max_tokens=20)79```80 81## Core Concepts82 83### 1. Context Managers84 85Guidance uses Pythonic context managers for chat-style interactions.86 87```python88from guidance import system, user, assistant, gen89 90lm = models.Transformers("microsoft/Phi-4-mini-instruct")91 92# System message93with system():94 lm += "You are a JSON generation expert."95 96# User message97with user():98 lm += "Generate a person object with name and age."99 100# Assistant response101with assistant():102 lm += gen("response", max_tokens=100)103 104print(lm["response"])105```106 107**Benefits:**108- Natural chat flow109- Clear role separation110- Easy to read and maintain111 112### 2. Constrained Generation113 114Guidance ensures outputs match specified patterns using regex or grammars.115 116#### Regex Constraints117 118```python119from guidance import models, gen120 121lm = models.Transformers("microsoft/Phi-4-mini-instruct")122 123# Constrain to valid email format124lm += "Email: " + gen("email", regex=r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")125 126# Constrain to date format (YYYY-MM-DD)127lm += "Date: " + gen("date", regex=r"\d{4}-\d{2}-\d{2}")128 129# Constrain to phone number130lm += "Phone: " + gen("phone", regex=r"\d{3}-\d{3}-\d{4}")131 132print(lm["email"]) # Guaranteed valid email133print(lm["date"]) # Guaranteed YYYY-MM-DD format134```135 136**How it works:**137- Regex converted to grammar at token level138- Invalid tokens filtered during generation139- Model can only produce matching outputs140 141#### Selection Constraints142 143```python144from guidance import models, gen, select145 146lm = models.Transformers("microsoft/Phi-4-mini-instruct")147 148# Constrain to specific choices149lm += "Sentiment: " + select(["positive", "negative", "neutral"], name="sentiment")150 151# Multiple-choice selection152lm += "Best answer: " + select(153 ["A) Paris", "B) London", "C) Berlin", "D) Madrid"],154 name="answer"155)156 157print(lm["sentiment"]) # One of: positive, negative, neutral158print(lm["answer"]) # One of: A, B, C, or D159```160 161### 3. Token Healing162 163Guidance automatically "heals" token boundaries between prompt and generation.164 165**Problem:** Tokenization creates unnatural boundaries.166 167```python168# Without token healing169prompt = "The capital of France is "170# Last token: " is "171# First generated token might be " Par" (with leading space)172# Result: "The capital of France is Paris" (double space!)173```174 175**Solution:** Guidance backs up one token and regenerates.176 177```python178from guidance import models, gen179 180lm = models.Transformers("microsoft/Phi-4-mini-instruct")181 182# Token healing enabled by default183lm += "The capital of France is " + gen("capital", max_tokens=5)184# Result: "The capital of France is Paris" (correct spacing)185```186 187**Benefits:**188- Natural text boundaries189- No awkward spacing issues190- Better model performance (sees natural token sequences)191 192### 4. Grammar-Based Generation193 194Define complex structures by composing grammar functions. The template-string195`grammar=` form is not part of current guidance — build grammars from196composable functions, or use `guidance.json()` for JSON.197 198```python199from guidance import models, gen200from guidance import json as gen_json201from pydantic import BaseModel, Field202 203lm = models.Transformers("microsoft/Phi-4-mini-instruct")204 205# JSON via a Pydantic schema (guidance.json compiles the schema to a grammar)206class Person(BaseModel):207 name: str = Field(pattern=r"[A-Za-z ]+")208 age: int209 email: str = Field(pattern=r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")210 211lm += gen_json(name="person", schema=Person)212 213print(lm["person"]) # Guaranteed valid JSON matching the schema214 215# Or compose grammar functions directly:216grammar = "name=" + gen("name", regex=r"[A-Za-z ]+") + " age=" + gen("age", regex=r"[0-9]+")217lm += grammar218```219 220**Use cases:**221- Complex structured outputs222- Nested data structures223- Programming language syntax224- Domain-specific languages225 226### 5. Guidance Functions227 228Create reusable generation patterns with the `@guidance` decorator.229 230```python231from guidance import guidance, gen, models232 233@guidance234def generate_person(lm):235 """Generate a person with name and age."""236 lm += "Name: " + gen("name", max_tokens=20, stop="\n")237 lm += "\nAge: " + gen("age", regex=r"[0-9]+", max_tokens=3)238 return lm239 240# Use the function241lm = models.Transformers("microsoft/Phi-4-mini-instruct")242lm = generate_person(lm)243 244print(lm["name"])245print(lm["age"])246```247 248**Stateful Functions:**249 250```python251@guidance(stateless=False)252def react_agent(lm, question, tools, max_rounds=5):253 """ReAct agent with tool use."""254 lm += f"Question: {question}\n\n"255 256 for i in range(max_rounds):257 # Thought258 lm += f"Thought {i+1}: " + gen("thought", stop="\n")259 260 # Action261 lm += "\nAction: " + select(list(tools.keys()), name="action")262 263 # Execute tool264 tool_result = tools[lm["action"]]()265 lm += f"\nObservation: {tool_result}\n\n"266 267 # Check if done268 lm += "Done? " + select(["Yes", "No"], name="done")269 if lm["done"] == "Yes":270 break271 272 # Final answer273 lm += "\nFinal Answer: " + gen("answer", max_tokens=100)274 return lm275```276 277## Backend Configuration278 279### OpenAI (remote — unconstrained only)280 281> Remote API backends cannot do constrained generation (regex/select/grammar);282> use them only for plain chat/`gen()`. For constraints, use a local backend.283 284```python285from guidance import models286 287lm = models.OpenAI(288 model="gpt-4o-mini",289 api_key="your-api-key" # Or set OPENAI_API_KEY env var290)291```292 293### Local Models (Transformers)294 295```python296from guidance.models import Transformers297 298lm = Transformers(299 "microsoft/Phi-4-mini-instruct",300 device="cuda" # Or "cpu"301)302```303 304### Local Models (llama.cpp)305 306```python307from guidance.models import LlamaCpp308 309lm = LlamaCpp(310 model_path="/path/to/model.gguf",311 n_ctx=4096,312 n_gpu_layers=35313)314```315 316## Common Patterns317 318### Pattern 1: JSON Generation319 320```python321from guidance import models, gen, system, user, assistant322 323lm = models.Transformers("microsoft/Phi-4-mini-instruct")324 325with system():326 lm += "You generate valid JSON."327 328with user():329 lm += "Generate a user profile with name, age, and email."330 331with assistant():332 lm += """{333 "name": """ + gen("name", regex=r'"[A-Za-z ]+"', max_tokens=30) + """,334 "age": """ + gen("age", regex=r"[0-9]+", max_tokens=3) + """,335 "email": """ + gen("email", regex=r'"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"', max_tokens=50) + """336}"""337 338print(lm) # Valid JSON guaranteed339```340 341### Pattern 2: Classification342 343```python344from guidance import models, gen, select345 346lm = models.Transformers("microsoft/Phi-4-mini-instruct")347 348text = "This product is amazing! I love it."349 350lm += f"Text: {text}\n"351lm += "Sentiment: " + select(["positive", "negative", "neutral"], name="sentiment")352lm += "\nConfidence: " + gen("confidence", regex=r"[0-9]+", max_tokens=3) + "%"353 354print(f"Sentiment: {lm['sentiment']}")355print(f"Confidence: {lm['confidence']}%")356```357 358### Pattern 3: Multi-Step Reasoning359 360```python361from guidance import models, gen, guidance362 363@guidance364def chain_of_thought(lm, question):365 """Generate answer with step-by-step reasoning."""366 lm += f"Question: {question}\n\n"367 368 # Generate multiple reasoning steps369 for i in range(3):370 lm += f"Step {i+1}: " + gen(f"step_{i+1}", stop="\n", max_tokens=100) + "\n"371 372 # Final answer373 lm += "\nTherefore, the answer is: " + gen("answer", max_tokens=50)374 375 return lm376 377lm = models.Transformers("microsoft/Phi-4-mini-instruct")378lm = chain_of_thought(lm, "What is 15% of 200?")379 380print(lm["answer"])381```382 383### Pattern 4: ReAct Agent384 385```python386from guidance import models, gen, select, guidance387 388@guidance(stateless=False)389def react_agent(lm, question):390 """ReAct agent with tool use."""391 tools = {392 "calculator": lambda expr: eval(expr),393 "search": lambda query: f"Search results for: {query}",394 }395 396 lm += f"Question: {question}\n\n"397 398 for round in range(5):399 # Thought400 lm += f"Thought: " + gen("thought", stop="\n") + "\n"401 402 # Action selection403 lm += "Action: " + select(["calculator", "search", "answer"], name="action")404 405 if lm["action"] == "answer":406 lm += "\nFinal Answer: " + gen("answer", max_tokens=100)407 break408 409 # Action input410 lm += "\nAction Input: " + gen("action_input", stop="\n") + "\n"411 412 # Execute tool413 if lm["action"] in tools:414 result = tools[lm["action"]](lm["action_input"])415 lm += f"Observation: {result}\n\n"416 417 return lm418 419lm = models.Transformers("microsoft/Phi-4-mini-instruct")420lm = react_agent(lm, "What is 25 * 4 + 10?")421print(lm["answer"])422```423 424### Pattern 5: Data Extraction425 426```python427from guidance import models, gen, guidance428 429@guidance430def extract_entities(lm, text):431 """Extract structured entities from text."""432 lm += f"Text: {text}\n\n"433 434 # Extract person435 lm += "Person: " + gen("person", stop="\n", max_tokens=30) + "\n"436 437 # Extract organization438 lm += "Organization: " + gen("organization", stop="\n", max_tokens=30) + "\n"439 440 # Extract date441 lm += "Date: " + gen("date", regex=r"\d{4}-\d{2}-\d{2}", max_tokens=10) + "\n"442 443 # Extract location444 lm += "Location: " + gen("location", stop="\n", max_tokens=30) + "\n"445 446 return lm447 448text = "Tim Cook announced at Apple Park on 2024-09-15 in Cupertino."449 450lm = models.Transformers("microsoft/Phi-4-mini-instruct")451lm = extract_entities(lm, text)452 453print(f"Person: {lm['person']}")454print(f"Organization: {lm['organization']}")455print(f"Date: {lm['date']}")456print(f"Location: {lm['location']}")457```458 459## Best Practices460 461### 1. Use Regex for Format Validation462 463```python464# ✅ Good: Regex ensures valid format465lm += "Email: " + gen("email", regex=r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")466 467# ❌ Bad: Free generation may produce invalid emails468lm += "Email: " + gen("email", max_tokens=50)469```470 471### 2. Use select() for Fixed Categories472 473```python474# ✅ Good: Guaranteed valid category475lm += "Status: " + select(["pending", "approved", "rejected"], name="status")476 477# ❌ Bad: May generate typos or invalid values478lm += "Status: " + gen("status", max_tokens=20)479```480 481### 3. Leverage Token Healing482 483```python484# Token healing is enabled by default485# No special action needed - just concatenate naturally486lm += "The capital is " + gen("capital") # Automatic healing487```488 489### 4. Use stop Sequences490 491```python492# ✅ Good: Stop at newline for single-line outputs493lm += "Name: " + gen("name", stop="\n")494 495# ❌ Bad: May generate multiple lines496lm += "Name: " + gen("name", max_tokens=50)497```498 499### 5. Create Reusable Functions500 501```python502# ✅ Good: Reusable pattern503@guidance504def generate_person(lm):505 lm += "Name: " + gen("name", stop="\n")506 lm += "\nAge: " + gen("age", regex=r"[0-9]+")507 return lm508 509# Use multiple times510lm = generate_person(lm)511lm += "\n\n"512lm = generate_person(lm)513```514 515### 6. Balance Constraints516 517```python518# ✅ Good: Reasonable constraints519lm += gen("name", regex=r"[A-Za-z ]+", max_tokens=30)520 521# ❌ Too strict: May fail or be very slow522lm += gen("name", regex=r"^(John|Jane)$", max_tokens=10)523```524 525## Comparison to Alternatives526 527| Feature | Guidance | Instructor | Outlines | LMQL |528|---------|----------|------------|----------|------|529| Regex Constraints | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |530| Grammar Support | ✅ CFG | ❌ No | ✅ CFG | ✅ CFG |531| Pydantic Validation | ❌ No | ✅ Yes | ✅ Yes | ❌ No |532| Token Healing | ✅ Yes | ❌ No | ✅ Yes | ❌ No |533| Local Models | ✅ Yes | ⚠️ Limited | ✅ Yes | ✅ Yes |534| API Models | ✅ Yes | ✅ Yes | ⚠️ Limited | ✅ Yes |535| Pythonic Syntax | ✅ Yes | ✅ Yes | ✅ Yes | ❌ SQL-like |536| Learning Curve | Low | Low | Medium | High |537 538**When to choose Guidance:**539- Need regex/grammar constraints540- Want token healing541- Building complex workflows with control flow542- Using local models (Transformers, llama.cpp)543- Prefer Pythonic syntax544 545**When to choose alternatives:**546- Instructor: Need Pydantic validation with automatic retrying547- Outlines: Need JSON schema validation548- LMQL: Prefer declarative query syntax549 550## Performance Characteristics551 552**Latency Reduction:**553- 30-50% faster than traditional prompting for constrained outputs554- Token healing reduces unnecessary regeneration555- Grammar constraints prevent invalid token generation556 557**Memory Usage:**558- Minimal overhead vs unconstrained generation559- Grammar compilation cached after first use560- Efficient token filtering at inference time561 562**Token Efficiency:**563- Prevents wasted tokens on invalid outputs564- No need for retry loops565- Direct path to valid outputs566 567## Resources568 569- **Documentation**: https://guidance.readthedocs.io570- **GitHub**: https://github.com/guidance-ai/guidance (18k+ stars)571- **Notebooks**: https://github.com/guidance-ai/guidance/tree/main/notebooks572- **Discord**: Community support available573 574## See Also575 576- `references/constraints.md` - Comprehensive regex and grammar patterns577- `references/backends.md` - Backend-specific configuration578- `references/examples.md` - Production-ready examples579 580 581 Discovery context
Discovered by repository scan. No exact path reference found in the snapshot’s root AGENTS.md.