Bỏ qua đến nội dung chính

Triển khai luồng RAG

📖 Nội dung bài học

Họ phông chữ

Tóm tắt

Giờ bạn đã hiểu luồng RAG về mặt khái niệm, hãy cùng nhau triển khai nó từng bước bằng một ví dụ thực tế. Bạn sẽ thực hiện qua cả năm giai đoạn của quy trình RAG, từ chia nhỏ văn bản đến tìm các tài liệu liên quan cho các truy vấn của người dùng.

Thiết lập Cơ sở dữ liệu Vector

Để triển khai này, bạn sẽ dùng một lớp VectorIndex tùy chỉnh, cung cấp các chức năng cơ bản cần thiết để lưu trữ và tìm kiếm embedding. Lớp này xử lý việc lưu trữ vector, tính toán khoảng cách (dùng độ tương đồng cosine) và truy xuất tài liệu.

Triển khai RAG năm bước

Hãy cùng xem qua từng bước của quy trình RAG:

Bước 1: Chia nhỏ văn bản theo phần

Đầu tiên, bạn cần chia tài liệu nguồn thành các phần nhỏ dễ quản lý. Bạn sẽ dùng cách chia nhỏ theo phần giống như trước:

chunks = chunk_by_section(text)

Thao tác này chia tệp report.md thành các phần logic mà bạn có thể xử lý riêng lẻ.

Bước 2: Tạo embedding cho mỗi phần

Tiếp theo, bạn chuyển đổi mỗi phần văn bản thành một embedding số, nắm bắt ý nghĩa ngữ nghĩa của nó:

embeddings = generate_embedding(chunks)

Các embedding này cho phép bạn thực hiện các so sánh toán học giữa các đoạn văn bản khác nhau.

Bước 3: Lưu trữ embedding trong Cơ sở dữ liệu Vector

Bây giờ bạn tạo kho vector và điền nó bằng các embedding và văn bản liên quan:

store = VectorIndex()

for embedding, chunk in zip(embeddings, chunks):
    store.add_vector(embedding, {"content": chunk})

Lưu ý rằng bạn lưu trữ cả embedding và nội dung văn bản gốc. Điều này rất quan trọng vì khi bạn truy xuất các embedding tương tự sau này, bạn cần truy cập vào văn bản thực tế, chứ không chỉ là các vector số. Riêng embedding không hữu ích cho bạn với tư cách là nhà phát triển - bạn cần nội dung có thể đọc được bằng con người mà nó đại diện.

Bước 4: Tạo embedding cho truy vấn của người dùng

Khi người dùng đặt câu hỏi, bạn cần chuyển đổi truy vấn của họ thành cùng một không gian embedding như các tài liệu đã lưu trữ:

user_embedding = generate_embedding("What did the software engineering dept do last year?")

Bước 5: Tìm kiếm các tài liệu liên quan

Cuối cùng, bạn tìm kiếm trong kho vector để tìm các phần liên quan nhất:

results = store.search(user_embedding, 2)

for doc, distance in results:
    print(distance, "\n", doc["content"][0:200], "\n")

Thao tác này trả về hai phần giống nhau nhất cùng với điểm số khoảng cách cosine của chúng.

Sơ đồ trên minh họa cách cơ sở dữ liệu vector xử lý truy vấn của người dùng. Khi bạn đặt câu hỏi, nó sẽ được chuyển đổi thành một vector embedding và cơ sở dữ liệu sẽ tìm các vector được lưu trữ "gần" nhất với nó trong không gian đa chiều.

Hiểu kết quả

Khi bạn chạy ví dụ này với truy vấn về bộ phận kỹ thuật phần mềm, bạn sẽ nhận lại hai phần liên quan:

  • Phần 2: Kỹ thuật phần mềm - Cải tiến độ ổn định của Dự án Phoenix (khoảng cách: 0,71)
  • Phần Phương pháp (khoảng cách: 0,72)

Điểm khoảng cách càng thấp, nội dung càng giống với truy vấn của bạn. Cả hai kết quả đều liên quan đến câu hỏi của bạn về những gì bộ phận kỹ thuật phần mềm đã đạt được.

Tại sao lại lưu trữ nội dung với Embedding

Bạn có thể tự hỏi tại sao bạn lại lưu trữ văn bản gốc cùng với mỗi embedding. Lý do là thực tế: embedding chỉ là mảng số không có ý nghĩa trực tiếp đối với con người. Khi tìm kiếm của bạn trả về các embedding tương tự nhất, bạn cần nội dung văn bản thực tế để hiểu những gì đã tìm thấy và dùng nó để tạo phản hồi.

Một số triển khai chỉ lưu trữ một ID trỏ lại văn bản gốc, nhưng để đơn giản, bạn đang lưu trữ nội dung trực tiếp với mỗi vector.

Tiếp theo là gì

Triển khai này bao gồm luồng công việc RAG cốt lõi, nhưng vẫn còn những cải tiến bạn có thể thực hiện. Trong các ứng dụng thực tế, bạn có thể gặp các tình huống mà cách tiếp cận cơ bản này không hoạt động như mong đợi và bạn sẽ khám phá những tinh chỉnh đó trong các phần sắp tới.

Tải xuống

🔁 Bài học liên quan

📚 Nguồn & ghi nhận

Bài học có hữu ích không?

Góp ý / Báo lỗiPhát hiện sai sót hoặc có ý tưởng cải thiện?