0Pricing
AI Engineering Academy · Pelajaran

Keluaran Terstruktur dengan Pydantic

Definisikan model Pydantic sebagai skema keluaran Anda, teruskan model tersebut ke API melalui fitur keluaran terstruktur yang baru, dan deserialisasikan respons secara otomatis menjadi objek Python bertipe.

Keluaran Terstruktur dengan Pydantic adalah pelajaran AI Engineering Academy gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Engineering Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Engineering Academy mencakup 4 pelajaran total.

Mengapa Pydantic untuk Keluaran LLM?

Pydantic adalah pustaka validasi data Python yang mendefinisikan skema data menggunakan petunjuk tipe Python. Pydantic unggul dalam memvalidasi dan melakukan deserialisasi data dari sumber eksternal — dan keluaran LLM adalah salah satu sumber eksternal paling tidak andal yang akan Anda temui. Menggabungkan skema Pydantic dengan keluaran terstruktur OpenAI memberikan respons yang aman tipe, tervalidasi, dan dideserialisasi secara otomatis dari model AI.

Alih-alih menulis data = json.loads(response) lalu mengekstrak bidang dan melakukan konversi tipe secara manual, Anda mendapatkan objek Python bertipe lengkap yang setiap bidangnya dijamin memiliki tipe yang benar, lengkap dengan pelengkapan otomatis di IDE dan validasi saat runtime. Beginilah cara tim rekayasa AI profesional menangani ekstraksi terstruktur.

Mendefinisikan Skema Pydantic Dasar

Model Pydantic adalah kelas yang mewarisi BaseModel dengan bidang yang didefinisikan menggunakan anotasi tipe Python. Tipe bidang dapat berupa tipe primitif Python, model Pydantic lain untuk struktur bertingkat, atau tipe dari modul typing untuk daftar, tipe opsional, dan gabungan.

from pydantic import BaseModel, Field
from typing import Optional, List
from enum import Enum

class Sentiment(str, Enum):
    positive = 'positive'
    negative = 'negative'
    neutral = 'neutral'

class ReviewAnalysis(BaseModel):
    sentiment: Sentiment
    confidence: float = Field(ge=0.0, le=1.0, description='Confidence score 0-1')
    key_themes: List[str] = Field(description='Main topics mentioned in the review')
    summary: str = Field(max_length=200, description='One-sentence summary')
    product_name: Optional[str] = Field(default=None, description='Product mentioned, if any')
    would_recommend: Optional[bool] = None

# Pydantic validates types and constraints at instantiation
example = ReviewAnalysis(
    sentiment=Sentiment.positive,
    confidence=0.95,
    key_themes=['fast delivery', 'good quality'],
    summary='Customer loves the product and quick shipping.',
    product_name='Wireless Headphones',
    would_recommend=True
)
print(example.model_dump_json(indent=2))

Pydantic dengan Keluaran Terstruktur OpenAI

Berikan kelas model Pydantic Anda secara langsung ke parameter response_format dari client.beta.chat.completions.parse(). SDK secara otomatis mengonversi model tersebut menjadi JSON Schema, mengirimkannya ke API, dan melakukan deserialisasi terhadap respons kembali menjadi objek Python bertipe.

import openai
from pydantic import BaseModel
from typing import List, Optional
from enum import Enum

client = openai.OpenAI()

class Sentiment(str, Enum):
    positive = 'positive'
    negative = 'negative'
    neutral = 'neutral'

class ReviewAnalysis(BaseModel):
    sentiment: Sentiment
    confidence: float
    key_themes: List[str]
    summary: str
    would_recommend: Optional[bool]

review_text = '''
I bought this laptop for my design work and I am blown away. It handles Photoshop
like a dream, the screen colors are beautiful, and it has not slowed down once in
three months. Battery life could be better but overall highly recommend!
'''

result = client.beta.chat.completions.parse(
    model='gpt-4o-mini',
    messages=[
        {'role': 'system', 'content': 'Analyze the customer review and extract structured information.'},
        {'role': 'user', 'content': review_text}
    ],
    response_format=ReviewAnalysis
)

