Quay lại các trường hợp sử dụng
Xử lý dữ liệu

Trích xuất dữ liệu bằng AI — đầu ra có cấu trúc từ PDF, hóa đơn và văn bản không có cấu trúc

Trường hợp sử dụng đơn giản nhưng có giá trị. Hóa đơn, biên lai, hợp đồng, khách hàng tiềm năng, CV — bất cứ nơi nào trước đây bạn sẽ xây dựng parser, một LLM tuân theo JSON schema có thể xử lý trong 30 dòng, chính xác hơn và bạn có thể triển khai trong một ngày thay vì một quý.

Mô hình được đề xuất

Được xem xét lần cuối vào .

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

extract.py
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 null cho 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ệuModel đề 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àiClaude 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.