Chuyển đến nội dung chính

Kiến trúc RAG cho dữ liệu y tế

Với dữ liệu y tế, RAG không chỉ cần tìm đoạn văn có nghĩa gần với câu hỏi. Hệ thống còn phải xác định đúng bệnh nhân, đúng loại tài liệu, đúng thời điểm và chỉ đưa những thông tin người dùng được phép truy cập vào ngữ cảnh của mô hình.

RAG với dữ liệu y tế là cách kết hợp truy xuất thông tin với mô hình ngôn ngữ để trả lời dựa trên hồ sơ, hướng dẫn chuyên môn hoặc tài liệu lâm sàng cụ thể. So với RAG trên tài liệu thông thường, miền y tế yêu cầu kiểm soát dữ liệu và nguồn chặt chẽ hơn vì một đoạn thông tin sai bệnh nhân hoặc sai thời điểm có thể làm thay đổi hoàn toàn ý nghĩa của câu trả lời.

Bài viết này tiếp tục từ kiến trúc RAG cơ bản và tập trung vào phần khó hơn: biến dữ liệu y tế không đồng nhất thành một kho tri thức có thể truy xuất, đồng thời hạn chế việc mô hình suy diễn vượt quá bằng chứng được cung cấp.

Vì sao RAG trên dữ liệu y tế khó hơn tìm kiếm tài liệu?

Một kho dữ liệu y tế có thể chứa ghi chú khám bệnh, kết quả xét nghiệm, đơn thuốc, chẩn đoán, báo cáo hình ảnh, tài liệu hướng dẫn và nhiều loại dữ liệu khác. Hai đoạn văn có thể rất giống nhau về ngữ nghĩa nhưng thuộc hai bệnh nhân khác nhau hoặc được ghi nhận ở hai thời điểm khác nhau.

Vì vậy, tìm kiếm dựa trên embedding đơn thuần thường chưa đủ. Hệ thống cần kết hợp semantic retrieval với metadata như mã bệnh nhân, loại tài liệu, ngày ghi nhận, cơ sở y tế, chuyên khoa và quyền truy cập.

Luồng RAG phù hợp hơn cho dữ liệu y tế
```
1. Câu hỏi: Người dùng gửi yêu cầu.
↓
2. Kiểm soát truy cập: Xác định người dùng được phép xem bệnh nhân và loại dữ liệu nào.
↓
3. Metadata filtering: Giới hạn dữ liệu theo bệnh nhân, thời gian, loại tài liệu hoặc chuyên khoa.
↓
4. Retrieval: Tìm các đoạn phù hợp nhất trong tập dữ liệu đã được phép truy cập.
↓
5. Generation: Gemini tổng hợp câu trả lời và chỉ sử dụng bằng chứng được cung cấp.
↓
6. Output: Trả câu trả lời kèm nguồn hoặc thông tin hỗ trợ truy vết.
```

Thứ tự này rất quan trọng. Quyền truy cập và metadata nên được áp dụng trước hoặc trong retrieval thay vì truy xuất toàn bộ dữ liệu rồi mới cố loại bỏ thông tin nhạy cảm sau đó.

Chuẩn hóa dữ liệu trước khi tạo embedding

Dữ liệu lâm sàng thường không được viết như một tài liệu hoàn chỉnh. Một bản ghi có thể chứa nhiều trường riêng biệt như triệu chứng, thuốc đang dùng, kết quả xét nghiệm và đánh giá của bác sĩ. Nếu ghép mọi thứ thành một chuỗi dài rồi chia chunk theo số ký tự, hệ thống dễ làm mất cấu trúc quan trọng.

Với RAG y tế, một chiến lược tốt hơn là tạo chunk theo đơn vị ngữ nghĩa. Ví dụ, một kết quả xét nghiệm có thể là một chunk; một phần Assessment trong ghi chú lâm sàng có thể là chunk khác; danh sách thuốc có thể được lưu như một nhóm riêng.

Ví dụ: thay vì lưu cả hồ sơ khám trong một chunk, có thể tách thành “Chief complaint”, “Medications”, “Laboratory results”, “Assessment” và “Plan”. Mỗi chunk vẫn mang metadata cho biết nó thuộc lần khám nào và bệnh nhân nào.

