记忆跨会话压缩,TaoToken Key 该保留哪些字段
2026/9/17 23:47:30 网站建设 项目流程

1. 从context_length_exceeded到记忆字段:先给 Key 和 Base URL

长任务跑到第 N 轮,Claude Code 返回API Error: 400 prompt is too long: context_length_exceeded,或者 Codex CLI 出现stream error: context length exceeded,表面看是上下文窗口被塞满,实际是记忆系统没有做字段分层。很多团队第一反应是把历史对话整包丢给摘要模型,结果摘要调用本身又消耗 Token,而且下一轮召回了不该召回的旧内容,todo 状态照样丢。先把接入路径固定下来:到 TaoToken 官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=memory_compress_fields 拿到 Key,再把请求地址设为https://taotoken.net/api。后续的字段保留清单、压缩前后 Token 对照,都基于这个入口复现。Base URL 在工具配置里不要带 UTM,只写https://taotoken.net/api

我以“记忆系统设计者”的视角处理这个问题。Token 消耗方不是整段对话,而是记忆压缩与摘要调用。也就是说,每一次把长上下文压成 memory pack,都要有预算、有字段白名单、有可回滚版本。原文讨论的 Harness 层四类机制可以保留:上下文预算与卸载、压缩、todo-state 复述、跨会话记忆。但落到工程上,不能只写概念,要回答三个问题:哪些字段必须跨会话保留?压缩调用走哪个 Base URL?压缩前后 Token 怎么对照?

先给一条最小接入路径。

1.1 Claude Code:settings.json 与 ANTHROPIC_*

Claude Code 侧建议把配置写进~/.claude/settings.json,让环境变量随会话加载。不同版本可能读取ANTHROPIC_API_KEYANTHROPIC_AUTH_TOKEN,二选一即可,不要同时写两个不同值。

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "YOUR_API_KEY", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514", "ANTHROPIC_SMALL_FAST_MODEL": "claude-3-5-haiku-20241022" } }

如果当前 Claude Code 版本使用 auth token 字段,可以替换为:

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }

改完后重启 Claude Code,用/status或一次最小对话确认请求确实走了https://taotoken.net/api。如果仍然报 401,优先检查 Key 是否复制完整、是否有多余空格、当前终端是否覆盖了旧环境变量。

1.2 Codex:config.toml,不要套 ANTHROPIC_*

Codex 侧不要使用ANTHROPIC_*。它走的是 Codex 自己的 provider 配置。典型配置在~/.codex/config.toml,核心是 provider、base_url、env_key 三项。

model = "gpt-5" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"

本地环境变量这样设置:

export TAOTOKEN_API_KEY="YOUR_API_KEY"

如果你的 Codex 版本要求wire_api = "responses",以本地实际报错为准切换。关键是:Codex 的 Key 走TAOTOKEN_API_KEY,Base URL 走https://taotoken.net/api,不要把 Claude Code 的ANTHROPIC_*变量复制过来。

1.3 CC Switch 三件套

如果你用 CC Switch 管理多套配置,核心只保留三件套:provider 名称、Base URL、API Key。模型映射可以另加,但不要和 Key 混在同一个字段里。

{ "provider": "TaoToken", "baseUrl": "https://taotoken.net/api", "apiKey": "YOUR_API_KEY", "defaultModel": "claude-sonnet-4-20250514" }

不同 CC Switch 版本的字段名可能略有差异,但排查时先确认这三项:请求地址是不是https://taotoken.net/api,Key 是不是YOUR_API_KEY对应的真实值,当前激活的 provider 是不是 TaoToken。更多控制台操作入口统一走 TaoToken 官网:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=memory_compress_fields_config 。

2. TaoToken Key 字段保留清单:must_keep / summarize / drop 三档

跨会话记忆压缩最容易犯的错,是把“保留字段”做成“保留对话”。对话是载体,字段才是状态。作为记忆系统设计者,我会把 memory pack 分成三档:

  • must_keep:跨会话必须原样或近原样保留,压缩后仍要能恢复目标。
  • summarize:可以摘要,但必须保留来源引用和摘要版本。
  • drop:不写回记忆,需要时从本地文件或日志重新读取。

一个可直接落地的字段保留配置如下:

