Giới thiệu
Chào mừng bạn đến với bài viết tiếp theo trong chuỗi Practical Series của chúng tôi. Trong bài viết trước, chúng tôi đã khám phá một số phương pháp Chunking, đặc biệt là agentic chunking. Hôm nay, chúng ta sẽ tìm hiểu một kỹ thuật mới có tên Late Chunking, một phương pháp hứa hẹn cải thiện đáng kể trong giai đoạn Chunking và Retrieval của RAG.
Lưu ý: Trước khi tiếp tục, tôi xin nhắc lại rằng bài viết này không phải là một giải thích chi tiết về tài liệu nghiên cứu. Mục đích chính của bài viết này là để tìm hiểu kiến thức mới và diễn giải theo cách của riêng mình. Một số thông tin có thể chưa rõ ràng, vì vậy tôi khuyến khích bạn đọc tài liệu gốc và các nguồn tham khảo để có cái nhìn sâu sắc hơn.
Late Chunking
Vấn đề Nảy Sinh
Chúng ta hãy bắt đầu! Hãy cùng nhau điểm qua Abstract và Method của nghiên cứu liên quan để có cái nhìn tổng quan trước khi đi sâu hơn.
Trong bài viết trước, tôi đã miêu tả một số cách thức chunking thường được sử dụng. Chúng ta thường chia nhỏ văn bản thành các đoạn văn nhỏ và nhúng (embed) từng đoạn văn đó thành các nhúng độc lập. Tuy nhiên, việc này dẫn đến tình trạng mất đi thông tin ngữ cảnh. Hãy xem xét một ví dụ đơn giản:
"Python là một ngôn ngữ lập trình phổ biến. Nó được sử dụng rộng rãi trong khoa học dữ liệu, trí tuệ nhân tạo, và phát triển web. Guido van Rossum là người tạo ra nó vào năm 1991."
Nếu chúng ta chunk theo từng câu, văn bản sẽ bị tách thành ba câu:
- "Python là một ngôn ngữ lập trình phổ biến."
- "Nó được sử dụng rộng rãi trong khoa học dữ liệu, trí tuệ nhân tạo, và phát triển web."
- "Guido van Rossum là người tạo ra nó vào năm 1991."
Như bạn đã thấy, từ "Nó" ở câu thứ hai và thứ ba thực sự đại diện cho từ "Python". Tuy nhiên, do chúng ta đã nhúng chúng độc lập, mô hình không thể nhận biết được ngữ nghĩa của từ này, từ đó dẫn đến việc mất mát thông tin ngữ cảnh.
Để giải quyết vấn đề này, tác giả đã giới thiệu một phương pháp mới gọi là Late Chunking.
Nguyên Tắc Hoạt Động
Bây giờ, chúng ta hãy đi vào chủ đề chính. Tác giả đề xuất một cách tiếp cận mới có tên Late Chunking, tức là chia chunk muộn. Thay vì chia nhỏ văn bản và nhúng độc lập, phương pháp này sử dụng mô hình nhúng ngữ cảnh dài để nhúng toàn bộ văn bản sau đó mới thực hiện việc chia chunk. Điều này hy vọng sẽ giúp khắc phục tình trạng mất mát thông tin.
Mô Hình Nhúng Câu (Sentence Transformer)
Để hiểu rõ hơn về phương pháp này, chúng ta cùng xem qua mô hình nhúng câu. Mô hình này sử dụng BERT để nhúng từng token. Sau đó, chúng ta sẽ sử dụng mean pooling để tổng hợp các nhúng của các token thành một nhúng câu duy nhất. Điều này giúp cho mỗi token chứa thông tin từ các token khác.
Thuật Toán Late Chunking
Thuật toán của Late Chunking hoạt động như sau:
- Chunker(T, S): Sử dụng chiến thuật chunking để đưa ra các chunk.
- Model(τ1, ... τm): Sử dụng Long Context Embedding Model để nhúng lại các token.
- Gom các nhúng token theo từng chunk từ bước 1 và thực hiện mean pooling cho danh sách các chunk đã được gom đó.
Long Late Chunking
Có những trường hợp mà văn bản quá dài và mô hình không thể chứa hết. Để giải quyết vấn đề này, tác giả đề xuất một thuật toán mới gọi là Long Late Chunking. Ý tưởng chính là sử dụng Overlap Token w để giảm thiểu sự mất mát thông tin giữa các macro chunk.
Tuy nhiên, câu hỏi hiện ra là liệu Overlap Token w có đủ thông tin ngữ cảnh quan trọng hay không.
Dù không thể đảm bảo 100% rằng w luôn chứa ngữ cảnh quan trọng, nhưng chúng ta có thể tin vào sự liền mạch của ngữ cảnh trong nhiều văn bản. Điều này có nghĩa là một token w sẽ nằm ở cuối một chunk và đầu của chunk tiếp theo, giúp giữ lại ngữ cảnh cần thiết.
Lựa Chọn Overlap Token w
Khi lựa chọn overlap token w, cần có chiến lược hợp lý để tăng khả năng chứa ngữ cảnh hữu ích. Nếu không, việc phân chia ở vị trí ngẫu nhiên có thể dẫn đến những thiếu sót nghiêm trọng.
Thực Hành
Bây giờ chúng ta hãy thử triển khai một chút mã để hiểu rõ hơn về ứng dụng của Late Chunking. Tôi sẽ sử dụng mô hình của tác giả trên Hugging Face.
Mã ví dụ
python
from sentence_transformers import SentenceTransformer
import numpy as np
import torch
from sklearn.metrics.pairwise import cosine_similarity
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
embedding_model = SentenceTransformer('jinaai/jina-embeddings-v2-base-en', trust_remote_code=True).to(device)
text = "Berlin là thủ đô và thành phố lớn nhất của Đức, về cả diện tích và dân số. Với hơn 3,85 triệu cư dân, nó là thành phố đông dân nhất trong Liên minh Châu Âu, tính theo dân số trong giới hạn thành phố."
# Chia nhỏ câu và nhúng chúng
list_chunks = [chunk + '.' for chunk in text.split('.') if chunk]
# Các bước nhúng và tính toán điểm tương đồng cosine tại đây...
Kết quả cho thấy rằng việc nhúng toàn bộ văn bản và sau đó chia chunk đã cải thiện nhiều tỷ lệ tương đồng giữa các chunk và truy vấn.
Kết Luận
Cuối cùng, Late Chunking cố gắng cải thiện việc nhúng bằng cách nhúng toàn bộ văn bản trước khi chia thành chunk. Tuy nhiên, nó cũng có một số nhược điểm như phụ thuộc vào mô hình nhúng ngữ cảnh dài và không phải lúc nào cũng tương thích với mọi mô hình. Mặc dù đây là một ý tưởng hay, quyết định sử dụng phương pháp sẽ tùy thuộc vào từng bài toán cụ thể. Nếu có đủ ngân sách, tôi cá nhân thích sử dụng mô hình tìm kiếm dựa trên đối tượng.
Cảm ơn bạn đã dành thời gian đọc bài viết này! Hẹn gặp lại bạn trong các bài viết tiếp theo. Nếu bạn thấy bài viết hữu ích, hãy nhấn nút upvote và đánh dấu chúng tôi nhé.