Structured Output từ LLM: Enforce JSON Schema với Instructor, Outlines, Pydantic

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.
Sơ đồ kiến trúc structured output pipeline từ LLM sang application code
Structured output pipeline: từ LLM sang application code

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 API giữa Instructor, Outlines, và Pydantic AI cho structured output
So sánh API structured output libraries

So sánh nhanh

Tiêu chí Instructor Outlines Pydantic AI
Constrained decoding Không Không
Streaming
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

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

Structured Output từ LLM: Enforce JSON Schema với Instructor, Outlines, Pydantic

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….

Xem thêm

LLM Observability: Cách giám sát và quản lý chất lượng AI sinh văn bản

LLM Observability là gì và tại sao quan trọng Khi triển khai LLM vào production, bạn không thể chỉ đoạn thời gian chạy (latency) hay tỷ lệ lỗi (error rate)….

Xem thêm

ONNX Runtime: Triển khai mô hình AI đa nền tảng hiệu năng cao

Khi bạn train một mô hình AI trên GPU và deploy lên thiết bị biên (edge), bạn thường mắc kẹt giữa hàng loạt định dạng model: PyTorch, TensorFlow, ONNX, TensorRT,…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất