
Output terstruktur LLM adalah mekanisme yang menjamin respons model bahasa sesuai dengan skema yang telah ditentukan sebelumnya, bukan hanya JSON yang valid, tetapi JSON yang valid terhadap skema dengan bidang, tipe, dan batasan tepat yang Anda tentukan. Setiap penyedia utama kini mendukungnya secara native, dan hal ini telah mengubah cara aplikasi LLM produksi dibangun.
Ringkasan Cepat: Output Terstruktur Sekilas
Jika waktu Anda terbatas, berikut adalah gambaran lanskap pada tahun 2026:
| Aspek | Detail |
|---|---|
| Apa itu | Respons dari LLM yang ditegakkan oleh skema, struktur terjamin, bukan "usaha terbaik" |
| Siapa yang mendukung | OpenAI, Anthropic, Gemini, Cohere, xAI (Grok), plus lokal melalui Ollama/vLLM |
| Mekanisme kunci | Decoding terbatas, token tidak valid disamarkan sebelum sampling |
| Mode JSON vs Mode Ketat | Mode JSON = sintaksis valid saja. Mode Ketat = kepatuhan skema penuh |
| Pustaka Python | Pydantic (BaseModel + Field) untuk definisi skema |
| Pustaka TypeScript | Zod (z.object + .describe) untuk definisi skema |
| Pendekatan pemula terbaik | OpenAI dengan Pydantic atau Zod melalui SDK native |
| Pustaka produksi terbaik | Instructor (Python) atau SDK native (TypeScript) |
| Jebakan terbesar | Meletakkan bidang penalaran SETELAH bidang jawaban, model memutuskan sebelum berpikir |
| Overhead latensi | 50-200ms pada panggilan pertama (kompilasi skema), di-cache setelahnya |
Sekarang mari kita uraikan setiap bagiannya.
Apa Itu Output Terstruktur LLM?
Output terstruktur adalah perbedaan antara berharap LLM mengembalikan JSON yang valid dan menjaminnya. Saat Anda mengaktifkan output terstruktur, model secara fisik tidak dapat menghasilkan token yang melanggar skema Anda. Anda mendefinisikan JSON Schema (atau model Pydantic, atau skema Zod), melewatkannya ke API, dan mendapatkan kembali respons yang cocok dengannya setiap saat.
Mengapa ini penting? Sebelum adanya output terstruktur, pengembang menulis parser regex yang rapuh, membungkus setiap panggilan LLM dalam blok try/catch JSON.parse, dan tetap berurusan dengan respons yang "hampir benar", yaitu JSON valid yang kehilangan bidang atau memiliki tipe yang salah. Seluruh kelas bug tersebut telah hilang.
Ada tiga tingkat penegakan struktur, dan mereka mewakili evolusi yang jelas:
- Rekayasa prompt, "Silakan kembalikan JSON dengan bidang-bidang ini." Tidak dapat diandalkan. Model mungkin mematuhinya 80-90% dari waktu.
- Mode JSON, Menjamin JSON yang valid secara sintaksis, tetapi tidak menegakkan skema Anda. Anda bisa mendapatkan
{"foo": "bar"}ketika Anda mengharapkan{"name": string, "age": number}. - Mode Ketat / Decoding terbatas, Menjamin kepatuhan skema 100%. Model secara harfiah tidak dapat mengeluarkan token yang tidak valid. Inilah arti "output terstruktur" pada tahun 2026.
Pada awal 2026, OpenAI, Anthropic, dan Google Gemini semuanya mendukung output terstruktur native. Ekosistem telah menyatu.
Putusan: Jika Anda mengurai respons LLM dengan regex atau JSON.parse di produksi, Anda melakukannya dengan cara yang sulit. Output terstruktur native menghilangkan seluruh mode kegagalan tersebut.
Mode JSON vs Mode Ketat: Apa yang Sebenarnya Berubah?
Perbedaan ini sering membingungkan banyak pengembang karena namanya terdengar mirip. Padahal tidak.
| Fitur | Mode JSON | Mode Ketat (Output Terstruktur) |
|---|---|---|
| Parameter API | type: "json_object" | type: "json_schema" dengan strict: true |
| Menjamin JSON valid | Ya | Ya |
| Menjamin kepatuhan skema | Tidak | Ya |
| Mekanisme | Bias token pasca-hoc | Decoding terbatas (FSM) |
| Dapat mengembalikan bidang tak terduga | Ya | Tidak |
| Dapat menghilangkan bidang wajib | Ya | Tidak |
| Penegakan tipe | Tidak ada | Penuh (string, number, array, dll.) |
| Kapan digunakan | Anda tidak memiliki skema di muka | Segala sesuatu di produksi |
Linimasa: OpenAI memperkenalkan Mode JSON pada akhir 2023. Ini adalah langkah maju, tetapi pengembang dengan cepat menyadari bahwa "JSON valid" saja tidak cukup, mereka membutuhkan JSON yang valid terhadap skema. Pada Agustus 2024, OpenAI meluncurkan Output Terstruktur dengan Mode Ketat, yang menggunakan decoding terbatas untuk menjamin kepatuhan skema. Pada 2025-2026, setiap penyedia utama telah mengadopsi pendekatan yang sama.
Mode JSON masih memiliki kasus penggunaan yang sempit: ketika Anda benar-benar tidak mengetahui bentuk respons di muka dan hanya menginginkan beberapa JSON valid untuk eksplorasi yang tidak terstruktur. Namun, hal ini jarang terjadi di produksi.
Putusan: Gunakan Mode Ketat untuk segala sesuatu di produksi. Mode JSON secara efektif sudah usang untuk kasus penggunaan yang terikat skema. Jika Anda memiliki skema (dan seharusnya begitu), gunakan type: "json_schema" dengan strict: true.
Bagaimana Cara Kerja Decoding Terbatas Sebenarnya?
Berikut adalah mekanisme yang memungkinkan kepatuhan skema 100%, bukan 99,9%, tetapi benar-benar 100%.
Saat Anda mengirim JSON Schema ke penyedia dengan Mode Ketat diaktifkan, skema tersebut dikompilasi menjadi mesin keadaan hingga (finite state machine/FSM). FSM ini mewakili setiap jalur valid melalui skema Anda. Pada setiap langkah generasi token, mesin inferensi memeriksa token mana yang akan menjaga output pada jalur valid dan mana yang tidak. Token yang tidak valid logits-nya diatur ke negatif tak terhingga sebelum sampling, yang berarti mereka memiliki probabilitas nol untuk dipilih.
<!-- IMAGE: constrained-decoding diagram showing FSM token masking during structured output generation -->Anggaplah ini seperti autocomplete yang ditingkatkan kekuatannya. Jika model baru saja mengeluarkan {"rating": dan skema Anda menyatakan rating adalah integer, satu-satunya token yang diizinkan berikutnya adalah token digit. Tanda kutip, huruf, tanda kurung, semua disamarkan. Model tidak dapat mengeluarkan "lima" bahkan jika model "ingin" melakukannya.
Ini adalah mekanisme inti yang sama yang digunakan oleh XGrammar (mesin di balik vLLM, SGLang, dan sebagian besar server inferensi lokal) dan Outlines (pustaka Python open-source untuk generasi terbatas). Penyedia API hanya telah membangunnya ke dalam infrastruktur inferensi mereka.
Ada satu trade-off yang perlu diketahui: permintaan pertama dengan skema baru mengalami hit latensi kompilasi (biasanya 50-200ms) saat FSM dibangun. Permintaan berikutnya dengan skema yang sama menggunakan FSM yang di-cache dan menambahkan overhead yang hampir nol. Ada juga pertimbangan kualitas yang halus, membatasi kosakata token kadang-kadang dapat mengurangi kualitas output untuk bidang kreatif atau bebas, jadi fokuskan skema Anda pada data yang benar-benar terstruktur.
Putusan: Decoding terbatas adalah apa yang membedakan "biasanya berhasil" dari "selalu berhasil". Ini adalah rekayasa yang membuat output terstruktur siap produksi.
Implementasi Multi-Provider: OpenAI, Anthropic, dan Gemini
Berikut adalah sesuatu yang tidak ditunjukkan oleh panduan lain: tugas ekstraksi yang sama diimplementasikan di ketiga penyedia utama. Kita akan mengekstrak ulasan produk terstruktur dari teks yang tidak terstruktur.
Skema Pydantic (digunakan bersama di semua penyedia):
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")Implementasi 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 objectImplementasi OpenAI adalah yang paling matang. Metode parse() menerima model Pydantic secara langsung dan mengembalikan objek bertipe. Satu batasan: Mode Ketat OpenAI mendukung subset dari JSON Schema, tidak ada $ref, anyOf terbatas, dan semua bidang harus wajib dengan additionalProperties: false.
Implementasi 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)Output terstruktur native Anthropic menggunakan output_config.format dengan JSON Schema. Ini mencapai GA pada awal 2026. Anthropic juga mendukung pola lama mendefinisikan alat "palsu" dan mengekstrak melalui tool_use, itu masih berfungsi tetapi output terstruktur native lebih bersih untuk ekstraksi murni.
Implementasi 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 mendukung model Pydantic secara langsung di SDK Python melalui response_schema. Fitur unik: Gemini menghormati propertyOrdering dalam skema, sehingga Anda dapat mengontrol urutan output bidang (berguna untuk pola penalaran-dulu).
Perbandingan Penyedia
| Fitur | OpenAI | Anthropic | Gemini |
|---|---|---|---|
| Parameter API | response_format | output_config.format | response_schema |
| Input skema | Pydantic atau JSON Schema | JSON Schema | Pydantic atau JSON Schema |
| Mode ketat | strict: true | Implisit dengan json_schema | Implisit |
| Streaming | Ya (JSON parsial) | Ya | Ya |
| Penanganan penolakan | Bidang message.refusal | Respons error | Respons error |
| Alternatif penggunaan alat | Ya | Ya (metode asli) | Ya |
| Cache kompilasi skema | Ya (sisi server) | Ya | Ya |
| Pengurutan properti | Tidak ada dukungan native | Tidak | Ya (propertyOrdering) |
Putusan: OpenAI memiliki DX paling halus dengan metode parse()-nya. Anthropic menawarkan model dasar yang paling mampu. Pengurutan properti Gemini sangat berguna secara unik. Ketiganya menyelesaikan pekerjaan, pilih berdasarkan hubungan penyedia Anda yang sudah ada.
Pola Pydantic untuk Pengembang Python
Pydantic adalah standar de facto untuk mendefinisikan skema output terstruktur di Python. Berikut adalah pola-pola yang penting.
Skema Dasar dengan Deskripsi
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")String description tersebut bukan hanya untuk dokumentasi, mereka menjadi bagian dari JSON Schema yang dikirim ke model dan secara langsung memengaruhi apa yang dihasilkan model. Anggaplah mereka sebagai rekayasa prompt di dalam skema.
Model Bersarang
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")Batasi kedalaman bersarang maksimal 2-3 level. Skema yang sangat bersarang meningkatkan tingkat error dan memperlambat kompilasi skema.
Pola Penalaran-Dulu
Ini adalah pola desain skema yang paling berdampak. Letakkan bidang reasoning sebelum bidang jawaban Anda:
# 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 menghasilkan token dari kiri ke kanan. Jika category datang pertama, model memilih kategori dan kemudian merasionalisasikannya. Jika reasoning datang pertama, model mengerjakan masalah dan kemudian berkomitmen pada kategori. Ini adalah chain-of-thought yang tertanam dalam skema.
Ekspor JSON Schema
# Generate the JSON Schema for any Pydantic model
schema = ProductReview.model_json_schema()
# Pass this to any provider that accepts raw JSON SchemaPutusan: Pydantic + bidang deskriptif + pengurutan penalaran-dulu adalah trifecta output terstruktur Python. Kuasai ketiga pola ini dan Anda akan menangani 90% kasus penggunaan.
Pola Zod untuk Pengembang TypeScript
Zod adalah setara TypeScript dari Pydantic, dan sama sentralnya dengan alur kerja output terstruktur.
Skema Dasar dengan Deskripsi
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>;Seperti Field(description=...) milik Pydantic, .describe() milik Zod menjadi bagian dari JSON Schema dan membimbing output model.
Integrasi dengan 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!Integrasi dengan 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 menggunakan Zod secara native dengan generateObject(), menjadikannya integrasi TypeScript paling bersih. Ini berfungsi dengan OpenAI, Anthropic, Gemini, dan penyedia lain melalui API terunifikasi.
Konversi JSON Schema
import { zodToJsonSchema } from "zod-to-json-schema";
const jsonSchema = zodToJsonSchema(ProductReview);
// Use with any provider that accepts raw JSON SchemaPutusan: Zod + .describe() + Vercel AI SDK adalah tumpukan output terstruktur TypeScript. Jika Anda berada di ekosistem Node/Next.js, ini adalah jalur dengan hambatan paling sedikit.
Output Terstruktur vs Pemanggilan Fungsi: Kapan Anda Menggunakan Masing-masing?
Ini adalah salah satu sumber kebingungan paling umum. Keduanya melibatkan skema, keduanya mengembalikan data terstruktur, tetapi mereka memecahkan masalah yang berbeda.
Output terstruktur berkata: "Berikan saya data dalam bentuk yang persis ini." Ini untuk ekstraksi, klasifikasi, dan pemformatan. Anda menarik informasi terstruktur keluar dari teks yang tidak terstruktur.
Pemanggilan fungsi (penggunaan alat) berkata: "Berikut adalah tindakan yang dapat Anda ambil, putuskan mana yang akan dijalankan dan berikan argumennya." Ini untuk alur kerja agen di mana model memilih dari beberapa alat dan memicu tindakan.
Kebingungan ini masuk akal secara historis. "Output terstruktur" asli Anthropic sebenarnya adalah pemanggilan fungsi, Anda akan mendefinisikan alat palsu bernama extract_review dan mengambil argumennya. Itu masih berfungsi, tetapi output terstruktur native lebih sederhana untuk ekstraksi murni.
| Skenario | Pendekatan Terbaik | Mengapa |
|---|---|---|
| Ekstrak data dari teks | Output terstruktur | Langsung, latensi lebih rendah, skema tunggal |
| Klasifikasikan ke dalam kategori | Output terstruktur | Satu respons, satu skema |
| Agen memutuskan alat mana yang dipanggil | Pemanggilan fungsi | Model memilih dari beberapa alat |
| Orkestrasi multi-langkah | Pemanggilan fungsi | Pemanggilan alat berurutan |
| Ekstrak data DAN putuskan tindakan berikutnya | Keduanya | Output terstruktur untuk ekstraksi, pemanggilan fungsi untuk orkestrasi |
Output terstruktur mendukung pipeline pemanggilan alat dalam sistem agen AI. Lihat panduan kami tentang agen AI untuk bisnis untuk melihat bagaimana ini masuk ke dalam alur kerja produksi.
Putusan: Gunakan output terstruktur ketika Anda tahu bentuk data yang seharusnya. Gunakan pemanggilan fungsi ketika model perlu memilih tindakan. Dalam praktiknya, sebagian besar aplikasi menggunakan keduanya, output terstruktur untuk ekstraksi data dan pemanggilan fungsi untuk orkestrasi agen.
Pola Produksi: Error, Retry, dan Streaming
Mendapatkan output terstruktur yang berfungsi dalam demo itu mudah. Menjaganya agar andal di produksi memerlukan penanganan tiga hal: penolakan, kegagalan validasi, dan streaming.
Penanganan Penolakan
Kadang-kadang model menolak untuk menghasilkan output yang Anda minta, biasanya karena filter keamanan menandai input tersebut. Ketika ini terjadi, API output terstruktur tidak mengembalikan skema Anda. Mereka mengembalikan penolakan.
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.parsedJika Anda melewatkan pemeriksaan penolakan dan mencoba mengakses .parsed pada penolakan, Anda akan mendapatkan None dan error downstream yang membingungkan. Periksa dulu, selalu.
Pola Retry dengan Umpan Balik Validasi
Kepatuhan skema dijamin oleh decoding terbatas, tetapi ketepatan semantik tidak. Model mungkin mengembalikan {"rating": 1, "sentiment": "positive"}, skema valid, konten kontradiktif. Di sinilah validasi + retry berperan.
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 memberi umpan balik error validasi kembali ke model saat retry, sehingga dapat memperbaiki diri sendiri. Untuk pola retry manual tanpa 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 Output Terstruktur
Untuk respons terstruktur besar, array panjang, banyak bidang, objek bersarang kompleks, streaming memungkinkan Anda merender hasil parsial secara progresif.
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}")Satu jebakan: potongan streaming individu tidak valid terhadap skema secara mandiri. Bidang reasoning mungkin sudah terisi sementara rating masih None. Rencanakan UI Anda sesuai, tampilkan status pemuatan untuk bidang yang belum terisi.
Putusan: Pemeriksaan penolakan adalah hal yang mutlak. Retry dengan umpan balik validasi menangkap error semantik. Streaming layak dilakukan untuk respons apa pun yang memakan waktu lebih dari beberapa detik.
Perbandingan Pustaka Output Terstruktur
Anda dapat menggunakan output terstruktur melalui API native, tetapi pustaka menambahkan validasi, retry, streaming, dan dukungan multi-provider. Berikut adalah lanskapnya.
Instructor adalah opsi paling populer dengan 11K+ bintang GitHub dan 3Juta+ unduhan bulanan. Ini membungkus OpenAI, Anthropic, Gemini, Cohere, Ollama, dan lainnya dengan antarmuka berbasis Pydantic yang terunifikasi. Fitur utama: retry otomatis dengan umpan balik validasi, streaming melalui create_partial(), dan pengaturan yang sangat sederhana (instructor.from_openai(client)). Jika Anda adalah tim Python, mulailah dari sini.
BAML mengambil pendekatan berbeda: skema-first melalui DSL kustom. Anda mendefinisikan skema dalam file .baml dan secara otomatis menghasilkan klien untuk Python, TypeScript, Ruby, dan lainnya. Algoritma SAP-nya (schema-aligned parsing) menangani output model yang berantakan dengan baik. Terbaik untuk tim lintas bahasa atau ketika Anda menginginkan kontrak antara lapisan LLM dan lapisan aplikasi Anda. Trade-off: langkah build tambahan dan sintaks baru untuk dipelajari.
LangChain menawarkan .with_structured_output(schema) untuk output terstruktur yang agnostik penyedia. Nyaman jika Anda sudah berada di ekosistem LangChain. Trade-off: ini adalah dependensi yang berat, dan abstraksi dapat menyembunyikan fitur khusus penyedia yang mungkin Anda butuhkan.
API Native, panggilan langsung dengan response_format / output_config, memerlukan nol dependensi selain SDK penyedia. Anda mendapatkan kontrol penuh dan visibilitas penuh. Terbaik untuk kasus penggunaan sederhana atau tim yang lebih menyukai abstraksi minimal.
| Pustaka | Bahasa | Penyedia | Auto Retry | Streaming | Bintang GitHub | Kurva Belajar |
|---|---|---|---|---|---|---|
| Instructor | Python, TS | 15+ | Ya | Ya | 11K+ | Rendah |
| BAML | Python, TS, Ruby, Go | Semua (agnostik DSL) | Ya | Ya | 7K+ | Sedang |
| LangChain | Python, TS | 20+ | Sebagian | Ya | 100K+ | Sedang-Tinggi |
| API Native | Apa saja | 1 per SDK | Tidak | Ya | N/A | Rendah |
Memilih pustaka output terstruktur yang tepat adalah bagian dari keputusan tumpukan AI yang lebih luas. Kami menguraikan tumpukan lengkap dalam Panduan Tumpukan AI Terbaik untuk SaaS kami.
Lihat Pustaka Terbaik untuk Output Terstruktur LLM [segera hadir] kami untuk perbandingan mendalam tentang Instructor, BAML, Mirascope, dan lainnya.
Putusan: Mulailah dengan Instructor untuk Python, API native untuk TypeScript. Beralih ke BAML jika Anda membutuhkan kontrak skema lintas bahasa. Hindari LangChain hanya untuk output terstruktur, itu berlebihan.
Praktik Terbaik Desain Skema (dan Kesalahan Umum)
Desain skema Anda secara langsung memengaruhi kualitas output. Berikut adalah pola-pola yang penting dan kesalahan-kesalahan yang mengurangi akurasi Anda.
Letakkan Penalaran Sebelum Jawaban
Kami membahas ini di bagian Pydantic, tetapi perlu diulang karena ini adalah keputusan desain dengan dampak tertinggi:
# 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 menghasilkan dari kiri ke kanan. Urutan bidang adalah urutan prompt. Penalaran pertama berarti model harus mengerjakan masalah sebelum berkomitmen pada jawaban.
Tabel Anti-Pola
| Kesalahan | Masalah | Solusi |
|---|---|---|
| Bidang penalaran setelah jawaban | Model memutuskan sebelum berpikir | Pindahkan penalaran sebelum jawaban |
| Sangat bersarang (4+ level) | Tingkat error lebih tinggi, kompilasi lebih lambat | Dataran ke 2-3 level |
| Tidak ada deskripsi bidang | Model menebak apa yang Anda inginkan | Tambahkan .describe() / Field(description=...) |
| Penanganan null hilang | Model berhalusinasi nilai untuk mengisi bidang | Gunakan Optional / .nullable() |
| Skema terlalu besar (50+ bidang) | Waktu habis kompilasi, penurunan kualitas | Pisahkan menjadi beberapa panggilan |
| Opsi enum yang samar | Model memilih kategori yang salah | Gunakan opsi spesifik yang tidak tumpang tindih |
Tangani Null Secara Eksplisit
Jika sebuah bidang mungkin tidak memiliki data dalam teks sumber, buatlah opsional. Memaksa bidang wajib ketika data tidak ada menyebabkan halusinasi:
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")Jaga Skema Tetap Fokus
Satu skema per tugas. Jangan mencoba mengekstrak semuanya dalam satu skema masif tunggal. Jika Anda membutuhkan 50+ bidang, pisahkan menjadi beberapa panggilan ekstraksi. Mode Ketat OpenAI memiliki batas praktis pada kompleksitas skema, dan bahkan ketika berfungsi, skema yang sangat besar menurunkan kualitas output.
Putusan: Penalaran-dulu, bidang deskriptif, null eksplisit, dan skema fokus. Dapatkan keempat hal ini dengan benar dan akurasi output terstruktur Anda akan meningkat secara terukur.
Output Terstruktur dengan LLM Lokal
Anda tidak memerlukan penyedia API untuk output terstruktur. Mesin inferensi lokal mendukungnya melalui decoding terbatas berbasis tata bahasa, mekanisme fundamental yang sama, berjalan pada perangkat keras Anda sendiri.
Ollama
Jalur termudah untuk output terstruktur lokal. Ollama menerima JSON Schema melalui parameter 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 menggunakan XGrammar di bawah kap mesin untuk decoding terbatas. Jaminan yang sama dengan penyedia API: kepatuhan skema 100%.
vLLM dan SGLang
Untuk inferensi lokal tingkat produksi, vLLM dan SGLang keduanya mendukung output terstruktur melalui parameter guided_json dan guided_regex. XGrammar adalah backend default, memberikan overhead hampir nol pada generasi JSON, hingga 3,5x lebih cepat daripada mesin tata bahasa alternatif.
Outlines
Outlines adalah pustaka Python open-source yang mempelopori generasi terbatas berbasis tata bahasa. Ini berfungsi dengan model Hugging Face apa pun dan mendukung JSON Schema, regex, dan batasan tata bahasa bebas konteks penuh (CFG/EBNF). Ini juga diintegrasikan ke dalam vLLM dan SGLang sebagai opsi backend tata bahasa.
Perbedaan utama dari penyedia API: output terstruktur lokal tidak memiliki batasan subset skema. Anda mengontrol tata bahasa sepenuhnya. Tetapi kualitas model bervariasi lebih banyak, model lokal 7B parameter tidak akan menyaingi GPT-4o atau Claude pada tugas ekstraksi kompleks. Skema akan selalu valid; kualitas konten tergantung pada model.
Putusan: Ollama untuk pengembangan, vLLM/SGLang dengan XGrammar untuk produksi. Output terstruktur lokal sudah cukup matang untuk sebagian besar kasus penggunaan, dengan catatan bahwa model yang lebih kecil menghasilkan konten berkualitas lebih rendah di dalam skema.
FAQ
Apa itu output terstruktur dalam LLM?
Output terstruktur adalah mekanisme yang menjamin respons LLM sesuai dengan JSON Schema yang telah ditentukan sebelumnya. Berbeda dengan teks biasa atau bahkan Mode JSON, output terstruktur menggunakan decoding terbatas untuk memastikan setiap bidang, tipe, dan batasan dalam skema Anda terpenuhi -- 100% dari waktu, bukan "biasanya."
Apa perbedaan antara Mode JSON dan Output Terstruktur?
Mode JSON menjamin JSON yang valid secara sintaksis tetapi tidak menegakkan skema Anda, Anda bisa mendapatkan objek JSON valid apa pun. Output Terstruktur (Mode Ketat) menjamin kepatuhan skema penuh melalui decoding terbatas. Gunakan Mode Ketat untuk produksi; Mode JSON hanya relevan ketika Anda tidak memiliki skema di muka.
Penyedia LLM mana yang mendukung output terstruktur secara native?
OpenAI (sejak Agustus 2024), Google Gemini (2024, diperluas 2026), Anthropic (beta November 2025, GA awal 2026), Cohere, dan xAI (Grok) semuanya mendukung output terstruktur native. Di sisi lokal, Ollama, vLLM, dan SGLang mendukungnya melalui decoding terbatas berbasis tata bahasa.
Bagaimana decoding terbatas menjamin kepatuhan skema?
JSON Schema dikompilasi menjadi mesin keadaan hingga (FSM). Pada setiap langkah generasi token, hanya token yang menjaga output pada jalur valid melalui FSM yang diizinkan, token tidak valid logits-nya diatur ke negatif tak terhingga. Ini berarti token tidak valid memiliki probabilitas nol untuk dihasilkan, memberi Anda jaminan matematis, bukan statistik.
Haruskah saya menggunakan output terstruktur atau pemanggilan fungsi?
Gunakan output terstruktur untuk ekstraksi dan klasifikasi, ketika Anda menginginkan data dalam bentuk tertentu. Gunakan pemanggilan fungsi untuk alur kerja agen, ketika model perlu memutuskan tindakan mana yang akan diambil. Banyak aplikasi produksi menggunakan keduanya: output terstruktur untuk ekstraksi data dan pemanggilan fungsi untuk orkestrasi.
Bisakah saya melakukan streaming output terstruktur?
Ya. OpenAI mendukung streaming dengan metode parse(), dan Instructor menyediakan create_partial() untuk streaming model Pydantic yang mengisi bidang per bidang. Perlu diingat bahwa potongan streaming individu tidak valid terhadap skema secara mandiri, bidang terisi secara bertahap.
Apa itu pustaka Instructor?
Instructor adalah pustaka output terstruktur paling populer (11K+ bintang GitHub, 3Juta+ unduhan bulanan). Ini membungkus SDK penyedia dengan validasi berbasis Pydantic, retry otomatis dengan umpan balik validasi, dan dukungan streaming. Ini berfungsi dengan OpenAI, Anthropic, Gemini, Cohere, Ollama, dan 10+ penyedia lainnya.
Apakah output terstruktur berfungsi dengan LLM lokal?
Ya. Ollama mendukung output terstruktur melalui parameter format dengan JSON Schema. vLLM dan SGLang mendukungnya melalui parameter guided_json. Ketiganya menggunakan XGrammar atau Outlines untuk decoding terbatas. Jaminan kepatuhan skema sama dengan penyedia API; kualitas konten tergantung pada model.
Apa kesalahan desain skema yang umum?
Kesalahan teratas: meletakkan bidang penalaran setelah bidang jawaban (model memutuskan sebelum berpikir), skema yang sangat bersarang (4+ level meningkatkan error), deskripsi bidang yang hilang (model menebak maksud), tidak ada penanganan null untuk data opsional (memaksa halusinasi), dan skema yang terlalu besar (50+ bidang menurunkan kualitas).
Apakah output terstruktur menambah latensi?
Ada overhead kompilasi skema pada permintaan pertama, biasanya 50-200ms saat FSM dibangun. Permintaan berikutnya dengan skema yang sama menggunakan FSM yang di-cache dan menambahkan latensi yang hampir nol. Untuk sebagian besar aplikasi, ini dapat diabaikan dibandingkan dengan waktu inferensi model keseluruhan.
Bisakah saya menggunakan output terstruktur dengan gambar atau input multimodal?
Ya. Output terstruktur berlaku untuk format respons, bukan input. Anda dapat mengirim gambar ke GPT-4o atau Gemini dengan skema output terstruktur dan mendapatkan kembali analisis gambar yang sesuai dengan skema. Ini sangat kuat untuk alur kerja ekstraksi visual, mengekstrak data terstruktur dari struk, formulir, atau gambar produk.