{ "memory_policy_version": "1.0", "must_keep": [ "task_goal", "hard_constraints", "decisions", "todo_state", "artifact_refs", "interface_contracts", "failed_attempts" ], "summarize": [ "conversation_history", "tool_outputs", "test_logs", "long_file_excerpts" ], "drop": [ "api_keys", "pii", "full_source_code", "duplicate_stacktraces", "temporary_debug_prints" ], "budget": { "total_memory_tokens": 3000, "task_goal": 300, "hard_constraints": 400, "decisions": 900, "todo_state": 600, "artifact_refs": 300, "failed_attempts": 500 } }

这份配置的重点不是字段多,而是字段之间有优先级。task_goalhard_constraints决定任务会不会跑偏;decisions决定后续不重复讨论;todo_state决定下一步动作;artifact_refs决定模型知道去哪里读取真实文件;failed_attempts决定不会重复踩坑。相反,完整源码、重复堆栈、临时调试输出、密钥、个人身份信息,都不应该进入跨会话记忆包。

可以把每个字段的保留策略写成表:

字段是否跨会话保留压缩方式示例
task_goal必须原文保留,限制 300 Token 内将旧项目迁移到新构建链
hard_constraints必须编号去重,保留否定条件不得改动公共 API
decisions必须只留结论、理由、日期选择方案 B,因兼容旧数据
todo_state必须只留未完成和阻塞项待补测试用例,等待接口确认
artifact_refs必须路径 + 行号 + 校验和src/a.ts:120
interface_contracts必须保留入参、出参、错误码POST /v1/job
failed_attempts必须保留失败命令与结论升级依赖后启动失败
conversation_history可摘要分段摘要 + 来源 ID第 1-8 轮讨论记录
tool_outputs可摘要只留异常行和统计测试失败 3 例
full_source_code不保留卸载到本地文件通过 artifact_refs 读取
api_keys不保留禁止写入YOUR_API_KEY只在环境变量

这张表可以直接变成压缩 prompt 的约束。摘要模型不需要“聪明地猜”,它只需要按字段白名单输出。记忆压缩调用本身也要走 TaoToken,入口仍然是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=memory_compress_fields_pipeline 。

3. 压缩链路的工程实现:预算、卸载、摘要、todo-state 复述

上下文预算不是“还剩多少窗口”,而是“每一类记忆最多占多少”。我的做法是三层预算:

  1. 系统层固定预算:系统提示、工具定义、输出格式,通常不可压缩。
  2. 任务层记忆预算:task_goal、constraints、decisions、todo_state,按上表分配。
  3. 证据层按需预算:文件、日志、工具输出,不直接进 prompt,只保留引用,需要时本地读取。

卸载机制很关键。不要把所有文件内容都塞进上下文。把大文件转成artifact_refs

{ "artifact_refs": [ { "path": "src/service/order.ts", "line": 120, "reason": "订单状态机入口", "checksum": "sha256:..." }, { "path": "logs/test-run-042.log", "line": 880, "reason": "失败堆栈首次出现位置", "checksum": "sha256:..." } ] }

下一轮需要细节时,由本地工具按路径和行号读取,而不是让记忆包携带全文。这样既减少 Token,也避免旧文件内容污染新任务。

摘要调用可以这样写。下面脚本使用 OpenAI 兼容方式访问 TaoToken,Base URL 写https://taotoken.net/api,Key 从环境变量读取:

import os import json from openai import OpenAI client = OpenAI( api_key=os.environ["TAOTOKEN_API_KEY"], base_url="https://taotoken.net/api", ) MEMORY_POLICY = { "must_keep": [ "task_goal", "hard_constraints", "decisions", "todo_state", "artifact_refs", "interface_contracts", "failed_attempts", ], "summarize": [ "conversation_history", "tool_outputs", "test_logs", ], "drop": [ "api_keys", "pii", "full_source_code", "duplicate_stacktraces", "temporary_debug_prints", ], } def compress_memory(raw_messages, model="claude-sonnet-4-20250514"): system_prompt = f""" 你是跨会话记忆压缩器。只输出 JSON,不要输出解释。 必须保留字段:{", ".join(MEMORY_POLICY["must_keep"])} 可摘要字段:{", ".join(MEMORY_POLICY["summarize"])} 禁止写回字段:{", ".join(MEMORY_POLICY["drop"])} 输出结构: {{ "task_goal": "", "hard_constraints": [], "decisions": [], "todo_state": [], "artifact_refs": [], "interface_contracts": [], "failed_attempts": [], "summaries": {{ "conversation_history": "", "tool_outputs": "", "test_logs": "" }} }} """ resp = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": json.dumps(raw_messages, ensure_ascii=False)}, ], temperature=0.1, ) content = resp.choices[0].message.content usage = resp.usage return content, usage if __name__ == "__main__": with open("raw_session.json", "r", encoding="utf-8") as f: raw = json.load(f) memory_pack, usage = compress_memory(raw) with open("memory_pack.json", "w", encoding="utf-8") as f: f.write(memory_pack) print("prompt_tokens:", usage.prompt_tokens) print("completion_tokens:", usage.completion_tokens) print("total_tokens:", usage.total_tokens)

