Khám phá RAG - Hướng dẫn xây dựng chatbot với RAG

ngày 05-12-2024

1. Giới thiệu về RAG

Có thể thấy Chatbot đã và đang trở thành một phần không thể thiếu trong các hệ thống dịch vụ khách hàng, hỗ trợ trực tuyến, và tư vấn tự động để giúp khách hàng nhanh chóng có được câu trả lời khi cần hỗ trợ, tư vấn. Đặc biệt, Chatbot còn có thể giúp giới thiệu sản phẩm, đề xuất các chương trình khuyến mãi hoặc thậm chí hỗ trợ khách hàng đặt hàng ngay trong cuộc trò chuyện. 
Trước đây vào khoản trước 2010 để ChatBot thời bấy giờ  dựa trên những quy tắt cứng nhắc và được chỉ định trước. Các Chatbot này sử dụng các công nghệ như biểu đồ trạng thái hay tìm kiếm từ khóa để tạo phản hồi. Những Chatbot này chỉ có thể trả lời đơn giản dựa trên các mẫu câu đã được lập trình sẵn. 
Giai đoạn sau những năm 2010, Chatbot bắt đầu sữ dụng deep learning để xử lý và hiểu ngôn ngữ tự nhiên, thay vì những quy tắt cứng nhắc trước đó. Các mô hình LLM sau này được đào tạo trên lượng dữ liệu khổng lồ và sử dụng kiến trúc Transformer, cho phép hiểu ngữ cảnh và tạo ra phản hồi tự nhiên như con người. Tuy nhiên, dù hiệu quả nhưng những chatbot này vẫn gặp phải những hạn chế đó là sự phụ thuộc vào dữ liệu đã đào tạo trước, điều này dẫn đến việc chatbot không thể trả lời chính xác các câu hỏi nằm ngoài phạm vi dữ liệu đã đào tạo, hoặc tạo ra các kiến thức mới mà chúng chưa từng tiếp cận. 
Vậy làm thế nào để khắc phục vấn đề này? 
Câu trả lời chính là Retrieval Augmented Generation (RAG), một kỹ thuật tiên tiến đang cách mạng hóa lĩnh vực xử lý ngôn ngữ tự nhiên và trí tuệ nhân tạo.   
Vậy Retrieval Augmented Generation (RAG) là gì ?
Retrieval Augmented Generation (RAG), là một kỹ thuật kết hợp hai yếu tố quan trọng là truy xuất dữ liệu và tạo sinh câu trả lời theo yêu cầu. Cụ thể hơn, RAG hoạt động theo hai bước chính:   
  1. Truy xuất dữ liệu (Retrieval): Khi nhận được câu hỏi, hệ thống RAG sẽ tìm kiếm thông tin liên quan từ các nguồn dữ liệu. Các nguồn này có thể là dữ liệu liên quan đến công ty hay là dữ liệu chăm sóc khách hàng. Quá trình truy xuất này giống như việc chúng ta sử dụng từ khóa để tìm kiếm thông tin trên Google.  
  2. Tạo sinh (Generation): Sau khi đã thu thập đủ thông tin, RAG sẽ sử dụng một mô hình ngôn ngữ lớn (LLM) để tạo ra câu trả lời hoàn chỉnh và dễ hiểu. LLM đóng vai trò như một "tư vấn viên" tài ba, sử dụng thông tin đã truy xuất để viết nên câu trả lời phù hợp với câu hỏi của chúng ta.  
Giống như một "nhân viên tư vấn thông minh", RAG kết hợp sức mạnh của các mô hình ngôn ngữ lớn (LLM) như GPT, Gemini… với khả năng truy xuất thông tin chính xác từ các nguồn kiến thức nội bộ do chúng ta cung cấp. Kết quả là RAG giúp chúng ta tạo ra những chatbot có thể trả lời thông minh hơn, khéo léo hơn và chính xác hơn.
RAG mang lại nhiều lợi ích nổi bật cho chatbot, giúp nâng cao hiệu suất và trải nghiệm người dùng. Bằng cách đưa ra câu trả lời chính xác dựa trên dữ liệu được cung cấp và phù hợp với ngữ cảnh. RAG còn dựa trên thông tin cá nhân hay lịch sử tương tác từ đó tạo ra những phản hồi riêng biệt và đáp ứng tốt hơn đối với từng tệp khách hàng. Ngoài ra RAG giúp giải thích rõ ràng và minh bạch bằng cách trích dẫn nguồn gốc thông tin để tăng cường sự tin cậy từ người dùng.

