☰
Codex 越用越慢?从 MEMORY.md 膨胀到 95.7% 瘦身的排查实录:把 settings 改到 TaoToken 的完整复盘
2026/10/18 22:22:28 网站建设 项目流程

1. Codex 越用越慢的真实场景:从 MEMORY.md 膨胀说起

Codex 用久了变慢,很多人第一反应是模型波动或者网络问题。我一开始也这么想,直到发现一个更隐蔽的原因:本地记忆文件在悄悄膨胀。Codex 这类 Coding Agent 会把长期偏好、工作区规则、历史任务摘要写进MEMORY.md和memory_summary.md,每次新会话默认加载。文件越大,默认塞进上下文的内容越多,模型判断越容易跑偏。

具体表现很难用单个 Bug 解释:任务还没开始,先重复一大段旧规则;已完成的项目被当成当前背景;仓库已经升级,回答里还引用旧提交号;简单要求需要多次确认,长任务越来越容易跑偏。这些现象叠加在一起,体感就是"越用越慢、越用越啰嗦"。

我实测下来,当时MEMORY.md已经到 1,875 行、201,111 字节,包含 40 组历史任务,整个记忆目录约 2.0 MB。清理后主文件剩 150 行、8,698 字节,按字节减少 95.7%,摘要从 99 行降到 60 行,目录降到 976 KB,对话和 62 份任务回放摘要全部保留。

这篇复盘聚焦一件事:怎么把"每轮默认加载的知识"和"需要时再查的历史证据"分开。排查顺序是先做只读盘点,再识别膨胀来源,然后建立分层目录、备份重写、逐项确认清理对象、同步摘要、用 Git 验收,最后用真实任务测量效果。适合长期使用 Codex 或类似 Coding Agent、感觉响应变慢的开发者跟做。

2. TaoToken 前置准备:把 settings 改到 TaoToken 的完整配置

在动手清理记忆之前,先把模型接入层固定下来,否则你无法判断变慢是记忆膨胀还是接入配置问题。我用的方案是把 Codex 的 settings 指向 TaoToken,Base URL、Key、Model ID 三件套一次配齐,后续排查才有稳定基线。

TaoToken 官网是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。你需要先去控制台生成 API Key,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,Key 管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,遇到字段不确定时对照文档最稳。

Codex 的配置通常落在~/.codex/config.toml或项目级 settings 里。下面是一份可复制的 TOML 片段,路径和字段按你本地实际文件调整:

# ~/.codex/config.toml model = "claude-sonnet-4-5" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"

对应的环境变量在 shell 里导出,不要写进仓库:

export TAOTOKEN_API_KEY="sk-你的Key"

如果你用的是 Claude Code 或 Cline 这类工具,配置思路一致:Base URL 填https://taotoken.net/api,Key 填控制台生成的密钥,Model ID 填你实际要用的模型名。三件套缺一不可,只填 Base URL 不填 Model ID 是最常见的半配置状态,表现为请求能发出但返回异常。

配好之后先别急着清理记忆,跑一个最小请求确认接入层是通的。这一步的意义是把变量隔离:如果接入层本身有问题,后面所有"变慢"的观察都不可信。

3. 可复制配置与排查脚本:只读盘点加分层目录

接入层固定后,进入记忆排查。第一步是只读盘点,不要拿到目录就递归删除。先确认主文件、摘要、日志、更新单和回放分别占多少空间:

set -euo pipefail MEM_DIR="$HOME/.codex/memories" wc -l -c "$MEM_DIR/MEMORY.md" "$MEM_DIR/memory_summary.md" du -sh "$MEM_DIR" find "$MEM_DIR" -maxdepth 3 -type f -print | sort

如果目录由 Git 管理,再补两条:

git -C "$MEM_DIR" status --short git -C "$MEM_DIR" log -5 --oneline

这一步要回答三个问题:哪些文件会默认进入新会话,哪些只是按需证据,目录里是否已有未提交修改。第三点很重要,你自己的改动不能被清理脚本覆盖。

识别膨胀来源时,重点看四类内容:重复规则(同一约束同时写在摘要、主记忆和工作区说明中)、陈旧动态事实(提交号、版本号、当前部署、临时地址)、任务流水账(某天做了什么、跑了哪些命令)、冲突结论(旧技术栈与新技术栈都被写成当前命令)。模型不是 SQL 数据库,不会按时间戳只选最新一行,相互矛盾的自然语言同时出现时它只能猜,猜错就表现为答非所问。

我采用三层目录边界。活跃索引层MEMORY.md和memory_summary.md只保留长期有效信息:稳定偏好和验收口径、架构与安全边界、工作区定位、冲突时的决策原则。按日日志层放当天进展和临时笔记,例如memory/2026-08-25.md,可追溯但不要求每个新任务读取。证据归档层放完整排障记录、发布回读、旧版本快照和任务回放,进入memory/archive/,仍可搜索但不再充当当前指令。

凭据、私钥、签名材料和客户私有文件内容不能靠分层解决,它们根本不应进入记忆目录。

备份和重写主文件:

set -euo pipefail MEM_DIR="$HOME/.codex/memories" STAMP="$(date +%Y%m%d-%H%M%S)" BACKUP_DIR="$MEM_DIR/archive/pre-slim-$STAMP" mkdir -p "$BACKUP_DIR" cp -p "$MEM_DIR/MEMORY.md" "$BACKUP_DIR/" cp -p "$MEM_DIR/memory_summary.md" "$BACKUP_DIR/"

