Back to Explore
Xây dựng hệ thống RAG doanh nghiệp: Kiểm chứng câu trả lời trước khi hiển thị cho người dùng

Xây dựng hệ thống RAG doanh nghiệp: Kiểm chứng câu trả lời trước khi hiển thị cho người dùng

Bài viết đi sâu vào kỹ thuật kiểm chứng (validation) trong hệ thống RAG doanh nghiệp. Từ việc kiểm tra định dạng, đối chiếu trích dẫn (quotes) đến việc xây dựng vòng lặp phản hồi (feedback loop), giúp đảm bảo độ chính xác và tin cậy trước khi phản hồi đến người dùng cuối.

Website
Upvote this postSign in to upvote this article.

Giới thiệu

Đây là phần cuối trong chuỗi bài về "Enterprise Document Intelligence" (Trí tuệ tài liệu doanh nghiệp), tập trung vào "viên gạch" cuối cùng: Generation (Tạo sinh). Trước đó, chúng ta đã đi qua parsing tài liệu, parsing câu hỏi và truy xuất (retrieval). Bài viết này sẽ giải quyết vấn đề: làm thế nào để đảm bảo câu trả lời từ LLM là chính xác, có căn cứ và có thể kiểm chứng trước khi hiển thị cho người dùng.

Ảnh minh họa

1. Tin tưởng nhưng phải kiểm chứng (Trust but verify)

Đầu ra có cấu trúc (structured output) chỉ là bước khởi đầu. LLM thường xuyên gặp các lỗi như: trích dẫn sai dòng, diễn giải lại các nội dung được yêu cầu trích dẫn nguyên văn, hoặc gán nhãn complete_answer_found=True cho một câu trả lời không đầy đủ.

1.1. Bộ kiểm chứng (Validator)

Bộ kiểm chứng cần thực hiện 3 kiểm tra chính:

  • Hình dạng (Shape): Đảm bảo câu trả lời khớp với schema đã định nghĩa.
  • Bằng chứng (Evidence): Mọi Span phải tham chiếu đến dải dòng (line range) thực tế, mọi trích dẫn phải là chuỗi con của các dòng được trích dẫn.
  • Định dạng (Format): Kiểm tra ISO 8601 cho ngày tháng, ISO 4217 cho tiền tệ.
def validate_answer(answer: AnswerBase, line_df: pd.DataFrame,
                    parsed_q: ParsedQuestion | None = None) -> list[str]:
    errors: list[str] = []
    valid_lines = set(line_df["overall_line_num"].values)

    # Kiểm tra schema
    if parsed_q is not None:
        ExpectedSchema = ANSWER_REGISTRY[parsed_q.expected_answer_shape]
        if not isinstance(answer, ExpectedSchema):
            errors.append(f"shape mismatch: {ExpectedSchema.__name__} expected")

    # Kiểm tra tính nhất quán
    if bool(answer.items) != answer.answer_found:
        errors.append(f"answer_found mismatch len(items)={len(answer.items)}")

    # Kiểm tra chi tiết từng span
    for i, item in enumerate(answer.items):
        for j, sp in enumerate(item.spans):
            if sp.line_start not in valid_lines:
                errors.append(f"line_start {sp.line_start} not in input")
            if sp.quote:
                cited = _join_cited_lines(line_df, sp)
                if _normalize(sp.quote) not in _normalize(cited):
                    errors.append(f"quote not verbatim in cited lines")
    return errors

1.2. Thách thức với trích dẫn nguyên văn (Verbatim)

Việc kiểm tra trích dẫn thường thất bại do:

  1. Khoảng trắng và tham chiếu: PDF parser thường chia nhỏ đoạn văn. Cần chuẩn hóa (collapse whitespace, loại bỏ [N]) trước khi so sánh.
  2. Nhầm lẫn dòng liền kề: LLM thường chọn sai số dòng (off-by-one).
  3. Trích dẫn bị cắt cụt: Span không bao phủ hết nội dung trích dẫn.

1.3. Xử lý khi validation thất bại

Có 3 hướng xử lý:

  • Retry: Thử lại với prompt nghiêm ngặt hơn.
  • Flag for review: Trả về câu trả lời kèm cảnh báo.
  • Reject: Từ chối trả lời nếu là các nghiệp vụ quan trọng (pháp lý, tài chính).

2. "Not Found" là một kết quả hạng nhất

Trong RAG doanh nghiệp, trả lời sai nguy hiểm hơn là không trả lời. Để thực hiện "Not Found" hiệu quả:

  • Schema phải cho phép items=[], answer_found=False.
  • System prompt phải ép buộc model trả về trạng thái này nếu không tìm thấy dữ liệu.
  • Code phía sau phải xử lý trường hợp answer_found=False một cách rõ ràng thay vì cố gắng render dữ liệu rỗng.

3. Nâng cấp trích dẫn lên Bounding Box (Bbox)

Để hiển thị vùng bôi vàng trên PDF, ta cần ánh xạ từ số dòng (line number) sang tọa độ (x0, y0, x1, y1). Việc này được thực hiện bằng cách join kết quả của LLM với line_df đã được tạo từ bước parsing.

def bboxes_for_citation(line_df, *, page, line_start, line_end):
    matched = line_df[
        (line_df["page_num"] == page) &
        (line_df["line_num"] >= line_start) &
        (line_df["line_num"] <= line_end)
    ]
    return {"x0": matched["x0"].min(), "y0": matched["y0"].min(), ...}

4. Đóng vòng lặp phản hồi (Feedback Loop)

Thay vì chỉ là generate -> respond, hệ thống cần có các tín hiệu phản hồi:

  • Same-run signals: Nếu complete_answer_found=False, hệ thống tự động mở rộng phạm vi truy xuất (retrieval) và gọi lại model.
  • Long-term signals: Lưu trữ các từ khóa mới (llm_discovered_keywords) vào từ điển chuyên gia để cải thiện truy xuất cho các lần sau.

5. Kết luận

Việc kiểm chứng câu trả lời trước khi hiển thị không chỉ là một bước kỹ thuật, mà là một yêu cầu bắt buộc để xây dựng hệ thống RAG tin cậy. Bằng cách sử dụng schema chặt chẽ, validation nghiêm ngặt và các vòng lặp phản hồi, bạn có thể biến một model LLM thông thường thành một hệ thống doanh nghiệp có khả năng tự kiểm soát và cải thiện chất lượng.

Discussion (0)

You need to log in to post comments. Log In

No comments yet. Start the discussion!

Do you like this post?

Upvote to push this post higher on the community feed

Details

Posted by: @admin
Categories: AI Tools
Date posted: 8 tháng 7, 2026