2. Kiến trúc ứng dụng RAG 

Với RAG, chúng ta có thể tận dụng tri thức từ dữ liệu do các hệ thống LLMs cung cấp kết hợp với thông tin, dữ liệu bổ sung trong ngữ cảnh cụ thể giúp mở rộng và nâng cao lượng tri thức của LLMs một cách hiệu quả. Chẳng hạn Chatbot tại CSC sẽ được đưa vào dữ liệu về các khóa học của trung tâm.
Để có thể xây dựng một Chatbot áp dụng phương pháp RAG thì không thể bỏ qua quá trình đầu tiên là Indexing. Indexing là quá trình tổ chức, tối ưu hóa và chuẩn bị dữ liệu để hỗ trợ truy xuất thông tin hiệu quả và chính xác.
Quá trình này bắt đầu bằng việc thu thập dữ liệu từ các nguồn như tài liệu văn bản, cơ sở dữ liệu nội bộ hoặc dữ liệu từ website. Sau đó dữ liệu được tiền xử lý để loại bỏ dữ liệu không cần thiết và chia nhỏ thành các đoạn văn bản (chunks) phù hợp với giới hạn xử lý của mô hình ngôn ngữ lớn (LLMs). 
Những đoạn văn bản này được chuyển đổi thành các vector biểu diễn bằng cách sử dụng các mô hình embedding như OpenAI Embeddings, Sentence Transformers,… cho phép hệ thống hiểu và tìm kiếm dựa trên ý nghĩa ngữ nghĩa thay vì chỉ khớp từ khóa. Các vector này được lưu trữ trong vector stores như FAISS, Pinecone,…
Trong quá trình Indexing, một câu hỏi được đặt ra là “Tại sao chúng ta lại dùng Vector database thay vì Tranditional database?”
Đáp án cho câu hỏi này là vì khả năng xử lý dữ liệu ngữ nghĩa vượt trội. Vector database lưu trữ dữ liệu dưới dạng vector trong không gian đa chiều cho phép biểu diễn ý nghĩa của câu và từ. Điều này giúp chúng ta tìm kiếm thông tin dựa trên ngữ cảnh thông qua các phương pháp như similarity search, thay vì chỉ khớp từ khóa như trong traditional database. Ngoài ra vector database được tối ưu hóa cho các ứng dụng AI và học máy, hỗ trợ xử lý dữ liệu lớn và cung cấp tốc độ truy vấn nhanh nhờ các thuật toán tiên tiến. Trong khi đó traditional database chủ yếu lưu trữ dữ liệu dạng scalar và sử dụng các truy vấn SQL, không đáp ứng tốt các yêu cầu về ngữ nghĩa và tính linh hoạt trong hệ thống RAG.
Sau khi chúng ta xây dựng xong vector store, thì bước tiếp theo là xây dựng Retrieval để Chatbot có thể truy vấn dữ liệu liên quan đến câu hỏi của người dùng. Khi người dùng nhập câu hỏi, hệ thống sẽ chuyển câu hỏi thành vector biểu diễn ngữ nghĩa bằng cách sử dụng các mô hình nhúng (Embedding Model). Sau đó, vector này được so sánh với các vector đã lưu trong vector store để tìm ra những đoạn văn hoặc tài liệu phù hợp nhất về mặt ngữ nghĩa. Quá trình này không chỉ dựa trên từ khóa, mà còn xem xét ý nghĩa ngữ cảnh, giúp truy xuất thông tin ngay cả khi cách diễn đạt không khớp hoàn toàn. 
Bước tiếp theo của RAG là Augmented Generation, tạo sinh kết quả. Sau khi chúng ta tìm được những đoạn văn bản phù hợp, chúng ta sẽ đưa vào Prompt câu hỏi của người dùng kèm theo kết quả truy vấn có được để LLM tạo sinh ra câu trả lời hoàn chỉnh, chính xác và mạch lạc cho người dùng.

3. Xây dựng Chatbot với RAG 

3.1. LangChain

