Xây dựng AI Agent chuẩn Production với Pydantic AI: Hướng dẫn thực hành Python

AI tutorial - IT technology blog
AI tutorial - IT technology blog

Khoảng cách về độ tin cậy: Tại sao dữ liệu tất định lại quan trọng trong AI

Làm việc với các Mô hình ngôn ngữ lớn (LLM) thường mang lại cảm giác như đang đánh cược vào một phản hồi JSON. Bạn soạn thảo một prompt hoàn hảo, nhưng thỉnh thoảng mô hình lại trả về một dấu phẩy thừa, một lời mở đầu dài dòng hoặc một chuỗi ký tự ở nơi mà cơ sở dữ liệu của bạn mong đợi một số nguyên. Trong kinh nghiệm xây dựng các hệ thống hỗ trợ tự động của tôi, những sự không nhất quán nhỏ này gây ra hơn 80% lỗi vận hành trong các ứng dụng dựa trên LLM.

Mặc dù LangChain cung cấp một hệ sinh thái rộng lớn, nhiều lập trình viên nhận thấy bản chất “nặng về chuỗi” (string-heavy) của nó rất khó để debug. Đây là lúc Pydantic AI thay đổi cuộc chơi. Được tạo ra bởi đội ngũ đứng sau thư viện xác thực Pydantic tiêu chuẩn ngành, framework này coi các đầu ra của LLM là dữ liệu có cấu trúc phải vượt qua kiểm tra schema trước khi logic của bạn được thực thi. Nó biến “hộp đen” của LLM thành một thành phần có kiểu dữ liệu rõ ràng và có thể dự đoán được.

Làm chủ các agent type-safe là sự khác biệt giữa một bản mẫu (prototype) và một hệ thống bền bỉ. Bằng cách sử dụng type hint của Python để định nghĩa đầu ra cho agent, bạn sẽ lấy lại được lợi ích từ tính năng tự động hoàn thành của IDE và phân tích tĩnh. Thay vì phát hiện ra một phản hồi sai định dạng vào lúc 3 giờ sáng khi lưu lượng truy cập tăng vọt, bạn sẽ bắt được các lỗi không khớp schema ngay trong quá trình phát triển.

Tại sao Pydantic AI đang ngày càng phổ biến

  • Linh hoạt mô hình: Chuyển đổi giữa OpenAI, Gemini và Groq chỉ bằng cách thay đổi một dòng mã.
  • Tự động xác thực: Tận dụng Pydantic v2 để đảm bảo đầu ra khớp chính xác với đặc tả của bạn.
  • Dependency Injection sạch sẽ: Truyền các kết nối cơ sở dữ liệu hoặc các client đã xác thực vào công cụ mà không cần biến toàn cục.
  • Logic Python chuẩn: Không còn bị lạc trong các “chuỗi” (chains) phức tạp hay các đồ thị nội bộ ẩn giấu. Tất cả chỉ là Python.

Cài đặt: Chuẩn bị môi trường phát triển

Pydantic AI yêu cầu Python 3.9 trở lên. Tôi khuyên bạn nên sử dụng một môi trường ảo riêng biệt để tránh xung đột phụ thuộc với các thư viện cũ hơn.

# Tạo và kích hoạt môi trường ảo của bạn
python -m venv venv
source venv/bin/activate  # Người dùng Windows: venv\Scripts\activate

# Cài đặt thư viện cốt lõi và hỗ trợ OpenAI
pip install pydantic-ai openai

Bạn sẽ cần một API key để tiếp tục. Mặc dù hướng dẫn này sử dụng GPT-4o của OpenAI, logic vẫn tương tự nếu bạn thích Claude hoặc các mô hình chạy cục bộ qua Ollama. Thiết lập key của bạn trong terminal:

export OPENAI_API_KEY='nhập-api-key-của-bạn-tại-đây'

Triển khai: Tạo bộ phân loại Type-Safe

Hãy xây dựng một Bộ phân loại Ticket hỗ trợ (Support Ticket Classifier). Agent này sẽ chuyển đổi các email lộn xộn của khách hàng thành các đối tượng có cấu trúc. Nếu LLM cố gắng tạo ra một danh mục nằm ngoài danh sách cho phép, Pydantic AI sẽ tự động kích hoạt một vòng lặp sửa lỗi.

1. Định nghĩa Schema dữ liệu

Chúng ta bắt đầu bằng cách định nghĩa “hình dáng” của dữ liệu. Sử dụng model Pydantic đảm bảo mọi trường đều được xác thực.

from pydantic import BaseModel, Field
from enum import Enum

