
Đầu ra có cấu trúc của LLM là cơ chế đảm bảo phản hồi của mô hình ngôn ngữ tuân thủ một lược đồ được xác định trước, không chỉ là JSON hợp lệ, mà là JSON tuân thủ lược đồ với chính xác các trường, kiểu dữ liệu và ràng buộc mà bạn đã chỉ định. Mọi nhà cung cấp lớn hiện nay đều hỗ trợ tính năng này một cách native (tích hợp sẵn), và nó đã thay đổi cách các ứng dụng LLM trong môi trường production được xây dựng.
Tóm tắt nhanh: Đầu ra có cấu trúc trong nháy mắt
Nếu bạn không có nhiều thời gian, đây là bức tranh toàn cảnh vào năm 2026:
| Khía cạnh | Chi tiết |
|---|---|
| Nó là gì | Phản hồi từ LLM được ép buộc bởi lược đồ, cấu trúc được đảm bảo, không phải "cố gắng hết sức" |
| Ai hỗ trợ | OpenAI, Anthropic, Gemini, Cohere, xAI (Grok), plus local qua Ollama/vLLM |
| Cơ chế chính | Giải mã bị ràng buộc (constrained decoding), các token không hợp lệ bị loại bỏ trước khi lấy mẫu |
| JSON Mode vs Strict Mode | JSON Mode = chỉ đúng cú pháp. Strict Mode = tuân thủ đầy đủ lược đồ |
| Thư viện Python | Pydantic (BaseModel + Field) để định nghĩa lược đồ |
| Thư viện TypeScript | Zod (z.object + .describe) để định nghĩa lược đồ |
| Cách tiếp cận khởi đầu tốt nhất | OpenAI với Pydantic hoặc Zod qua SDK native |
| Thư viện production tốt nhất | Instructor (Python) hoặc SDK native (TypeScript) |
| Sai lầm lớn nhất | Đặt trường lập luận (reasoning) SAU trường câu trả lời, mô hình quyết định trước khi suy nghĩ |
| Độ trễ thêm vào | 50-200ms ở lần gọi đầu tiên (biên dịch lược đồ), sau đó được lưu cache |
Bây giờ hãy cùng phân tích từng phần.
Đầu ra có cấu trúc của LLM là gì?
Đầu ra có cấu trúc là sự khác biệt giữa việc hy vọng LLM trả về JSON hợp lệ và đảm bảo điều đó. Khi bạn bật đầu ra có cấu trúc, mô hình về mặt vật lý không thể tạo ra các token vi phạm lược đồ của bạn. Bạn định nghĩa một JSON Schema (hoặc mô hình Pydantic, hoặc lược đồ Zod), truyền nó vào API, và nhận lại một phản hồi khớp với nó mỗi lần.
Tại sao điều này quan trọng? Trước khi có đầu ra có cấu trúc, các nhà phát triển phải viết các bộ phân tích regex dễ vỡ, bọc mọi lệnh gọi LLM trong các khối try/catch JSON.parse, và vẫn phải đối phó với các phản hồi "gần đúng", JSON hợp lệ nhưng thiếu một trường hoặc sai kiểu dữ liệu. Toàn bộ lớp lỗi đó đã biến mất.
Có ba mức độ thực thi cấu trúc, đại diện cho một sự tiến hóa rõ ràng:
- Kỹ thuật prompt, "Vui lòng trả về JSON với các trường này." Không đáng tin cậy. Mô hình có thể tuân thủ 80-90% số lần.
- JSON Mode, Đảm bảo JSON đúng cú pháp, nhưng không thực thi lược đồ của bạn. Bạn có thể nhận được
{"foo": "bar"}khi mong đợi{"name": string, "age": number}. - Strict Mode / Giải mã bị ràng buộc, Đảm bảo tuân thủ lược đồ 100%. Mô hình thực sự không thể xuất ra các token không hợp lệ. Đây là ý nghĩa của "đầu ra có cấu trúc" vào năm 2026.
Tính đến đầu năm 2026, OpenAI, Anthropic, và Google Gemini đều hỗ trợ đầu ra có cấu trúc native. Hệ sinh thái đã hội tụ.
Kết luận: Nếu bạn đang phân tích cú pháp phản hồi LLM bằng regex hoặc JSON.parse trong production, bạn đang làm theo cách khó khăn. Đầu ra có cấu trúc native loại bỏ hoàn toàn chế độ thất bại đó.
JSON Mode vs Strict Mode: Điều gì thực sự thay đổi?
Sự phân biệt này khiến nhiều nhà phát triển bối rối vì tên gọi nghe có vẻ tương tự nhau. Nhưng chúng không giống nhau.
| Tính năng | JSON Mode | Strict Mode (Đầu ra có cấu trúc) |
|---|---|---|
| Tham số API | type: "json_object" | type: "json_schema" với strict: true |
| Đảm bảo JSON hợp lệ | Có | Có |
| Đảm bảo tuân thủ lược đồ | Không | Có |
| Cơ chế | Thiên vị token hậu kỳ | Giải mã bị ràng buộc (FSM) |
| Có thể trả về các trường không mong đợi | Có | Không |
| Có thể bỏ sót các trường bắt buộc | Có | Không |
| Thực thi kiểu dữ liệu | Không | Đầy đủ (string, number, array, v.v.) |
| Khi nào sử dụng | Bạn không có lược đồ từ trước | Mọi thứ trong production |
Dòng thời gian: OpenAI giới thiệu JSON Mode vào cuối năm 2023. Đó là một bước tiến, nhưng các nhà phát triển nhanh chóng nhận ra "JSON hợp lệ" là chưa đủ, họ cần JSON tuân thủ lược đồ. Vào tháng 8 năm 2024, OpenAI ra mắt Đầu ra có cấu trúc với Strict Mode, sử dụng giải mã bị ràng buộc để đảm bảo tuân thủ lược đồ. Đến năm 2025-2026, mọi nhà cung cấp lớn đều đã áp dụng cách tiếp cận tương tự.
JSON Mode vẫn có một trường hợp sử dụng hẹp: khi bạn thực sự không biết hình dạng của phản hồi trước và chỉ muốn một số JSON hợp lệ để khám phá phi cấu trúc. Nhưng điều này hiếm gặp trong production.
Kết luận: Sử dụng Strict Mode cho mọi thứ trong production. JSON Mode thực tế đã bị loại bỏ cho các trường hợp sử dụng bị ràng buộc bởi lược đồ. Nếu bạn có một lược đồ (và bạn nên có), hãy sử dụng type: "json_schema" với strict: true.
Giải mã bị ràng buộc hoạt động như thế nào?
Đây là cơ chế giúp đạt được sự tuân thủ lược đồ 100%, không phải 99,9%, mà là thực sự 100%.
Khi bạn gửi một JSON Schema đến nhà cung cấp với Strict Mode được bật, lược đồ sẽ được biên dịch thành một máy trạng thái hữu hạn (FSM). FSM này đại diện cho mọi đường dẫn hợp lệ thông qua lược đồ của bạn. Tại mỗi bước tạo token, công cụ suy luận kiểm tra xem token nào sẽ giữ đầu ra trên một đường dẫn hợp lệ và token nào thì không. Các token không hợp lệ được đặt logits thành âm vô cực trước khi lấy mẫu, nghĩa là chúng có xác suất bằng 0 được chọn.
<!-- IMAGE: constrained-decoding diagram showing FSM token masking during structured output generation -->Hãy nghĩ về nó như autocomplete được tăng cường sức mạnh. Nếu mô hình vừa xuất ra {"rating": và lược đồ của bạn nói rằng rating là một số nguyên, thì các token duy nhất được phép tiếp theo là các token chữ số. Dấu ngoặc kép, chữ cái, dấu ngoặc vuông, tất cả đều bị loại bỏ. Mô hình không thể xuất ra "five" ngay cả khi nó "muốn" làm vậy.
Đây là cùng một cơ chế cốt lõi được sử dụng bởi XGrammar (công cụ đứng sau vLLM, SGLang và hầu hết các máy chủ suy luận cục bộ) và Outlines (thư viện Python nguồn mở cho tạo sinh bị ràng buộc). Các nhà cung cấp API chỉ tích hợp nó vào cơ sở hạ tầng suy luận của họ.
Có một sự đánh đổi cần biết: yêu cầu đầu tiên với một lược đồ mới chịu chi phí độ trễ biên dịch (thường là 50-200ms) trong khi FSM được xây dựng. Các yêu cầu tiếp theo với cùng lược đồ sử dụng FSM đã lưu cache và thêm gần như không có độ trễ. Cũng có một cân nhắc tinh tế về chất lượng, việc ràng buộc từ vựng token đôi khi có thể giảm chất lượng đầu ra cho các trường sáng tạo hoặc tự do, vì vậy hãy giữ các lược đồ của bạn tập trung vào dữ liệu thực sự có cấu trúc.
Kết luận: Giải mã bị ràng buộc là thứ phân biệt "thường hoạt động" với "luôn hoạt động." Đó là kỹ thuật giúp đầu ra có cấu trúc sẵn sàng cho production.
Triển khai đa nhà cung cấp: OpenAI, Anthropic và Gemini
Đây là điều mà không hướng dẫn nào khác chỉ cho bạn: cùng một tác vụ trích xuất được triển khai trên cả ba nhà cung cấp lớn. Chúng ta sẽ trích xuất một đánh giá sản phẩm có cấu trúc từ văn bản phi cấu trúc.
Lược đồ Pydantic (chia sẻ trên tất cả các nhà cung cấp):
from pydantic import BaseModel, Field
from typing import Literal
class ProductReview(BaseModel):
reasoning: str = Field(description="Think through the review before scoring")
rating: int = Field(description="Rating from 1-5", ge=1, le=5)
sentiment: Literal["positive", "negative", "neutral"]
pros: list[str] = Field(description="Key positive points")
cons: list[str] = Field(description="Key negative points")
summary: str = Field(description="One-sentence summary")Triển khai OpenAI
from openai import OpenAI
client = OpenAI()
response = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=[
{"role": "system", "content": "Extract a structured review from the text."},
{"role": "user", "content": review_text}
],
response_format=ProductReview, # Pydantic model directly
)
review = response.choices[0].message.parsed # Typed ProductReview objectTriển khai của OpenAI là trưởng thành nhất. Phương thức parse() chấp nhận trực tiếp một mô hình Pydantic và trả về một đối tượng đã gõ kiểu. Một ràng buộc: Strict Mode của OpenAI hỗ trợ một tập con của JSON Schema, không có $ref, hạn chế anyOf, và tất cả các trường phải là bắt buộc với additionalProperties: false.
Triển khai Anthropic
from anthropic import Anthropic
client = Anthropic()
response = client.messages.create(
model="claude-sonnet-4-5-20250514",
max_tokens=1024,
messages=[
{"role": "user", "content": f"Extract a structured review:\n\n{review_text}"}
],
output_config={
"format": {
"type": "json_schema",
"json_schema": ProductReview.model_json_schema()
}
}
)
import json
review_data = json.loads(response.content[0].text)
review = ProductReview(**review_data)Đầu ra có cấu trúc native của Anthropic sử dụng output_config.format với một JSON Schema. Nó đạt GA (phát hành chung) vào đầu năm 2026. Anthropic cũng hỗ trợ mẫu cũ hơn là định nghĩa một công cụ "giả" và trích xuất qua tool_use, cách này vẫn hoạt động nhưng đầu ra có cấu trúc native sạch hơn cho việc trích xuất thuần túy.
Triển khai Gemini
from google import genai
client = genai.Client()
response = client.models.generate_content(
model="gemini-2.0-flash",
contents=f"Extract a structured review:\n\n{review_text}",
config={
"response_mime_type": "application/json",
"response_schema": ProductReview, # Pydantic model directly
}
)
import json
review = ProductReview(**json.loads(response.text))Gemini hỗ trợ trực tiếp các mô hình Pydantic trong Python SDK qua response_schema. Một tính năng độc đáo: Gemini tôn trọng propertyOrdering trong lược đồ, vì vậy bạn có thể kiểm soát thứ tự xuất trường (hữu ích cho mẫu lập luận-trước).
So sánh nhà cung cấp
| Tính năng | OpenAI | Anthropic | Gemini |
|---|---|---|---|
| Tham số API | response_format | output_config.format | response_schema |
| Đầu vào lược đồ | Pydantic hoặc JSON Schema | JSON Schema | Pydantic hoặc JSON Schema |
| Chế độ nghiêm ngặt | strict: true | Ngầm định với json_schema | Ngầm định |
| Streaming | Có (JSON từng phần) | Có | Có |
| Xử lý từ chối | Trường message.refusal | Phản hồi lỗi | Phản hồi lỗi |
| Thay thế tool-use | Có | Có (phương pháp gốc) | Có |
| Cache biên dịch lược đồ | Có (phía máy chủ) | Có | Có |
| Sắp xếp thuộc tính | Không hỗ trợ native | Không | Có (propertyOrdering) |
Kết luận: OpenAI có trải nghiệm nhà phát triển (DX) bóng bẩy nhất với phương thức parse(). Anthropic cung cấp các mô hình nền tảng mạnh mẽ nhất. Khả năng sắp xếp thuộc tính của Gemini đặc biệt hữu ích. Cả ba đều hoàn thành công việc, hãy chọn dựa trên mối quan hệ nhà cung cấp hiện tại của bạn.
Các mẫu Pydantic cho nhà phát triển Python
Pydantic là tiêu chuẩn thực tế để định nghĩa các lược đồ đầu ra có cấu trúc trong Python. Dưới đây là các mẫu quan trọng.
Lược đồ cơ bản với mô tả
from pydantic import BaseModel, Field
from typing import Literal, Optional
class ExtractedEntity(BaseModel):
reasoning: str = Field(description="Think step by step about the entity")
name: str = Field(description="Full name of the entity")
entity_type: Literal["person", "company", "location"]
confidence: float = Field(description="Confidence score 0.0-1.0", ge=0.0, le=1.0)
context: Optional[str] = Field(description="Surrounding context, if relevant")Những chuỗi description đó không chỉ dành cho tài liệu, chúng trở thành một phần của JSON Schema được gửi đến mô hình và ảnh hưởng trực tiếp đến những gì mô hình tạo ra. Hãy nghĩ về chúng như kỹ thuật prompt bên trong lược đồ.
Các mô hình lồng nhau
class Address(BaseModel):
street: str
city: str
country: str
postal_code: Optional[str] = None
class Company(BaseModel):
reasoning: str = Field(description="Analysis of the company details")
name: str
industry: Literal["tech", "finance", "healthcare", "retail", "other"]
headquarters: Address # Nested model
key_products: list[str] = Field(description="Top 3 products or services")Giữ mức độ lồng ghép tối đa 2-3 cấp. Các lược đồ lồng ghép sâu làm tăng tỷ lệ lỗi và làm chậm quá trình biên dịch lược đồ.
Mẫu Lập luận-Trước (Reasoning-First)
Đây là mẫu thiết kế lược đồ có tác động lớn nhất. Đặt một trường reasoning trước các trường câu trả lời của bạn:
# Reliable JSON from Any LLM: Pydantic + Zod Patterns for 2026
class ClassificationBad(BaseModel):
category: Literal["spam", "ham"]
confidence: float
# Good -- model reasons through the problem first
class ClassificationGood(BaseModel):
reasoning: str = Field(description="Analyze the text before classifying")
category: Literal["spam", "ham"]
confidence: float = Field(ge=0.0, le=1.0)LLM tạo token từ trái sang phải. Nếu category đứng trước, mô hình chọn một danh mục và sau đó hợp lý hóa nó. Nếu reasoning đứng trước, mô hình xử lý vấn đề và sau đó cam kết với một danh mục. Đó là chain-of-thought được tích hợp vào lược đồ.
Xuất JSON Schema
# Generate the JSON Schema for any Pydantic model
schema = ProductReview.model_json_schema()
# Pass this to any provider that accepts raw JSON SchemaKết luận: Pydantic + các trường mô tả + thứ tự lập luận-trước là bộ ba đầu ra có cấu trúc của Python. Thành thạo ba mẫu này và bạn sẽ xử lý được 90% các trường hợp sử dụng.
Các mẫu Zod cho nhà phát triển TypeScript
Zod là phiên bản TypeScript của Pydantic, và nó cũng quan trọng không kém trong các quy trình làm việc đầu ra có cấu trúc.
Lược đồ cơ bản với mô tả
import { z } from "zod";
const ProductReview = z.object({
reasoning: z.string().describe("Think through the review before scoring"),
rating: z.number().int().min(1).max(5),
sentiment: z.enum(["positive", "negative", "neutral"]),
pros: z.array(z.string()).describe("Key positive points"),
cons: z.array(z.string()).describe("Key negative points"),
summary: z.string().describe("One-sentence summary"),
});
// Infer the TypeScript type automatically
type ProductReview = z.infer<typeof ProductReview>;Giống như Field(description=...) của Pydantic, .describe() của Zod trở thành một phần của JSON Schema và hướng dẫn đầu ra của mô hình.
Tích hợp với OpenAI Node SDK
import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
const client = new OpenAI();
const response = await client.beta.chat.completions.parse({
model: "gpt-4o-2024-08-06",
messages: [
{ role: "system", content: "Extract a structured review." },
{ role: "user", content: reviewText },
],
response_format: zodResponseFormat(ProductReview, "product_review"),
});
const review = response.choices[0].message.parsed; // Typed!Tích hợp với Vercel AI SDK
import { generateObject } from "ai";
import { openai } from "@ai-sdk/openai";
const { object: review } = await generateObject({
model: openai("gpt-4o"),
schema: ProductReview,
prompt: `Extract a structured review:\n\n${reviewText}`,
});
// review is fully typed as ProductReviewVercel AI SDK sử dụng Zod native với generateObject(), làm cho nó trở thành tích hợp TypeScript sạch nhất. Nó hoạt động với OpenAI, Anthropic, Gemini và các nhà cung cấp khác thông qua một API thống nhất.
Chuyển đổi JSON Schema
import { zodToJsonSchema } from "zod-to-json-schema";
const jsonSchema = zodToJsonSchema(ProductReview);
// Use with any provider that accepts raw JSON SchemaKết luận: Zod + .describe() + Vercel AI SDK là ngăn xếp đầu ra có cấu trúc của TypeScript. Nếu bạn đang ở trong hệ sinh thái Node/Next.js, đây là con đường ít kháng cự nhất.
Đầu ra có cấu trúc so với Function Calling: Khi nào sử dụng cái nào?
Đây là một trong những nguồn gây nhầm lẫn phổ biến nhất. Cả hai đều liên quan đến lược đồ, cả hai đều trả về dữ liệu có cấu trúc, nhưng chúng giải quyết các vấn đề khác nhau.
Đầu ra có cấu trúc nói: "Hãy cho tôi dữ liệu theo hình dạng chính xác này." Nó dành cho việc trích xuất, phân loại và định dạng. Bạn đang kéo thông tin có cấu trúc ra khỏi văn bản phi cấu trúc.
Function calling (sử dụng công cụ) nói: "Đây là các hành động bạn có thể thực hiện, hãy quyết định hành động nào để chạy và cung cấp các đối số." Nó dành cho các quy trình làm việc agent nơi mô hình chọn từ nhiều công cụ và kích hoạt hành động.
Sự nhầm lẫn là hợp lý về mặt lịch sử. "Đầu ra có cấu trúc" ban đầu của Anthropic thực chất là function calling, bạn sẽ định nghĩa một công cụ giả gọi là extract_review và lấy các đối số. Điều đó vẫn hoạt động, nhưng đầu ra có cấu trúc native đơn giản hơn cho việc trích xuất thuần túy.
| Kịch bản | Cách tiếp cận tốt nhất | Tại sao |
|---|---|---|
| Trích xuất dữ liệu từ văn bản | Đầu ra có cấu trúc | Trực tiếp, độ trễ thấp hơn, một lược đồ |
| Phân loại vào các danh mục | Đầu ra có cấu trúc | Một phản hồi, một lược đồ |
| Agent quyết định gọi công cụ nào | Function calling | Mô hình chọn từ nhiều công cụ |
| Điều phối nhiều bước | Function calling | Gọi công cụ tuần tự |
| Trích xuất dữ liệu VÀ quyết định hành động tiếp theo | Cả hai | Đầu ra có cấu trúc để trích xuất, function calling để điều phối |
Đầu ra có cấu trúc cung cấp năng lượng cho các pipeline gọi công cụ trong các hệ thống AI agent. Xem hướng dẫn về AI agents cho doanh nghiệp của chúng tôi để biết cách chúng phù hợp với các quy trình làm việc production.
Kết luận: Sử dụng đầu ra có cấu trúc khi bạn biết hình dạng dữ liệu nên như thế nào. Sử dụng function calling khi mô hình cần chọn một hành động. Trong thực tế, hầu hết các ứng dụng sử dụng cả hai, đầu ra có cấu trúc để trích xuất dữ liệu và function calling để điều phối agent.
Các mẫu Production: Lỗi, Thử lại và Streaming
Làm cho đầu ra có cấu trúc hoạt động trong bản demo thì dễ. Giữ cho nó đáng tin cậy trong production đòi hỏi phải xử lý ba thứ: từ chối, thất bại xác thực và streaming.
Xử lý từ chối
Đôi khi mô hình từ chối tạo ra đầu ra bạn yêu cầu, thường là vì các bộ lọc an toàn đã gắn cờ đầu vào. Khi điều này xảy ra, các API đầu ra có cấu trúc không trả về lược đồ của bạn. Chúng trả về một sự từ chối.
response = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=messages,
response_format=ProductReview,
)
# ALWAYS check for refusal before accessing parsed content
if response.choices[0].message.refusal:
print(f"Model refused: {response.choices[0].message.refusal}")
else:
review = response.choices[0].message.parsedNếu bạn bỏ qua kiểm tra từ chối và cố gắng truy cập .parsed trên một sự từ chối, bạn sẽ nhận được None và một lỗi downstream khó hiểu. Hãy kiểm tra trước, luôn luôn.
Mẫu thử lại với phản hồi xác thực
Tuân thủ lược đồ được đảm bảo bởi giải mã bị ràng buộc, nhưng tính đúng đắn ngữ nghĩa thì không. Mô hình có thể trả về {"rating": 1, "sentiment": "positive"}, lược đồ hợp lệ, nhưng nội dung mâu thuẫn. Đó là lúc xác thực + thử lại phát huy tác dụng.
import instructor
client = instructor.from_openai(OpenAI())
# Instructor handles retries automatically
review = client.chat.completions.create(
model="gpt-4o",
response_model=ProductReview,
max_retries=3, # Retries with validation error feedback
messages=[
{"role": "user", "content": review_text}
],
)Instructor đưa lỗi xác thực trở lại mô hình khi thử lại, để nó có thể tự sửa chữa. Đối với các mẫu thử lại thủ công mà không có Instructor:
from pydantic import ValidationError
for attempt in range(3):
try:
response = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=messages,
response_format=ProductReview,
)
review = response.choices[0].message.parsed
# Run additional semantic validation here
break
except ValidationError as e:
messages.append({"role": "assistant", "content": str(response)})
messages.append({"role": "user", "content": f"Validation error: {e}. Fix it."})Streaming đầu ra có cấu trúc
Đối với các phản hồi có cấu trúc lớn, mảng dài, nhiều trường, các đối tượng lồng ghép phức tạp, streaming cho phép bạn hiển thị dần dần các kết quả từng phần.
import instructor
client = instructor.from_openai(OpenAI())
# Stream partial results as fields populate
review_stream = client.chat.completions.create_partial(
model="gpt-4o",
response_model=ProductReview,
messages=[{"role": "user", "content": review_text}],
)
for partial_review in review_stream:
# Fields populate one by one as tokens stream in
if partial_review.summary:
print(f"Summary so far: {partial_review.summary}")Một điểm cần lưu ý: các chunk streaming riêng lẻ không tự thân tuân thủ lược đồ. Trường reasoning có thể được điền trong khi rating vẫn là None. Hãy lên kế hoạch giao diện người dùng của bạn cho phù hợp, hiển thị trạng thái tải cho các trường chưa được điền.
Kết luận: Kiểm tra từ chối là bắt buộc. Thử lại với phản hồi xác thực bắt các lỗi ngữ nghĩa. Streaming xứng đáng cho bất kỳ phản hồi nào mất hơn vài giây.
So sánh các thư viện đầu ra có cấu trúc
Bạn có thể sử dụng đầu ra có cấu trúc thông qua các API native, nhưng các thư viện thêm xác thực, thử lại, streaming và hỗ trợ đa nhà cung cấp. Đây là bức tranh toàn cảnh.
Instructor là tùy chọn phổ biến nhất với hơn 11K sao GitHub và hơn 3 triệu lượt tải xuống hàng tháng. Nó bọc OpenAI, Anthropic, Gemini, Cohere, Ollama và nhiều hơn nữa với một giao diện thống nhất dựa trên Pydantic. Các tính năng chính: tự động thử lại với phản hồi xác thực, streaming qua create_partial(), và thiết lập cực kỳ đơn giản (instructor.from_openai(client)). Nếu bạn là nhóm Python, hãy bắt đầu từ đây.
BAML đi theo một cách tiếp cận khác: ưu tiên lược đồ thông qua DSL tùy chỉnh. Bạn định nghĩa các lược đồ trong các tệp .baml và tự động tạo client cho Python, TypeScript, Ruby và nhiều ngôn ngữ khác. Thuật toán SAP (parsing phù hợp lược đồ) của nó xử lý các đầu ra mô hình lộn xộn một cách mượt mà. Tốt nhất cho các nhóm đa ngôn ngữ hoặc khi bạn muốn các hợp đồng giữa lớp LLM và lớp ứng dụng của mình. Sự đánh đổi: bước build thêm và một cú pháp mới cần học.
LangChain cung cấp .with_structured_output(schema) cho đầu ra có cấu trúc không phụ thuộc nhà cung cấp. Tiện lợi nếu bạn đã ở trong hệ sinh thái LangChain. Sự đánh đổi: nó là một dependency nặng, và sự trừu tượng có thể che giấu các tính năng cụ thể của nhà cung cấp mà bạn có thể cần.
API Native, các lệnh gọi trực tiếp với response_format / output_config, không yêu cầu dependency nào ngoài SDK của nhà cung cấp. Bạn có toàn quyền kiểm soát và khả năng hiển thị đầy đủ. Tốt nhất cho các trường hợp sử dụng đơn giản hoặc các nhóm thích sự trừu tượng tối thiểu.
| Thư viện | Ngôn ngữ | Nhà cung cấp | Tự động thử lại | Streaming | Sao GitHub | Độ khó học |
|---|---|---|---|---|---|---|
| Instructor | Python, TS | 15+ | Có | Có | 11K+ | Thấp |
| BAML | Python, TS, Ruby, Go | Tất cả (không phụ thuộc DSL) | Có | Có | 7K+ | Trung bình |
| LangChain | Python, TS | 20+ | Một phần | Có | 100K+ | Trung bình-Cao |
| API Native | Bất kỳ | 1 mỗi SDK | Không | Có | N/A | Thấp |
Việc chọn thư viện đầu ra có cấu trúc phù hợp là một phần của quyết định ngăn xếp AI rộng hơn. Chúng tôi phân tích toàn bộ ngăn xếp trong Hướng dẫn ngăn xếp AI tốt nhất cho SaaS.
Xem Các thư viện tốt nhất cho đầu ra có cấu trúc LLM [sắp ra mắt] của chúng tôi để so sánh chuyên sâu về Instructor, BAML, Mirascope và nhiều hơn nữa.
Kết luận: Bắt đầu với Instructor cho Python, API native cho TypeScript. Chuyển sang BAML nếu bạn cần các hợp đồng lược đồ đa ngôn ngữ. Tránh LangChain chỉ vì đầu ra có cấu trúc, nó là quá mức cần thiết.
Các phương pháp hay nhất thiết kế lược đồ (và các lỗi phổ biến)
Thiết kế lược đồ của bạn ảnh hưởng trực tiếp đến chất lượng đầu ra. Dưới đây là các mẫu quan trọng và những sai lầm khiến bạn mất độ chính xác.
Đặt lập luận trước câu trả lời
Chúng ta đã đề cập đến điều này trong phần Pydantic, nhưng cần nhắc lại vì đây là quyết định thiết kế có tác động cao nhất:
# Before: model guesses the answer, then rationalizes
class Bad(BaseModel):
answer: str
reasoning: str
# After: model thinks first, then commits
class Good(BaseModel):
reasoning: str = Field(description="Think step by step")
answer: strLLM tạo từ trái sang phải. Thứ tự trường là thứ tự prompt. Lập luận trước nghĩa là mô hình phải xử lý vấn đề trước khi cam kết với một câu trả lời.
Bảng các Anti-Pattern
| Sai lầm | Vấn đề | Khắc phục |
|---|---|---|
| Trường lập luận sau câu trả lời | Mô hình quyết định trước khi suy nghĩ | Di chuyển lập luận trước câu trả lời |
| Lồng ghép sâu (4+ cấp) | Tỷ lệ lỗi cao hơn, biên dịch chậm hơn | Làm phẳng xuống 2-3 cấp |
| Không có mô tả trường | Mô hình đoán những gì bạn muốn | Thêm .describe() / Field(description=...) |
| Thiếu xử lý null | Mô hình hallucinate một giá trị để điền vào trường | Sử dụng Optional / .nullable() |
| Lược đồ quá lớn (50+ trường) | Hết thời gian biên dịch, giảm chất lượng | Chia thành nhiều lệnh gọi |
| Các tùy chọn enum mơ hồ | Mô hình chọn sai danh mục | Sử dụng các tùy chọn cụ thể, không chồng chéo |
Xử lý Null một cách rõ ràng
Nếu một trường có thể không có dữ liệu trong văn bản nguồn, hãy làm cho nó tùy chọn. Ép buộc một trường bắt buộc khi dữ liệu không tồn tại dẫn đến hallucination:
class PersonInfo(BaseModel):
name: str # Always present
email: Optional[str] = Field(None, description="Email if mentioned, null otherwise")
phone: Optional[str] = Field(None, description="Phone if mentioned, null otherwise")Giữ các lược đồ tập trung
Một lược đồ cho mỗi tác vụ. Đừng cố gắng trích xuất mọi thứ trong một lược đồ khổng lồ duy nhất. Nếu bạn cần 50+ trường, hãy chia thành nhiều lệnh gọi trích xuất. Strict Mode của OpenAI có các giới hạn thực tế về độ phức tạp của lược đồ, và ngay cả khi nó hoạt động, các lược đồ rất lớn làm giảm chất lượng đầu ra.
Kết luận: Lập luận-trước, các trường mô tả, null rõ ràng và các lược đồ tập trung. Làm đúng bốn điều này và độ chính xác đầu ra có cấu trúc của bạn sẽ tăng lên đáng kể.
Đầu ra có cấu trúc với Local LLMs
Bạn không cần nhà cung cấp API cho đầu ra có cấu trúc. Các công cụ suy luận cục bộ hỗ trợ nó thông qua giải mã bị ràng buộc dựa trên ngữ pháp, cùng một cơ chế cơ bản, chạy trên phần cứng của riêng bạn.
Ollama
Con đường dễ nhất cho đầu ra có cấu trúc cục bộ. Ollama chấp nhận một JSON Schema qua tham số format:
import ollama
from pydantic import BaseModel
class Country(BaseModel):
name: str
capital: str
languages: list[str]
response = ollama.chat(
model="llama3.2",
messages=[{"role": "user", "content": "Tell me about Japan."}],
format=Country.model_json_schema(),
)
import json
country = Country(**json.loads(response.message.content))Ollama sử dụng XGrammar bên dưới để giải mã bị ràng buộc. Cùng một đảm bảo như các nhà cung cấp API: tuân thủ lược đồ 100%.
vLLM và SGLang
Đối với suy luận cục bộ cấp production, vLLM và SGLang đều hỗ trợ đầu ra có cấu trúc thông qua các tham số guided_json và guided_regex. XGrammar là backend mặc định, mang lại độ trễ gần như bằng không khi tạo JSON, nhanh hơn gấp 3,5 lần so với các engine ngữ pháp thay thế.
Outlines
Outlines là thư viện Python nguồn mở đã tiên phong trong tạo sinh bị ràng buộc dựa trên ngữ pháp. Nó hoạt động với bất kỳ mô hình Hugging Face nào và hỗ trợ JSON Schema, regex và các ràng buộc ngữ pháp phi ngữ cảnh đầy đủ (CFG/EBNF). Nó cũng được tích hợp vào vLLM và SGLang như một tùy chọn backend ngữ pháp.
Sự khác biệt chính so với các nhà cung cấp API: đầu ra có cấu trúc cục bộ không có giới hạn tập con lược đồ. Bạn kiểm soát hoàn toàn ngữ pháp. Nhưng chất lượng mô hình thay đổi nhiều hơn, một mô hình cục bộ 7B tham số sẽ không khớp với GPT-4o hoặc Claude trong các tác vụ trích xuất phức tạp. Lược đồ sẽ luôn hợp lệ; chất lượng nội dung phụ thuộc vào mô hình.
Kết luận: Ollama cho phát triển, vLLM/SGLang với XGrammar cho production. Đầu ra có cấu trúc cục bộ đã đủ trưởng thành cho hầu hết các trường hợp sử dụng, với lưu ý rằng các mô hình nhỏ hơn tạo ra nội dung chất lượng thấp hơn trong lược đồ.
FAQ
Đầu ra có cấu trúc trong LLM là gì?
Đầu ra có cấu trúc là một cơ chế đảm bảo phản hồi của LLM tuân thủ một JSON Schema được xác định trước. Không giống như văn bản thuần túy hoặc thậm chí JSON Mode, đầu ra có cấu trúc sử dụng giải mã bị ràng buộc để đảm bảo mọi trường, kiểu dữ liệu và ràng buộc trong lược đồ của bạn đều được đáp ứng -- 100% số lần, không phải "thường xuyên".
Sự khác biệt giữa JSON Mode và Đầu ra có cấu trúc là gì?
JSON Mode đảm bảo JSON đúng cú pháp nhưng không thực thi lược đồ của bạn, bạn có thể nhận được bất kỳ đối tượng JSON hợp lệ nào. Đầu ra có cấu trúc (Strict Mode) đảm bảo tuân thủ đầy đủ lược đồ thông qua giải mã bị ràng buộc. Sử dụng Strict Mode cho production; JSON Mode chỉ liên quan khi bạn không có lược đồ từ trước.
Những nhà cung cấp LLM nào hỗ trợ đầu ra có cấu trúc native?
OpenAI (từ tháng 8 năm 2024), Google Gemini (2024, mở rộng 2026), Anthropic (beta tháng 11 năm 2025, GA đầu năm 2026), Cohere và xAI (Grok) đều hỗ trợ đầu ra có cấu trúc native. Ở phía cục bộ, Ollama, vLLM và SGLang hỗ trợ nó thông qua giải mã bị ràng buộc dựa trên ngữ pháp.
Giải mã bị ràng buộc đảm bảo tuân thủ lược đồ như thế nào?
JSON Schema được biên dịch thành một máy trạng thái hữu hạn (FSM). Tại mỗi bước tạo token, chỉ các token giữ đầu ra trên một đường dẫn hợp lệ thông qua FSM mới được phép, các token không hợp lệ được đặt logits thành âm vô cực. Điều này có nghĩa là các token không hợp lệ có xác suất bằng 0 được tạo ra, mang lại cho bạn một đảm bảo toán học, không phải thống kê.
Tôi nên sử dụng đầu ra có cấu trúc hay function calling?
Sử dụng đầu ra có cấu trúc để trích xuất và phân loại, khi bạn muốn dữ liệu theo một hình dạng cụ thể. Sử dụng function calling cho các quy trình làm việc agent, khi mô hình cần quyết định hành động nào để thực hiện. Nhiều ứng dụng production sử dụng cả hai: đầu ra có cấu trúc để trích xuất dữ liệu và function calling để điều phối.
Tôi có thể stream đầu ra có cấu trúc không?
Có. OpenAI hỗ trợ streaming với phương thức parse(), và Instructor cung cấp create_partial() để streaming các mô hình Pydantic điền từng trường một. Hãy nhớ rằng các chunk streaming riêng lẻ không tự thân tuân thủ lược đồ, các trường được điền dần dần.
Thư viện Instructor là gì?
Instructor là thư viện đầu ra có cấu trúc phổ biến nhất (hơn 11K sao GitHub, hơn 3 triệu lượt tải xuống hàng tháng). Nó bọc các SDK nhà cung cấp với xác thực dựa trên Pydantic, tự động thử lại với phản hồi xác thực và hỗ trợ streaming. Nó hoạt động với OpenAI, Anthropic, Gemini, Cohere, Ollama và hơn 10 nhà cung cấp khác.
Đầu ra có cấu trúc có hoạt động với Local LLMs không?
Có. Ollama hỗ trợ đầu ra có cấu trúc qua tham số format với JSON Schema. vLLM và SGLang hỗ trợ nó thông qua các tham số guided_json. Cả ba đều sử dụng XGrammar hoặc Outlines để giải mã bị ràng buộc. Đảm bảo tuân thủ lược đồ giống như các nhà cung cấp API; chất lượng nội dung phụ thuộc vào mô hình.
Các sai lầm thiết kế lược đồ phổ biến là gì?
Các sai lầm hàng đầu: đặt trường lập luận sau trường câu trả lời (mô hình quyết định trước khi suy nghĩ), các lược đồ lồng ghép sâu (4+ cấp làm tăng lỗi), thiếu mô tả trường (mô hình đoán ý định), không xử lý null cho dữ liệu tùy chọn (ép buộc hallucination) và các lược đồ quá lớn (50+ trường làm giảm chất lượng).
Đầu ra có cấu trúc có thêm độ trễ không?
Có chi phí biên dịch lược đồ ở yêu cầu đầu tiên, thường là 50-200ms trong khi FSM được xây dựng. Các yêu cầu tiếp theo với cùng lược đồ sử dụng FSM đã lưu cache và thêm gần như không có độ trễ. Đối với hầu hết các ứng dụng, điều này không đáng kể so với thời gian suy luận mô hình tổng thể.
Tôi có thể sử dụng đầu ra có cấu trúc với hình ảnh hoặc đầu vào đa phương thức không?
Có. Đầu ra có cấu trúc áp dụng cho định dạng phản hồi, không phải đầu vào. Bạn có thể gửi một hình ảnh đến GPT-4o hoặc Gemini với một lược đồ đầu ra có cấu trúc và nhận lại một phân tích hình ảnh tuân thủ lược đồ. Điều này mạnh mẽ cho các quy trình làm việc trích xuất hình ảnh, trích xuất dữ liệu có cấu trúc từ hóa đơn, biểu mẫu hoặc hình ảnh sản phẩm.