analysis = result.choices[0].message.parsed
print(f'Sentiment: {analysis.sentiment.value}')
print(f'Confidence: {analysis.confidence}')
print(f'Themes: {analysis.key_themes}')
print(f'Recommend: {analysis.would_recommend}')

Model Pydantic Bertingkat

Skema Pydantic dapat merujuk pada model Pydantic lain, sehingga memungkinkan keluaran terstruktur bertingkat dengan tingkat kedalaman apa pun. Ini ideal untuk mengekstrak data hierarkis dari dokumen seperti kontrak, faktur, resume, dan rekam medis.

from pydantic import BaseModel
from typing import List, Optional

class Address(BaseModel):
    street: Optional[str]
    city: str
    country: str
    postal_code: Optional[str]

class ContactInfo(BaseModel):
    email: Optional[str]
    phone: Optional[str]
    address: Optional[Address]

class Person(BaseModel):
    full_name: str
    age: Optional[int]
    job_title: Optional[str]
    contact: ContactInfo
    skills: List[str]

# When you pass Person to response_format, the API generates:
# {
#   "full_name": "...",
#   "contact": {
#     "email": "...",
#     "address": { "city": "...", "country": "..." }
#   },
#   "skills": ["...", "..."]
# }
print('Nested model defined - pass to response_format for extraction')

Validasi Bidang dengan Validator Pydantic

Validator Pydantic memungkinkan Anda menambahkan logika validasi khusus di luar pemeriksaan tipe sederhana. Anda dapat memvalidasi bahwa skor keyakinan berada di antara 0 dan 1, bahwa harga tidak negatif, atau bahwa string tanggal memiliki format yang benar. Saat LLM mengembalikan nilai yang gagal divalidasi, Pydantic memunculkan ValidationError yang dapat Anda tangkap dan tangani.

from pydantic import BaseModel, Field, field_validator
from typing import Optional
import re

class ExtractedContact(BaseModel):
    name: str
    email: Optional[str] = None
    phone: Optional[str] = None
    confidence: float = Field(ge=0.0, le=1.0)

    @field_validator('email')
    @classmethod
    def validate_email(cls, v):
        if v is not None:
            # Basic email format check
            if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', v):
                raise ValueError(f'Invalid email format: {v}')
        return v

    @field_validator('phone')
    @classmethod
    def normalize_phone(cls, v):
        if v is not None:
            # Remove non-digit characters for normalization
            digits = re.sub(r'[^0-9+]', '', v)
            return digits
        return v

try:
    contact = ExtractedContact(name='Alice', email='not-an-email', confidence=0.9)
except Exception as e:
    print(f'Validation error: {e}')

Mengekstrak Daftar Objek

Pola yang umum adalah mengekstrak beberapa instans entitas yang sama dari sebuah dokumen — semua item baris dari faktur, semua item tindakan dari transkrip rapat, atau semua entitas dari artikel berita. Bungkus model Anda dalam model wadah dengan bidang daftar untuk menangani kasus ini dengan rapi.

import openai
from pydantic import BaseModel
from typing import List

client = openai.OpenAI()

class ActionItem(BaseModel):
    task: str
    assignee: str
    due_date: str  # or use datetime with proper parsing
    priority: str  # high / medium / low

class MeetingNotes(BaseModel):
    meeting_title: str
    action_items: List[ActionItem]
    key_decisions: List[str]

meeting_transcript = '''
Q3 Planning Meeting - June 2025
Decision: Launch new feature in July.
Decision: Extend free trial to 30 days.
Action: Alice to finalize designs by June 30th - High priority.
Action: Bob to write API docs by July 5th - Medium priority.
Action: Carol to set up staging environment by June 28th - High priority.
'''

result = client.beta.chat.completions.parse(
    model='gpt-4o-mini',
    messages=[
        {'role': 'system', 'content': 'Extract structured data from meeting notes.'},
        {'role': 'user', 'content': meeting_transcript}
    ],
    response_format=MeetingNotes
)
notes = result.choices[0].message.parsed
for item in notes.action_items:
    print(f'[{item.priority.upper()}] {item.task} -> {item.assignee} by {item.due_date}')

Bidang Opsional dan Nilai Bawaan