这段脚本的重点不是模型多强,而是把must_keepsummarizedrop变成了可执行约束。每次压缩后记录usage,就能做压缩前后 Token 对照。

todo-state 复述不能只放在记忆包里,还要在每一轮请求的尾部显式复述。推荐模板:

[Memory Pack v1] 目标:... 硬约束: 1. ... 已完成: - ... 未完成: - ... 阻塞: - ... 下一步: - ... 相关文件: - src/service/order.ts:120

把 todo-state 放在靠近当前用户消息的位置,能明显降低长任务中“忘记下一步”的概率。跨会话恢复时,先读取memory_pack.json,再把 todo-state 复述到当前轮,而不是把整个历史重新加载。

4. 压缩前后 Token 对照:可复现实验与字段保留结果

为了判断压缩是否有效,不要只看“感觉短了”。建议做一张压缩前后 Token 对照表。下面是一次示例运行的对照数据,实际数字以你的项目为准:

字段压缩前 Token压缩后 Token策略
task_goal320180原文保留,去掉背景修辞
hard_constraints860240编号去重,合并同类限制
decisions4200900只留结论、理由、日期
todo_state1500600只留未完成和阻塞项
artifact_refs1800300路径 + 行号 + 原因
interface_contracts900320保留入参、出参、错误码
failed_attempts2600500保留失败命令与结论
conversation_history420001200分段摘要 + 来源 ID
tool_outputs680000卸载为本地日志引用
test_logs21000260只留异常行和统计
合计1421804500压缩比约 31.6:1

这个对照表要配合版本号。每次压缩输出memory_policy_versionmemory_pack_version,比如:

{ "memory_policy_version": "1.0", "memory_pack_version": "2025-06-01T10:00:00Z", "task_goal": "将旧项目迁移到新构建链", "hard_constraints": [ "不得改动公共 API", "必须保留旧数据兼容层" ], "decisions": [ { "date": "2025-05-30", "decision": "采用方案 B", "reason": "兼容旧数据,迁移成本低" } ], "todo_state": [ { "id": "T1", "status": "pending", "content": "补充迁移后回归测试", "blocked_by": "等待接口确认" } ], "artifact_refs": [ { "path": "src/service/order.ts", "line": 120, "reason": "订单状态机入口" } ], "interface_contracts": [ { "name": "POST /v1/job", "request": ["jobId", "payload"], "response": ["status", "traceId"], "errors": ["400", "409", "500"] } ], "failed_attempts": [ { "command": "npm run build:legacy", "result": "失败", "reason": "旧依赖与 Node 22 不兼容" } ], "summaries": { "conversation_history": "第 1-8 轮确认迁移范围;第 9-14 轮对比两套构建链;第 15 轮确定方案 B。", "tool_outputs": "测试失败 3 例,均为旧数据字段映射缺失。", "test_logs": "失败集中在 order_status 映射,见 logs/test-run-042.log:880。" } }

生成这张表的方法也很简单。压缩前用 tokenizer 估算原始 transcript,压缩后再估算 memory pack,同时记录摘要调用的usage.prompt_tokensusage.completion_tokens。重点看三个指标:

  1. 记忆包 Token 是否稳定在预算内,比如 3000 到 4500。
  2. 摘要调用 Token 是否下降,而不是每轮都重新摘要全量历史。
  3. todo 完成率是否提升,任务目标是否在跨会话后仍然一致。

如果记忆包越来越长,通常是must_keep里混入了日志;如果摘要调用越来越贵,通常是每一轮都把全量历史重新发给摘要模型。正确做法是增量摘要:上一版 memory pack + 本轮新增对话,生成下一版 memory pack。这样压缩成本与增量上下文成正比,而不是与总历史长度成正比。

5. Claude Code / Codex / CC Switch 排障:Key 字段、模型映射与常见错误

接入 TaoToken 后,常见问题通常集中在 Key、Base URL、模型名、协议四类。下面按工具拆开。

5.1 Claude Code 常见错误