Metadata có vai trò gần như ngang với embedding. Một record tối giản có thể chứa nội dung văn bản cùng các thuộc tính như patient_id, document_type, encounter_date và source_id.

documents = [
    {
        "text": "HbA1c: 7.1%. Mẫu được lấy trong lần khám ngoại trú.",
        "patient_id": "P001",
        "document_type": "laboratory",
        "encounter_date": "2026-01-10",
        "source_id": "LAB-001"
    },
    {
        "text": "Đang sử dụng metformin theo đơn hiện tại.",
        "patient_id": "P001",
        "document_type": "medication",
        "encounter_date": "2026-01-10",
        "source_id": "MED-001"
    }
]

Dữ liệu trên chỉ là ví dụ giả lập. Trong hệ thống thật, thông tin nhận dạng và dữ liệu sức khỏe cần được xử lý theo yêu cầu bảo mật, quyền truy cập và quy định áp dụng cho tổ chức triển khai.

Lọc metadata trước khi tính độ tương đồng

Giả sử bác sĩ đang xem hồ sơ bệnh nhân P001 và hỏi: “Kết quả HbA1c gần đây là bao nhiêu?”. Nếu vector database chứa hàng triệu đoạn từ nhiều bệnh nhân, không nên tìm top-k trên toàn bộ kho dữ liệu.

Hệ thống nên giới hạn tập ứng viên theo patient_id và quyền truy cập trước, sau đó mới tính similarity. Đây là khác biệt quan trọng giữa một demo RAG và kiến trúc có thể áp dụng cho dữ liệu nhạy cảm.

def filter_documents(
    documents,
    patient_id,
    allowed_types=None
):
    filtered = [
        doc
        for doc in documents
        if doc["patient_id"] == patient_id
    ]

    if allowed_types:
        filtered = [
            doc
            for doc in filtered
            if doc["document_type"] in allowed_types
        ]

    return filtered


candidates = filter_documents(
    documents,
    patient_id="P001",
    allowed_types={"laboratory"}
)

Trong production, logic này thường được thực hiện ngay trong vector database hoặc tầng truy cập dữ liệu. Danh sách patient_id hay document_type không nên được tin tưởng chỉ vì chúng xuất hiện trong câu hỏi của người dùng; hệ thống phải lấy phạm vi truy cập từ phiên đăng nhập hoặc cơ chế phân quyền đáng tin cậy.

Kết hợp retrieval với Gemini để trả lời có căn cứ

Sau khi retrieval trả về các đoạn phù hợp, chúng được đưa vào Gemini dưới dạng context. Với dữ liệu y tế, prompt nên tách rõ câu hỏi, bằng chứng và quy tắc tạo câu trả lời.

Ví dụ dưới đây sử dụng Gemini thông qua SDK Python. Tên model được lấy từ biến môi trường để ứng dụng có thể dùng model được cấu hình cho project thay vì phụ thuộc vào một model ID cố định.

import os
from google import genai

client = genai.Client(
    api_key=os.environ["GEMINI_API_KEY"]
)

MODEL_NAME = os.environ["GEMINI_MODEL"]


def build_context(retrieved_docs):
    blocks = []

    for doc in retrieved_docs:
        blocks.append(
            f"""SOURCE_ID: {doc["source_id"]}
DATE: {doc["encounter_date"]}
TYPE: {doc["document_type"]}
CONTENT: {doc["text"]}"""
        )

    return "\n\n".join(blocks)


def answer_question(question, retrieved_docs):
    context = build_context(retrieved_docs)

    prompt = f"""Bạn đang hỗ trợ truy xuất thông tin từ hồ sơ y tế.

Chỉ sử dụng thông tin trong EVIDENCE.
Không tự bổ sung dữ kiện không xuất hiện trong EVIDENCE.
Nếu dữ liệu không đủ, hãy nói rõ là chưa đủ thông tin.
Khi nêu một dữ kiện, hãy kèm SOURCE_ID tương ứng.

EVIDENCE:
{context}

QUESTION:
{question}
"""

    response = client.models.generate_content(
        model=MODEL_NAME,
        contents=prompt
    )

    return response.text

