Kết quả đầu ra có cấu trúc và sử dụng công cụ tạo prompt cho lập trình

Đầu ra văn bản là ổn cho trò chuyện. Nhưng các ứng dụng sản xuất cần dữ liệu - những đối tượng JSON, các trường được định kiểu, schema được xác thực. Bạn cần LLM trả về một từ điển Python, chứ không phải một đoạn văn.

🔄 Tóm tắt nhanh: Trong Bài học 2, bạn đã học các kỹ thuật tạo prompt - few-shot, CoT, prompt hệ thống. Những kỹ thuật đó tạo ra văn bản tốt. Bài học này sẽ làm cho văn bản đó có thể được máy phân tích cú pháp.

Thứ tự ưu tiên về độ tin cậy của đầu ra có cấu trúc: Đầu ra có cấu trúc > JSON Mode > Chỉ prompt. Chúng ta hãy cùng tìm hiểu từng cấp độ.

Cấp độ 1: Chỉ prompt (Không nên làm điều này trong môi trường sản xuất)

Cách tiếp cận đơn giản: Thêm "Phản hồi bằng JSON" vào prompt của bạn.

response = client.chat.completions.create(
    model="gpt-4.1",
    messages=[{"role": "user", "content": "Trích xuất tên và email từ văn bản này. Phản hồi bằng JSON.\n\nText: Liên hệ với John tại john@example.com"}]
)

Cách này hoạt động khoảng 80% thời gian. 20% còn lại? Mô hình bọc JSON trong các code block markdown, thêm văn bản giải thích trước JSON, sử dụng tên trường không mong muốn hoặc trả về JSON không hợp lệ.

Không bao giờ sử dụng chế độ chỉ prompt cho đầu ra có cấu trúc trong môi trường sản xuất.

Cấp độ 2: JSON Mode

JSON Mode đảm bảo JSON hợp lệ về mặt cú pháp. Mô hình sẽ luôn trả về JSON có thể phân tích được.

response = client.chat.completions.create(
    model="gpt-4.1",
    messages=[{"role": "user", "content": "Trích xuất tên và email dưới dạng JSON"}],
    response_format={"type": "json_object"}
)

Điều được đảm bảo: Cú pháp JSON hợp lệ.

Điều không được đảm bảo: Schema cụ thể của bạn. Bạn có thể nhận được {"name": "John"} một lần và {"full_name": "John", "email_address": "john@example.com"} lần tiếp theo.

Kiểm tra nhanh: JSON Mode trả về {"name": "John", "email": "john@example.com"} trong lần gọi đầu tiên và {"user": {"name": "John"}, "contact": "john@example.com"} trong lần gọi thứ hai. Cả hai đều là JSON hợp lệ. Có gì sai?

Câu trả lời: Code xử lý tiếp theo của bạn mong đợi các tên trường cụ thể ở các cấp độ lồng nhau cụ thể. JSON hợp lệ với schema không thể đoán trước gần như tệ như JSON không hợp lệ - code phân tích cú pháp của bạn sẽ bị lỗi trong cả hai trường hợp. Bạn cần thực thi schema, chứ không chỉ là xác thực cú pháp.

Cấp độ 3: Đầu ra có cấu trúc (Sử dụng cái này)

Đầu ra có cấu trúc thực thi schema chính xác của bạn. Bạn xác định các trường, kiểu dữ liệu và độ lồng nhau - mô hình sẽ khớp chúng một cách chính xác.

OpenAI:

from pydantic import BaseModel

class ContactInfo(BaseModel):
    name: str
    email: str
    company: str | None = None

response = client.beta.chat.completions.parse(
    model="gpt-4.1",
    messages=[{"role": "user", "content": "Thông tin liên hệ: John tại john@example.com, làm việc tại Acme Corp"}],
    response_format=ContactInfo
)

contact = response.choices[0].message.parsed
# contact.name == "John"
# contact.email == "john@example.com"
# contact.company == "Acme Corp"

Anthropic (Claude) với Instructor:

import instructor
from anthropic import Anthropic