Phần này sẽ minh họa các bước xây dựng Chatbot cơ bản theo kiến trúc RAG trên LangChain. Đây là framework được viết bằng Python và JavaScript cung cấp các công cụ để chúng ta có thể thao tác và xây dựng ứng dụng dựa trên LLMs.
LangChain giúp thực hiện bước retrieval bằng cách kết nối mô hình với các vectorstore, cho phép tìm kiếm thông tin trong một kho tài liệu lớn. Sau đó, LangChain kết hợp dữ liệu truy vấn được với khả năng tạo phản hồi của mô hình, cung cấp cho người dùng các câu trả lời được cải thiện và chính xác hơn.
Ngoài ra LangChain còn hỗ trợ việc xây dựng các mô hình lưu trữ bộ nhớ (memory) để duy trì ngữ cảnh và cải thiện các cuộc trò chuyện giúp ứng dụng RAG trở nên thông minh và linh hoạt hơn trong các tác vụ trò chuyện và trả lời câu hỏi. Nhờ vậy, LangChain giúp tăng cường khả năng tìm kiếm và tạo ra các câu trả lời, mang lại trải nghiệm người dùng tốt hơn trong các ứng dụng RAG mà chúng ta xây dựng.

3.2. Xây dựng Chatbot đơn giản với RAG

(Code minh họa trên nền tảng Google Colab)
Bước 1: Tải các thư viện và khai báo API key.
Trước tiên, chúng ta cần tải xuống các thư viện cần thiết:   
!pip install -qU \
      python-dotenv \
      langchain \
      langchain_openai \
      langchain_community \
      langchain-huggingface \
      langchain-google-genai \
      streamlit \
      faiss-cpu \
      sentence-transformers \
      pypdf \
      docx2txt
Tiếp theo, chúng ta sẽ tạo và khai báo GOOGLE_API_KEY trong Secrets. Lưu ý là ngoài Gemini, chúng ta có thể sử dụng các mô hình khác như GPT-4,… để cho hiệu quả tốt hơn.
Chúng ta có thể lấy Google API key từ https://aistudio.google.com/apikey một cách miễn phí.
Bước 2: Chuẩn bị dữ liệu
Sau khi khai báo việc đầu tiên cần làm load  các file dữ liệu. Để có thể tải lên những dữ liệu đó ta sử dụng Loader của LangChain. Loader chịu trách nhiệm chuyển đổi các tài liệu từ các định dạng không đồng nhất (như PDF, DOCX, Excel, PowerPoint, v.v.) thành các đối tượng tài liệu mà mô hình có thể xử lý.
#Tải dữ liệu từ folder (.txt)
from langchain_community.document_loaders import DirectoryLoader, TextLoader
file_path = "/content/drive/MyDrive/Cam_nang_txt"
loader = DirectoryLoader(
        file_path,
        glob="*.txt",
        loader_cls=TextLoader
    )
docs = loader.load()
Bước 3: Tiến hành xử lí dữ liệu và đưa vào Vector store
Sau khi đã tải dữ liệu chúng ta tiếp tục xử lí dữ liệu bằng cách chia nhỏ thành các đoạn (chunks) thông qua RecursiveCharacterTextSplitter để đảm bảo mỗi đoạn có kích thước phù hợp, Sau khi chia nhỏ ta sử dụng HuggingFaceEmbeddings để chuyển đổi văn bản thành các vector (embeddings). Sau đó lưu các chunks này vào trong một vectorstore sử dụng FAISS.
from langchain_text_splitters.character import  RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
 