Dokumen dunia nyata tidak selalu lengkap. Resume mungkin tidak mencantumkan nomor telepon; faktur mungkin tidak memiliki nomor faktur; ulasan produk mungkin tidak menyebutkan nama produk. Rancang model Pydantic Anda agar dapat menangani data yang hilang dengan baik menggunakan bidang Optional dengan nilai bawaan yang sesuai.

Bidang yang dianotasi sebagai Optional[str] = None memberi tahu Pydantic dan LLM bahwa bidang tersebut boleh tidak ada. Model akan mengembalikan null dalam JSON untuk bidang yang tidak dapat diekstraknya, dan Pydantic akan melakukan deserialisasi menjadi None milik Python, sehingga Anda dapat menanganinya dengan rapi pada tahap berikutnya tanpa pengecualian KeyError.

Mengonversi Model Pydantic menjadi JSON Schema

Model Pydantic yang Anda definisikan secara otomatis dikonversi menjadi JSON Schema saat diteruskan ke API. Anda dapat memeriksa skema ini untuk memahami secara tepat apa yang akan diberlakukan oleh API, yang berguna untuk men-debug kasus ketika model tidak mengembalikan struktur yang Anda harapkan.

from pydantic import BaseModel, Field
from typing import List, Optional
import json

class ProductExtraction(BaseModel):
    name: str = Field(description='Product name as mentioned in the text')
    price_usd: Optional[float] = Field(default=None, description='Price in USD')
    features: List[str] = Field(default_factory=list)
    in_stock: bool = Field(description='Whether the product is currently available')

# See the JSON Schema that will be sent to the API
schema = ProductExtraction.model_json_schema()
print(json.dumps(schema, indent=2))
# This shows exactly what constraints the API will enforce

Menangani Kegagalan Ekstraksi

Bahkan dengan keluaran terstruktur, ekstraksi dapat gagal dalam dua cara: model menolak merespons (mengembalikan penolakan), atau dokumen memang tidak memuat informasi yang diminta sehingga model mengembalikan null untuk bidang yang diperlukan — yang memicu kesalahan validasi Pydantic karena bidang yang diperlukan tidak boleh bernilai null.

Pendekatan paling aman adalah menjadikan semua bidang Optional dengan nilai bawaan, menerima nilai null untuk data yang hilang, dan menerapkan validasi logika bisnis Anda sendiri setelah ekstraksi. Hal ini memisahkan perhatian ekstraksi (mengambil data dari teks) dari perhatian validasi (memeriksa bahwa data memenuhi persyaratan Anda).

import openai
from pydantic import BaseModel, ValidationError
from typing import Optional

client = openai.OpenAI()

class ContactExtraction(BaseModel):
    name: Optional[str] = None
    email: Optional[str] = None
    phone: Optional[str] = None

try:
    result = client.beta.chat.completions.parse(
        model='gpt-4o-mini',
        messages=[
            {'role': 'system', 'content': 'Extract contact information.'},
            {'role': 'user', 'content': 'I would like to discuss partnership opportunities.'}
        ],
        response_format=ContactExtraction
    )
    msg = result.choices[0].message
    if msg.refusal:
        print('Refused:', msg.refusal)
    else:
        contact = msg.parsed
        if not any([contact.name, contact.email, contact.phone]):
            print('No contact information found in text')
        else:
            print(contact.model_dump())
except ValidationError as e:
    print('Validation failed:', e)

Menggunakan Pustaka instructor dengan Pydantic

Pustaka instructor adalah paket pihak ketiga populer yang menambal klien OpenAI untuk mendukung ekstraksi berbasis Pydantic dengan percobaan ulang otomatis saat validasi gagal. Jika model mengembalikan keluaran yang gagal dalam validasi Pydantic Anda, instructor secara otomatis mencoba lagi dengan perintah yang menyertakan kesalahan validasi, sehingga model memiliki kesempatan untuk memperbaiki dirinya sendiri.

Ini sangat berguna dalam pipeline ekstraksi massal ketika Anda tidak dapat meninjau setiap hasil secara manual dan ingin sistem memperbaiki dirinya sendiri tanpa campur tangan manusia.