client = instructor.from_anthropic(Anthropic())

contact = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Liên hệ: John tại john@example.com, Acme Corp"}],
    response_model=ContactInfo
)

Thư viện Instructor hoạt động trên hơn 15 nhà cung cấp và bổ sung tính năng tự động thử lại với xác thực.

Gọi hàm và sử dụng công cụ

Việc gọi hàm cho phép LLM gọi code của bạn. Bạn định nghĩa các hàm có sẵn dưới dạng JSON schema; mô hình sẽ quyết định khi nào và cách gọi chúng.

Khi nào nên sử dụng gọi hàm:

  • LLM cần dữ liệu bên ngoài (tra cứu cơ sở dữ liệu, gọi API)
  • LLM cần thực hiện các hành động (gửi email, tạo bản ghi)
  • Bạn muốn LLM lựa chọn giữa nhiều khả năng

Ví dụ: Công cụ tra cứu thời tiết

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "Full city name (e.g., 'San Francisco', not 'SF')"
                },
                "unit": {
                    "type": "string",
                    "enum": ["metric", "imperial"],
                    "description": "Temperature unit system"
                }
            },
            "required": ["city"]
        }
    }
}]

Các quy tắc chính cho định nghĩa công cụ:

  • Mô tả chi tiết — mô hình sẽ đọc những mô tả này để quyết định khi nào và cách gọi
  • Ràng buộc Enum — cho các tham số có giá trị hợp lệ cố định
  • Bắt buộc so với tùy chọn — đánh dấu những gì là bắt buộc
  • Ví dụ trong mô tả — "Tên thành phố đầy đủ (ví dụ: 'San Francisco')"

Kiểm tra nhanh: Bạn định nghĩa 20 công cụ cho LLM agent của mình. Thời gian phản hồi tăng từ 200ms lên 2 giây. Tại sao?

Câu trả lời: Mỗi định nghĩa công cụ tiêu tốn token trong cửa sổ ngữ cảnh. 20 schema công cụ chi tiết có thể thêm hàng nghìn token cho mỗi yêu cầu, làm tăng độ trễ và chi phí. Giải pháp: chỉ bao gồm các công cụ liên quan đến nhiệm vụ hiện tại. Nếu người dùng đang hỏi về thời tiết, đừng bao gồm các công cụ cơ sở dữ liệu. Việc lựa chọn công cụ động dựa trên ngữ cảnh hội thoại giúp danh sách công cụ gọn nhẹ.

Các mẫu xác thực và thử lại

Ngay cả với đầu ra có cấu trúc, vẫn có thể xảy ra lỗi: Mô hình có thể tạo ra giá trị không hợp lệ về mặt logic (trường email chứa "N/A" thay vì email hợp lệ) hoặc vượt quá giới hạn (danh sách có 100 mục trong khi bạn chỉ muốn 5).

Quá trình xác thực của Pydantic bắt được những lỗi này:

from pydantic import BaseModel, Field, field_validator

class TaskExtraction(BaseModel):
    title: str = Field(max_length=100)
    priority: int = Field(ge=1, le=5)
    tags: list[str] = Field(max_length=5)

    @field_validator('title')
    def title_not_empty(cls, v):
        if not v.strip():
            raise ValueError('Title cannot be empty')
        return v

Khi quá trình xác thực thất bại, Instructor sẽ tự động thử lại - gửi thông báo lỗi trở lại mô hình để nó có thể khắc phục sự cố cụ thể.