text_splitter = RecursiveCharacterTextSplitter(
      chunk_size=1200,
      chunk_overlap=200
)
doc_chunks = text_splitter.split_documents(docs)
#Embedding các chunks này và đưa vào vector store
embeddings = HuggingFaceEmbeddings()
vectordb = FAISS.from_documents(doc_chunks, embeddings)
Chúng ta có thể lưu lại để có thể tái sử dụng.
# Lưu vector store
vectordb.save_local("index")
Bước 4: Tiếp tục xây dựng một chuỗi hội thoại truy xuất thông tin (Conversational Retrieval Chain)
Sau khi đã hoàn thành các bước chuẩn bị dữ liệu chúng ta tiến hành xây dựng chuỗi chain. Đầu tiên chúng ta khởi tạo mô hình ngôn ngữ gemini-1.5-pro qua ChatGoogleGenerativeAI, với tham số temperature = 0 để đảm bảo kết quả đầu ra có tính nhất quán cao. Sau đó chúng ta cấu hình một retriever từ vectorstore để truy xuất thông tin từ các tài liệu đã được lưu trữ. Tiếp theo chúng ta thiết lập memory bằng ConversationBufferMemory, giúp lưu trữ và duy trì cuộc trò chuyện, tạo ngữ cảnh cho các phản hồi của mô hình. Cuối cùng tạo ra ConversationalRetrievalChain để kết hợp các thành phần này, thực hiện quá trình map-reduce để tìm kiếm và trả lời câu hỏi, đồng thời lưu lại ngữ cảnh và cải thiện khả năng tương tác trong các cuộc trò chuyện.
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
from langchain_google_genai import ChatGoogleGenerativeAI
 
llm = ChatGoogleGenerativeAI(model="gemini-1.5-pro")
retriever = vectordb.as_retriever(
        search_kwargs={
                  "k": 2, # số lượng kết quả của truy vấn trả về
    }
    )
memory = ConversationBufferMemory(
        llm=llm,
        output_key="answer",
        memory_key="chat_history",
        return_messages=True
    )
chain = ConversationalRetrievalChain.from_llm(
        llm=llm,
        retriever=retriever,
        chain_type="map_reduce",
        memory=memory,
        verbose=True
    )
Bước 5: Xây dựng một khung chat đơn giản và kiểm tra
Triển khai một vòng lặp hội thoại đơn giản và sử dụng bộ nhớ hội thoại để lưu trữ ngữ cảnh. Lệnh memory.clear() được gọi đầu tiên để đảm bảo bộ nhớ được làm sạch trước khi bắt đầu cuộc trò chuyện. Trong vòng lặp, chúng ta nhập câu hỏi thông qua input nếu nội dung là “exit” thì vòng lặp kết thúc.
Mỗi câu hỏi của người dùng được gửi đến mô hình xử lý chuỗi (chain) cùng với lịch sử hội thoại hiện tại (memory.chat_memory.messages). Mô hình sẽ trả về câu trả lời tương ứng, được lưu trong biến assistant_response. Câu trả lời sau đó được in ra màn hình với định dạng "assistant: ". Bộ nhớ giúp duy trì ngữ cảnh của cuộc trò chuyện, đảm bảo rằng chatbot có thể tham chiếu lại các câu hỏi trước đó để trả lời chính xác hơn.
memory.clear()  
while True:
    user_input = input("user: ")
    if user_input.lower() == "exit":
        break
 
    response = chain({"question": user_input, "chat_history": memory.chat_memory.messages})
    assistant_response = response["answer"]
 
    print("assistant: ", assistant_response)
Chúng ta hãy thử hỏi nó câu hỏi “Nội dung của khóa học lập trình python cơ bản ?” và xem phản hồi của nó.
Và đây là câu trả lời của chatbot.
 Đây là một câu trả lời chính xác khi so với tài liệu mà chúng ta cung cấp. Và chúng ta hãy hỏi thêm một câu “Mục tiêu của nó là gì ?” Nó ở đây đang ám chỉ về khóa học lập trình python cơ bản. 
Chúng ta có thể thấy rằng nhờ vào memory mà chatbot có thể hiểu được ngữ cảnh và đưa ra câu trả lời cho chúng ta.
Để dễ quan sát và kiểm tra hơn chúng ta có thể in ra lịch sử của đoạn hội thoại
Và sau vài đoạn code đơn giản chúng đã có thể tạo ra một chatbot với RAG.
Dựa vào source code trên chúng ta có thể tiến hành xây dựng một chatbot tương tự với Streamlit có giao diện như sau:
Lưu ý: chúng ta nên sử dụng các model embedding và chat generate hỗ trợ tiếng Việt để có thể cho ra kết quả tốt nhất khi sử dụng tiếng Việt.

4. Những vấn đề cần giải quyết khi áp dụng RAG trong thực tế