# pip install instructor
import instructor
import openai
from pydantic import BaseModel, Field
from typing import Optional

# Patch the OpenAI client with instructor
client = instructor.from_openai(openai.OpenAI())

class ProductInfo(BaseModel):
    name: str
    price_usd: float = Field(gt=0, description='Price must be positive')
    brand: Optional[str] = None

# instructor automatically retries if Pydantic validation fails
product = client.chat.completions.create(
    model='gpt-4o-mini',
    messages=[
        {'role': 'user', 'content': 'The Sony WH-1000XM5 headphones cost $279.99 at Best Buy.'}
    ],
    response_model=ProductInfo,  # instructor-specific parameter
    max_retries=3
)
print(f'{product.name}: ${product.price_usd} by {product.brand}')

Gabungan Terbedakan dan Skema Dinamis

Pydantic mendukung gabungan terbedakan — skema yang strukturnya bergantung pada nilai bidang pembeda. Ini berguna ketika berbagai tipe dokumen memiliki dasar yang sama tetapi bidang tambahan yang berbeda. Sebagai contoh, laporan pengeluaran mungkin memiliki tanda terima penerbangan (dengan keberangkatan/kedatangan) atau tanda terima hotel (dengan tanggal check-in/check-out).

Dengan menggunakan tipe Union bersama bidang pembeda Literal, Anda dapat mendefinisikan satu skema ekstraksi yang menangani berbagai varian dokumen, dengan model memilih subtipe yang benar berdasarkan isi dokumen. Pydantic secara otomatis memvalidasi terhadap subtipe yang benar berdasarkan nilai pembeda.

from pydantic import BaseModel
from typing import Union, Literal, Optional

class FlightExpense(BaseModel):
    expense_type: Literal['flight']
    airline: str
    departure_city: str
    arrival_city: str
    amount_usd: float

class HotelExpense(BaseModel):
    expense_type: Literal['hotel']
    hotel_name: str
    check_in: str
    check_out: str
    amount_usd: float

class MealExpense(BaseModel):
    expense_type: Literal['meal']
    restaurant: Optional[str]
    amount_usd: float

class ExpenseReport(BaseModel):
    submitter: str
    expenses: list[Union[FlightExpense, HotelExpense, MealExpense]]
    total_usd: float

print('Discriminated union schema - model selects correct subtype per item')

Pemeriksaan Singkat

Uji pemahaman Anda tentang konsep Rekayasa AI dari pelajaran ini.

Ringkasan Pelajaran

Dalam pelajaran ini Anda mempelajari bahwa: subkelas Pydantic BaseModel mendefinisikan skema ekstraksi bertipe kuat yang diberlakukan oleh keluaran terstruktur OpenAI pada tingkat API, model bertingkat, bidang Optional, dan tipe List menangani struktur dokumen dunia nyata yang kompleks, dan pustaka instructor menambahkan percobaan ulang otomatis saat validasi gagal untuk pipeline ekstraksi massal yang tangguh. Selanjutnya, kita akan membangun pipeline ekstraksi informasi lengkap untuk sumber teks tidak terstruktur.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Keluaran Terstruktur dengan Pydantic” gratis?

Ya — teks lengkap “Keluaran Terstruktur dengan Pydantic” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Engineering Academy, upgrade ke CoddyKit PRO. Kursus AI Engineering Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Keluaran Terstruktur dengan Pydantic”?

Definisikan model Pydantic sebagai skema keluaran Anda, teruskan model tersebut ke API melalui fitur keluaran terstruktur yang baru, dan deserialisasikan respons secara otomatis menjadi objek Python… Kamu berlatih AI Engineering Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Engineering Academy?

Tidak diperlukan pengalaman sebelumnya. AI Engineering Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Keluaran Terstruktur dengan Pydantic” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Engineering Academy ini?

Ya. Setiap pelajaran AI Engineering Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Mode JSON dan response_format
  2. Keluaran Terstruktur dengan Pydantic
  3. Mengekstrak Data dari Teks Tidak Terstruktur
  4. Memvalidasi dan Mencoba Ulang Keluaran yang Buruk
← Kembali ke AI Engineering Academy