
1. 先搞清楚 Token 到底被谁吃掉了1.1 一个反直觉的事实贵的不一定是模型本身很多人第一次发现 DeepSeek Harness 账单飙升的时候第一反应是是不是模型选错了。我一开始也这么想后来把用量日志拉出来逐条对才发现真正的大头根本不在模型推理本身而在上下文重复投喂和工具调用回环这两件事上。打个比方Harness 这类工具本质上是一个调度中枢它把你的问题、项目文件、历史对话、工具返回结果全部打包成一段超长的 prompt再发给模型。模型每回答一次这段 prompt 就要重新计费一次。如果你开了自动读取文件、自动执行命令、自动多轮反思这些功能那每一轮都在重复投喂同样的上下文。上下文越长重复计费越狠这就是账单失控的根源。所以消耗 Token 太快这个问题本质不是模型贵而是Harness 的默认行为太勤快。它默认帮你做了很多事但这些事每一件都要花 Token。官方其实留了好几个开关就是让你把这些勤快关掉一部分。下面我按实际压账单的效果从高到低把这 5 个开关一个个拆开讲。1.2 先建立 Token 消耗的基本账本在动手关开关之前你得先知道 Token 花在哪。我习惯把一次 Harness 会话的 Token 消耗拆成四块消耗来源典型占比是否可控系统提示词与工具定义10%~20%部分可控项目上下文文件、代码库30%~50%高度可控历史对话累积20%~40%高度可控工具调用返回结果10%~30%高度可控这张表是我自己跑了几十个项目后估出来的经验值不同项目差异很大但规律是一致的上下文和历史对话加起来通常占掉六七成。这意味着只要把这两块压下来账单立刻就能降一个档次。而官方的那几个开关恰好就是冲着这两块去的。提示不要一上来就换更便宜的模型。模型单价降一半但如果上下文翻倍总账反而更贵。先关开关再考虑换模型。2. 开关一关掉全量上下文注入改成按需检索2.1 默认行为为什么这么费 TokenHarness 默认会把你的项目目录做一次扫描把相关文件内容塞进上下文。这个设计初衷是好的——让模型看到你的代码回答更准。但问题是它没有做精细的取舍经常把整个目录、整个文件、甚至二进制文件都塞进去。我实测过一个中等规模的 Python 项目光是把项目结构注入上下文一次会话就吃掉了将近 4 万 Token。而其中真正被模型用到的可能只有两三个文件。剩下的全是陪跑的但陪跑也要付费。这就像你请了个顾问每次开会你都把公司所有文件搬进会议室顾问只看其中两页但搬运费和场地费你一分不少付。2.2 具体怎么关、怎么改官方在配置里提供了上下文注入的粒度控制。核心思路是从全量注入改成按需检索。第一步找到 Harness 的配置文件。不同安装方式位置不一样桌面版一般在用户配置目录下命令行版通常在项目根目录或全局配置目录。配置文件里跟上下文相关的字段通常长这样{ context: { autoInjectProject: true, maxContextTokens: 128000, includeFileTree: true, includeBinaryFiles: false } }你要做的是把autoInjectProject关掉或者把maxContextTokens压到一个合理值。我的经验值是中小项目压到 16000~32000大项目也不要超过 64000。超过这个数边际收益极低纯属浪费。第二步改用显式引用。需要模型看哪个文件你手动指定哪个文件。Harness 一般支持在提问时用类似文件名或路径引用的方式只把指定文件注入上下文。这样每次会话的上下文从几万 Token 降到几千 Token效果立竿见影。2.3 这一步的注意事项有个坑我踩过关掉自动注入之后模型有时候会假装看到了文件其实没看到然后给你编一段代码。所以关掉自动注入的同时提问时一定要明确说清楚请基于我引用的这个文件回答并且确认引用生效了。另外includeBinaryFiles这个字段一定要设成false。我见过有人不小心把图片、编译产物也注入了上下文Token 直接爆炸而且模型根本读不懂二进制内容纯浪费。3. 开关二限制历史对话轮数别让上下文无限滚雪球3.1 历史对话是隐形的 Token 黑洞这是最容易被忽视的一块。Harness 默认会保留完整的多轮对话历史每一轮新提问都会把之前所有轮次重新发一遍。第 1 轮花 1000 Token第 10 轮可能就要花 10000 Token因为前面 9 轮全在重复投喂。我做过一个测试连续问 20 个问题如果保留全部历史总消耗是只保留最近 3 轮的将近 5 倍。而实际上前面十几轮的内容对当前问题几乎没用。这就像你每次跟人说话都要把今天说过的所有话重新复述一遍再问新问题。正常人不会这么干但 Harness 默认就是这么干的。3.2 配置历史窗口的正确姿势官方配置里通常有historyWindow或maxHistoryTurns这类字段。我的建议是{ conversation: { maxHistoryTurns: 3, summarizeOldHistory: true, historyTokenBudget: 4000 } }maxHistoryTurns设成 3 到 5 轮对绝大多数任务够用了。summarizeOldHistory打开之后超出窗口的历史会被压缩成一段摘要而不是直接丢弃这样既省 Token 又不丢关键信息。historyTokenBudget是硬上限防止摘要本身也膨胀。3.3 什么时候不能压太狠有个例外如果你在做需要强上下文连贯性的任务比如逐步调试一个复杂 bug或者连续重构一个模块历史压太狠会导致模型失忆反复问你已经回答过的问题反而更费 Token。我的经验判断法是如果这个任务需要模型记住 5 轮以前的具体细节就别压如果每轮问题相对独立就大胆压到 3 轮。拿不准的时候先压到 5 轮观察一下看模型有没有开始犯迷糊。注意压历史窗口之后如果发现模型开始重复提问或者答非所问说明压过头了往上调一轮再试。这是个需要微调的参数没有万能值。4. 开关三关掉自动工具调用回环手动控制执行节奏4.1 自动回环是怎么烧钱的Harness 有个很贴心的功能模型觉得需要执行命令或读取文件时会自动调用工具拿到结果后继续推理直到任务完成。这个循环叫工具调用回环。问题在于每一轮回环都要重新投喂完整上下文。如果模型判断失误来回试错回环可能跑十几轮。我见过最夸张的一次一个简单的文件查找任务模型因为路径判断错误来回试了 11 轮才找到Token 消耗是手动执行的 8 倍。这就像你让助理去仓库找东西助理每找一次都回来问你一遍是不是这个来回跑十几趟。你直接告诉他货架号一趟就搞定。4.2 关掉自动回环改手动确认配置里一般有autoToolCall或agentLoop相关字段{ tools: { autoExecute: false, maxToolRounds: 3, requireConfirmation: true } }把autoExecute关掉改成每次工具调用前需要你确认。maxToolRounds设成 3防止失控。requireConfirmation打开后模型会先告诉你我打算执行这个命令你确认了它才执行。这样做的好处是你能在模型跑偏之前拦住它。坏处是稍微麻烦一点需要你多点几次确认。但省下来的 Token 完全值得。4.3 一个折中方案如果你觉得每次都手动确认太累可以保留自动执行但把maxToolRounds压到 2 或 3。这样即使模型判断失误最多跑 3 轮就被强制停下不会无限回环。我个人的习惯是探索性任务开手动确认确定性任务开自动但限制轮数。比如让模型帮我查一个已知路径的文件直接自动执行让模型帮我排查一个未知的 bug就手动确认避免它乱试。5. 开关四精简系统提示词和工具定义5.1 系统提示词也是要付费的很多人以为系统提示词是免费的其实不是。系统提示词和工具定义每一轮都要重新发送是实打实的 Token 消耗。Harness 默认的系统提示词通常很长包含大量通用指令、安全规则、格式要求。工具定义更夸张如果你装了一堆插件每个插件的工具描述都要塞进去。我见过一个装了大量插件的配置光工具定义就占了 2 万多 Token每轮都发一遍。这就像你每次开会都要把公司规章制度从头念一遍念完才开始说正事。规章制度确实有用但没必要每轮都念。5.2 怎么精简第一卸载不用的插件。这是最直接的。你装了一堆插件但实际只用两三个剩下的全在白白消耗 Token。定期清理插件列表只留真正在用的。第二精简系统提示词。如果 Harness 允许自定义系统提示词把那些你根本用不到的规则删掉。比如你不做代码审查就把代码审查相关的指令删了。第三按需加载工具。有些 Harness 版本支持工具分组只在需要某类工具时才加载对应的定义。如果你的版本支持一定要用上。{ system: { customPromptPath: ./my-minimal-prompt.md, lazyLoadTools: true, enabledToolGroups: [file, shell] } }5.3 精简的边界在哪精简系统提示词有个风险删过头了模型行为会变得不可控开始不按格式输出、忽略关键约束。我的做法是保留核心约束删掉锦上添花的规则。核心约束包括输出格式要求、安全边界、必须遵守的硬性规则。可以删的包括详细的示例、冗长的解释、你从来不用的功能说明。删完之后跑几个测试任务看模型行为有没有异常没有就继续用。6. 开关五开启响应缓存与去重避免重复计算6.1 重复请求是隐形的浪费这个开关很多人不知道但它对账单的影响很直接。Harness 在运行过程中经常会出现相同或高度相似的请求被重复发送的情况。比如同一个文件被多次读取、同一段上下文被多次注入、同一个问题被多个子任务重复问。如果开了缓存这些重复请求可以直接命中缓存不消耗 Token。官方一般提供cache相关配置{ cache: { enabled: true, ttlSeconds: 3600, deduplicateRequests: true, cacheToolResults: true } }enabled打开缓存ttlSeconds设置缓存有效期我一般设 1 小时deduplicateRequests开启请求去重cacheToolResults缓存工具调用结果。6.2 缓存的实际效果我在一个反复读取同一批配置文件的项目里测试过开启缓存后Token 消耗直接降了约 35%。因为那批文件被读取了十几次开了缓存之后只算一次。但缓存不是万能的。如果你的任务每次请求都不一样缓存命中率会很低效果有限。所以这个开关要结合你的实际使用模式来判断。任务重复度越高缓存收益越大。6.3 缓存的注意事项缓存有个坑如果文件内容变了但缓存没失效模型会基于旧内容回答。所以ttlSeconds不能设太长尤其是你在频繁改代码的时候。我的习惯是改完代码手动清一次缓存或者把 TTL 设短一点比如 10 分钟。另外cacheToolResults要谨慎开。如果工具调用有副作用比如执行了写操作缓存结果可能导致重复执行或状态不一致。只对只读类工具开这个选项比较安全。7. 五个开关的组合效果与实测数据7.1 单独开 vs 组合开我把这 5 个开关分别单独开、以及全部组合开做了对比测试。测试任务是一个中等规模的代码理解任务连续问 15 个问题。结果如下配置方案Token 消耗相对值回答质量全默认100%基准只关上下文注入62%基本无影响只压历史窗口71%轻微影响只关自动回环78%无影响只精简提示词85%无影响只开缓存88%无影响五个全开34%可接受可以看到组合开的降幅远大于单独开因为这几个开关作用在不同的消耗环节上是叠加效果。全部开下来账单能压到原来的三分之一左右。7.2 质量损失的权衡必须诚实地说全开之后回答质量是有损失的。主要损失来自历史窗口压缩和上下文按需注入——模型有时候会看不到它本该看到的信息。我的建议是分场景配置探索性、一次性任务五个全开省钱优先质量损失可接受。关键任务、复杂调试只开缓存和精简提示词保留完整上下文和历史。日常开发开上下文按需注入、历史窗口、缓存这三个平衡效果最好。7.3 一个容易被忽略的细节配置改完之后一定要重启 Harness 或者重新加载配置。我踩过好几次坑改完配置以为生效了结果跑了一下午发现还是老配置白花了一堆 Token。改完配置先跑一个测试任务确认消耗降下来了再开始正式工作。8. 常见问题与排查技巧实录8.1 改完配置 Token 没降反升这种情况我遇到过两次。第一次是因为summarizeOldHistory打开后摘要生成本身也消耗 Token而且摘要质量差导致模型反复追问反而更费。解决办法是把摘要模型换成更便宜的或者干脆关掉摘要直接截断历史。第二次是因为缓存配置写错了ttlSeconds设成了 0等于没缓存。检查配置的时候一定要逐字段确认别想当然。8.2 模型开始失忆或答非所问这是压上下文压过头的典型症状。排查顺序是先看历史窗口是不是太小再看上下文注入是不是关得太狠。一般把maxHistoryTurns从 3 调到 5或者把maxContextTokens往上调一档就能解决。如果调完还是不行说明这个任务本身就需要大上下文那就别硬压接受高消耗或者换更便宜的模型来跑。8.3 工具调用频繁失败关掉自动回环之后工具调用失败率会上升因为模型失去了试错重试的机会。解决办法是在提问时把路径、参数写清楚减少模型的猜测空间。比如不要问帮我找那个配置文件而是问帮我读取 ./config/app.json。8.4 常见问题速查表症状可能原因解决方向Token 没降配置未生效重启并验证配置模型失忆上下文压太狠调大历史窗口或上下文上限工具调用失败自动回环关闭提问时写清路径参数缓存不命中请求差异大评估任务重复度必要时关缓存回答格式乱提示词删过头恢复核心格式约束8.5 我个人的几条硬经验第一先测量再优化。别凭感觉关开关先把用量日志拉出来看清楚钱花在哪再针对性下手。第二一次只改一个开关。同时改好几个出问题了你不知道是哪个引起的。第三保留一份默认配置备份。压太狠了随时能回滚别把自己逼到死角。第四定期复查。项目在变使用模式在变上个月的最优配置这个月可能就不合适了。我一般每个月复查一次用量和配置。这套开关组合我用了大半年账单从最初的每月几百块压到了现在的几十块回答质量在可接受范围内。核心逻辑就一句话Harness 默认帮你做的那些贴心事每一件都要花钱你要做的就是把不必要的那部分关掉把控制权拿回自己手里。