Việc đưa source_id vào context giúp câu trả lời có thể tham chiếu trở lại bản ghi đã được truy xuất. Đây không phải là bảo đảm tuyệt đối rằng mọi câu trả lời đều chính xác, nhưng nó tạo điều kiện để ứng dụng kiểm tra và hiển thị nguồn cho người dùng.

Điểm cần phân biệt: citation do mô hình sinh ra chỉ đáng tin khi ứng dụng kiểm tra rằng source_id thực sự tồn tại trong tập tài liệu đã gửi. Không nên cho phép mô hình tự tạo ID nguồn rồi hiển thị trực tiếp như một citation hợp lệ.

Thời gian và trạng thái bệnh nhân phải trở thành một phần của retrieval

Trong dữ liệu y tế, một thông tin đúng ở thời điểm trước có thể không còn đúng ở hiện tại. Danh sách thuốc, chẩn đoán, kết quả xét nghiệm và kế hoạch điều trị đều có thể thay đổi theo thời gian.

Vì vậy, câu hỏi “Bệnh nhân đang dùng thuốc gì?” khác với “Bệnh nhân từng dùng thuốc gì?”. Câu đầu yêu cầu ưu tiên trạng thái hiện tại; câu sau có thể cần toàn bộ lịch sử.

Một retriever tốt nên hiểu hoặc suy ra loại truy vấn trước khi tìm kiếm. Có thể áp dụng filter theo ngày, sắp xếp theo encounter_date hoặc ưu tiên các record đánh dấu là active. Nếu dữ liệu nguồn đã có cấu trúc rõ ràng, truy vấn cơ sở dữ liệu có cấu trúc đôi khi phù hợp hơn vector search.

Câu hỏi Retrieval phù hợp
Kết quả xét nghiệm gần nhất là gì? Lọc theo loại xét nghiệm, ưu tiên record mới nhất.
Các triệu chứng được ghi nhận trong lần khám trước? Xác định encounter cụ thể rồi truy xuất ghi chú của lần khám đó.
Có ghi nhận dị ứng thuốc không? Ưu tiên dữ liệu dị ứng có cấu trúc, dùng semantic search như lớp bổ sung.

Điều này dẫn đến một nguyên tắc quan trọng: không phải mọi câu hỏi đều nên được giải quyết bằng cùng một vector search. RAG y tế thực tế thường là hybrid retrieval, kết hợp dữ liệu có cấu trúc, metadata, tìm kiếm từ khóa và semantic search.

Ba lớp kiểm soát không nên bỏ qua

Khi RAG được dùng với thông tin sức khỏe, chất lượng câu trả lời chỉ là một phần của bài toán. Hệ thống còn cần kiểm soát dữ liệu nào được truy xuất, dữ liệu nào được gửi tới mô hình và kết quả nào được phép hiển thị.

  • Access control: xác thực người dùng và giới hạn phạm vi dữ liệu trước khi retrieval. Vector database không nên trở thành cách vượt qua quyền truy cập của hệ thống hồ sơ gốc.
  • Grounding: yêu cầu Gemini dựa trên evidence, đồng thời giữ source_id để câu trả lời có thể được kiểm tra lại.
  • Output validation: kiểm tra citation, định dạng và những trường dữ liệu quan trọng trước khi hiển thị kết quả cho người dùng hoặc chuyển sang hệ thống khác.

Ngoài ra, cần có cơ chế logging phù hợp để đánh giá retrieval và điều tra lỗi. Log không nên vô tình sao chép toàn bộ dữ liệu nhạy cảm sang một hệ thống giám sát không được thiết kế để lưu loại thông tin đó.

RAG cũng không biến một mô hình ngôn ngữ thành hệ thống chẩn đoán đáng tin cậy một cách tự động. Nếu ứng dụng ảnh hưởng đến quyết định lâm sàng, cần có quy trình đánh giá, kiểm thử, giám sát và con người chịu trách nhiệm phù hợp với mục đích triển khai.

Đánh giá RAG y tế nên tách retrieval và generation

Khi câu trả lời sai, cần biết lỗi đến từ đâu. Nếu tài liệu đúng không xuất hiện trong top-k, đó là lỗi retrieval. Nếu tài liệu đúng đã được đưa vào context nhưng Gemini vẫn trả lời sai, vấn đề nằm ở bước generation hoặc prompt.