旧主文件出现几十个任务章节时,建议新建精简版本而不是逐段删除。新文件先写稳定偏好、硬边界和工作区索引,再逐条对照旧文件补漏。我给活跃层设了两个上限:MEMORY.md不超过 150 行或 15 KiB,memory_summary.md不超过 60 行或 4 KiB。上限不是通用标准,关键是默认层必须有预算。

清理对象逐项确认,本次盘点结果如下:

对象体积或数量处理
旧 MEMORY.md201,111 B备份后用精简索引替换
raw_memories.md289,360 B确认是阶段性聚合后清理
已处理更新单39 份 / 79,721 B确认已合并后移除
重复归档201,111 B校验内容重复后清理
.DS_Store3 个 / 24,588 B清理
rollout summary62 份 / 334,646 B保留

不要只看扩展名判断。名为 archive 的文件也可能是唯一证据,名为 raw 的文件也可能尚未消费。删除前至少比较内容、修改时间和引用关系。

4. 验证请求与成功结果:Git 验收加真实任务测量

只瘦身MEMORY.md很容易出现"删了但仍然记得"的错觉。如果新会话先加载memory_summary.md,而摘要仍包含旧项目和旧版本,问题并没有消失。顺序应当是:确定新的主记忆,从新主记忆提炼摘要,清点已消费更新单,新建干净任务验证。旧线程已经读过旧内容,磁盘修改不会让现有上下文倒带,验收一定要包含新任务。

用 Git 做可回读验收。我的自动脚本曾经中途失败:macOS awk 对路径正则的处理与预期不同,同时 Markdown 还有两处尾部空白,文件虽然改了但提交并未完成。因此至少执行:

git status --short git diff --cached --stat git diff --cached --check

这三条命令分别回答:改了什么、改了多少、格式是否可提交。它们比脚本最后打印的 done 可靠得多。最终提交包含 41 个文件变化,新增 208 行、删除 6,447 行,仓库压缩后只有一个约 402 KiB 的 pack,工作区干净。

测量是否真的有效,不要只比较目录大小,也不要只靠主观体感。准备 3 到 5 个真实任务,固定模型、仓库状态和提示词,记录:第一次有效工具调用耗时、输入与输出 Token、引用过期事实的次数、重复确认次数、最终验收是否一次通过。清理前后的冷缓存、热缓存也要区分,新任务用于观察记忆层,旧长线程还会受当前对话长度和 compaction 影响。

验证接入层是否正常,可以用模型对话页发一个最小请求: https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite 。如果这里返回正常,说明 Base URL、Key、Model ID 三件套没问题,变慢的锅就不在接入层。

5. 本篇常见错排查:401、local proxy failed 与 reading choices

排查过程中最容易撞上的几类报错,逐个对照。

401 Unauthorized 通常有三种原因:Key 没导出到当前 shell、Key 复制时带了空格或换行、环境变量名和配置里的env_key不一致。检查方式是echo $TAOTOKEN_API_KEY | head -c 8,确认前缀正确且无多余字符。如果配置里写的是env_key = "TAOTOKEN_API_KEY",环境变量就必须叫这个名字,大小写敏感。

local proxy failed 多出现在你本地还挂着其他转发工具时。先确认没有残留进程占用端口,再确认base_url没有被本地代理改写。配置里base_url应直接是https://taotoken.net/api,不要指向127.0.0.1之类的本地地址。

reading choices 报错一般是响应结构不符合预期,常见于wire_api字段和实际接口不匹配。如果你用的是 chat 类接口,wire_api = "chat";如果工具走的是另一套协议,对照接入文档调整。这个错误和记忆膨胀无关,但会伪装成"变慢",因为请求在重试。

OAuth 相关报错出现在用 Claude Code 或类似工具时,通常是登录态和 API Key 混用。用 Key 接入就不要再走 OAuth 流程,两者选其一。Claude Code 的接入配置参考 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=ClaudeCodeAnthropic&utm_campaign=rewrite ,里面有完整的 Base URL、Key、Model ID 填写位置。

还有一个隐蔽的坑:清理脚本跑完显示 done,但 Git 提交没成功。表现是下次新会话仍然加载旧记忆。回到第 4 节的git status --short确认工作区状态,别信脚本的输出。

如果排查完接入层和记忆层还是慢,再考虑是不是当前线程太长。长线程受对话长度和 compaction 影响,和记忆层是两回事。开一个新任务对比,能快速区分。

6. 长期编码与 Agent 场景的稳定接入

把 settings 改到 TaoToken 之后,长期编码和 Agent 场景的稳定性主要取决于两件事:接入层固定,记忆层有预算。接入层固定意味着 Base URL、Key、Model ID 三件套不随意变动,排查时变量可控。记忆层有预算意味着默认加载的内容有上限,历史证据移出默认层但保持可检索。

如果你经常跑长任务或 Agent 工作流,可以考虑用 Coding Plan 把额度和管理集中起来: https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。配合前面说的分层目录,活跃索引保持精简,按日日志和证据归档按需检索,Codex 的响应会稳定很多。

这次清理确认了两件事:活跃主记忆可以从 201KB 降到 8.7KB,同时保留核心规则;历史也不必删除,只要移出默认加载层并保持可检索。它没有证明所有 Codex 任务都会固定提速多少,这个结论要靠同一套任务长期对比。如果你的 Coding Agent 也开始慢、啰嗦、爱引用旧结论,排查顺序可以是:先看默认上下文,再看规则冲突,然后核验磁盘现场,最后才讨论模型是否变化。

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

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

立即咨询