Chunking là gì?
Hãy tưởng tượng bạn có một file tài liệu siêu dài cỡ 100 trang. Nếu bạn đưa cả tài liệu này cho LLM xử lý, nó sẽ nhìn bạn kiểu: "Giỡn mặt hả bro, đưa nhiêu đây đọc sao cho nổi?" Để nó đỡ nổi giận và xâm chiếm trái đất thì chúng ta cần phải chia tài liệu thành những câu hoặc đoạn văn ngắn hơn. Lúc đó thì nó mới có thể xử lý hiệu quả được nguồn thông tin khổng lồ mà bạn đưa vào
Hay khi bạn có một tấm ảnh chất lượng 4K siêu sắc nét, và bạn muốn đưa hết tấm ảnh đó vào AI để nó edit theo ý bạn. Vậy thì chẳng khác nào bắt nó đứng trước một bức tranh khổng lồ và đòi hỏi phân tích từng chi tiết cùng lúc. Chunking sẽ giúp chia nhỏ bức ảnh thành từng mảnh, để AI có thể phân tích từ từ, không bị "nghẹn".
Late Chunking là gì?
Trong Retrieval-Augmented Generation (RAG), chunking là quá trình chia một tài liệu dài thành các "chunks" nhỏ hơn (mỗi chunk chứa khoảng 512 token). Điều này rất quan trọng vì các LLMs thường bị giới hạn về lượng văn bản có thể xử lý cùng một lúc. Bằng cách chia tài liệu thành các chunk nhỏ, mỗi phần có thể được lưu trữ riêng lẻ trong Vector Database.
Trong quá trình truy xuất, khi người dùng đưa ra một câu hỏi, Embedding Model sẽ mã hóa câu hỏi đó thành một vector. Vector này sau đó được sử dụng để tìm và truy xuất các chunks văn bản phù hợp nhất từ Vector Database. Những chunk được truy xuất này, đại diện cho các phần liên quan nhất của tài liệu gốc, sau đó sẽ được đưa vào LLM để tổng hợp một câu trả lời dựa trên thông tin chứa trong các chunks đó. Điều này đảm bảo rằng câu trả lời được đưa ra dựa trên các phần có liên quan nhất của văn bản.
![]() |
Các bước trong hệ thống RAG cơ bản (source) |
Các phương pháp chunking truyền thống khi chia văn bản thành các chunks nhỏ thường dẫn đến việc làm mất đi các kết nối quan trọng giữa các phần khác nhau của văn bản. Tại vì khi bạn cắt tài liệu ra những đoạn nhỏ, thì những đoạn đó sẽ bị cô lập và mất đi mối quan hệ tới các đoạn khác. Embedding vector của những đoạn bị cô lập đó sẽ chỉ tổng hợp được thông tin nội bộ trong đoạn, nhưng không tổng hợp được thông tin liên quan giữa các đoạn khác nhau.
Trong hình dưới đây, một bài viết trên Wikipedia được chia thành nhiều đoạn câu. Bạn có thể thấy các từ như "its" và "the city" đều ám chỉ "Berlin", nhưng "Berlin" chỉ được nhắc đến ở câu đầu tiên. Nếu giờ bạn cắt đoạn văn ra các câu riêng lẻ thì ngữ cảnh của các từ "its" và "the city" sẽ không còn nữa.
![]() |
Ngữ nghĩa bị cắt mất khi ta dùng kỹ thuật chunking cơ bản (source) |
Điều này có nghĩa là, nếu chúng ta chia một bài viết dài thành các câu như trong ví dụ ở trên, RAG có thể gặp khó khăn khi trả lời câu hỏi kiểu "Dân số của Berlin là bao nhiêu?" Vì tên thành phố và số dân không xuất hiện cùng nhau trong một câu, và khi không có ngữ cảnh đầy đủ của cả tài liệu, một LLM chỉ được cung cấp một trong các đoạn này sẽ không thể giải quyết được các tham chiếu như "it" hay "the city".
Có một số phương pháp heuristic để giảm thiểu vấn đề này, chẳng hạn như resampling lại với sliding window, sử dụng nhiều context window lengths, và thực hiện quét tài liệu nhiều lần. Tuy nhiên, giống như tất cả các phương pháp heuristic khác, những cách tiếp cận này có tính may rủi; chúng có thể hiệu quả trong một số trường hợp, nhưng không có gì đảm bảo về mặt lý thuyết rằng chúng luôn thành công.
Một phương pháp encoding "ngây thơ" (ảnh bên trái) là sử dụng các câu, đoạn văn, hoặc giới hạn độ dài tối đa để chia nhỏ văn bản trước. Sau đó, một embedding model sẽ được áp dụng lặp đi lặp lại trên các chunks đã được chia. Để tạo ra một embedding duy nhất cho mỗi chunk, nhiều embedding models sử dụng mean pooling trên các embeddings ở cấp độ token để xuất ra một embedding vector duy nhất.
![]() |
So sánh giữa "Naive Chunking" và "Late Chunking" (source) |
Ngược lại, Late Chunking sẽ áp dụng một transformer layer của embedding model lên toàn bộ văn bản hoặc càng nhiều phần của văn bản càng tốt trước. Điều này tạo ra một chuỗi các vector biểu diễn cho mỗi token (là cái cục "token emb" ở trong hình), đã được bao gồm thông tin từ toàn bộ văn bản. Sau đó, mean pooling được áp dụng cho từng đoạn của chuỗi "token emb" này, tạo ra các embedding vector cho mỗi chunk (ở trong hình là chunk1 embedding, chunk2 embedding, ...) với sự cân nhắc đến ngữ cảnh của toàn bộ văn bản. Khác "Naive Chunking", phương pháp tạo ra các embedding vector độc lập và phân phối giống hệt nhau (independent and identically distributed - i.i.d), "Late Chunking" tạo ra một tập hợp các embedding vectors mà mỗi vector đều được ảnh hưởng bởi những vector trước đó, nhờ vậy mã hóa được nhiều thông tin ngữ cảnh hơn cho từng đoạn.
Rõ ràng, để áp dụng hiệu quả Late Chunking, chúng ta cần các embedding models hỗ trợ ngữ cảnh dài (long-context embedding models), ví dụ như "jina-embeddings-v2-base-en", có khả năng xử lý tối đa 8192 token, tương đương khoảng mười trang văn bản tiêu chuẩn.
Kết quả thử nghiệm
Cách cài đặt Late Chunking, các bạn có thể tham khảo trong GitHub repo, hoặc Colab Notebook này.
Khi áp dụng Late Chunking vào ví dụ Wikipedia ở trên, bạn có thể thấy ngay sự cải thiện về độ tương đồng ngữ nghĩa. Ví dụ, trong cụm từ "the city" và "Berlin", các vector biểu diễn cho "the city" giờ đây chứa các thông tin của "Berlin" được nhắc đến trước đó.
Bảng trên so sánh độ tương đồng cosine giữa embedding vector của từ "Berlin" và các câu khác nhau trong bài viết có liên quan tới Berlin. Cột "Sim. on naive chunking" hiển thị các giá trị tương đồng giữa embedding vector của truy vấn "Berlin" và các embedding vector sử dụng phương pháp Naive Chunking, còn cột "Sim. on late chunking" biểu thị kết quả với phương pháp Late Chunking.
0 Comments