
Khi sử dụng LLM trong production, bạn không chỉ cần câu trả lời hay — bạn cần câu trả lời có cấu trúc, có kiểu, có thể chạy code tiếp. Việc parse free-text thành JSON thủ công đầy rủi ro: thiếu trường, sai kiểu, hallucination. Structured output giải quyết bằng cách ép LLM tuân thủ schema trước khi generate.
Tại sao structured output quan trọng?
Hầu hết ứng dụng AI thực tế đều cần output có cấu trúc: phân tích sentiment trả về JSON, chatbot gọi function, RAG trả về citation list, data pipeline chuyển LLM thành record database. Free-text generation vì thế chỉ phù hợp cho trải nghiệm người dùng cuối, không phải cho integration.
Ba thách thức chính khi làm việc với structured output:
- Schema compliance: LLM có thể bỏ trường, thừa trường, hoặc sai kiểu dù prompt rõ ràng.
- Type safety: Output cần match kiểu dữ liệu trong codebase (Pydantic, Zod, TypeScript interface).
- Latency & retry: Nếu output sai, bạn phải retry — tốn token, tăng chi phí, giảm trải nghiệm.

Ba thư viện chính cho structured output
Instructor (Python)
Thư viện của Jason Liu, xây dựng trên top của OpenAI, Anthropic, Google, Mistral APIs. Instructor wrap Pydantic model thành LLM response format, tự động retry nếu validation fail, hỗ trợ streaming partial objects.
import instructor
from pydantic import BaseModel
from openai import OpenAI
client = instructor.from_openai(OpenAI())
class User(BaseModel):
name: str
age: int
email: str | None = None
user = client.chat.completions.create(
model="gpt-4o",
response_model=User,
messages=[{"role": "user", "content": "Jason is 25, email [email protected]"}]
)
print(user.name, user.age) # Jason 25
Ưu điểm Instructor: auto-retry với validation error, streaming support, multi-provider. Nhược điểm: phụ thuộc Pydantic, chưa hỗ trợ tốt non-OpenAI provider.
Outlines (Python)
Thư viện của Dottie AI, sử dụng constrained decoding — ép LLM generate token theo regex hoặc JSON schema trực tiếp ở level logit, không phải post-process. Hỗ trợ llama.cpp, vLLM, transformers.
import outlines
from transformers import AutoTokenizer, AutoModelForCausalLM
model = outlines.models.transformers(
"microsoft/Phi-3-mini-4k-instruct",
device="cuda"
)
generator = outlines.generate.json(model, User)
user_json = generator("Jason is 25, email [email protected]")
print(user_json) # {"name": "Jason", "age": 25, "email": "[email protected]"}
Ưu điểm Outlines: constrained decoding không cần API trả về schema, hỗ trợ local models. Nhược điểm: cần hiểu biết về model internals, chưa ổn định với tất cả provider.
Pydantic AI (Python)
Pydantic AI — framework mới từ Pydantic team, tích hợp sẵn response validation, dependency injection, tool calling. So với Instructor, Pydantic AI có tool calling system mạnh hơn, phù hợp cho agentic workflows.
from pydantic_ai import Agent
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
agent = Agent('openai:gpt-4o', output_type=User)
result = agent.run_sync('Jason is 25')
print(result.output.name, result.output.age)

So sánh nhanh
| Tiêu chí | Instructor | Outlines | Pydantic AI |
|---|---|---|---|
| Constrained decoding | Không | Có | Không |
| Streaming | Có | Có | Có |
| Local models | Hạn chế | Tốt | Trung bình |
| Tool calling | Thủ công | Không | Tích hợp sẵn |
| Multi-provider | Tốt | Trung bình | Tốt |
TypeScript ecosystem: Zod + AI SDK
Nếu bạn dùng Next.js hoặc Node.js, Vercel AI SDK là lựa chọn hàng đầu. Kết hợp với Zod để define schema, AI SDK tự generate function call, parse result, retry nếu fail.
import { generateText } from 'ai';
import { z } from 'zod';
const result = await generateText({
model: openai('gpt-4o'),
prompt: 'Extract user info: Jason is 25, email [email protected]',
experimental_output: z.object({
name: z.string(),
age: z.number(),
email: z.string().email().optional()
})
});
console.log(result.experimental_output);
Best practices
- Pydantic/Zod model là source of truth: Không viết schema lặp lại ở prompt. Dùng một model cho cả validation và documentation.
- Đặt max_retries: LLM có thể fail 10-20% lần đầu với schema phức tạp. Đặt retry logic ngay từ đầu.
- Log raw response khi fail: Khi validation fail, log raw LLM output để debug — đôi khi model trả về kiểu khác schema (ví dụ: “25” string thay vì number).
- Dùng enum thay vì free text: Khi output có tập giá trị cố định, dùng Enum trong schema — giảm hallucination.
- Test với adversarial inputs: Cho LLM những input edge case: dài, ngắn, thiếu thông tin, có thông tin nhiễu. Kiểm tra retry behavior.
Kết luận
Structured output không còn là “nice-to-have” — nó là requirement khi đưa LLM vào production. Instructor phù hợp cho Python team cần multi-provider, Pydantic AI tốt nhất cho agentic workflows, Outlines dành cho local model. Với TypeScript, Vercel AI SDK + Zod là combination mạnh nhất hiện tại.
Nguồn tham khảo:
1. Instructor GitHub — thư viện structured output Python
2. Outlines GitHub — constrained decoding framework
3. Pydantic AI — type-safe LLM framework
4. Vercel AI SDK — TypeScript structured output
