CYBERSOFT
Đăng nhập

Kiểm thử chatbot RAG: grounding, trích dẫn và chống ảo giác trong y tế

Chuyên nâng caoY tếAI AgentNâng caoKinh nghiệmThực tế
🗓 1 tháng trước21 phút đọc·👁 1,342 lượt xem👤 395 người đọc

Đo tách lớp retrieval và generation, kiểm chứng faithfulness/groundedness, tính đúng của trích dẫn, phát hiện ảo giác, ảnh hưởng của chunking và cửa sổ ngữ cảnh, xây eval dataset và guardrails an toàn cho miền y tế.

1. RAG là gì và tại sao kiểm thử nó lại khó

RAG (retrieval-augmented generation) là kiến trúc ghép một bộ truy hồi tài liệu với một mô hình ngôn ngữ lớn. Khi người dùng đặt câu hỏi, hệ thống tìm các đoạn tài liệu liên quan nhất rồi nhồi chúng vào ngữ cảnh để mô hình sinh câu trả lời. Mục tiêu là để câu trả lời bắt nguồn từ tri thức thật thay vì trí nhớ mờ nhạt của mô hình. Trong y tế, RAG thường trả lời về phác đồ, tương tác thuốc hay hướng dẫn nội bộ bệnh viện. Chính vì đầu ra chạm tới sức khoẻ con người, sai một câu có thể gây hại thật.

Kiểm thử RAG khó vì đầu ra không tất định và không có một đáp án chuỗi ký tự duy nhất. Cùng một câu hỏi có thể sinh nhiều diễn đạt đúng khác nhau, nên so sánh chuỗi cứng là vô nghĩa. Hơn nữa, lỗi có thể nằm ở tầng truy hồi (lấy sai đoạn) hoặc ở tầng sinh (bịa dù đoạn đúng). Nếu chỉ nhìn câu trả lời cuối, ta không biết trách khâu nào. Vì thế nguyên tắc cốt lõi của bài này là ĐO TÁCH LỚP: kiểm retrieval riêng, kiểm generation riêng, rồi mới kiểm end-to-end.

Pipeline RAG: đâu là điểm cần kiểm thử Query câu hỏi bệnh nhân Retriever embed · top-k · rerank ⚑ retrieval quality Context chunk · window ⚑ chunking effect LLM Generate answer + citation ⚑ faithfulness Oracle-first: đáp án phải BẮT NGUỒN từ tài liệu lấy về, mọi khẳng định có trích dẫn kiểm chứng được groundedness = answer ⊆ retrieved context · citation trỏ đúng đoạn nguồn Đo tách lớp retrieval: recall@k, MRR, nDCG generation: faithfulness, answer relevancy Y tế: chặn hại không tư vấn liều thuốc ngoài nguồn nghi ngờ → từ chối + chuyển bác sĩ
Pipeline RAG với các điểm cần kiểm thử: retrieval quality, chunking, faithfulness; oracle-first là đáp án phải bắt nguồn từ tài liệu lấy về.
Oracle của RAG không phải 'câu trả lời trông hợp lý', mà là 'mọi khẳng định đều truy được về đoạn nguồn đã lấy'. Đây là bất biến ta sẽ neo mọi test vào.

2. Chất lượng truy hồi: đo tầng retriever trước tiên

Nếu retriever lấy sai đoạn, không mô hình nào cứu được câu trả lời. Vì thế bước đầu là dựng một tập câu hỏi kèm nhãn đoạn tài liệu đúng (ground-truth passages). Với mỗi câu hỏi, ta chạy retriever và so danh sách top-k trả về với nhãn. Ba thước đo phổ biến là recall@k (có bắt được đoạn đúng trong top-k không), MRR (đoạn đúng nằm càng cao càng tốt) và nDCG (thưởng cho thứ hạng và mức liên quan). Đo tầng này tách biệt giúp bạn biết nâng cấp embedding hay thêm rerank có thật sự cải thiện gốc rễ.

typescript
// eval-retrieval.ts — đo tầng retriever tách biệt với ground-truth passages
import { retrieve } from "../rag/retriever";
import goldens from "./retrieval-goldens.json"; // [{ q, relevantDocIds: string[] }]

function recallAtK(returned: string[], relevant: string[], k: number) {
  const top = new Set(returned.slice(0, k));
  const hit = relevant.filter((id) => top.has(id)).length;
  return hit / relevant.length;
}
function reciprocalRank(returned: string[], relevant: string[]) {
  const idx = returned.findIndex((id) => relevant.includes(id));
  return idx === -1 ? 0 : 1 / (idx + 1);
}