RAG mặc dù đã giải quyết được vấn đề mà LLM truyền thống gặp phải chẳng hạn như trả lời chính xác các câu hỏi nằm ngoài phạm vi dữ liệu đã đào tạo. Nhưng cũng còn một số vấn đề phải cân nhắc, xử lý khi ứng dụng thực tế:  
Một trong những vấn đề lớn mà RAG thường gặp phải là độ trễ. Trong quá trình phản hồi RAG phải thực hiện hai bước chính là truy xuất thông tin từ nguồn bên ngoài và sau đó tạo phản hồi tự nhiên dựa trên thông tin đó, thời gian xử lý có thể kéo dài, đặc biệt khi nguồn dữ liệu lớn hoặc kết nối mạng không ổn định. Giả sử người dùng hỏi một chatbot y tế: “Tôi cần thông tin về các loại thuốc điều trị huyết áp cao phù hợp với người tiểu đường.” Hệ thống RAG sẽ phải truy xuất thông tin từ các cơ sở dữ liệu y khoa hoặc tài liệu chuyên ngành để đưa ra danh sách các loại thuốc phù hợp. Nếu cơ sở dữ liệu quá lớn hoặc server chứa thông tin gặp sự cố, quá trình truy xuất có thể bị kéo dài, khiến người dùng phải chờ đợi vài phút hoặc lâu hơn. Trong tình huống nhạy cảm như chăm sóc y tế, sự chậm trễ này không chỉ gây khó chịu mà còn tiềm ẩn rủi ro nếu người dùng cần thông tin khẩn cấp để đưa ra quyết định quan trọng. Điều này cho thấy rằng, mặc dù RAG rất hữu ích, nhưng việc tối ưu hóa tốc độ truy xuất và xử lý là một thách thức quan trọng cần được giải quyết. 
Hệ thống RAG khi ứng dụng với dữ liệu nội bộ thường gặp phải vấn đề về bảo mật và quyền riêng tư nếu không được quản lý chặt chẽ. Một trong những rủi ro lớn là chatbot có thể vô tình tiết lộ thông tin cá nhân của chúng ta cho những người không được phép. Ví dụ, trong một trường học, nếu hệ thống RAG được tích hợp để hỗ trợ tra cứu điểm số và thông tin học sinh, nhưng không có cơ chế kiểm soát quyền truy cập tốt, bất kỳ ai cũng có thể nhập bừa tên của chúng ta để truy vấn. Chatbot, do không phân biệt được người dùng hợp lệ, có thể trả về thông tin cá nhân như điểm số, lịch sử học tập, hoặc địa chỉ liên lạc của chúng ta. Việc này không chỉ vi phạm quyền riêng tư cá nhân mà còn có thể bị lạm dụng cho mục đích xấu. 

5. Kết luận

Retrieval-Augmented Generation (RAG) là một công nghệ đột phá trong việc xây dựng chatbot thông minh và linh hoạt. Bằng cách kết hợp sức mạnh của các mô hình ngôn ngữ lớn (LLM) với khả năng truy xuất thông tin từ các nguồn dữ liệu bên ngoài, RAG không chỉ giúp khắc phục những hạn chế của LLM truyền thống mà còn mang lại trải nghiệm tương tác tự nhiên và chính xác hơn. RAG đặc biệt hữu ích trong việc giải quyết các câu hỏi ngoài phạm vi dữ liệu đã đào tạo, đồng thời cung cấp phản hồi tùy chỉnh dựa trên ngữ cảnh hoặc lịch sử hội thoại.
Tuy nhiên, khi triển khai RAG trong thực tế, vẫn còn những thách thức cần giải quyết như độ trễ trong phản hồi, đảm bảo bảo mật và quyền riêng tư khi làm việc với dữ liệu nội bộ. Việc tối ưu hóa tốc độ xử lý và thiết lập các cơ chế bảo vệ thông tin là những yếu tố cần thiết để phát huy tối đa tiềm năng của RAG, đồng thời đảm bảo tính an toàn và minh bạch trong ứng dụng thực tế. Với các bước phát triển phù hợp, RAG hứa hẹn sẽ tiếp tục là công cụ quan trọng trong việc xây dựng các hệ thống chatbot hiện đại, mang lại giá trị vượt trội cho người dùng và doanh nghiệp.
ai
Trung Tâm Tin Học
ai
Trung Tâm Tin Học
Chào mừng bạn đến với Trung Tâm Tin Học.
Bạn đang cần hỗ trợ thông tin gì ạ? Hãy Chat ngay với chúng tôi nhé.