现象可能原因处理
401 UnauthorizedKey 错误或环境变量未加载检查YOUR_API_KEY,重启 Claude Code
404 Not FoundBase URL 写错或多了路径确认ANTHROPIC_BASE_URLhttps://taotoken.net/api
model not found模型 ID 不在当前账号可用列表换成控制台可见模型 ID
prompt is too long记忆包未压缩或全量历史注入启用字段白名单和 artifact_refs
输出格式不稳定摘要 temperature 过高压缩调用 temperature 设为 0.1 或 0

Claude Code 的配置建议只保留一个 Base URL 来源。不要同时在 shell、settings.json、项目.env里写不同地址,否则很难定位请求到底走了哪里。

5.2 Codex 常见错误

Codex 的排障重点是不要套用ANTHROPIC_*。如果config.toml里 provider 配错,常见表现是 401 或直接回退到默认 provider。

model = "gpt-5" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"

检查顺序:

echo $TAOTOKEN_API_KEY cat ~/.codex/config.toml

确认TAOTOKEN_API_KEY有值,base_urlhttps://taotoken.net/api,当前model_providertaotoken。如果报协议不匹配,再切换wire_api,不要改 Key 字段名。

5.3 CC Switch 三件套检查

CC Switch 的问题通常不是配置写错,而是激活了旧 provider。检查三件套:

{ "provider": "TaoToken", "baseUrl": "https://taotoken.net/api", "apiKey": "YOUR_API_KEY" }

如果切换后仍走旧地址,先看 CC Switch 当前激活项,再重启终端或 IDE。模型映射字段只负责把本地模型名映射到服务端模型名,Key 和 Base URL 不要放在模型映射里。

6. 验收与回滚:压缩后目标丢失怎么办

记忆压缩不是一次性任务,而是持续管道。建议每次生成 memory pack 后做四项验收:

  1. 目标一致性:让模型只读 memory pack,复述任务目标,和原目标对比。
  2. 约束完整性:检查hard_constraints是否包含所有否定条件和边界。
  3. todo 连续性:检查未完成项、阻塞项、下一步是否都在。
  4. 引用可解析:artifact_refs的路径和行号是否能在本地打开。

如果压缩后目标丢失,不要直接让模型“再想一遍”。优先做回滚:

  • 保留上一版memory_pack.json
  • 提高task_goalhard_constraints的预算。
  • decisions从摘要改为“结论 + 理由”双字段。
  • 检查summaries.conversation_history是否覆盖了关键决策轮次。
  • 减少drop名单误伤,比如不要把接口契约误判为长文档。

一个最小回滚配置如下:

{ "rollback": { "enabled": true, "keep_versions": 5, "compare_on_restore": [ "task_goal", "hard_constraints", "todo_state", "decisions" ] } }

安全上,记忆包一定不要写入密钥、个人身份信息、完整源码和生产数据。需要查库或执行命令时,由读者在本地环境执行,不要把数据库连接交给 Agent 直连。记忆系统只保存恢复任务所需的字段和引用。

7. 结语:把 TaoToken Key 当作记忆压缩链路的入口

回到最初的问题:跨会话压缩不是“把聊天记录总结一下”,而是设计一套字段保留策略。task_goalhard_constraintsdecisionstodo_stateartifact_refsinterface_contractsfailed_attempts这些字段必须跨会话保留;长对话、工具输出、测试日志可以摘要;完整源码、重复堆栈、密钥、个人身份信息不写回。压缩调用走 TaoToken,Base URL 固定为https://taotoken.net/api,Key 用YOUR_API_KEY占位,所有压缩前后 Token 对照都记录usage

如果你还没接入,可以先到 TaoToken 官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=memory_compress_fields_cta 了解入口;然后按顺序做四步:

  1. 模型对话:https://taotoken.net/models/detail/chat?utm_source=taotoken_aicg_blog_end&utm_content=memory_compress_fields_chat
  2. Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=memory_compress_fields_plan
  3. 创建 Key:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=memory_compress_fields_keys
  4. Claude Code 文档:https://taotoken.net/doc/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_content=memory_compress_fields_doc

把 Key 拿到后,Claude Code 用settings.jsonANTHROPIC_*,Codex 用config.tomlTAOTOKEN_API_KEY,CC Switch 只检查 provider、Base URL、API Key 三件套。最后用一份字段保留配置和一张压缩前后 Token 对照表验收。这样长任务跨会话时,目标不会漂,todo 不会丢,摘要调用也不会变成新的 Token 黑洞。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询