Giới thiệu: Vấn đề thực tế mà ai cũng gặp phải

Khi bạn làm việc với AI API, có một tình huống rất hay xảy ra: AI trả về dữ liệu dạng văn bản tự do (free text), và bạn phải tự viết code để "cắt ghép" trích xuất thông tin. Ví dụ: yêu cầu AI liệt kê 5 sản phẩm, nhưng kết quả trả về là một đoạn văn bản dài, và bạn phải dùng split(), regex... để tách ra. Thật mệt mỏi!

Giải pháp: Kết hợp Pydantic với AI API để AI tự động trả về dữ liệu đúng format, và Pydantic sẽ xác thực (validate) dữ liệu đó. Bạn nhận được Python object chính xác như mong muốn, không cần xử lý thủ công.

Trong bài viết này, mình sẽ hướng dẫn bạn từng bước, từ cài đặt đến ứng dụng thực tế. (Nếu chưa có tài khoản API, bạn có thể Đăng ký tại đây để nhận tín dụng miễn phí khi bắt đầu.)

Pydantic là gì? Giải thích đơn giản cho người mới

Hãy tưởng tượng bạn điền đơn xin việc. Đơn có các ô: Họ tên, Tuổi, Lương mong muốn. Nếu bạn điền "Họ tên" vào ô "Tuổi", đơn sẽ bị đánh dấu sai. Pydantic hoạt động giống như cái "đơn" đó - nó định nghĩa trước cấu trúc dữ liệu bạn muốn, và tự động kiểm tra xem dữ liệu nhập vào có đúng format không.

# Định nghĩa cấu trúc dữ liệu với Pydantic
from pydantic import BaseModel

class NhanVien(BaseModel):
    ho_ten: str
    tuoi: int
    luong: float

Tạo object - Pydantic tự kiểm tra type

nv = NhanVien(ho_ten="Nguyễn Văn A", tuoi=25, luong=15000000) print(nv.ho_ten) # Output: Nguyễn Văn A

Thử sai format - Pydantic sẽ báo lỗi!

nv_sai = NhanVien(ho_ten="Test", tuoi="hai mươi lăm", luong="15 triệu")

→ ValidationError: tuổi phải là số nguyên

Thiết lập môi trường và kết nối HolySheep AI API

Bước 1: Cài đặt thư viện cần thiết

# Cài đặt các thư viện cần thiết
pip install pydantic openai httpx

openai phiên bản mới hỗ trợ nhiều provider

httpx để gọi API với custom base_url

Bước 2: Kết nối với HolySheep AI

HolySheep AI là API provider với giá cực kỳ cạnh tranh: GPT-4.1 chỉ $8/MTok, rẻ hơn 85% so với nguồn khác. Đặc biệt hỗ trợ WeChat Pay và Alipay cho người dùng Trung Quốc.

import os
from openai import OpenAI
from pydantic import BaseModel
from typing import List, Optional

============ CẤU HÌNH API HOLYSHEEP ============

