乐于分享
好东西不私藏

Claude Code源码解构:压缩提示工程(二)

Claude Code源码解构:压缩提示工程(二)

Claude Code源码解构:压缩提示工程(二):深度摘要与状态保留

接上篇(一),我们继续深入深度摘要的防幻觉策略和状态保留机制。

三、深度摘要的防幻觉策略

在这里插入图片描述

当令牌预算触发压缩后,系统会调用 streamCompactSummary 函数,向模型发送一个精心设计的 System Prompt,要求其生成结构化的对话摘要。

3.1 摘要 Prompt 模板

Please generate a detailed summary of the conversation so far.

Format your response with <analysis> and <summary> tags.

<analysis>
First, think through the key points, user intent, technical decisions, and pending tasks.
</analysis>

<summary>
1. Primary Request and Intent:
   [详细描述]

2. Key Technical Concepts:
   - [概念 1]
   - [概念 2]

3. Files and Code Sections:
   - [文件名 1]
      - [总结为什么这个文件很重要]
      - [对此文件所做更改的摘要]
      - [重要的代码片段]

4. Errors and fixes:
    - [错误 1 的详细描述]:
      - [你如何修复错误]
      - [用户对错误的反馈,如果有]

5. Problem Solving:
   [解决的问题和正在进行的故障排除的描述]

6. All user messages: 
    - [详细的非工具调用的用户消息]

7. Pending Tasks:
   - [任务 1]
   - [任务 2]

8. Current Work:
   [当前工作的精确描述]

9. Optional Next Step:
   [要采取的可选下一步]
</summary>

请根据迄今为止的对话提供你的摘要,遵循此结构并确保你的回复精确和彻底。

该 Prompt 强制要求模型以 <analysis>(思考逻辑)和 <summary>(正式摘要)格式输出,确保涵盖用户意图、技术决策、修改的文件列表及下一步待办事项。

3.2 <analysis> 与 <summary> 的实战意义

在源码的实现中,这两个模块承载了截然不同的工程使命:

  • • <analysis>(思考暂存区):这是模型的Chain of Thought(思维链)。系统强制要求模型在输出摘要前,先在 <analysis> 标签内把事情”过一遍脑子”。这能大幅降低幻觉(Hallucination)。但关键在于,这个模块对用户和未来的上下文是不可见的。源码中的 formatCompactSummary 函数会通过正则 /<analysis>[\s\S]*?<\/analysis>/ 将其直接删除。
  • • <summary>(浓缩上下文):这是真正保留给下一轮对话的正式摘要

3.3 代码层面的实战回复示例

假设你让 Claude 帮忙重构登录组件,期间读取了文件并修复了报错,触发 /compact 后,模型实际返回的 XML 结构如下:

<analysis>
好的,梳理一下。
1. 用户让我把 src/components/Login.tsx 的状态管理改成 Zustand。
2. 我用 Read 读了文件,用 Edit 修改了 useAuth 为 useAuthStore。
3. 修改后报错:Property 'token' does not exist。
4. 我在 store/authStore.ts 补上了 token 的类型。目前已修复。
</analysis>


<summary>

1. Primary Request and Intent:
   将 Login.tsx 的状态管理重构为 Zustand。

2. Key Technical Concepts:
   - Zustand (状态管理) / TypeScript

3. Files and Code Sections:
   - src/components/Login.tsx:替换了 useContext 为 Zustand hook。
   - src/store/authStore.ts:在 AuthState 接口补充了 token?: string。

4. Errors and fixes:
    - 报错 Property 'token' does not exist:
      - 修复:在 store/authStore.ts 添加了类型定义。

5. Pending Tasks:
   - 为 Login.tsx 添加单元测试。

6. Current Work:
   准备编写测试用例。
</summary>

关键点<analysis> 被系统删除,只保留 <summary> 作为新对话的起点。

四、状态保留与场景复现

这是 Claude Code 压缩机制中最容易被忽视、但也是最核心的”防失忆”设计。

4.1 为什么需要状态重注入?

如果压缩只是简单地”清空历史 + 插入摘要”,模型会立刻陷入”我知道我做过什么,但我不知道我手里有什么”的尴尬境地。

问题:摘要里说”已修复 auth.ts”,但模型手里没有 auth.ts 的最新代码。它怎么继续写 session.ts?

答案:在清空历史后,系统会立即重新读取关键文件,并将它们作为”附件”(Attachment)注入新对话的首轮。

4.2 状态重注入的三大支柱

支柱
源码函数
作用
文件内容重读 createPostCompactFileAttachments
重新读取最近访问的 5 个文件最新内容
计划进度恢复 createPlanModeAttachmentIfNeeded
恢复 /plan 任务树的执行状态
Skill 规则激活 createSkillAttachmentIfNeeded
重新激活已加载的 Skill 规则

4.3 对话状态转换实例

步骤一:压缩前(Before Compact)

[
  {
 "role": "user", "content": "帮我重构 auth.ts..." },
  {
 "role": "assistant", "tool_calls": [{"name": "Read", "args": {"file": "auth.ts"}}] },
  {
 "role": "user", "content": "[File: auth.ts ... 500 lines]", "type": "tool_result" },
  // ... 经过 50 轮对话,Token 达到 195k ...

  {
 "role": "assistant", "content": "下一步处理 session.ts" }
]

步骤二:压缩中(During Compact)
系统执行 messages = [],清空所有历史消息。

步骤三:压缩后(After Compact)
系统立即将”脱水”后的精华重新注入 messages 数组,作为后续对话的新起点:

[
  // A. 插入边界标记 (System Message)

  {

    "type"
: "system",
    "subtype"
: "compact_boundary",
    "content"
: "Conversation compacted",
    "compactMetadata"
: { "trigger": "auto", "preTokens": 190000 }
  }
,
  // B. 注入深度摘要 (User Message)

  {

    "role"
: "user",
    "content"
: "This session is being continued... [Summary: 已完成 auth.ts 重构,修复了 JWT 漏洞。下一步:session.ts...]"
  }
,
  // C. 状态重注入 (Attachment Messages)

  {

    "role"
: "user",
    "content"
: "[File Attachment: auth.ts(最新磁盘内容)]",
    "isAttachment"
:true
  }
,
  {

    "role"
: "user",
    "content"
: "[Plan Attachment: 当前重构计划进度表]",
    "isAttachment"
:true
  }

]

这就是”不受上下文限制”的真相:不是真的有无限空间,而是通过**”摘要 + 关键文件内容重读 + 进度计划重注入”**,在清空历史后,瞬间为模型搭建了一个”案发现场”,让它能够无缝衔接。


下一篇(三):三层压缩策略 + 实战排障指南 + 完整场景复现


参考文献:

  1. 1. Claude Code源码:compact.ts
  2. 2. Anthropic Claude API Documentation