{"product_id":"session-memory-compaction-conversation-dai-khong-lo-tran-context","title":"Session Memory Compaction — Conversation dài không lo tràn context","description":"\n\u003cp\u003eContext window của Claude là hữu hạn — claude-haiku-4-5 có 200k tokens, claude-opus-4-5 có 200k tokens. Conversation dài sẽ tới lúc đạt giới hạn này và bạn phải xử lý. \u003cstrong\u003eSession Memory Compaction\u003c\/strong\u003e là kỹ thuật \"nén\" lịch sử hội thoại cũ thành tóm tắt, giải phóng space cho conversation tiếp tục.\u003c\/p\u003e\n\n\u003ch2\u003eVấn đề: Context Window Overflow\u003c\/h2\u003e\n\n\u003cp\u003eKhông xử lý context overflow dẫn đến:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eAPI error:\u003c\/strong\u003e Request bị reject vì quá context limit\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eMất thông tin:\u003c\/strong\u003e Truncate cứng mất đi context quan trọng\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eChi phí tăng:\u003c\/strong\u003e Mỗi request trả tiền cho toàn bộ history\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eLatency tăng:\u003c\/strong\u003e Xử lý context lớn chậm hơn\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch2\u003eBa chiến lược xử lý\u003c\/h2\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n\u003cth\u003eChiến lược\u003c\/th\u003e\n\u003cth\u003eƯu điểm\u003c\/th\u003e\n\u003cth\u003eNhược điểm\u003c\/th\u003e\n\u003cth\u003eKhi nào dùng\u003c\/th\u003e\n\u003c\/tr\u003e\n  \u003c\/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n\u003ctd\u003eSliding window\u003c\/td\u003e\n\u003ctd\u003eĐơn giản, nhanh\u003c\/td\u003e\n\u003ctd\u003eMất thông tin cũ hoàn toàn\u003c\/td\u003e\n\u003ctd\u003eSmall talk, tasks ngắn\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eSummarization\u003c\/td\u003e\n\u003ctd\u003eGiữ được context quan trọng\u003c\/td\u003e\n\u003ctd\u003eCó thể mất chi tiết\u003c\/td\u003e\n\u003ctd\u003eHầu hết ứng dụng\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eHierarchical memory\u003c\/td\u003e\n\u003ctd\u003eGiữ nhiều thông tin nhất\u003c\/td\u003e\n\u003ctd\u003ePhức tạp hơn\u003c\/td\u003e\n\u003ctd\u003eLong-term assistants\u003c\/td\u003e\n\u003c\/tr\u003e\n  \u003c\/tbody\u003e\n\u003c\/table\u003e\n\n\u003ch2\u003eChiến lược 1: Sliding Window (đơn giản)\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003eimport anthropic\n\nclient = anthropic.Anthropic()\n\ndef sliding_window_chat(messages: list, new_message: str,\n                        max_messages: int = 20) -\u0026gt; tuple:\n    \"\"\"\n    Giữ tối đa max_messages cuối cùng trong history.\n    Đơn giản nhưng mất context cũ.\n    \"\"\"\n    # Thêm message mới\n    messages.append({\"role\": \"user\", \"content\": new_message})\n\n    # Trim nếu vượt quá giới hạn\n    if len(messages) \u0026gt; max_messages:\n        messages = messages[-max_messages:]\n        print(f\"[Trimmed to last {max_messages} messages]\")\n\n    response = client.messages.create(\n        model=\"claude-haiku-4-5\",\n        max_tokens=500,\n        messages=messages,\n    )\n\n    answer = response.content[0].text\n    messages.append({\"role\": \"assistant\", \"content\": answer})\n\n    return answer, messages\n\n# Usage\nconversation = []\nwhile True:\n    user_input = input(\"Bạn: \")\n    if user_input.lower() in [\"quit\", \"exit\"]:\n        break\n    answer, conversation = sliding_window_chat(conversation, user_input)\n    print(f\"Claude: {answer}\n\")\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eChiến lược 2: Summarization Compaction (khuyến nghị)\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003eCOMPACTION_PROMPT = \"\"\"Bạn đang giúp tóm tắt lịch sử hội thoại để giải phóng bộ nhớ.\n\nTóm tắt cuộc hội thoại sau thành một đoạn văn ngắn gọn nhưng đầy đủ thông tin.\nBao gồm:\n1. Chủ đề chính đã thảo luận\n2. Các quyết định hoặc kết luận quan trọng\n3. Thông tin cụ thể quan trọng (số liệu, tên, ngày tháng)\n4. Trạng thái hiện tại của task (nếu có)\n\nLịch sử hội thoại:\n{conversation_history}\n\nViết tóm tắt ngắn gọn (tối đa 300 từ), third-person perspective.\"\"\"\n\ndef compact_conversation(messages: list) -\u0026gt; str:\n    \"\"\"Tóm tắt danh sách messages thành một đoạn văn ngắn.\"\"\"\n\n    # Format history thành text\n    history_text = \"\"\n    for msg in messages:\n        role = \"Người dùng\" if msg[\"role\"] == \"user\" else \"Claude\"\n        content = msg[\"content\"] if isinstance(msg[\"content\"], str) else str(msg[\"content\"])\n        history_text += f\"{role}: {content}\n\n\"\n\n    prompt = COMPACTION_PROMPT.format(conversation_history=history_text)\n\n    response = client.messages.create(\n        model=\"claude-haiku-4-5\",\n        max_tokens=400,\n        messages=[{\"role\": \"user\", \"content\": prompt}],\n        temperature=0.0,\n    )\n\n    return response.content[0].text\n\nclass CompactingChatbot:\n    \"\"\"Chatbot tự động compact khi context gần đầy.\"\"\"\n\n    def __init__(self, system_prompt: str = \"\", max_tokens_threshold: int = 150000,\n                 keep_recent: int = 10):\n        self.system_prompt = system_prompt\n        self.max_tokens = max_tokens_threshold\n        self.keep_recent = keep_recent\n        self.messages = []\n        self.compacted_summary = \"\"\n        self.total_tokens_used = 0\n        self.compaction_count = 0\n\n    def _estimate_tokens(self) -\u0026gt; int:\n        \"\"\"Ước tính số tokens trong conversation hiện tại.\"\"\"\n        total_chars = sum(\n            len(msg[\"content\"]) if isinstance(msg[\"content\"], str) else 0\n            for msg in self.messages\n        )\n        return total_chars \/\/ 4  # Rough estimate: 4 chars per token\n\n    def _should_compact(self) -\u0026gt; bool:\n        return self._estimate_tokens() \u0026gt; self.max_tokens\n\n    def _compact(self):\n        \"\"\"Compact phần cũ của conversation.\"\"\"\n        if len(self.messages) \u0026lt;= self.keep_recent:\n            return\n\n        # Chia messages thành: cũ (sẽ compact) và mới (giữ lại)\n        old_messages = self.messages[:-self.keep_recent]\n        recent_messages = self.messages[-self.keep_recent:]\n\n        # Tóm tắt phần cũ\n        print(f\"[Compacting {len(old_messages)} messages...]\")\n        new_summary = compact_conversation(old_messages)\n\n        # Kết hợp với summary cũ nếu có\n        if self.compacted_summary:\n            combine_prompt = f\"\"\"Kết hợp hai tóm tắt sau thành một:\n\nTÓM TẮT CŨ:\n{self.compacted_summary}\n\nTÓM TẮT MỚI:\n{new_summary}\n\nViết tóm tắt kết hợp (tối đa 400 từ):\"\"\"\n\n            response = client.messages.create(\n                model=\"claude-haiku-4-5\",\n                max_tokens=500,\n                messages=[{\"role\": \"user\", \"content\": combine_prompt}],\n                temperature=0.0,\n            )\n            self.compacted_summary = response.content[0].text\n        else:\n            self.compacted_summary = new_summary\n\n        # Rebuild messages với summary + recent\n        self.messages = recent_messages\n        self.compaction_count += 1\n        print(f\"[Compaction #{self.compaction_count} done. Summary: {len(self.compacted_summary)} chars]\")\n\n    def chat(self, user_message: str) -\u0026gt; str:\n        \"\"\"Gửi message và nhận response, tự động compact khi cần.\"\"\"\n\n        # Kiểm tra và compact nếu cần\n        if self._should_compact():\n            self._compact()\n\n        # Thêm user message\n        self.messages.append({\"role\": \"user\", \"content\": user_message})\n\n        # Build system prompt với summary (nếu có)\n        system = self.system_prompt\n        if self.compacted_summary:\n            system += f\"\n\n[CONTEXT FROM EARLIER CONVERSATION]\n{self.compacted_summary}\"\n\n        # Gọi API\n        response = client.messages.create(\n            model=\"claude-haiku-4-5\",\n            max_tokens=800,\n            system=system,\n            messages=self.messages,\n        )\n\n        answer = response.content[0].text\n        self.messages.append({\"role\": \"assistant\", \"content\": answer})\n        self.total_tokens_used += response.usage.input_tokens + response.usage.output_tokens\n\n        return answer\n\n    def get_stats(self) -\u0026gt; dict:\n        return {\n            \"messages_in_memory\": len(self.messages),\n            \"has_summary\": bool(self.compacted_summary),\n            \"compaction_count\": self.compaction_count,\n            \"estimated_current_tokens\": self._estimate_tokens(),\n            \"total_tokens_used\": self.total_tokens_used,\n        }\n\n# Ví dụ sử dụng\nbot = CompactingChatbot(\n    system_prompt=\"Bạn là trợ lý lập kế hoạch dự án. Hãy giúp user theo dõi tiến độ.\",\n    max_tokens_threshold=50000,  # Compact khi \u0026gt; 50k tokens (thấp để demo)\n    keep_recent=6  # Giữ 6 messages gần nhất\n)\n\n# Simulate conversation dài\nquestions = [\n    \"Tôi đang làm dự án website cho khách hàng ABC.\",\n    \"Deadline là ngày 15\/4. Hiện tại đã xong design và backend API.\",\n    \"Frontend cần thêm 2 tuần nữa. Team có 3 người frontend.\",\n    \"Khách hàng muốn thêm tính năng payment gateway.\",\n    \"Chúng ta có nên dùng Stripe hay VNPay?\",\n    \"Tóm tắt lại tiến độ dự án hiện tại cho tôi.\",\n]\n\nfor q in questions:\n    print(f\"User: {q}\")\n    answer = bot.chat(q)\n    print(f\"Claude: {answer[:150]}...\")\n    print(f\"Stats: {bot.get_stats()}\")\n    print()\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eChiến lược 3: Hierarchical Memory\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003eclass HierarchicalMemory:\n    \"\"\"\n    Bộ nhớ phân cấp:\n    - Working memory: conversation gần nhất (detail level)\n    - Episodic memory: tóm tắt sessions trước\n    - Semantic memory: facts quan trọng, user preferences\n    \"\"\"\n\n    def __init__(self):\n        self.working_memory = []     # Messages gần nhất\n        self.episodic_memory = []    # Tóm tắt từng session\n        self.semantic_memory = {}    # Key facts about user\/project\n\n    def update_semantic_memory(self, conversation: list):\n        \"\"\"Extract và lưu facts quan trọng.\"\"\"\n        if not conversation:\n            return\n\n        history = \"\n\".join([\n            f\"{m['role'].title()}: {m['content'][:100]}\"\n            for m in conversation[-10:]\n        ])\n\n        response = client.messages.create(\n            model=\"claude-haiku-4-5\",\n            max_tokens=200,\n            messages=[{\n                \"role\": \"user\",\n                \"content\": f\"\"\"Từ conversation sau, extract các facts quan trọng về user\/project.\nFormat: JSON dict với keys là categories.\n\n{history}\n\nChỉ trả về JSON:\"\"\"\n            }],\n            temperature=0.0,\n        )\n\n        import json, re\n        text = response.content[0].text.strip()\n        match = re.search(r\"{.*}\", text, re.DOTALL)\n        if match:\n            try:\n                new_facts = json.loads(match.group())\n                self.semantic_memory.update(new_facts)\n            except json.JSONDecodeError:\n                pass\n\n    def build_context_for_request(self) -\u0026gt; str:\n        \"\"\"Tạo context string từ tất cả memory layers.\"\"\"\n        context_parts = []\n\n        if self.semantic_memory:\n            facts = \"\n\".join(f\"- {k}: {v}\" for k, v in self.semantic_memory.items())\n            context_parts.append(f\"Known facts:\n{facts}\")\n\n        if self.episodic_memory:\n            recent_episodes = self.episodic_memory[-3:]  # 3 sessions gần nhất\n            episodes_text = \"\n\n\".join(recent_episodes)\n            context_parts.append(f\"Previous sessions:\n{episodes_text}\")\n\n        return \"\n\n\".join(context_parts)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eKhi nào compact?\u003c\/h2\u003e\n\n\u003cp\u003eCó 3 trigger phổ biến:\u003c\/p\u003e\n\n\u003col\u003e\n  \u003cli\u003e\n\u003cstrong\u003eToken threshold:\u003c\/strong\u003e Compact khi estimated tokens vượt X% của context limit\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eMessage count:\u003c\/strong\u003e Compact sau mỗi N messages (đơn giản, predictable)\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTime-based:\u003c\/strong\u003e Compact sau mỗi session\/ngày\u003c\/li\u003e\n\u003c\/ol\u003e\n\n\u003cpre\u003e\u003ccode\u003eclass SmartCompactionTrigger:\n    def __init__(self, max_tokens: int = 100000, max_messages: int = 50,\n                 compact_ratio: float = 0.7):\n        self.max_tokens = max_tokens\n        self.max_messages = max_messages\n        self.compact_ratio = compact_ratio  # Compact khi đạt 70% giới hạn\n\n    def should_compact(self, messages: list, current_tokens: int) -\u0026gt; bool:\n        return (\n            current_tokens \u0026gt; self.max_tokens * self.compact_ratio\n            or len(messages) \u0026gt; self.max_messages\n        )\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eMemory compaction là kỹ thuật nền tảng cho mọi ứng dụng chatbot nghiêm túc. Kết hợp với \u003ca href=\"\/collections\/nang-cao\"\u003ePrompt Caching\u003c\/a\u003e để giảm chi phí sau mỗi compaction cycle.\u003c\/p\u003e\n","brand":"Minh Tuấn","offers":[{"title":"Default Title","offer_id":47721832284372,"sku":null,"price":0.0,"currency_code":"VND","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0821\/0264\/9044\/files\/session-memory-compaction-conversation-dai-khong-lo-tran-context.jpg?v=1774521726","url":"https:\/\/claude.vn\/products\/session-memory-compaction-conversation-dai-khong-lo-tran-context","provider":"CLAUDE.VN","version":"1.0","type":"link"}