Vì vậy, bộ test nên chứa câu hỏi cùng tài liệu hoặc record được kỳ vọng truy xuất. Có thể đánh giá xem evidence cần thiết có xuất hiện trong top-k hay không trước khi đánh giá câu trả lời cuối.

Ở tầng generation, nên kiểm tra ít nhất ba yếu tố: câu trả lời có được evidence hỗ trợ hay không, có bỏ sót thông tin quan trọng không và citation có trỏ đúng source hay không. Với những trường nhạy cảm như liều thuốc, giá trị xét nghiệm hoặc ngày tháng, kiểm tra có cấu trúc thường đáng tin cậy hơn việc chỉ dùng một mô hình khác để chấm điểm tự động.

Nguyên tắc thực tế: nếu hệ thống không thể chỉ ra record nào đã hỗ trợ một dữ kiện quan trọng, dữ kiện đó không nên được coi là đã được grounding chỉ vì câu trả lời nghe hợp lý.

RAG cho dữ liệu y tế không chỉ là thêm Gemini vào một vector database. Kiến trúc tốt phải kết hợp semantic retrieval với metadata, thời gian, quyền truy cập và nguồn dữ liệu có thể kiểm chứng. Khi những lớp này được thiết kế ngay từ đầu, RAG mới trở thành một nền tảng đáng tin cậy hơn cho các ứng dụng hỏi đáp, tìm kiếm hồ sơ và hỗ trợ khai thác tri thức y khoa.

© The CS Note · THE CS NOTE

Nội dung gốc thuộc tác giả. Vui lòng không đăng lại toàn văn khi chưa được phép, trừ trường hợp pháp luật hoặc giấy phép áp dụng cho phép. Nội dung của bên thứ ba tuân theo quyền và giấy phép tương ứng.

Nguồn gốc: Kiến trúc RAG cho dữ liệu y tế

Về trang chủ Về đầu bài

Bài Đăng Phổ Biến

Bài toán tháp Hà nội

Trải nghiệm Tháp Hà Nội Kéo thả đĩa hoặc chạm vào các nút bên dưới để di chuyển. Bạn phải chuyển toàn bộ đĩa sang cột ngoài cùng bên phải (Cột 3) mà không đặt đĩa to lên đĩa nhỏ. Cột 1 Cột 2 Cột 3 Điều khiển & Chế độ Số lượng đĩa 4 Tốc độ máy giải ↪ Undo ↻ Chơi lại 🤖 Máy tự giải Thống kê ván chơi Nước đã đi 0 Thời gian 00:00 Tối thiểu cần 15 Kỷ lục của bạn - Lịch sử và Nguồn gốc Truyền thuyết Bài toán Tháp Hà Nội (hay Tháp Brahma) là một trò chơi xếp hình toán học kinh điển được giới thiệu lần đầu vào năm 1883 bởi nhà toán học người Pháp Édouard L...

Bài toán phân tích cảm xúc trong văn bản

Bài toán phân tích cảm xúc (sentiment analysis) là một bài toán NLP nhằm xác định thái độ hoặc cảm xúc được thể hiện trong văn bản. Ví dụ, từ một đánh giá như “Điện thoại đẹp, chạy nhanh nhưng pin hơi yếu”, hệ thống có thể nhận biết rằng người dùng có cả nhận xét tích cực và tiêu cực. Điểm thú vị của bài toán nằm ở khoảng cách giữa cách con người hiểu ngôn ngữ và cách máy tính xử lý dữ liệu. Một hệ thống phân tích cảm xúc cần biến văn bản tự nhiên thành dữ liệu có cấu trúc, học được các mẫu ngôn ngữ từ dữ liệu huấn luyện và đưa ra dự đoán hợp lý trên những câu chưa từng gặp. 1. Bài toán phân tích cảm xúc bắt đầu từ đâu? Hãy tưởng tượng một cửa hàng trực tuyến có hàng nghìn đánh giá mỗi ngày. Con người có thể đọc từng đánh giá để biết khách hàng hài lòng hay không, nhưng việc này nhanh chóng trở nên tốn thời gian khi dữ liệu tăng lên. NLP có thể biến bài toán đó thành một bài toán phân loại. Với mỗi văn bản, hệ thống nhận vào một chuỗi ký...

