聊一聊怎么节省 Token,又不让 AI 降智

聊一聊怎么节省 Token,又不让 AI 降智
AI Agent Token 节流删噪声不删证据AI Agent 用久了最明显的问题往往不是“模型不会写代码”而是它太能花 Token。一次简单修改本来只需要定位一个函数、改几行代码、跑一次测试。Agent 实际执行时却可能变成一连串往返读文件 A解释文件 A搜索关键字读取搜索结果再读文件 A修改一处重新读取文件 A验证修改接着读取文件 B修改文件 B跑构建读取几百行日志总结日志再读文件 C继续修复。表面上它很勤奋实际上大量 Token 花在重复读取、重复解释、无关日志和过程叙述上。真正支撑判断的信息可能只占很小一部分。很多人一提到节省 Token就会想到压缩提示词、减少上下文、让 AI 回答短一点。这些方法有时有效也很容易把 AI 变笨。上下文砍得太狠模型看不到调用关系日志压得太粗错误行号没了历史删得太干净用户前面强调过的限制也跟着消失。Token 节流应该从“区分有效信息和无效信息”开始。节省的目标不是让 AI 少知道而是让它少吞重复、噪声和机械过程同时保留判断所需的证据、约束和结构。这篇文章结合几个开源项目和官方文档讨论一套不降智的上下文治理思路。1 删噪声不删证据1.1 “省 Token 省到降智”是怎么发生的AI 降智最常见的原因是压缩时删掉了关键信息。构建失败日志里有src/main.cpp(128): error C2065: config : undeclared identifier src/main.cpp(129): error C2143: syntax error : missing ; before }如果压缩成构建失败存在语法错误。Token 少了模型也基本没法继续判断。它不知道哪个文件失败、哪一行失败、错误码是什么也不知道下一步应该读哪段代码。更合理的压缩应该保留定位能力构建失败 - src/main.cpp:128C2065config 未声明 - src/main.cpp:129C2143缺少分号可能由上一行错误引发 下一步 - 优先读取 src/main.cpp 第 120-135 行 - 检查 config 的声明、作用域和 include 路径这段摘要比原始日志短得多但关键证据还在文件路径、行号、错误码、推断原因和下一步动作。模型拿到它仍然能继续工作。1.2 上下文也有价值分层节省 Token 前先要区分上下文价值。高价值上下文包括用户目标、用户限制、当前任务状态、相关文件路径、函数签名、类型定义、调用关系、错误码、错误行号、失败条件、已完成修改、测试结果和下一步动作。低价值上下文包括礼貌套话、操作过程作文、重复读取的完整文件、无关日志、已经失效的计划、大段构建噪声、同一结论的多次复述以及工具返回里的冗余包装。上下文窗口应该留给第一类内容。第二类内容越多成本越高模型越容易被噪声干扰。1.3 提纯不是压短好的 Token 节省不只是把文本变短而是让信息密度变高。它至少要保留三种能力定位能力模型知道下一步该读哪里恢复能力长任务压缩后还能接上决策依据模型知道为什么这样改而不只是知道“之前改过”。很多压缩方案只追求短最后把有效信息也压没了。真正需要的是提纯去掉噪声留下证据。2 Aider 的 Repo Map用仓库地图替代整仓硬塞2.1 大仓库不能直接塞给模型面对大仓库最粗暴的做法是整仓投喂。这样做的问题很明显Token 消耗巨大无关文件淹没关键文件模型注意力被分散每一轮还要重复付费上下文窗口很快打满。只给当前文件也不可靠。模型看不到接口定义、调用方、被调用方、配置入口和测试入口容易修一个文件坏一片逻辑。更稳的方式是先给模型一张仓库地图。2.2 Repo Map 的做法Aider 会向 LLM 发送一份简洁的 Git 仓库地图包含重要类、函数、类型和调用签名帮助模型理解正在编辑的代码与仓库其他部分的关系。模型一开始不一定需要完整源码但需要知道项目里有哪些关键符号。仓库地图通常包含文件列表、关键类、关键函数、方法签名、类型定义、重要接口和模块关系。Aider 文档还提到repo map 可以帮助模型仅凭关键 API 信息完成一部分任务需要更多代码时模型再根据地图判断应该读取哪些具体文件。这就省掉了大量盲目探索。2.3 Token 预算控制repo map 本身也可能很大。Aider 不是无脑发送完整地图而是在 token budget 内选择最相关的部分。对于大型仓库它会分析完整 repo map使用图排序算法选择最重要、最相关并且能放进当前 token budget 的代码片段。--map-tokens可以影响 repo map 的 token 预算默认值为 1k tokens。这提供了一个很好的范式不要把仓库当成文本整体 要把仓库当成图结构。 先给地图 再按需展开 最后只读取真正要修改的文件。2.4 仓库上下文的三层结构可以把仓库上下文分成三层。第一层是仓库地图用来放目录结构、关键模块、核心类、核心函数、接口、调用关系、配置入口和测试入口。第二层是相关片段用来放当前任务涉及的函数、调用方和被调用方、类型定义、错误附近代码。第三层是完整文件只在真正需要修改、需要整体理解或者涉及复杂状态流转时展开。这种结构比整仓硬塞更省也比只看当前文件更稳。3 Repomix把仓库打包成 AI 友好的上下文Repomix 的路线和 Aider 不同。Aider 更像“动态仓库地图 按需读取”Repomix 更像“把仓库整理成一份适合 LLM 消化的上下文包”。Repomix 可以把整个仓库打包成一个 AI-friendly 文件方便喂给 ChatGPT、Claude、Gemini、Grok、DeepSeek 等大模型。典型用法是运行npx repomixlatest然后生成类似repomix-output.xml的文件供 AI 分析。它能避免几类常见浪费把node_modules、dist、build等无关目录塞给模型把.gitignore已经排除的内容塞给模型不知道整包大概多少 token不同模型需要不同格式却手工整理把敏感信息误塞进上下文。Repomix 的核心能力包括 AI-Optimized Output、Token Counting、Git-Aware、Security-Focused 和 Multiple Output Formats。它的节省方式更偏输入整理把散乱仓库整理成单一上下文让用户知道 token 规模通过 ignore 和配置减少无关文件用统一格式降低模型解析成本。Repomix 更适合一次性场景比如让 AI 快速理解一个项目、做全局代码审查、生成项目说明、分析架构、制定迁移计划或者一次性向网页模型喂项目上下文。持续修改时每轮都把整仓包塞回上下文仍然会贵。更合理的做法是第一次理解项目时用 Repomix 打包全局上下文后续具体修改只传 repo map、相关片段和目标文件阶段性总结时再重新生成摘要或差异包。4 Gitingest用 Digest 降低仓库投喂门槛Gitingest 的定位更轻量。它可以把任意 Git 仓库转换成一个简单的代码库文本 digest用于喂给任意 LLM。它的页面提供了几个实用的上下文控制入口Exclude、Include、Include files under: 50kB、Directory Structure、Files Content。它不是简单复制仓库而是在生成 digest 时允许控制文件范围和大小。它的核心思路是把仓库转换成 LLM 容易读取的 digest保留目录结构按 include / exclude 控制范围过滤过大的文件生成可复制或下载的文本结果。Gitingest 节省的是人工整理仓库上下文的成本同时减少无关内容进入模型。它适合快速让网页 AI 看一个开源项目、讨论项目结构、生成初步 README、做代码库概览。和 Repomix 类似它更适合项目理解和上下文准备不适合每轮 Agent 编辑中反复整仓投喂。用于持续开发时可以把它当作第一轮上下文输入后续再转为按需读取。5 LangChain / LangGraph 的短期记忆治理5.1 长对话为什么会浪费 TokenAgent 任务跑久以后历史消息会越来越长。里面可能有早期计划、工具调用结果、中间失败、用户纠正、已完成修改、旧日志、无效尝试和阶段总结。全部保留Token 成本上升模型还容易被旧信息干扰全部删除模型又会丢掉用户约束和任务状态。5.2 LangChain 的三类策略LangChain 的 short-term memory 文档提到长对话可能超过 LLM 上下文窗口常见方案包括 trim messages、delete messages 和 summarize messages。trim messages 是在调用模型前移除部分消息delete messages 是从 LangGraph state 中永久删除消息summarize messages 是把早期历史总结成摘要替换原消息。文档也提醒简单 trim 或 delete 可能丢失信息一些应用会受益于更复杂的摘要方法。5.3 编程 Agent 的摘要应该像状态快照对编程任务来说“之前已经做了一些修改目前还有构建错误需要继续排查”这种摘要太虚。它看起来保留了上下文实际上无法恢复任务。更适合编程 Agent 的摘要应该像状态快照任务目标 - 修复 Windows 下构建失败 用户约束 - 不改公开接口 - 不引入第三方依赖 - 保持 VS2010 兼容 已确认事实 - PowerShell 5.1 日志可能是 UTF-16LE - src/a.cpp 存在非 ASCII 字符 - 当前构建使用 MSBuild 已修改 - src/a.cpp中文日志改为 ASCII - src/b.cppstatic 成员定义移动到 cpp 当前失败 - src/c.cpp:128 C2065config 未声明 下一步 - 读取 src/c.cpp 第 120-135 行 - 检查 config 的声明和 include 路径这种摘要更长一点但可恢复。旧上下文被删掉后模型还能继续工作。长对话压缩应保留目标、约束、已读事实、已做修改、当前错误、未解决风险、下一步动作以及禁止重复的失败尝试。这比简单保留“最后 N 条消息”更可靠。6 Claude Code 的 Memory / Rules规则也需要节流6.1 规则文件也会浪费 Token很多团队把大量规则写进项目记忆文件代码风格、目录结构、构建命令、测试命令、提交规范、前端规则、后端规则、数据库规则、部署流程、历史坑点。这些规则如果每次会话都加载就会长期占用上下文。Claude Code 文档说明CLAUDE.md文件会在每个会话开始时读取作为上下文使用指令越具体、越简洁Claude 越容易稳定遵循。文档也直接提醒CLAUDE.md会消耗上下文建议每个文件控制在 200 行以内超过 200 行会消耗更多上下文并可能降低遵循效果。6.2 分层加载规则节省 Token 的核心不是删掉规则而是分层加载。全局常驻规则只保留安全边界、项目核心约定、输出格式和构建入口。路径级规则放在对应目录比如src/frontend下的前端规则、src/backend下的后端规则、database下的迁移规则、legacy下的老编译器规则。任务级 Skill 则按任务启用比如批量编辑、编译诊断、文档生成、代码审查、性能分析。Claude Code 文档提到子目录里的CLAUDE.md不会一开始全部加载而是在 Claude 读取这些子目录文件时才进入上下文大型 monorepo 也可以通过排除设置跳过不相关的CLAUDE.md。这说明规则也应该只在相关时加载。6.3 通用方法对任何 Agent 系统来说规则文件都应该遵循几条原则常驻规则短路径规则准任务 Skill 按需启用重复规则不要多处复制人类注释不要进入模型上下文过期规则及时删除。规则越多模型不一定越聪明。很多时候规则越短、越具体遵循反而更稳。7 Prompt Caching稳定前缀也能省 Token7.1 每轮都重复的内容有些 Token 不是无效信息而是每轮都必须重复出现的信息比如系统提示、工具说明、输出格式、项目约定、固定示例和安全边界。这类内容不能删但可以缓存。OpenAI 文档说明模型提示经常包含系统提示和通用指令等重复内容Prompt Caching 可以减少延迟和输入 token 成本。缓存命中依赖 prompt 前缀精确匹配因此应该把静态内容放在提示开头把变量内容放在末尾。7.2 前缀和后缀的设计适合放在前缀的内容包括系统角色、工具定义、输出协议、项目核心规则、少量固定示例和安全边界。适合放在后缀的内容包括当前用户任务、当前文件片段、本轮工具结果、本轮错误日志、临时约束和下一步请求。结构可以这样设计[稳定前缀] - 系统规则 - 工具说明 - 输出格式 - 项目核心约定 [动态后缀] - 当前任务 - 当前证据 - 当前错误 - 当前需要模型判断的问题OpenAI 文档明确写到缓存命中只可能发生在 prompt 的 exact prefix match 中静态内容和示例应放在开头变量内容放在末尾。7.3 Anthropic 的 cache_controlAnthropic 也支持类似思路。Claude 平台文档提到可以通过cache_control指定缓存行为自动缓存方式会在请求体顶层添加cache_control系统自动把 cache breakpoint 应用到最后一个可缓存块。能稳定复用的上下文不要每轮重新全价处理。但 Prompt Caching 不是万能药。它能降低重复前缀成本不能解决上下文本身混乱的问题。一个巨大、过期、冲突的规则文件即使命中缓存仍然会干扰模型判断。8 agent-thrift合并工具调用减少机械往返8.1 具体浪费在哪agent-thrift是我做的一个开源 Skill思路比较小而具体减少 AI 编程助手在文件操作上的重复往返。当 AI 改代码时它常常反复“读文件 → 改一处 → 再读 → 再改 → 复核”。每一步都是一次 API 调用又慢又费 token。agent-thrift把这些零碎动作合并成单次 Python 脚本调用。它的能力包括批量编辑、工程体检、编译诊断、改动对比、安全读写和自动备份。批量编辑可以一次完成备份、多处替换和写回工程体检可以扫描调试刷屏和非 ASCII 字符编译诊断可以跑构建并解析报错。8.2 节省点agent-thrift的节省点主要有几类N 次工具调用压成 1 次改完不复读scan、diagnose、diff_bak返回结构化摘要输出零废话脚本处理机械 I/O。其中最关键的是工具调用合并。AI 改代码真正的开销是工具调用往返每改一处都要把文件内容和工具结果重新塞回上下文多次小改近似等于多次完整往返。8.3 为什么不降智它不隐藏模型需要判断的代码。需要看文件时照样完整读砍掉的是重复重读和废话叙述机械文件操作交给确定性 Python 脚本模型的判断权仍在模型手里。这类方案解决的是工具往返浪费但不是全部答案。它应该和 repo map、短期记忆、prompt caching、规则按需加载结合使用。9 不降智的 Token 节流架构七层合起来9.1 第一层稳定前缀缓存稳定前缀用于放系统规则、工具定义、输出协议、安全边界和项目核心约定。目标是提高 Prompt Caching 命中率降低重复前缀成本。9.2 第二层短规则常驻常驻规则必须短、准、稳定。不要把所有项目知识都塞进去不要把只在某个目录生效的规则全局加载也不要把历史坑点写成一整本书。可以借鉴 Claude Code 的做法把规则文件控制在合理长度并让子目录规则在相关文件被读取时才进入上下文。9.3 第三层仓库地图仓库地图解决全局结构问题。可以借鉴 Aider repo map列出关键文件抽取重要类和函数保留方法签名控制 token budget按相关性动态选择片段。9.4 第四层按需展开代码根据任务读取相关片段比如错误附近 20 行、函数定义、调用方、被调用方、接口定义、配置入口和测试文件。只有在需要整体理解时才读取完整文件。9.5 第五层工具调用合并把机械过程交给脚本多次 grep 变成一次搜索摘要多次 read 变成一次多文件读取多次 edit 变成一次 batch-editbuild log diagnose 变成一次诊断结果diff count 变成一次结构化摘要。这一层可以借鉴agent-thrift。9.6 第六层长任务状态快照长对话不要只保留最近 N 条消息。更好的做法是生成任务状态目标、约束、已确认事实、已修改文件、当前失败、风险和下一步。可以借鉴 LangChain 的 trim / delete / summarize 思路但编程场景里要把摘要做成结构化状态。9.7 第七层阶段性仓库打包需要全局理解时可以用 Repomix 或 Gitingest 生成项目 digest。进入持续编辑阶段后切回 repo map 按需读取避免每轮整仓投喂。10 各方案对比方案核心方法最适合的场景节省 Token 的方式Aider Repo Map仓库地图 图排序 token budget持续代码编辑、大仓库理解、跨文件修改用低 token 地图提供全局感需要时再展开具体文件Repomix仓库打包成 AI-friendly 单文件一次性分析项目、代码审查、架构理解、网页模型投喂过滤无关文件、尊重 gitignore、提前知道 token 规模Gitingest仓库转 digest include / exclude 控制快速分享仓库给 LLM、生成项目概览、轻量上下文准备快速生成可投喂 digest通过 include / exclude 控制范围LangChain / LangGraphtrim / delete / summarize messages多轮 Agent、长任务、任务状态延续、对话历史治理裁剪无效历史摘要早期消息保留关键状态Claude Code MemoryCLAUDE.md 目录级规则 路径级加载长期项目协作、团队规范注入、Monorepo规则按范围加载控制 CLAUDE.md 长度Prompt Caching稳定前缀 exact prefix match重复系统提示、固定工具定义、多轮相同项目约定复用稳定前缀降低输入 token 成本agent-thrift批量编辑 诊断 结构化摘要AI 编程助手改代码、频繁文件操作、编译诊断N 次工具调用压成 1 次脚本处理确定性 I/OAider、Repomix、Gitingest 都在处理仓库上下文问题但路线不同。Aider 是动态地图加按需读取适合持续编辑Repomix 是整仓打包适合一次性理解Gitingest 更轻量适合快速概览。LangChain 和 Claude Code 处理的是记忆和规则问题。LangChain 更关注长对话历史Claude Code 更关注项目级规则。编程 Agent 通常需要两者配合历史做状态快照规则按范围加载。Prompt Caching 处理的是前缀重复成本和上下文质量本身不是一回事。它可以和任何方案配合省钱但不能替代上下文治理。agent-thrift处理的是工具往返浪费。它和上述方案互补仓库结构用地图表达记忆做快照规则按范围加载缓存稳定前缀机械文件操作交给脚本。11 落地清单11.1 输入侧建立 repo map过滤无关目录忽略构建产物控制单文件大小按需读取具体片段保留错误证据不要整仓反复投喂。11.2 记忆侧短规则常驻长规则按需历史做状态快照用户约束不可丢失败尝试要记录过期过程要删除。11.3 工具侧合并工具调用批量编辑批量读取构建日志结构化diff 结果数字化搜索结果带上下文编码和备份交给脚本。11.4 输出侧少写过程作文多输出状态表保留文件、行号、错误码明确下一步不要每轮复述背景不要把完整日志贴回聊天。11.5 缓存侧静态内容放前缀动态任务放后缀保持工具定义稳定不要频繁改变系统提示顺序充分利用 Prompt Caching。12 让 AI 少做搬运工多做判断者仓库结构用地图表达完整代码按需展开长历史压成状态快照规则按范围加载重复前缀交给缓存机械文件操作交给脚本工具结果输出结构化证据。AI Agent 最宝贵的能力是判断不是反复搬运文件、复述日志和写过程作文。上下文治理做得好AI 不但更省 Token也更稳定。省掉的是噪声留下的是证据减少的是机械往返保留的是推理依据。13 参考项目与资料Aider Repo MapRepository map | aiderRepomixGitHub - yamadashy/repomix: Repomix is a powerful tool that packs your entire repository into a single, AI-friendly file. Perfect for when you need to feed your codebase to Large Language Models (LLMs) or other AI tools like Claude, ChatGPT, DeepSeek, Perplexity, Gemini, Gemma, Llama, Grok, and more. · GitHubGetting Started with Repomix | RepomixGitingestGitingestLangChain Short-term MemoryShort-term memory - Docs by LangChainClaude Code Memory / RulesHow Claude remembers your project - Claude Code DocsOpenAI Prompt Cachinghttps://developers.openai.com/api/docs/guides/prompt-cachingAnthropic Prompt CachingApp unavailable in region | Claude by Anthropicagent-thriftGitHub - Lanqingsong/-agent-thrift · GitHub