Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 4 — Trích xuất & chuẩn hóa dữ liệu có cấu trúc từ text thô

Đã đọc 0/8 mục · còn khoảng 4 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Bài 4 — Trích xuất & chuẩn hóa dữ liệu có cấu trúc

Sau bài 3 bạn có nhiều đoạn text thô kèm URL nguồn. Muốn so sánh đối thủ thì phải biến text thành bảng: mỗi đối thủ một hàng, mỗi tiêu chí một cột, và mỗi ô kèm nguồn. Đây là bước biến "đọc hiểu" thành "dữ liệu".

Nguyên tắc vàng: định nghĩa schema TRƯỚC

Đừng để LLM tự do trả về. Hãy ép nó điền vào một cấu trúc bạn định nghĩa sẵn (structured output). Điều này chống lan man và bắt buộc gắn nguồn.

from pydantic import BaseModel
from typing import Optional

class Fact(BaseModel):
    value: str            # ví dụ "0đ cho 3 lần đầu/tháng"
    source_url: str       # BẮT BUỘC
    confidence: float     # 0-1, agent tự đánh giá

class CompetitorRow(BaseModel):
    name: str
    withdrawal_fee: Optional[Fact] = None
    cashback: Optional[Fact] = None
    recent_hiring: Optional[Fact] = None

Mỗi dữ kiện là một Fact luôn đi kèm source_url. Không nguồn thì để trống, không được bịa.

Các bước trích xuất

  • Ghép text + URL thành một khối context cho LLM, giữ rõ đoạn nào từ URL nào.
  • Gọi LLM với chỉ dẫn nghiêm ngặt và schema:
prompt = f"""Trích thông tin về đối thủ {name} từ các nguồn dưới đây.
QUY TẮC:
- Chỉ dùng thông tin CÓ trong nguồn. Không suy đoán.
- Mỗi trường phải kèm source_url là URL đã chứa thông tin đó.
- Nếu không tìm thấy, để null. TUYỆT ĐỐI không bịa.

NGUỒN:
{sources_block}
"""
# gọi model với response_format = CompetitorRow
  • Validate bằng Pydantic. Nếu model trả sai schema, bắt lỗi và thử lại 1 lần.
  • Kiểm tra chéo source_url có thật nằm trong danh sách nguồn không — chống model tự chế URL.
def verify_sources(row, allowed_urls):
    for f in [row.withdrawal_fee, row.cashback, row.recent_hiring]:
        if f and f.source_url not in allowed_urls:
            f.confidence = 0.0   # cờ đỏ: nguồn không khớp
    return row

Chuẩn hóa (normalize) để so sánh được

Dữ liệu thô mỗi nơi một kiểu: "miễn phí", "0 đồng", "Free". Muốn so sánh phải quy về chuẩn:

  • Tiền tệ → cùng đơn vị (VND).
  • "miễn phí"/"free"/"0đ" → 0.
  • Ngày tháng → định dạng YYYY-MM-DD.
  • Đơn vị % giữ số, bỏ ký hiệu.
def normalize_fee(s):
    s = s.lower()
    if any(k in s for k in ["miễn phí", "free", "0đ", "0 đồng"]):
        return 0
    digits = "".join(ch for ch in s if ch.isdigit())
    return int(digits) if digits else None

Khung tư duy: mỗi ô = Giá trị + Nguồn + Độ tin

Một ô dữ liệu tốt luôn trả lời được 3 câu: Con số là gì? Lấy ở đâu? Tin được bao nhiêu? Thiếu bất kỳ vế nào thì ô đó chưa dùng được cho báo cáo ra quyết định.

Sai lầm thường gặp

  • Để LLM trả text tự do rồi tự parse — cực dễ vỡ và mất nguồn.
  • Không ép source_url — báo cáo đẹp nhưng không kiểm chứng được.
  • Tin URL do model tự sinh — model có thể chế ra URL nghe hợp lý mà không tồn tại.
  • Quên normalize — không thể so sánh "Free" với "1.000đ".
  • Không xử lý null — ép model điền bằng mọi giá dẫn tới bịa số.
  • Gộp nhiều đối thủ trong 1 lần gọi lớn — dễ lẫn nguồn giữa các đối thủ.

Checklist khâu trích xuất

  • [ ] Schema định nghĩa trước, mỗi Fact có source_url
  • [ ] Prompt cấm bịa, cho phép null
  • [ ] Validate schema + retry 1 lần
  • [ ] Kiểm tra source_url nằm trong nguồn thật
  • [ ] Dữ liệu đã normalize về đơn vị chung

Ví dụ: kết quả một hàng dữ liệu đạt chuẩn

{
  "name": "MoMo",
  "withdrawal_fee": {
    "value": "0đ cho 3 lần đầu/tháng, sau đó 0,5%",
    "source_url": "https://momo.vn/phi",
    "confidence": 0.9
  },
  "recent_hiring": {
    "value": "đang tuyển 2 vị trí Data Scientist",
    "source_url": "https://tuyendung.momo.vn",
    "confidence": 0.7
  }
}

Hàng dữ liệu này dùng được vì mỗi ô có value, source_url thật và confidence để bài 5-7 biết ô nào đủ tin cho khuyến nghị. Ô cashback để null vì không tìm thấy nguồn — đúng tinh thần "thà trống còn hơn bịa". Khi bạn nhìn thấy một hàng như thế này, khâu trích xuất coi như đạt.

Bài 5: tổng hợp các hàng dữ liệu này thành báo cáo so sánh mạch lạc.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi