Từ Chunking cơ bản đến Semantic Chunking
Giả sử ta có đoạn văn sau:
EvoCar là một công ty khởi nghiệp trong lĩnh vực xe điện đến từ Đông Nam Á. Với tham vọng trở thành thương hiệu toàn cầu, công ty đã nhanh chóng xây dựng nhà máy sản xuất và trung tâm nghiên cứu chỉ trong vòng 18 tháng. Đến năm thứ hai, EvoCar đã cho ra mắt mẫu xe điện đầu tiên, gây ấn tượng bởi thiết kế hiện đại và phạm vi di chuyển lên đến 500 km mỗi lần sạc.
Bên cạnh việc phục vụ thị trường nội địa, EvoCar đặt mục tiêu mở rộng sang các thị trường lớn như Mỹ và châu Âu. Họ đã mở văn phòng tại California, đồng thời tham gia các triển lãm công nghệ để quảng bá sản phẩm.
Tuy nhiên, con đường toàn cầu hóa không hề bằng phẳng. EvoCar đang phải cạnh tranh với các ông lớn như Tesla, BYD, cùng lúc đối mặt với chi phí sản xuất cao và lo ngại từ khách hàng về chất lượng sản phẩm mới. Để vượt qua những thách thức đó, công ty tuyên bố sẽ tăng đầu tư vào công nghệ pin và mở rộng hợp tác với các chuỗi cung ứng địa phương.
Chunking thông thường: chia đều nhưng thiếu hiểu
Nếu sử dụng thuật toán chia văn bản phổ biến như RecursiveCharacterTextSplitter, ta có thể cấu hình như sau:
splitter = RecursiveCharacterTextSplitter(
chunk_size=100,
chunk_overlap=0,
separators=["\n\n", "\n", ".", " "]
)
Kết quả là văn bản bị cắt thành các đoạn như:
-
“EvoCar là một công ty khởi nghiệp trong lĩnh vực xe điện đến từ Đông Nam Á. Với tham vọng trở thành thương hiệu toàn cầu, công ty đã nhanh chóng xây dựng nhà máy sản xuất và trung tâm nghiên cứu chỉ trong vòng 18 tháng.”
-
“Đến năm thứ hai, EvoCar đã cho ra mắt mẫu xe điện đầu tiên, gây ấn tượng bởi thiết kế hiện đại và phạm vi di chuyển lên đến 500 km mỗi lần sạc. Bên cạnh việc phục vụ thị trường nội địa, EvoCar đặt mục tiêu mở rộng sang các thị trường lớn như Mỹ và châu Âu.”
-
“Họ đã mở văn phòng tại California, đồng thời tham gia các triển lãm công nghệ để quảng bá sản phẩm. Tuy nhiên, con đường toàn cầu hóa không hề bằng phẳng. EvoCar đang phải cạnh tranh với các ông lớn như Tesla, BYD, cùng lúc đối mặt với chi phí sản xuất cao và lo ngại từ khách hàng về chất lượng sản phẩm mới.”
-
“Để vượt qua những thách thức đó, công ty tuyên bố sẽ tăng đầu tư vào công nghệ pin và mở rộng hợp tác với các chuỗi cung ứng địa phương.”
Ở đây, việc chia dựa trên độ dài ký tự dẫn đến những đoạn văn bị trộn lẫn giữa nhiều chủ đề khác nhau. Đặc biệt, đoạn thứ ba chứa cả nội dung về quảng bá sản phẩm lẫn những khó khăn mà công ty đang đối mặt – điều này khiến mô hình dễ hiểu sai nếu được hỏi về một chủ đề cụ thể.
🧠 Semantic Chunking: cắt đúng lúc, hiểu đúng nghĩa
Thay vì dựa vào độ dài cố định, semantic chunking tìm cách chia văn bản theo các đơn vị ngữ nghĩa hoàn chỉnh. Ứng dụng kỹ thuật này (ví dụ dùng embedding và đo độ tương đồng giữa các câu), văn bản sẽ được chia như sau:
-
Chunk 1 – Giới thiệu và giai đoạn thành lập:
“EvoCar là một công ty khởi nghiệp trong lĩnh vực xe điện đến từ Đông Nam Á. Với tham vọng trở thành thương hiệu toàn cầu, công ty đã nhanh chóng xây dựng nhà máy sản xuất và trung tâm nghiên cứu chỉ trong vòng 18 tháng.”
-
Chunk 2 – Thành tựu sản phẩm và thị trường mục tiêu:
“Đến năm thứ hai, EvoCar đã cho ra mắt mẫu xe điện đầu tiên, gây ấn tượng bởi thiết kế hiện đại và phạm vi di chuyển lên đến 500 km mỗi lần sạc. Bên cạnh việc phục vụ thị trường nội địa, EvoCar đặt mục tiêu mở rộng sang các thị trường lớn như Mỹ và châu Âu. Họ đã mở văn phòng tại California, đồng thời tham gia các triển lãm công nghệ để quảng bá sản phẩm.”
-
Chunk 3 – Thách thức và đối thủ cạnh tranh:
“Tuy nhiên, con đường toàn cầu hóa không hề bằng phẳng. EvoCar đang phải cạnh tranh với các ông lớn như Tesla, BYD, cùng lúc đối mặt với chi phí sản xuất cao và lo ngại từ khách hàng về chất lượng sản phẩm mới.”
-
Chunk 4 – Hướng đi chiến lược:
“Để vượt qua những thách thức đó, công ty tuyên bố sẽ tăng đầu tư vào công nghệ pin và mở rộng hợp tác với các chuỗi cung ứng địa phương.”
Như vậy, mỗi đoạn không chỉ liền mạch về mặt cấu trúc mà còn phản ánh một đơn vị thông tin độc lập: từ quá khứ – hiện tại – đến định hướng tương lai. Khi truy vấn thông tin theo chủ đề như “khó khăn của công ty” hay “kế hoạch phát triển thị trường”, hệ thống RAG sẽ dễ dàng chọn đúng chunk thay vì bị nhiễu.
⚙️ Semantic Chunking hoạt động như thế nào?
Việc "chia theo ngữ nghĩa" không còn đơn giản là ngắt văn bản theo câu hoặc ký tự. Thay vào đó, semantic chunking sử dụng sức mạnh của mô hình embedding ngôn ngữ để đo lường mức độ liên kết giữa các đơn vị văn bản, thường là câu hoặc đoạn ngắn. Dưới đây là một quy trình phổ biến:
📚 Quy trình cơ bản
-
Tách văn bản thành các câu hoặc đoạn ngắn.
Đây là bước chuẩn hóa đầu vào: giữ nguyên ngữ pháp, câu trọn vẹn. -
Chuyển từng câu thành vector embedding
Sử dụng mô hình pre-trained như (ví dụ một mô hình Sentence Transformers) để ánh xạ từng câu thành vector ngữ nghĩa. -
Tính độ tương đồng giữa các câu
Sử dụng cosine similarity để đo lường mức độ gần nhau về ý nghĩa giữa các câu. -
Ghép nhóm các câu gần nhau về ngữ nghĩa
Câu nào có liên kết cao (vượt ngưỡng threshold) sẽ được nhóm vào cùng một chunk. -
Tạo ra các chunk hoàn chỉnh
Mỗi chunk đại diện cho một chủ đề hoặc ý diễn đạt liền mạch, giúp giữ nguyên ngữ cảnh khi đưa vào hệ thống.
🧪 Minh họa: Semantic Chunking bằng Python
Dưới đây là một ví dụ đơn giản để chia một văn bản ngắn thành các chunk theo ngữ nghĩa.
🧾 Văn bản đầu vào:
sentences = [
"EvoCar là một công ty khởi nghiệp trong lĩnh vực xe điện.",
"Họ được thành lập tại Đông Nam Á vào năm 2020.",
"Trong hai năm đầu, công ty ra mắt mẫu xe điện đầu tiên.",
"Xe có thiết kế hiện đại và phạm vi di chuyển 500km.",
"EvoCar đã mở rộng sang Mỹ và châu Âu.",
"Họ gặp khó khăn về chi phí sản xuất và lòng tin từ khách hàng.",
"Công ty đầu tư mạnh vào công nghệ pin.",
"EvoCar hợp tác với nhiều chuỗi cung ứng địa phương."
]
⚙️ Mã nguồn xử lý Semantic Chunking:
from sentence_transformers import SentenceTransformer, util
# Load mô hình embedding
model = SentenceTransformer('keepitreal/vietnamese-sbert')
# Bước 1: Chuyển câu thành vector
embeddings = model.encode(sentences, convert_to_tensor=True)
# Bước 2: Tính độ tương đồng giữa các câu
similarity_matrix = util.pytorch_cos_sim(embeddings, embeddings)
# Bước 3: Nhóm câu theo ngữ nghĩa
# Quy tắc đơn giản: mỗi câu sẽ nhóm với các câu có độ tương đồng > 0.6
threshold = 0.6
used = set()
semantic_chunks = []
for i in range(len(sentences)):
if i in used:
continue
chunk = [sentences[i]]
used.add(i)
for j in range(i+1, len(sentences)):
if j not in used and similarity_matrix[i][j] > threshold:
chunk.append(sentences[j])
used.add(j)
semantic_chunks.append(" ".join(chunk))
# Kết quả
for idx, chunk in enumerate(semantic_chunks, 1):
print(f"Chunk {idx}:\n{chunk}\n")
📌 Kết quả mẫu:
Các bài viết thuộc chuỗi RAG Pattern Series
- Baseline RAG: Tìm Hiểu Về Basic Retriever
- Parent-Child Retriever: Mô Hình Truy Xuất Thông Tin với Ngữ Cảnh Rộng hơn
- Hypothetical Question Retriever (HQR) trong RAG
- Cải tiến Retriever bằng Hypothetical Document Embeddings HyDE
- Cache-Augmented Generation là gì và nó có tốt hơn RAG?