class Category(str, Enum):
    technical = "technical"
    billing = "billing"
    feature_request = "feature_request"

class TicketClassification(BaseModel):
    category: Category
    priority: int = Field(ge=1, le=5, description="1 là thấp, 5 là cao")
    summary: str
    is_urgent: bool

2. Khởi tạo Agent

Tiếp theo, chúng ta cấu hình agent. Chúng ta yêu cầu nó trả về một đối tượng TicketClassification thay vì một chuỗi văn bản thuần túy.

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel

model = OpenAIModel('gpt-4o')

classifier_agent = Agent(
    model,
    result_type=TicketClassification,
    system_prompt="Phân tích các ticket hỗ trợ khách hàng. Hãy chính xác với các mức độ ưu tiên.",
)

3. Nâng cấp với Tool

Các agent thực sự hữu ích khi chúng tương tác với hạ tầng hiện có của bạn. Pydantic AI sử dụng decorator @agent.tool để cấp quyền cho LLM truy cập vào các hàm bên ngoài, chẳng hạn như kiểm tra gói đăng ký của người dùng trong cơ sở dữ liệu.

from dataclasses import dataclass

@dataclass
class UserDeps:
    user_id: str
    has_premium: bool

@classifier_agent.tool
def check_subscription(ctx, user_id: str) -> str:
    # Hàm này giả lập việc tra cứu cơ sở dữ liệu
    status = "premium" if ctx.deps.has_premium else "free"
    return f"Người dùng {user_id} đang sử dụng gói {status}."

4. Thực thi Workflow

Chạy agent trong một hàm bất đồng bộ. Thuộc tính result.data sẽ là một đối tượng Python có kiểu dữ liệu đầy đủ, không phải là một dictionary hay một chuỗi.

async def main():
    deps = UserDeps(user_id="user_99", has_premium=True)
    
    result = await classifier_agent.run(
        "Tôi không thể truy cập cổng thanh toán và tôi cần thanh toán hóa đơn ngay lập tức!",
        deps=deps
    )
    
    print(f"Danh mục: {result.data.category}") # billing
    print(f"Độ ưu tiên: {result.data.priority}") # 5

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

Khả năng quan sát: Giám sát và Kiểm thử

Triển khai một agent mới chỉ là một nửa chặng đường. Bạn cần biết nó hoạt động như thế nào khi có sự cố xảy ra.

Tự phục hồi (Self-Healing Retries)

Điều gì xảy ra nếu LLM gán mức độ ưu tiên là “10” mặc dù chúng ta đã ràng buộc le=5? Pydantic AI xử lý việc này một cách nhẹ nhàng. Nó gửi lỗi xác thực ngược lại cho LLM, giải thích lỗi sai và yêu cầu một phản hồi đã được chỉnh sửa. Vòng lặp thử lại nội bộ này giúp giảm đáng kể mã xử lý lỗi thủ công.

Tích hợp sẵn Logfire để theo dõi

Pydantic AI tích hợp trực tiếp với Logfire. Điều này cung cấp một dòng thời gian trực quan của mọi cuộc gọi LLM, thực thi công cụ và nỗ lực xác thực. Thay vì phải lục lọi trong các bản log văn bản thô, bạn có một dashboard sạch sẽ hiển thị chính xác nơi mà prompt có thể đang gặp lỗi.

import logfire

logfire.configure()
logfire.instrument_openai()
# Các vết (trace) của Agent hiện đã được gửi đến dashboard của Logfire

Mocking cho Unit Test

Đừng bao giờ kiểm thử logic ứng dụng của bạn bằng cách thực hiện các cuộc gọi API trực tiếp; nó vừa chậm vừa tốn kém. Sử dụng TestModel để mô phỏng các phản hồi LLM khác nhau. Điều này cho phép bạn xác minh rằng các công cụ và dependency của mình hoạt động chính xác trong môi trường CI/CD được kiểm soát mà không tốn một xu nào cho token.

from pydantic_ai.models.test import TestModel

def test_agent_logic():
    test_model = TestModel()
    with classifier_agent.override(model=test_model):
        # Chạy các test case với mô hình mock
        pass

Bằng cách áp dụng các mô hình này, bạn sẽ thoát khỏi kiểu phát triển “viết prompt và cầu nguyện”. Bạn coi AI như một thành phần có cấu trúc, có kiểu dữ liệu rõ ràng trong kiến trúc phần mềm của mình — giống như một cơ sở dữ liệu hoặc một REST API. Kỷ luật này là thứ phân biệt các kịch bản thử nghiệm với các ứng dụng AI sẵn sàng cho môi trường production.

Share: