Quản lý lịch sử hội thoại: Pruning, summarization, sliding window
Chiến lược nén lịch sử hội thoại cho AI Agent: sliding window, recursive summarization và pruning để tránh hiện tượng lost-in-the-middle và kiểm soát chi phí...
Sau 20 lượt hội thoại, Agent của bạn bắt đầu quên những gì bạn yêu cầu ở đầu cuộc trò chuyện. Không phải vì context window đã đầy, mà vì cơ chế attention bị suy giảm theo hiện tượng "lost in the middle". Dưới đây là cách các hệ thống production nén 10.000 token lịch sử chat xuống còn 2.500 token tín hiệu cao mà không làm mất ý chính.
Vấn đề
LLM không có bộ nhớ làm việc vô hạn. Ngoài 20-30 lượt trò chuyện, lịch sử hội thoại thô trở thành nhiễu. Attention matrix đối xử mọi token như nhau, nên lời chào "hello" từ lượt 1 cạnh tranh dung lượng với schema API hiện tại ở lượt 25. Chi phí scaling theo hàm bậc hai (quadratic) có nghĩa là bạn đang trả tiền cho 10K token nhưng chỉ sử dụng hiệu quả 2K. Chúng ta cần các chiến lược đánh đổi độ dài context lấy độ liên quan (relevance).
Vấn đề trở nên nghiêm trọng khi Agent thực thi nhiệm vụ dài hạn: một lệnh "không bao giờ dùng regex để parse HTML" ở turn 1 sẽ bị lu mờ trước một đoạn code regex ở turn 50, không phải vì model ngu ngốc, mà vì attention weights giảm theo hàm mũ đối với token cũ. Đây là "context pollution" - khi lịch sử tích lũy làm loãng tín hiệu của nhiệm vụ hiện tại.
Ý tưởng cốt lõi
Thay vì lưu toàn bộ transcript, ta áp dụng ba chiến lược nén bổ trợ: sliding window (cửa sổ trượt), recursive summarization (tóm tắt đệ quy), và pruning (cắt tỉa chọn lọc). Mỗi cách tối ưu cho một phân khúc của bộ nhớ ngắn, trung và dài hạn.
Sliding Window: Cửa sổ di động trên dòng thời gian
Chiến lược này duy trì circular buffer của K lượt gần nhất (thường 4K-8K token). Khi đạt giới hạn, nội dung cũ nhất bị vứt bỏ hoàn toàn - O(1) memory, deterministic behavior.
Có hai biến thể:
- Fixed window: Luôn giữ đúng N lượt cuối. Đơn giản, dễ debug, nhưng sẽ cắt ngang ngay cả khi đang giữa một chủ đề quan trọng.
- Dynamic window: Phát hiện chuyển chủ đề (topic shift) qua embedding similarity. Khi user chuyển từ "debug Python" sang "gợi ý nhà hàng", hệ thống reset window, coi đây là session mới. Điều này ngăn "cross-contamination" - kiến thức về Python không làm nhiễu gợi ý ẩm thực.
Ví dụ cấu hình trong LangChain:
from langchain.memory import ConversationBufferWindowMemory
# Giữ 5 lượt gần nhất, bỏ phần còn lại
memory = ConversationBufferWindowMemory(
k=5,
return_messages=True
)Recursive Summarization: Nén thông tin theo cấp bậc
Thay vì giữ transcript từ lượt 1-10, ta dùng chính LLM để nén thành summary A. Khi có lượt 11-20, ta merge summary A với nội dung mới, tạo summary B ở mức độ trừu tượng cao hơn. Các lượt gần nhất (21-25) giữ nguyên verbatim.
Đây là semantic delta compression: giữ lại "state change" (user đã hiểu list comprehensions, preference là dark mode), bỏ "process noise" (lời giải thích dài dòng, scaffolding). Ngôn ngữ tự nhiên có độ dư thừa khoảng 80%, nên 10K token transcript có thể nén thành 500 token summary mà vẫn giữ ý chính.
Ví dụ cấu hình:
from langchain.memory import ConversationSummaryMemory
# Tự động tóm tắt khi vượt ngưỡng
memory = ConversationSummaryMemory(
llm=llm,
max_token_limit=1000
)Pruning: Cắt tỉa có chọn lọc
Thay vì xóa theo thời gian, ta xóa theo mức độ liên quan (relevance scoring). Dùng embedding similarity giữa câu query hiện tại và từng message trong lịch sử - giữ lại các message có similarity cao, bỏ "thank you", "got it".
Quan trọng nhất là giữ "anchor messages" - những constraint hoặc fact key được user nói ở đầu session (ví dụ: "dự án này dùng Python 3.9, không được dùng pandas"). Pruning đảm bảo những anchor này tồn tại suốt session dù đã cũ.
Kiến trúc Hybrid trong Production (ChatGPT/Claude):
- System layer: Pruning cho constraints và personality (giữ lâu dài)
- Working layer: Sliding window cho 10-20 lượt gần nhất (tốc độ cao)
- Archival layer: Recursive summarization cho phần giữa (trung bình)
Tại sao nó hoạt động
Power-law decay của relevance: Hội thoại tuân theo temporal locality (tính chất Markov). Lượt thứ 10 ảnh hưởng đến lượt 11 theo cấp số nhân ít hơn so với lượt 2 ảnh hưởng lượt 3. Sliding window khai thác điều này - giữ working set giống như OS giữ các page gần đây trong RAM.
Semantic delta compression: Khi ta nén "User hỏi về list comprehensions → Tôi giải thích syntax → User hiểu rồi" thành {user_knows: "list_comprehensions"}, ta đang lưu trạng thái (state) thay vì quá trình (process). Điều này loại bỏ ~80% entropy dư thừa của ngôn ngữ tự nhiên.
Trade-off giữa các approaches:
| Chiến lược | Độ phức tạp | Catastrophic Forgetting | Fidelity | Chi phí tính toán |
|---|---|---|---|---|
| Sliding Window | O(1) | Cao (mất sớm constraints) | Cao (verbatim) | Thấp |
| Summarization | O(N) | Trung bình (lỗi tích lũy) | Trung bình (mất số liệu cụ thể) | Cao (gọi LLM) |
| Pruning | O(N log N) | Thấp (giữ anchors) | Rất cao | Rất cao (embeddings) |
Ví dụ thực tế về nén token:
- Raw history: 10K tokens (greetings, debug logs, chit-chat)
- Sau summarization: 500 tokens (tóm tắt turns 1-40)
- Plus sliding window: 2K tokens (turns 41-50 verbatim)
- Effective context: 2.5K token tín hiệu cao thay vì 10K token nhiễu.
Ý nghĩa thực tế
Benchmarks từ nghiên cứu:
- Recursive summarization: cải thiện 35% consistency trên Multi-Session Chat dataset (Wang et al., 2023) so với baseline giữ nguyên transcript.
- Dynamic sliding window: factual consistency cao hơn trong meeting summarization khi window được căn chỉnh theo agenda segments thay vì fixed size (Liu & Chen, 2021).
- Tỷ lệ nén điển hình: 10K token → 2.5K effective context vẫn giữ 90% task success rate.
Ai đang dùng:
- ChatGPT/Claude: Hybrid approach - pruning cho system prompts, sliding window cho recent turns, summarization cho middle history.
- LangChain: Cung cấp
ConversationBufferWindowMemory(sliding),ConversationSummaryMemory(recursive), vàVectorStoreRetrieverMemory(pruning-based). - Production RAG: Kết hợp pruning với vector search - chỉ giữ lịch sử có cosine similarity > 0.7 với query hiện tại.
Khi nào dùng cái gì:
- Customer Support (session ngắn, 5-10 turns): Sliding window đủ dùng, triển khai đơn giản.
- Deep Research (100+ turns, multi-hour): Cần full summarization stack để tránh lost-in-the-middle.
- Personal Assistant (cross-session memory): Kết hợp pruning với MEMORY.md patterns để giữ anchors qua nhiều ngày.
Hạn chế thực tế:
- Summarization tích lũy lỗi như JPEG artifacts - mất tên riêng, số liệu cụ thể sau 3-4 lần nén đệ quy.
- Sliding window có "catastrophic forgetting" - lệnh "không dùng regex" ở turn 1 sẽ biến mất hoàn toàn ở turn 50.
- Pruning đòi hỏi "oracle" để phát hiện relevance - nếu user nói "cái đó" ám chỉ một khái niệm từ 20 turns trước, embedding similarity có thể bỏ lỡ implicit context.
Đào sâu hơn
Tài liệu chính thức:
- LangChain Memory Documentation - Implementation patterns cho conversation history.
- OpenAI Context Window Best Practices - Chiến lược quản lý token.
Cùng cụm: Memory & Context nâng cao
Kiến trúc Memory: Short-term, working, long-term
Hiểu rõ 3 tầng bộ nhớ và cách ánh xạ sang implementation trong Agent platform
MEMORY.md Patterns: Ghi nhớ có chọn lọc qua sessions
Cấu hình file MEMORY.md để agent nhớ anchors qua nhiều phiên làm việc
Context Files: Per-user, per-workspace, per-project
Phân cấp context theo workspace và project để tránh pollution
RAG cho Agent: Khi memory không đủ, tìm kiếm thêm
Bổ sung semantic retrieval khi conversation history quá ngắn để giữ toàn bộ kiến thức domain
Đọc tiếp
Multi-Agent & Teams: Shared memory giữa các agent
Khi nhiều agent cùng truy cập một conversation history, cần coordination như thế nào
Security & Multi-tenant: Cách ly lịch sử hội thoại
Đảm bảo conversation history của user A không leak sang context window của user B
Mở rộng:
- Wang et al. (2023), "Recursively Summarizing Enables Long-Term Dialogue Memory" - arXiv:2308.15022 - Cơ sở lý thuyết cho recursive summarization.
- Liu & Chen (2021), "Dynamic Sliding Window for Meeting Summarization" - arXiv:2108.13629 - Topic-aware window management.
Context Files: Per-user, per-workspace, per-project — Phân tầng bộ nhớ cho AI Agent
Chiến lược phân tầng context workspace/project/session để tránh lãng phí token và giảm nhiễu attention. Giải pháp thay thế cho việc nhét mọi thứ vào system p...
RAG cho Agent: Khi memory không đủ, tìm kiếm thêm — Hierarchical retrieval thay vì flat search
Tại sao RAG truyền thống thất bại với agent memory? Giải pháp phân cấp theme-episode-message và agentic loop giúp agent nhớ ngữ cảnh ngầm thay vì chỉ tìm từ...