Trường hợp sử dụng có giá trị nhưng nhàm chán
Trong hai thập kỷ, việc trích xuất dữ liệu có cấu trúc từ tài liệu phi cấu trúc là một dự án kéo dài cả quý: pipeline OCR, quy tắc regex, xử lý các trường hợp đặc biệt, mẫu bố cục cho từng nhà cung cấp. Với một LLM bị ràng buộc bởi JSON schema, công việc này chỉ còn 30 dòng mã, chính xác ngay lần chạy đầu và có thể triển khai trong một ngày. Các ví dụ dưới đây chạy trên Kunavo, một gateway độc lập tương thích với OpenAI, nhưng mô hình này thuộc về các model và hoạt động tương tự với bất kỳ model nào.
Chỉ trích xuất hóa đơn? Trang này là phần tổng quan xuyên tài liệu. Hướng dẫn trích xuất dữ liệu hóa đơn chuyên biệt đi sâu vào loại tài liệu đó: cách các phương pháp mẫu và model cũ so sánh với một cuộc gọi vision-LLM, hướng dẫn Python đầy đủ có ràng buộc schema, rào chắn số học, định tuyến model hai tầng và chi phí trên mỗi hóa đơn.
Các nhóm tài liệu mà phương pháp này đặc biệt hiệu quả:
- Hóa đơn, biên lai, đơn đặt hàng
- Hợp đồng, thỏa thuận pháp lý (trích xuất các bên, ngày tháng, nghĩa vụ)
- Sơ yếu lý lịch / CV (phân tích thành cấu trúc thân thiện với ATS)
- Làm giàu khách hàng tiềm năng từ chữ ký email hoặc trang web
- Hồ sơ y tế, báo cáo xét nghiệm (kèm xử lý PII)
- Tin đăng bất động sản, danh mục sản phẩm
- Phân loại email và nhập dữ liệu có cấu trúc
Mô hình cốt lõi trong 30 dòng
import json
from openai import OpenAI
client = OpenAI(api_key="sk-kn-...", base_url="https://api.kunavo.com/v1")
# The schema is the output contract. Claude enforces a json_schema
# response_format (json_object it does not), so the reply has this shape
# unless max_tokens cuts it off (finish_reason == "length").
STR = {"type": ["string", "null"]}
NUM = {"type": ["number", "null"]}
INVOICE = {
"type": "object",
"properties": {
"vendor": {"type": "string"},
"invoice_number": STR, "date_iso": STR, "due_date_iso": STR,
"currency": STR, "subtotal": NUM, "tax": NUM, "total": NUM,
"line_items": {"type": "array", "items": {
"type": "object",
"properties": {"description": {"type": "string"},
"qty": NUM, "unit_price": NUM, "amount": NUM},
"required": ["description", "qty", "unit_price", "amount"],
"additionalProperties": False,
}},
},
"required": ["vendor", "invoice_number", "date_iso", "due_date_iso",
"currency", "subtotal", "tax", "total", "line_items"],
"additionalProperties": False,
}
RESPONSE_FORMAT = {"type": "json_schema",
"json_schema": {"name": "invoice", "schema": INVOICE}}
RULES = "Extract the invoice. Use null for missing fields. Dates in ISO 8601."
# Extract structured fields from an invoice PDF (after OCR)
def extract_invoice(ocr_text: str) -> dict:
resp = client.chat.completions.create(
model="claude-haiku-4-5",
messages=[
{"role": "system", "content": RULES},
{"role": "user", "content": ocr_text},
],
response_format=RESPONSE_FORMAT,
max_tokens=1200,
)
return json.loads(resp.choices[0].message.content)
# Extract from an image directly (no OCR step needed)
def extract_invoice_from_image(image_url: str) -> dict:
resp = client.chat.completions.create(
model="claude-haiku-4-5", # vision + an enforced schema
messages=[
{"role": "system", "content": RULES},
{"role": "user", "content": [
{"type": "text", "text": "Extract this invoice:"},
{"type": "image_url", "image_url": {"url": image_url}},
]},
],
response_format=RESPONSE_FORMAT,
max_tokens=1200,
)
return json.loads(resp.choices[0].message.content)Có hai luồng: chỉ văn bản (sau một bước OCR riêng) và trực tiếp bằng vision (model vision đọc hình ảnh và xuất JSON trong một cuộc gọi). Luồng vision xây dựng nhanh hơn nhưng đắt hơn một chút cho mỗi cuộc gọi; luồng OCR rồi LLM rẻ hơn ở quy mô lớn vì OCR chỉ là chi phí một lần cho mỗi trang.
Benchmark độ chính xác
Trên một bộ dữ liệu hóa đơn công khai (1.000 hóa đơn từ 50 nhà cung cấp), chế độ JSON với system prompt 200 từ:
- Claude Haiku 4.5: độ chính xác cấp trường 96%
- Claude Sonnet 4.6: độ chính xác cấp trường 98%
- Templating truyền thống: 80-90% với nhà cung cấp đã biết, 0% với nhà cung cấp mới
LLM xử lý bố cục của nhà cung cấp mới theo zero-shot. Thêm 2-3 cặp ví dụ vào system prompt (few-shot), Haiku sẽ tiến gần độ chính xác của Sonnet với một phần nhỏ chi phí.
Chi phí trên mỗi tài liệu
- Hóa đơn (~2K token đầu vào, ~500 token đầu ra): Haiku ~$0,003, Sonnet ~$0,02
- Hợp đồng một trang (~5K token đầu vào): Haiku ~$0,005, Sonnet ~$0,04
- Hợp đồng 10 trang (~50K token đầu vào, đầu ra là bản tóm tắt có cấu trúc): Sonnet ~$0,30
- Sơ yếu lý lịch (~3K token đầu vào): Haiku ~$0,003
- Ảnh biên lai với vision: Haiku, khoảng bằng chi phí của một hóa đơn — hình ảnh được tính xấp xỉ 1.5K token đầu vào
Xử lý 10.000 hóa đơn/tháng: khoảng $30 với Haiku. Giải pháp thương mại gần nhất (Rossum, AWS Textract + hậu xử lý) có giá khoảng $2.000–5.000/tháng cho cùng khối lượng.
5 mô hình giúp duy trì độ chính xác cao
- Xử lý null rõ ràng: yêu cầu model sử dụng
nullcho các trường bị thiếu, không dùng "N/A" hoặc chuỗi rỗng. Mã downstream có thể phân biệt “không có” với “cố ý để trống” - Ngày ISO 8601: nêu rõ điều này. Nếu không, model sẽ chọn các định dạng theo khu vực và việc phân tích downstream sẽ hỏng
- Tiền tệ dưới dạng mã ISO: "USD" thay vì "$"; "EUR" thay vì "€". Tránh mơ hồ ($ có thể là USD, CAD hoặc AUD)
- Xác thực JSON: dùng Pydantic / Zod để áp dụng schema. Nếu không hợp lệ, hãy gửi lại lời nhắc kèm lỗi
- Kiểm tra thủ công 1% trong một tuần, sau đó duy trì 0,1%. Theo dõi độ chính xác cấp trường, không chỉ cấp bản ghi
Khi nào dùng model nào
| Loại tài liệu | Model đề xuất |
|---|---|
| Có cấu trúc đơn giản (hóa đơn, biên lai) | Claude Haiku 4.5 |
| Hợp đồng / thỏa thuận dài | Claude Sonnet 5 (xử lý ngữ cảnh dài) |
| Trực tiếp bằng vision (PDF không OCR) | Claude Haiku 4.5, hoặc Claude Sonnet 5 cho các trang lớn |
| Tác vụ quan trọng (pháp lý, y tế) | Claude Sonnet 5 + xác minh bởi con người |
| Nhập dữ liệu hàng loạt (100K+/ngày) | Haiku 4.5 + ví dụ few-shot + bộ nhớ đệm |
Các cân nhắc về tuân thủ
Đối với tài liệu chứa PII (hóa đơn có tên, địa chỉ; hồ sơ y tế có mọi thông tin), hãy giả danh hóa trước khi trích xuất hoặc sử dụng Zero Data Retention ở hệ thống trước đó. Xem hướng dẫn tuân thủ để biết các mẫu theo từng khu vực và phân tích chuyên sâu về DSGVO cho quy trình dành cho Đức.
Bắt đầu: /app/signup — thanh toán theo mức sử dụng; khoản nạp $10 đủ cho khoảng 3.000 lần trích xuất hóa đơn và số dư không bao giờ hết hạn. Đọc tài liệu chat tại /docs/chat để biết response_format thực thi điều gì trên từng họ mô hình và các mẫu sử dụng công cụ.
Câu hỏi thường gặp
Trích xuất dữ liệu từ tài liệu bằng LLM tốn bao nhiêu?
Chi phí khoảng 0,003–0,005 USD mỗi tài liệu với Claude Haiku 4.5 và khoảng 0,02–0,04 USD với Claude Sonnet 4.6. Xử lý 10.000 hóa đơn mỗi tháng tốn khoảng 30 USD, so với 2,000–5,000 USD cho các dịch vụ trích xuất thương mại.
Trích xuất dữ liệu bằng LLM không cần ví dụ chính xác đến mức nào?
Độ chính xác ở cấp trường dữ liệu đạt 95–98% mà không cần ví dụ, với khoảng 30 dòng mã — đủ chính xác để thay thế quy trình OCR kết hợp regex.
Nên dùng mô hình nào để trích xuất dữ liệu từ tài liệu?
Tài liệu có cấu trúc đơn giản như hóa đơn và biên lai dùng Claude Haiku 4.5. Hợp đồng dài dùng Claude Sonnet 4.6. Tài liệu được đọc trực tiếp dưới dạng ảnh dùng Claude Haiku 4.5, hoặc Sonnet 4.6 với trang lớn.
Làm thế nào để duy trì độ chính xác của trích xuất khi đưa vào môi trường thực tế?
Năm phương pháp: xử lý null rõ ràng, ngày theo ISO 8601, mã tiền tệ ISO, xác thực lược đồ và yêu cầu tạo lại khi đầu ra không hợp lệ, cùng với kiểm tra thủ công ngẫu nhiên — 1% đầu ra trong tuần đầu, sau đó duy trì ở mức 0,1%. Theo dõi độ chính xác ở cấp trường dữ liệu thay vì cấp bản ghi.