client = OpenAI( api_key="YOUR_HOLYSHEEP_API_KEY", # Thay bằng API key của bạn base_url="https://api.holysheep.ai/v1" # ✅ Base URL chính xác )

Kiểm tra kết nối

models = client.models.list() print("Kết nối thành công! Các model khả dụng:") for model in models.data[:5]: print(f" - {model.id}")

Ứng dụng thực tế: Trích xuất thông tin sản phẩm từ văn bản

Ví dụ 1: Định nghĩa schema cho dữ liệu sản phẩm

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

class DanhMucSanPham(str, Enum):
    DIEN_THOAI = "điện thoại"
    LAPTOP = "laptop"
    TABLET = "tablet"
    PHU_KIEN = "phụ kiện"

class SanPham(BaseModel):
    ten: str = Field(..., min_length=2, description="Tên sản phẩm")
    gia: float = Field(..., gt=0, description="Giá sản phẩm (VNĐ)")
    danh_muc: DanhMucSanPham
    mo_ta_ngan: str = Field(..., max_length=200)
    khuyen_mai: Optional[str] = None
    
    @field_validator('gia')
    @classmethod
    def gia_phai_la_so_duong(cls, v):
        if v <= 0:
            raise ValueError('Giá phải lớn hơn 0')
        return v

class DanhSachSanPham(BaseModel):
    san_phams: List[SanPham]
    tong_so: int
    nguon: str = "AI trích xuất"

Xem cấu trúc JSON schema

print(SanPham.model_json_schema())

Ví dụ 2: Gọi AI và nhận dữ liệu có cấu trúc

import json

def trich_xuat_san_pham(van_ban_mota: str) -> DanhSachSanPham:
    """
    Trích xuất thông tin sản phẩm từ văn bản mô tả
    """
    
    # Định nghĩa yêu cầu cho AI
    prompt = f"""Bạn là chuyên gia phân tích sản phẩm công nghệ.
Hãy đọc văn bản sau và trích xuất THÔNG TIN CHÍNH XÁC các sản phẩm:
    
VĂN BẢN:
{van_ban_mota}

YÊU CẦU TRẢ VỀ:
- Trả về danh sách các sản phẩm tìm được
- Mỗi sản phẩm gồm: tên, giá (VNĐ), danh mục, mô tả ngắn
- Nếu không có thông tin giá, hãy ước lượng hợp lý
- Trả về JSON theo đúng cấu trúc được định nghĩa"""
    
    response = client.chat.completions.create(
        model="gpt-4.1",
        messages=[
            {"role": "system", "content": "Bạn trả về JSON theo đúng schema được cung cấp."},
            {"role": "user", "content": prompt}
        ],
        response_format={
            "type": "json_schema",
            "json_schema": DanhSachSanPham.model_json_schema()
        },
        temperature=0.3
    )
    
    # Lấy kết quả JSON
    ket_qua_json = response.choices[0].message.content
    return DanhSachSanPham.model_validate_json(ket_qua_json)

============== SỬ DỤNG ==============

van_ban = """ Cửa hàng TechZone giới thiệu các sản phẩm mới: 1. iPhone 15 Pro Max - Giá 34.990.000đ - Smartphone cao cấp nhất của Apple 2. MacBook Air M3 - Giá 28.990.000đ - Laptop mỏng nhẹ cho dân văn phòng 3. iPad Air M2 - Giá 16.990.000đ - Tablet đa năng cho học sinh sinh viên 4. Tai nghe AirPods Pro 2 - Giá 5.990.000đ - Phụ kiện chống ồn chất lượng cao """

Gọi hàm và nhận kết quả đã được validate

ket_qua = trich_xuat_san_pham(van_ban)

Sử dụng dữ liệu dễ dàng như object thông thường

print(f"Tổng số sản phẩm: {ket_qua.tong_so}") for sp in ket_qua.san_phams: print(f"\n📱 {sp.ten}") print(f" 💰 Giá: {sp.gia:,.0f} VNĐ") print(f" 🏷️ Danh mục: {sp.danh_muc.value}") print(f" 📝 {sp.mo_ta_ngan}")

Ứng dụng nâng cao: Hệ thống phân tích đánh giá khách hàng

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

class CamXuc(str):
    TICH_CUC = "tích cực"
    TRUNG_TINH = "trung tính"
    TIEN_CUC = "tiêu cực"

class MucDo(int):
    def __new__(cls, value):
        if not 1 <= value <= 5:
            raise ValueError("Mức độ phải từ 1 đến 5 sao")
        return super().__new__(cls, value)

class DanhGiaKhachHang(BaseModel):
    noi_dung: str
    cam_xuc: CamXuc
    muc_do_hai_long: int = Field(..., ge=1, le=5, description="Sao từ 1-5")
    cac_tieu_chuan: List[str] = Field(default_factory=list)
    
class BaoCaoPhanTich(BaseModel):
    ngay_phan_tich: str
    tong_danh_gia: int
    diem_trung_binh: float
    ti_le_tich_cuc: float = Field(..., ge=0, le=1)
    cac_van_de_noi_bat: List[str] = Field(default_factory=list)
    danh_gia_mau: List[DanhGiaKhachHang]

def phan_tich_danh_gia(danh_sach_danh_gia: List[str]) -> BaoCaoPhanTich:
    prompt = f"""Phân tích các đánh giá khách hàng sau và trả về báo cáo JSON:
    
DANH SÁCH ĐÁNH GIÁ:
{chr(10).join(f"- {dg}" for dg in danh_sach_danh_gia)}

YÊU CẦU:
1. Đếm tổng số đánh giá
2. Tính điểm trung bình mức độ hài lòng (1-5 sao)
3. Tính tỷ lệ đánh giá tích cực
4. Liệt kê các vấn đề khách hàng phản ánh nhiều nhất
5. Chọn 2-3 đánh giá tiêu biểu
"""
    
    response = client.chat.completions.create(
        model="gpt-4.1",
        messages=[{"role": "user", "content": prompt}],
        response_format={
            "type": "json_schema", 
            "json_schema": BaoCaoPhanTich.model_json_schema()
        }
    )
    
    return BaoCaoPhanTich.model_validate_json(
        response.choices[0].message.content
    )

============== DEMO ==============

danh_gias = [ "Sản phẩm tốt, giao hàng nhanh nhưng đóng gói hơi đơn giản. 4 sao!", "Rất hài lòng! Nhân viên tư vấn nhiệt tình, sẽ ủng hộ tiếp ⭐⭐⭐⭐⭐", "Chất lượng không như kỳ vọng, màn hình có điểm sáng. 2 sao", "Giá cả hợp lý, bảo hành tốt. Mình mua lần 3 rồi, luôn tin tưởng!" ] bao_cao = phan_tich_danh_gia(danh_gias) print(f"📊 BÁO CÁO PHÂN TÍCH - {bao_cao.ngay_phan_tich}") print(f"Tổng đánh giá: {bao_cao.tong_danh_gia}") print(f"Điểm TB: {bao_cao.diem_trung_binh}/5 ⭐") print(f"Tỷ lệ tích cực: {bao_cao.ti_le_tich_cuc*100:.0f}%") print(f"\n⚠️ Vấn đề nổi bật:") for van_de in bao_cao.cac_van_de_noi_bat: print(f" • {van_de}")

Xử lý lỗi thông minh với Pydantic

from pydantic import ValidationError, BaseModel, Field
import json

class NguoiDung(BaseModel):
    ten: str = Field(..., min_length=2)