From 4a47c1328cf5267abaf30e17022fce576a3a503c Mon Sep 17 00:00:00 2001 From: rxy1212 Date: Sat, 20 Jun 2026 09:47:29 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E6=8F=92=E5=85=A5=20message=20=E4=BC=9A=E7=A0=B4=E5=9D=8F=20us?= =?UTF-8?q?er=20assistant=20=E4=BA=A4=E6=9B=BF=E5=87=BA=E7=8E=B0=E8=A7=84?= =?UTF-8?q?=E5=88=99=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add context compression and notification for snipped messages. --- s08_context_compact/code.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/s08_context_compact/code.py b/s08_context_compact/code.py index b9d78d425..c04ba397c 100644 --- a/s08_context_compact/code.py +++ b/s08_context_compact/code.py @@ -306,8 +306,27 @@ def snip_compact(messages, max_messages=50): if head_end >= tail_start: return messages snipped = tail_start - head_end - return messages[:head_end] + [{"role": "user", "content": f"[snipped {snipped} messages]"}] + messages[tail_start:] + # 构造清晰的系统断层通知,告知 Claude 上下文有缺失,避免其产生幻觉 + snip_text = f"\n\n[System Note: Snipped {snipped} history messages here for context compression]\n\n" + + # 对后半段进行深拷贝(Deep Copy)或浅拷贝,防止直接修改和污染外部传入的原始 messages 数组 + head_part = messages[:head_end] + tail_part = [msg.copy() for msg in messages[tail_start:]] + + # 将提示信息“无损”合并到后半段第一条消息中,天然继承原有的角色交替和工具流结构 + first_tail_msg = tail_part[0] + + if isinstance(first_tail_msg["content"], str): + # 场景 A:普通的纯文本消息 + first_tail_msg["content"] = snip_text + first_tail_msg["content"] + + elif isinstance(first_tail_msg["content"], list): + # 场景 B:Claude 3 常见的多模态(含图片)或包含 tool_use/tool_result 的 Content Block 列表 + # 在列表最前端插入一个标准的 text block + first_tail_msg["content"].insert(0, {"type": "text", "text": snip_text}) + + return head_part + tail_part # L2: microCompact — old result placeholders def collect_tool_results(messages): From 7c601a505bb1a3042d076b5d997bef377c816efe Mon Sep 17 00:00:00 2001 From: rxy1212 Date: Sat, 20 Jun 2026 09:48:24 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E6=8F=92=E5=85=A5=20message=20=E4=BC=9A=E7=A0=B4=E5=9D=8F=20us?= =?UTF-8?q?er=20assistant=20=E4=BA=A4=E6=9B=BF=E5=87=BA=E7=8E=B0=E8=A7=84?= =?UTF-8?q?=E5=88=99=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhance context compression by adding system notes and deep copying messages. --- s08_context_compact/README.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/s08_context_compact/README.md b/s08_context_compact/README.md index 22d967156..5f8d40d14 100644 --- a/s08_context_compact/README.md +++ b/s08_context_compact/README.md @@ -52,8 +52,27 @@ def snip_compact(messages, max_messages=50): if _is_tool_result_message(messages[tail_start]) and _message_has_tool_use(messages[tail_start - 1]): tail_start -= 1 snipped = tail_start - head_end - placeholder = {"role": "user", "content": f"[snipped {snipped} messages from conversation middle]"} - return messages[:head_end] + [placeholder] + messages[tail_start:] + + # 构造清晰的系统断层通知,告知 Claude 上下文有缺失,避免其产生幻觉 + snip_text = f"\n\n[System Note: Snipped {snipped} history messages here for context compression]\n\n" + + # 对后半段进行深拷贝(Deep Copy)或浅拷贝,防止直接修改和污染外部传入的原始 messages 数组 + head_part = messages[:head_end] + tail_part = [msg.copy() for msg in messages[tail_start:]] + + # 将提示信息“无损”合并到后半段第一条消息中,天然继承原有的角色交替和工具流结构 + first_tail_msg = tail_part[0] + + if isinstance(first_tail_msg["content"], str): + # 场景 A:普通的纯文本消息 + first_tail_msg["content"] = snip_text + first_tail_msg["content"] + + elif isinstance(first_tail_msg["content"], list): + # 场景 B:Claude 3 常见的多模态(含图片)或包含 tool_use/tool_result 的 Content Block 列表 + # 在列表最前端插入一个标准的 text block + first_tail_msg["content"].insert(0, {"type": "text", "text": snip_text}) + + return head_part + tail_part ``` 裁掉的是消息本身,只是在切口处多做一步保护;剩下的消息里 `tool_result` 内容仍在累积——第 34 条消息里可能躺着 30KB 的旧文件内容。→ L2。 From 5ee772448805a42fde19321fca0aa6254cdd6029 Mon Sep 17 00:00:00 2001 From: rxy1212 Date: Sat, 20 Jun 2026 09:49:40 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E6=8F=92=E5=85=A5=20message=20=E4=BC=9A=E7=A0=B4=E5=9D=8F=20us?= =?UTF-8?q?er=20assistant=20=E4=BA=A4=E6=9B=BF=E5=87=BA=E7=8E=B0=E8=A7=84?= =?UTF-8?q?=E5=88=99=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add context compression for message history in README. --- s08_context_compact/README.ja.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/s08_context_compact/README.ja.md b/s08_context_compact/README.ja.md index 84bfb381a..359e76834 100644 --- a/s08_context_compact/README.ja.md +++ b/s08_context_compact/README.ja.md @@ -52,8 +52,21 @@ def snip_compact(messages, max_messages=50): if _is_tool_result_message(messages[tail_start]) and _message_has_tool_use(messages[tail_start - 1]): tail_start -= 1 snipped = tail_start - head_end - placeholder = {"role": "user", "content": f"[snipped {snipped} messages from conversation middle]"} - return messages[:head_end] + [placeholder] + messages[tail_start:] + + snip_text = f"\n\n[System Note: Snipped {snipped} history messages here for context compression]\n\n" + + head_part = messages[:head_end] + tail_part = [msg.copy() for msg in messages[tail_start:]] + + first_tail_msg = tail_part[0] + + if isinstance(first_tail_msg["content"], str): + first_tail_msg["content"] = snip_text + first_tail_msg["content"] + + elif isinstance(first_tail_msg["content"], list): + first_tail_msg["content"].insert(0, {"type": "text", "text": snip_text}) + + return head_part + tail_part ``` 切り捨て自体は単純なままで、境界だけを保護する。残ったメッセージ内の `tool_result` 内容はまだ蓄積され続けている。34 番目のメッセージに 30KB の古いファイル内容が残っているかもしれない。→ L2。 From 439931df94f7a89e8f883843f82437c1f5f900b0 Mon Sep 17 00:00:00 2001 From: rxy1212 Date: Sat, 20 Jun 2026 09:50:43 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E6=8F=92=E5=85=A5=20message=20=E4=BC=9A=E7=A0=B4=E5=9D=8F=20us?= =?UTF-8?q?er=20assistant=20=E4=BA=A4=E6=9B=BF=E5=87=BA=E7=8E=B0=E8=A7=84?= =?UTF-8?q?=E5=88=99=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add boundary guard for message trimming in context compression. --- s08_context_compact/README.en.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/s08_context_compact/README.en.md b/s08_context_compact/README.en.md index 6b2f23593..e10fabbdf 100644 --- a/s08_context_compact/README.en.md +++ b/s08_context_compact/README.en.md @@ -52,8 +52,21 @@ def snip_compact(messages, max_messages=50): if _is_tool_result_message(messages[tail_start]) and _message_has_tool_use(messages[tail_start - 1]): tail_start -= 1 snipped = tail_start - head_end - placeholder = {"role": "user", "content": f"[snipped {snipped} messages from conversation middle]"} - return messages[:head_end] + [placeholder] + messages[tail_start:] + + snip_text = f"\n\n[System Note: Snipped {snipped} history messages here for context compression]\n\n" + + head_part = messages[:head_end] + tail_part = [msg.copy() for msg in messages[tail_start:]] + + first_tail_msg = tail_part[0] + + if isinstance(first_tail_msg["content"], str): + first_tail_msg["content"] = snip_text + first_tail_msg["content"] + + elif isinstance(first_tail_msg["content"], list): + first_tail_msg["content"].insert(0, {"type": "text", "text": snip_text}) + + return head_part + tail_part ``` Messages are still trimmed directly; this just adds one boundary guard. `tool_result` content within remaining messages still keeps accumulating — message #34 may still hold 30KB of old file contents. → L2.