Những điểm chính cần ghi nhớ

  • Sử dụng đầu ra có cấu trúc cho sản xuất — không phải JSON Mode, không phải chỉ prompt ("phản hồi bằng JSON")
  • Các mô hình Pydantic xác định schema của bạn: Tên trường, kiểu dữ liệu, ràng buộc và quy tắc xác thực
  • Việc gọi hàm kết nối LLM với code của bạn — chất lượng phụ thuộc vào mô tả schema chi tiết với các ví dụ và kiểu liệt kê
  • Thư viện Instructor (Python) bổ sung tính năng tự động thử lại khi xác thực thất bại trên hơn 15 nhà cung cấp
  • Giữ danh sách công cụ gọn nhẹ — chỉ bao gồm các công cụ liên quan đến nhiệm vụ hiện tại để quản lý độ trễ và chi phí
  • Câu 1:

    Ứng dụng của bạn gọi LLM và nhận được phản hồi có cấu trúc, nhưng 2% số lần phản hồi không vượt qua được quá trình xác thực Pydantic. Giải pháp tối ưu cho môi trường sản xuất là gì?

    GIẢI THÍCH:

    Thư viện Instructor (hơn 11.000 lượt đánh dấu sao trên GitHub, hơn 3 triệu lượt tải xuống hàng tháng) tự động hóa mô hình này. Nó bao bọc các lệnh gọi API bằng xác thực Pydantic và, khi thất bại, sẽ thử lại với thông báo lỗi được bao gồm - để LLM thấy điều gì đã xảy ra và sửa chữa nó. Kết quả điển hình: Tỷ lệ thành công lần đầu 98% → 99,9% với một lần thử lại. Đó là độ tin cậy ở cấp độ sản xuất.

  • Câu 2:

    Bạn định nghĩa một hàm để LLM gọi: get_weather(city: str, unit: str). LLM gọi hàm get_weather('NYC', 'celsius'). Nhưng API của bạn lại mong đợi 'New York City'' và 'metric'. Vấn đề là gì?

    GIẢI THÍCH:

    Việc gọi hàm chỉ tốt khi mô tả schema của bạn tốt. LLM đọc mô tả tham số của bạn để quyết định cách điền chúng. Mô tả mơ hồ tạo ra các đối số mơ hồ. Thêm ràng buộc enum cho các tùy chọn cố định, mô tả định dạng cho chuỗi, giá trị ví dụ trong mô tả và ràng buộc phạm vi cho số. Schema là hợp đồng của bạn với LLM. Thêm giá trị enum cho các đơn vị hợp lệ ('metric', 'imperial') và mô tả tham số thành phố: 'Tên đầy đủ của thành phố, ví dụ: Thành phố New York, không phải viết tắt.' LLM ánh xạ ý định của người dùng vào schema của bạn dựa trên mô tả tham số.

  • Câu 3:

    Bạn sử dụng JSON Mode và LLM trả về JSON hợp lệ — nhưng với tên trường không mong muốn (ví dụ: 'user_name' thay vì 'username'). Làm thế nào để ngăn chặn điều này?

    GIẢI THÍCH:

    JSON Mode cung cấp cho bạn JSON hợp lệ. Đầu ra có cấu trúc cung cấp cho bạn JSON hợp lệ khớp chính xác với schema của bạn. Nếu bạn định nghĩa username là trường chuỗi bắt buộc, đó là những gì bạn nhận được - mọi lúc. JSON Mode có thể trả về user_name, userName hoặc name tùy thuộc vào trạng thái của mô hình. Đối với code sản xuất, đầu ra có cấu trúc loại bỏ toàn bộ một nhóm lỗi phân tích cú pháp. JSON Mode đảm bảo cú pháp JSON hợp lệ nhưng không tuân thủ schema. Đầu ra có cấu trúc thực thi schema chính xác của bạn - bao gồm tên trường, kiểu dữ liệu và các trường bắt buộc/tùy chọn.

Thứ Hai, 04/05/2026 11:33
52 👨 31
Xác thực tài khoản!

Theo Nghị định 147/2024/ND-CP, bạn cần xác thực tài khoản trước khi sử dụng tính năng này. Chúng tôi sẽ gửi mã xác thực qua SMS hoặc Zalo tới số điện thoại mà bạn nhập dưới đây:

Số điện thoại chưa đúng định dạng!
Số điện thoại này đã được xác thực!
Bạn có thể dùng Sđt này đăng nhập tại đây!
Lỗi gửi SMS, liên hệ Admin
0 Bình luận
Sắp xếp theo
    ❖ Kỹ thuật thiết kế Prompt