KAN cho phân đoạn khối u não với bộ BraTS 2020

Kolmogorov-Arnold Network (KAN) mở ra một hướng khác với MLP truyền thống: thay vì chỉ học các trọng số vô hướng trên mỗi kết nối, KAN có thể học những hàm phi tuyến một biến trên các cạnh . Khi đưa ý tưởng này vào kiến trúc encoder-decoder như U-Net, ta có thể sử dụng convolution để giữ cấu trúc không gian của ảnh MRI và dùng KAN để thực hiện các phép biến đổi phi tuyến mạnh hơn trên representation trung gian. Một bài toán phù hợp để nghiên cứu hướng này là phân đoạn u thần kinh đệm trên BraTS 2020 . Dataset cung cấp MRI đa mô thức và yêu cầu xác định các vùng Whole Tumor (WT), Tumor Core (TC) và Enhancing Tumor (ET). Đây là bài toán 3D có sự mất cân bằng voxel lớn, hình dạng khối u rất đa dạng và ranh giới giữa các mô bệnh lý không đơn giản. Lưu ý học thuật quan trọng: U-KAN gốc được công bố cho nhiều benchmark phân đoạn ảnh y tế nhưng không báo cáo kết quả BraTS 2020. Một công trình sau đó đã mở rộng U-KAN sang 3D MRI brain tumor segmentation , nhưng đánh giá trên BraTS 2...

Tách từ trong tiếng Việt Word Segmentation

Tách từ tiếng Việt là bài toán xác định ranh giới giữa các từ trong một chuỗi văn bản. Khó khăn nằm ở chỗ khoảng trắng trong tiếng Việt thường phân cách các âm tiết , nhưng một từ hoàn chỉnh có thể gồm nhiều âm tiết như “sinh viên” , “đại học” , “công nghệ” hay “tự nhiên” . Tách từ đúng giúp các hệ thống NLP dựa trên từ biểu diễn văn bản hợp lý hơn, đặc biệt trong tìm kiếm, TF-IDF, phân loại văn bản, gán nhãn từ loại và một số mô hình ngôn ngữ tiếng Việt. Tuy nhiên, với các Transformer sử dụng tokenizer dưới mức từ như subword hoặc SentencePiece, tách từ thủ công không phải lúc nào cũng là bước bắt buộc . Việc có cần tách từ trước hay không phụ thuộc vào mô hình và pipeline cụ thể. Tóm tắt nội dung Khoảng trắng trong tiếng Việt không phải lúc nào cũng là ranh giới từ ; nhiều từ gồm hai hoặc nhiều âm tiết. Word segmentation và tokenization có liên quan nhưng không hoàn toàn đồng nghĩa. Ba hướng chính gồm dựa trên từ điển, mô hình thống kê và mô hình học sâu . Tron...

KAN là gì? Mạng Kolmogorov-Arnold khác MLP thế nào?

Kolmogorov-Arnold Network (KAN) là một kiến trúc mạng nơ-ron trong đó mỗi cạnh không chỉ chứa một trọng số vô hướng mà mang một hàm một biến có thể học được . Đây là khác biệt cốt lõi so với Multi-Layer Perceptron (MLP), nơi các cạnh chủ yếu thực hiện phép nhân với trọng số còn hàm kích hoạt thường được áp dụng tại các node. KAN được lấy cảm hứng từ định lý biểu diễn Kolmogorov-Arnold và đặc biệt đáng chú ý trong các bài toán xấp xỉ hàm, mô hình hóa khoa học và symbolic regression. Tuy nhiên, KAN không nên được hiểu là kiến trúc đã thay thế MLP trong mọi bài toán Deep Learning; khả năng biểu diễn, chi phí tính toán và mức độ phù hợp của hai kiến trúc khác nhau theo từng nhiệm vụ. Tóm tắt nội dung MLP học chủ yếu trọng số trên các cạnh , còn KAN đặt hàm một biến học được trên từng cạnh . Một KAN layer cộng kết quả của nhiều hàm cạnh để tạo activation của node tiếp theo. KAN gốc sử dụng B-spline để tham số hóa các hàm phi tuyến trên cạnh. KAN có lợi thế đáng chú ý về trực...