const K = 5;
let sumRecall = 0, sumMrr = 0;
for (const g of goldens) {
  const docs = await retrieve(g.q, { k: K });           // trả về mảng docId theo thứ hạng
  sumRecall += recallAtK(docs, g.relevantDocIds, K);
  sumMrr    += reciprocalRank(docs, g.relevantDocIds);
}
const recall = sumRecall / goldens.length;
const mrr = sumMrr / goldens.length;
console.log({ "recall@5": recall.toFixed(3), mrr: mrr.toFixed(3) });
// Oracle-first: gate CI chặn merge nếu recall@5 < baseline (vd 0.85) hoặc MRR tụt.
if (recall < 0.85) throw new Error("Retrieval regression: recall@5 dưới ngưỡng");
  • recall@k: retriever có lấy được ít nhất một đoạn đúng trong top-k không.
  • MRR: đoạn đúng nằm càng cao trong danh sách càng tốt.
  • nDCG: thưởng cho cả thứ hạng lẫn mức độ liên quan của từng đoạn.
  • Đo trên tập câu hỏi có nhãn cố định, chạy lại mỗi khi đổi embedding/chunking.
💡 Giữ retrieval-goldens tách khỏi generation-goldens. Một bug hồi quy retrieval sẽ hiện ngay ở recall@k mà không bị pha loãng bởi biến động của mô hình sinh.

3. Faithfulness & groundedness: câu trả lời có bám nguồn không

Faithfulness (còn gọi groundedness) đo mức độ mọi khẳng định trong câu trả lời được hỗ trợ bởi ngữ cảnh đã lấy về. Một câu trả lời có thể đúng ngữ pháp, trôi chảy, nhưng vẫn chứa một mệnh đề không hề có trong nguồn — đó là ảo giác. Cách kiểm phổ biến là tách câu trả lời thành các mệnh đề nguyên tử, rồi với mỗi mệnh đề hỏi: đoạn nguồn có suy ra được điều này không? Nếu một mệnh đề không được nguồn hỗ trợ, điểm faithfulness giảm. Đây là oracle mạnh nhất của RAG vì nó bắt đúng loại lỗi nguy hiểm nhất trong y tế.

typescript
// eval-faithfulness.ts — tách mệnh đề & kiểm từng cái có được nguồn hỗ trợ
import { askRag } from "../rag/pipeline";
import { splitClaims, entails } from "./nli"; // entails: dùng NLI hoặc LLM-judge có ràng buộc

type Case = { q: string };
export async function faithfulness(c: Case) {
  const { answer, contexts } = await askRag(c.q); // contexts = đoạn thật đã đưa vào prompt
  const claims = splitClaims(answer);              // mệnh đề nguyên tử
  const support = await Promise.all(
    claims.map(async (cl) => ({
      claim: cl,
      grounded: await entails(contexts.join("\n"), cl), // nguồn có suy ra mệnh đề?
    })),
  );
  const grounded = support.filter((s) => s.grounded).length;
  return {
    score: claims.length ? grounded / claims.length : 1,
    ungrounded: support.filter((s) => !s.grounded).map((s) => s.claim), // để review
  };
}
// Oracle: mọi mệnh đề y tế (liều, chống chỉ định) PHẢI grounded === true,
// nếu không → fail cứng, không tính điểm trung bình cho nhóm câu hỏi an toàn.
⚠️ Đừng dùng chính mô hình sinh để tự chấm faithfulness của nó bằng một prompt lỏng — nó thiên vị chính mình. Dùng NLI hoặc một LLM-judge độc lập có rubric rõ, và luôn giữ mẫu để người review.
🔒

Nội dung bị khoá

Bạn đang xem bản xem trước. Đăng nhập để mở khoá toàn bộ bài viết và tất cả tài liệu Tester/QA.

Đã xem 23% nội dung
  • Đọc trọn vẹn mọi bài viết
  • Lưu bài & ghi chú cá nhân
  • Theo dõi tiến độ đã đọc
  • Luyện phỏng vấn, ISTQB, Mock
Đăng nhập để đọc tiếp

Chưa có mã? Lấy mã qua Fanpage / Zalo CyberSoft.

0

💬 Bình luận (0)

Bạn có thể đọc mọi bình luận. Đăng nhập để bình luận

Chưa có bình luận nào. Hãy là người đầu tiên!