7. Output Terstruktur dengan Pydantic
Di bab-bab sebelumnya, kita telah bekerja dengan output LLM sebagai string teks mentah. Ini berfungsi dengan baik untuk chatbot di mana manusia membaca responsnya, tetapi ketika membangun agen AI di mana program perlu mem-parsing dan menginterpretasikan output LLM, kita membutuhkan data terstruktur yang dapat diprediksi. Di bab ini, kamu akan belajar cara menggunakan skema Pydantic untuk membuat LLM mengembalikan objek Python terstruktur.
7.1) Mengapa Output Terstruktur?
Masalah dengan Output LLM Teks Bebas
Mari kita mulai dengan memahami mengapa respons teks mentah menciptakan masalah dalam aplikasi nyata. Pertimbangkan skenario umum ini:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm = ChatOpenAI(model="gpt-4o-mini")
# Tanyakan kepada LLM tentang sebuah produk
message = HumanMessage(content="""
Ekstrak informasi produk dari teks ini:
"UltraWidget Pro berharga $299.99 dan saat ini tersedia."
""")
response = llm.invoke([message])
print(response.content)Output:
Nama Produk: UltraWidget Pro
Harga: $299.99
Ketersediaan: TersediaOutputnya terlihat bagus. Tetapi sekarang misalkan kamu perlu menggunakan data ini dalam aplikasi Python kamu. Bagaimana cara mengekstrak harga sebagai angka? Bagaimana cara memeriksa ketersediaan secara programatis? Kamu mungkin mencoba parsing string seperti ini:
# Pendekatan parsing yang rapuh
text = response.content
price_line = [line for line in text.split('\n') if 'Harga:' in line][0]
price_str = price_line.split('$')[1]
price = float(price_str) # Rapuh - bagaimana jika formatnya berubah?Parsing ini tampaknya berhasil. Tetapi sebenarnya tidak. Inilah alasannya:
Mengapa Pendekatan Ini Gagal:
- LLM mungkin memformat respons secara berbeda di lain waktu ("Harga: 299.99 USD" atau "Harga Retail: $299.99")
Berikut adalah contoh output berbeda yang dapat terjadi untuk prompt yang sama:
# Contoh 1
"Produknya adalah UltraWidget Pro, berharga $299.99, dan tersedia."
# Contoh 2
"Produk: UltraWidget Pro
Biaya: 299.99 dolar
Status: Tersedia"
# Contoh 3
"UltraWidget Pro - $299.99 (tersedia)"
# Contoh 4
"Saya menemukan UltraWidget Pro. Harganya $299.99 dan saat ini tersedia untuk dibeli."Ketika respons LLM berubah, kamu membutuhkan logika parsing yang benar-benar berbeda. Ini membuat sulit untuk membangun aplikasi yang andal.
- Respons LLM tidak dapat diprediksi: Prompt yang sama dapat menghasilkan format berbeda setiap kali
- Parsing string lebih sulit dari yang terlihat: Kamu perlu menangani
$, spasi, newline, koma, dan lainnya - Tidak ada keamanan tipe sama sekali: Kamu tidak bisa yakin apakah
priceadalah float, string, atau None - Penanganan error sulit: Jika LLM mengatakan "Harga tidak tersedia", panggilan
float()kamu akan crash - Tidak dapat dipelihara: Ubah prompt sedikit dan kamu menulis ulang semua kode parsing
Ide Inti: Python Membutuhkan Kontrak, Bukan Prosa
Pikirkan tentang ketika kamu berkomunikasi dengan server API di Python. Ketika kamu memanggil REST API tertentu, kamu mengharapkannya mengembalikan respons JSON yang terdefinisi:
# Kamu mengharapkan struktur ini
{
"product_name": "UltraWidget Pro",
"price": 299.99,
"in_stock": true
}Ketika membangun aplikasi AI, kamu membutuhkan prinsip yang sama. Output LLM harus dikembalikan sebagai data dengan struktur yang terdefinisi, bukan sebagai teks bentuk bebas setiap kali.
Prosa vs Kontrak:
- Prosa: Teks natural bentuk bebas. Bagus untuk dibaca manusia, tetapi sulit untuk diproses program.
- Kontrak: Data dengan struktur dan tipe yang terdefinisi. Sebuah janji bahwa "field-field ini akan ada dengan tipe-tipe ini."
Output terstruktur berarti mendefinisikan kontrak: "LLM, saya membutuhkan tepat field-field ini, dengan tepat tipe-tipe ini, dalam tepat format ini."
Di sinilah Pydantic masuk. Pydantic adalah library validasi data Python yang paling populer, dan LangChain menggunakannya untuk menerima output LLM dalam bentuk terstruktur.
Pergeseran Model Mental:
- Sebelumnya: "LLM, ceritakan tentang produk ini" → Parse teks yang tidak dapat diprediksi
- Setelahnya: "LLM, respons dalam format yang terdefinisi" → Terima objek Python terstruktur
Pergeseran dari prosa ke kontrak ini fundamental untuk membangun agen AI yang andal. Ketika agen perlu memutuskan tindakan berikutnya berdasarkan respons LLM (misalnya, beli jika tersedia, daftar untuk notifikasi jika tidak), ia harus menerima respons dalam format yang terdefinisi.
7.2) Output Terstruktur Pertama Kamu
Di 7.1, kita belajar mengapa LLM harus merespons dengan struktur yang terdefinisi alih-alih teks bentuk bebas. Sekarang mari kita lihat cara benar-benar mengimplementasikan ini.
Ide kunci: Hanya meminta LLM "tolong respons dalam format ini" tidak cukup. Kamu perlu mendefinisikan struktur data yang tepat dalam kode Python dan membuat LangChain meneruskannya ke LLM. Struktur data yang terdefinisi ini disebut skema (schema).
Apa itu Skema?
Skema (schema) adalah blueprint yang mendefinisikan struktur data. Ia menentukan:
- Field apa yang harus ada
- Tipe apa yang harus dimiliki setiap field (string, number, boolean, dll.)
- Constraint apa yang berlaku (opsional vs wajib, rentang valid, dll.)
Di Python, kita mendefinisikan skema menggunakan class BaseModel dari Pydantic. Berikut adalah contoh paling sederhana:
from pydantic import BaseModel
class ProductInfo(BaseModel):
product_name: str
price: float
in_stock: boolSkema ini mengatakan: "Objek ProductInfo harus memiliki tepat tiga field: product_name (string), price (float), dan in_stock (boolean)."
Pola Tiga Langkah: Define, Bind, Invoke
Menggunakan output terstruktur itu sederhana. Ingat saja tiga langkah:
- Define: Buat skema dengan class Pydantic
- Bind: Hubungkan skema ke LLM menggunakan
.with_structured_output() - Invoke: Panggil
.invoke()untuk mendapatkan objek bertipe
Ini adalah template standar yang akan kamu gunakan untuk sebagian besar tugas ekstraksi terstruktur:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from pydantic import BaseModel, Field
# Langkah 1: Definisikan skema
class ProductInfo(BaseModel):
product_name: str = Field(description="Nama lengkap produk")
price: float = Field(description="Harga dalam USD")
in_stock: bool = Field(description="Apakah produk tersedia")
# Langkah 2: Bind skema ke LLM
llm = ChatOpenAI(model="gpt-4o-mini")
structured_llm = llm.with_structured_output(ProductInfo)
# Langkah 3: Invoke dan dapatkan objek bertipe
message = HumanMessage(content="""
Ekstrak informasi produk dari teks ini:
"UltraWidget Pro berharga $299.99 dan saat ini tersedia."
""")
result = structured_llm.invoke([message])
# result sekarang adalah objek ProductInfo, bukan string
print(type(result)) # <class '__main__.ProductInfo'>
print(result.product_name) # UltraWidget Pro
print(result.price) # 299.99
print(result.in_stock) # TrueApa yang Baru Saja Terjadi?
- Definisi Skema: Kita mendefinisikan field dan tipe yang kita inginkan
- Binding:
.with_structured_output(ProductInfo)mengonfigurasi LLM untuk menggunakan output terstruktur - Invocation & Response: Ketika
.invoke()dipanggil, LangChain meneruskan JSON Schema ke LLM, dan LLM merespons dengan JSON yang cocok dengan struktur tersebut - Konversi Otomatis: LangChain mengonversi JSON ke objek
ProductInfo- tidak perlu kode parsing
Tidak ada parsing. Tidak ada konversi tipe. Tidak ada error.
Gunakan pola 3 langkah ini sebagai template kamu. Ikuti ini setiap kali kamu membutuhkan output terstruktur.
Deskripsi Field: Kunci untuk Memandu LLM
Dalam contoh definisi skema di atas, kita menggunakan Field(description="..."). Deskripsi ini bukan hanya dokumentasi. Ini adalah instruksi yang dibaca dan diikuti oleh LLM.
Dalam penggunaan Pydantic biasa, deskripsi Field bersifat opsional:
# Pydantic biasa - deskripsi adalah dokumentasi untuk manusia
class User(BaseModel):
name: str = Field(description="Nama pengguna") # Berfungsi baik tanpanyaTetapi ketika bekerja dengan LLM, mereka esensial:
# Dengan LLM - deskripsi menentukan perilaku LLM
class CustomerFeedback(BaseModel):
sentiment: str = Field(
description="Sentimen keseluruhan: 'positive', 'negative', atau 'neutral'"
)LLM membaca deskripsi ini dan menggunakannya untuk memutuskan cara merespons.
Mari kita lihat ini dalam aksi:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from pydantic import BaseModel, Field
class CustomerFeedback(BaseModel):
sentiment: str = Field(
description="Sentimen keseluruhan: 'positive', 'negative', atau 'neutral'"
)
main_issue: str = Field(
description="Keluhan atau kekhawatiran utama, jika ada. Gunakan 'none' jika tidak ada masalah yang disebutkan."
)
urgency: str = Field(
description="Seberapa mendesak masalahnya: 'low', 'medium', atau 'high'"
)
llm = ChatOpenAI(model="gpt-4o-mini")
structured_llm = llm.with_structured_output(CustomerFeedback)
message = HumanMessage(content="""
Analisis feedback pelanggan ini:
"Produknya berfungsi dengan baik, tetapi pengiriman memakan waktu 3 minggu. Saya sudah melewatkan deadline proyek saya. Tolong respons segera."
""")
result = structured_llm.invoke([message])
print(result.sentiment) # negative
print(result.main_issue) # Pengiriman lambat
print(result.urgency) # highBagaimana deskripsi membentuk keputusan LLM:
- Deskripsi
sentiment→ LLM belajar nilai valid adalah 'positive', 'negative', 'neutral' → Masalah pengiriman menyebabkan deadline terlewat, jadi memilih 'negative' - Deskripsi
main_issue→ LLM diinstruksikan untuk "menemukan keluhan utama" → Mengidentifikasi "pengiriman lambat" sebagai masalahnya - Deskripsi
urgency→ LLM belajar urgency harus 'low', 'medium', atau 'high' → Melihat "Tolong respons segera" dan memilih 'high'
Apa yang terjadi tanpa deskripsi?
sentiment: str # Tidak ada deskripsiLLM mungkin mengembalikan "negative", "bad", "unsatisfied", "2/5", "disappointed" dalam format yang tidak dapat diprediksi, membuat sulit bagi kode kamu untuk menangani nilai-nilai tersebut.
Poin kunci: Deskripsi field adalah bagian dari kode kamu yang mengontrol perilaku LLM. Tulis dengan jelas dan spesifik.
Field Kategorikal: Menentukan Nilai yang Diizinkan
Dalam contoh di atas, field sentiment hanya dapat memiliki tiga nilai: 'positive', 'negative', atau 'neutral'. Field yang harus menjadi salah satu dari sekumpulan nilai tertentu disebut field kategorikal.
Untuk field kategorikal, daftarkan semua nilai yang mungkin dalam deskripsi:
sentiment: str = Field(
description="Sentimen: tepat 'positive', 'negative', atau 'neutral' (huruf kecil)"
)Dengan menentukan "tepat" dan "(huruf kecil)", kita menekankan bahwa LLM harus merespons dengan tepat salah satu dari tiga nilai ini.
Namun, tidak ada jaminan LLM akan selalu merespons dengan salah satu nilai yang ditentukan. Itulah mengapa kamu harus menulis kode defensif.
Kasus di mana LLM mengembalikan nilai yang tidak terduga:
result.sentiment = "Positive" # Huruf kapital
result.sentiment = "NEGATIVE" # Semua huruf kapital
result.sentiment = "good" # Kata yang berbeda sama sekaliMenulis kode defensif:
allowed = {"positive", "negative", "neutral"}
# Konversi ke huruf kecil dan periksa
sentiment = result.sentiment.lower()
if sentiment not in allowed:
sentiment = "neutral" # Gunakan default untuk nilai yang tidak terduga
# Sekarang sentiment dijamin menjadi salah satu dari nilai yang diizinkanKesimpulan kunci:
- Tentukan nilai yang diizinkan dalam deskripsi → LLM lebih mungkin merespons dengan benar
- Validasi dalam kode → Tangani nilai yang tidak terduga dengan aman
Catatan: Bab 18 menunjukkan pola yang lebih kuat menggunakan enum Python untuk penegakan.
Perbandingan: Parsing Manual vs Output Terstruktur
Mari kita bandingkan tugas yang sama dengan dan tanpa output terstruktur untuk melihat perbedaannya:
Parsing Manual:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm = ChatOpenAI(model="gpt-4o-mini")
message = HumanMessage(content="""
Ekstrak nama produk, harga, dan ketersediaan dari:
"UltraWidget Pro berharga $299.99 dan saat ini tersedia."
Format: nama | harga | ketersediaan
""")
response = llm.invoke([message])
text = response.content
# Parsing manual
parts = text.split('|')
product_name = parts[0].strip()
price_str = parts[1].strip().replace('$', '')
price = float(price_str)
availability = parts[2].strip().lower()
in_stock = 'tersedia' in availability or 'available' in availability
print(f"Nama: {product_name}")
print(f"Harga: ${price}")
print(f"Tersedia: {in_stock}")Output Terstruktur:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from pydantic import BaseModel, Field
class ProductInfo(BaseModel):
product_name: str = Field(description="Nama lengkap produk")
price: float = Field(description="Harga dalam USD")
in_stock: bool = Field(description="Apakah produk tersedia")
llm = ChatOpenAI(model="gpt-4o-mini")
structured_llm = llm.with_structured_output(ProductInfo)
message = HumanMessage(content="""
Ekstrak informasi produk dari:
"UltraWidget Pro berharga $299.99 dan saat ini tersedia."
""")
result = structured_llm.invoke([message])
print(f"Nama: {result.product_name}")
print(f"Harga: ${result.price}")
print(f"Tersedia: {result.in_stock}")Perbedaan Kunci:
- Tidak Ada Logika Parsing: Versi terstruktur tidak memiliki kode parsing sama sekali
- Keamanan Tipe:
result.pricedijamin menjadi float - Kode Lebih Sederhana: Tidak ada regex, tidak ada pemisahan string, tidak ada konversi tipe manual
- Validasi: Pydantic memastikan semua field yang diperlukan ada
- Maintainability: Mengubah skema lebih mudah daripada memperbarui logika parsing
7.3) Pertimbangan Desain Skema
Sekarang setelah kamu tahu cara menggunakan output terstruktur, mari kita pelajari cara mendesain skema yang baik. Bagian ini mencakup prinsip desain praktis untuk membedakan field wajib dari field opsional.
Field Wajib
Secara default, semua field dalam model Pydantic adalah wajib. Ini berarti LLM harus mengekstrak atau menyimpulkan nilai untuk setiap field wajib dari prompt pengguna dan menyediakannya dalam respons.
from pydantic import BaseModel
class ProductInfo(BaseModel):
product_name: str
price: float
in_stock: boolKetika kamu menggunakan skema ini, LLM akan mencoba menemukan nilai untuk ketiga field (product_name, price, in_stock) dalam teks input.
Tetapi apa yang terjadi ketika prompt tidak memiliki informasi untuk field wajib?
Kita mungkin mengharapkan perilaku berikut:
- LLM tidak dapat menemukan informasi dalam prompt
- LLM menghilangkan field tersebut dari responsnya
- LangChain tidak dapat membuat instance
ProductInfoyang valid ValidationErrordimunculkan
Namun, ini tidak selalu terjadi.
Alasannya adalah LLM yang berbeda mungkin menangani informasi yang hilang secara berbeda.
Beberapa LLM (seperti model OpenAI) cenderung menghasilkan nilai bahkan ketika informasi yang diperlukan tidak ada dalam prompt. Dalam kasus ini, ValidationError tidak terjadi, tetapi ini dapat menyebabkan masalah yang lebih besar karena aplikasi Python kamu mungkin memproses informasi yang dibuat-buat seolah-olah itu nyata.
Kita akan membahas cara menyelesaikan masalah ini di Bagian 7.4: Ketika Terjadi Kesalahan.
Untuk saat ini, ketahui saja bahwa tidak semua LLM menangani informasi yang hilang dengan cara yang sama.
Field Opsional
Kamu mungkin memerlukan field yang secara sah dapat ada atau tidak ada, bahkan dalam kasus normal. Misalnya, catatan pengiriman (delivery_note) mungkin atau mungkin tidak diberikan oleh pelanggan, bahkan untuk pesanan yang valid.
Kapan menggunakan Optional:
- Data itu sendiri mungkin tidak ada (misalnya, ketika ulasan anonim diizinkan, ulasan anonim tidak memiliki nama pengulas)
- Kamu ingin LLM secara eksplisit menunjukkan informasi yang hilang daripada membuat nilai
Untuk membuat field opsional, gunakan tipe Optional Python dari modul typing:
from typing import Optional
class ProductReview(BaseModel):
rating: int
review_text: str
reviewer_name: Optional[str] = None # Ulasan anonim tidak memiliki nama pengulasCatatan: Pengguna Python 3.10+ dapat menggunakan
str | Nonealih-alihOptional[str].
Ketika field adalah Optional:
- LLM dapat menghilangkannya dari respons jika informasi tidak ditemukan dalam prompt
- Field yang dihilangkan diatur ke nilai default (
None)
Berikut adalah contoh lengkap:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from pydantic import BaseModel, Field
from typing import Optional
class ProductInfo(BaseModel):
product_name: str
price: float
in_stock: bool
discount_percentage: Optional[float] = None
warranty_years: Optional[int] = None
llm = ChatOpenAI(model="gpt-4o-mini")
structured_llm = llm.with_structured_output(ProductInfo)
message = HumanMessage(content="""
Ekstrak info produk: "UltraWidget Pro berharga $299.99 dan tersedia."
""")
result = structured_llm.invoke([message])
print(result.product_name) # UltraWidget Pro
print(result.price) # 299.99
print(result.in_stock) # True
print(result.discount_percentage) # None (tidak disebutkan)
print(result.warranty_years) # None (tidak disebutkan)Checklist Desain Skema
Sebelum menyelesaikan skema kamu, tanyakan pada diri sendiri:
Pemilihan Field:
- Apakah field wajib benar-benar esensial? (Apa yang terjadi jika field ini hilang dari prompt?)
- Bisakah field opsional secara sah tidak ada bahkan dalam kasus normal?
Spesifikasi Field:
- Apakah setiap field memiliki deskripsi yang jelas?
- Apakah field kategorikal dibatasi secara eksplisit? (misalnya, "harus tepat 'A', 'B', atau 'C'")
7.4) Ketika Terjadi Kesalahan
Dua masalah dapat terjadi ketika menggunakan output terstruktur:
- LLM menghilangkan nilai field wajib → ValidationError terjadi
- LLM membuat informasi yang hilang → Tidak ada ValidationError, tetapi kode kamu memproses data yang salah
Bagian ini mencakup cara menangani masing-masing.
Memahami Validation Error
Ketika prompt pengguna tidak memiliki informasi untuk field wajib yang didefinisikan dalam skema, LLM tidak dapat menyediakan nilai untuk field tersebut. Program Python kemudian memunculkan ValidationError:
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage
from pydantic import BaseModel, ValidationError
class ProductInfo(BaseModel):
product_name: str
price: float
in_stock: bool
llm = ChatAnthropic(model='claude-sonnet-4-5')
structured_llm = llm.with_structured_output(ProductInfo)
# Input tidak memiliki informasi yang diperlukan
message = HumanMessage(content="""
Ekstrak info produk dari: "Widget-nya bagus! Sangat direkomendasikan."
""")
try:
result = structured_llm.invoke([message])
print(result)
except ValidationError as e:
print("ValidationError terjadi")Catatan: Ketika prompt tidak memiliki informasi untuk field wajib, beberapa LLM mungkin membuat nilai dan menyediakannya dalam respons. Dalam kasus ini,
ValidationErrortidak akan terjadi, tetapi masalah yang lebih besar muncul. Kita akan membahas ini di bagian berikutnya.
Ketika prompt tidak memiliki informasi untuk field wajib dan ValidationError terjadi, ini sebenarnya membantu aplikasi Python kamu. Aplikasi dapat mendeteksi bahwa masalah terjadi dan menangani error dengan cara yang terkontrol. Strategi pemulihan error dibahas di Bab 14 (pemulihan error tingkat agen) dan Bab 17 (logika retry dengan manajemen state).
Masalah yang Lebih Besar: LLM Membuat Informasi yang Hilang
Seperti yang kita bahas di Bagian 7.3, beberapa LLM menunjukkan perilaku yang lebih berbahaya: mereka membuat nilai dan menyediakannya dalam respons ketika informasi hilang dari prompt.
Bagaimana masalah terjadi:
- Prompt tidak memiliki informasi yang diperlukan
- LLM menghasilkan nilai yang terlihat masuk akal
ValidationErrorTIDAK terjadi- Aplikasi Python kamu memproses data yang dibuat-buat seolah-olah itu nyata
Contoh:
class ProductInfo(BaseModel):
product_name: str
price: float
in_stock: bool
message = HumanMessage(content="""
Ekstrak info produk dari: "Widget-nya bagus!"
""")
# Ketika beberapa LLM membuat nilai untuk product_name, price, dan in_stock
result = structured_llm.invoke([message])
# Tidak ada error yang dimunculkan!
print(result.product_name) # "widget" (diekstrak dari teks)
print(result.price) # 0.0 (dibuat-buat!)
print(result.in_stock) # False (dibuat-buat!)
# Masalah: Kamu tidak bisa tahu nilai mana yang nyata vs dibuat-buatIni lebih buruk daripada ValidationError karena:
- Aplikasi Python kamu terus mengeksekusi dengan data yang buruk
- Kamu tidak tahu field mana yang nyata vs dibuat-buat
- Logika downstream mungkin membuat keputusan yang salah berdasarkan data palsu
Solusi: Gunakan Field Opsional dengan Validasi
Solusinya adalah mendefinisikan semua field wajib sebagai Optional, kemudian gunakan validator untuk memeriksa bahwa semua field wajib memiliki nilai.
from typing import Optional
from pydantic import BaseModel, model_validator, ValidationError
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
class ProductInfo(BaseModel):
# Ini sebenarnya wajib, tetapi dideklarasikan sebagai Optional
# Validasi nyata terjadi di validator di bawah
product_name: Optional[str] = None
price: Optional[float] = None
in_stock: Optional[bool] = None
@model_validator(mode='after')
def check_required_fields(self):
"""Validasi bahwa semua field esensial ada"""
if self.product_name is None or self.price is None or self.in_stock is None:
raise ValueError("Semua field (product_name, price, in_stock) harus disediakan")
return self
llm = ChatOpenAI(model="gpt-4o-mini")
structured_llm = llm.with_structured_output(ProductInfo)
# Tes dengan data tidak lengkap
message = HumanMessage(content="""
Ekstrak info produk dari: "Widget-nya bagus!"
""")
try:
result = structured_llm.invoke([message])
# Jika kita sampai di sini, semua field dijamin ada
print(f"Produk: {result.product_name}")
print(f"Harga: ${result.price}")
except ValidationError as e:
# Field wajib hilang - ekstraksi gagal
print(f"Ekstraksi tidak lengkap: {e}")Apa yang terjadi di sini:
@model_validatoradalah decorator Pydantic yang menambahkan logika validasi kustommode='after'berarti validasi berjalan setelah semua field telah di-parse- Jika ada field yang
None, kita memunculkanValueErroruntuk menandakan data tidak lengkap - Pydantic secara otomatis membungkus
ValueErrorini dalamValidationError
Mengapa ini berhasil:
Ketika prompt tidak memiliki informasi untuk field:
- LLM tidak membuat nilai dan menghilangkan field tersebut dari respons
- Dalam kasus ini, field tersebut menjadi
None - Jika field tersebut sebenarnya wajib, validator Pydantic memunculkan
ValueError - Pydantic membungkusnya sebagai
ValidationError
Dengan cara ini, aplikasi Python kamu menerima error eksplisit untuk ditangani, daripada data yang dibuat-buat.
Kesimpulan kunci: Ketika prompt tidak memiliki informasi untuk field wajib, mendapatkan ValidationError adalah normal dan diharapkan. Bahaya sebenarnya adalah data yang dibuat-buat. Gunakan field Optional dengan validator untuk mencegah LLM membuat informasi yang hilang, sambil secara eksplisit mendeteksi ketika field wajib hilang.
Ringkasan Bab:
Di bab ini, kamu belajar cara mengubah output LLM menjadi objek Python yang andal:
- Mengapa penting: Parsing teks bebas rapuh; output berbasis skema menyediakan keamanan tipe
- Cara menggunakannya: Definisikan skema dengan
BaseModelPydantic → Bind dengan.with_structured_output() - Prinsip desain: Pilih field wajib vs opsional, pandu LLM dengan deskripsi field
- Tangani masalah: ValidationError adalah normal; bahaya sebenarnya adalah data yang dibuat-buat