上个月我终于下了决心,把团队跑了大半年的AI辅助编程工作流从 Claude Code 整体迁到了 Pi。折腾完第一件事就是看 Token 账单:系统提示词从 1.4W 字符压到 200 字符,单次请求的输入 Token 直接缩水一大截,月度账单降了 85%。这数字不是玄学,是我一行一行改配置改出来的。
先交代背景。我们有好几个项目在用 AI 做代码生成、Code Review、单测补全和跨文件重构。之前一直用 Claude Code,效果确实强,但成本像漏水的桶。每次请求,工具自带的系统提示词接近 1.4W 字符,哪怕你只问一句“这个函数为什么报错”,这 1.4W 字符也会原封不动跟着请求发给模型。日积月累,Token 账单比代码量涨得还快。
这篇文章不打算写成官方教程,我把迁移过程的真实拆解、压提示词的思路、实测数据、踩过的坑都摆出来。适合谁看?正在重度使用 AI 编程工具、想优化 Token 成本、又不想牺牲太多代码质量的朋友。如果你只是偶尔拿 AI 写个脚本,那直接跳过也行,但如果你靠 AI 干活,这 85% 的降幅真的很香。
1. 先搞清楚钱到底烧在哪:系统提示词与 Token 计费
1.1 系统提示词不是你想的那一句“角色设定”
很多人以为系统提示词就是“你是一个编程助手”这种一句话。我第一次抓包看到实际发送内容时也愣了一下,里面包含了角色设定、工具调用格式、输出规范、安全约束、代码风格建议、内置工作流描述,甚至还有一些带示例的多轮引导。这些内容被固定在每轮请求的开头,不由你控制。
Claude Code 这类工具为了把复杂代码任务做稳,会在系统提示词里塞大量工具描述。每个工具都有名字、参数、返回值、使用约束,加起来几百行。再加上它对输出格式的约束,例如必须用思维链、必须给出 XML 格式的调用块等等,提示词膨胀到 1.4W 字符是很有可能的。讽刺的是,你只是想让模型总结一下最近提交信息,它也要背着整个“重型工具箱”跑一趟。
这里要引入一个基础概念:Token 就是模型计费的最小单位。中文里一个字大约对应 1 到 2 个 Token,英文一个词大概 1 到 2 个 Token。1 个 Token 不是 1 个汉字,大体上 750 个英文单词约等于 1000 Token。按字符粗算,1.4W 字符的提示词,至少相当于几千 Token。每次请求都携带这几个千 Token,是你账单的大头。
1.2 Token 计费里最容易被忽略的“重复扣款”
模型 API 的计费规则是输入输出分开算,输入 Token 单价通常低于输出 Token,但它贵在重复。每发一次请求,系统提示词、历史对话、工具返回结果都会被重新计算一遍。
我当时做过一个小统计:某工作流日均请求 200 次左右,单次输入约 4000 Token,其中 3500 Token 是系统提示词和固定格式内容,真正描述你本次任务的只有几百 Token。也就是说,每天将近 70 万 Token 花在了“每次都要重复搬运同一段提示词”上。按模型输入价格折算,一个月下来这个环节就要烧掉不少钱。更别提多轮对话场景里,历史记录还会继续堆叠,账单只增不减。
所以问题的核心不在于“模型贵不贵”,而是你背着大量固有负担在跑。如果能把系统提示词从 3500 Token 压到 50 Token,单次请求立刻掉一个量级,历史记录再做摘要压缩,整体成本降 85% 并不夸张。
1.3 为什么选 Pi:可控、可裁剪、没有绑定
Pi 是一个轻量级的编程代理工具,说直白点,它把系统提示词完全交给你自己写,模型接入层做得简单透明,工具调用也支持自定义格式。相比 Claude Code 那种“开箱即用但不好拆”的模式,Pi 更像是给愿意动手的人准备的半成品套件。
我选它之前做过几个对比维度:
- 系统提示词是否可完全覆盖。Claude Code 的底层提示词基本绕不开,Pi 可以把它当成空白模板,只有你想让它执行的指令,没有隐藏负担。
- 历史上下文策略是否灵活。Pi 支持按轮次摘要历史消息,不必把每一次对话都完整发给模型。
- 模型接入是否自由。Pi 兼容主流模型 API,也可以接本地模型,这样我不必被单一模型绑定。
- 工具调用是否可自定义。Pi 走的是可插拔工具协议,不需要和内置格式死磕。
这几点加在一起,让我觉得迁移是值得做的。省钱只是结果之一,更重要的是提示词层面的掌控感。
2. 系统提示词从 1.4W 到 200:压缩方法论
2.1 拆解原始提示词,找到真正有用的部分
压缩不是直接删到 200,而是先盘点原有 1.4W 字符里到底装了什么。我这里结合常见工具结构和自己项目的实操,把它分成几类:
- 人格化和冗长表达。比如“你是世界顶级的软件架构师,拥有二十年的经验,曾经主导过多个大型分布式系统设计”,这类内容很煽情但对模型行为影响有限。
- 宽泛的约束条款。类似“你应该编写高质量、可维护的代码,尽量遵守设计模式”,完全不具体,等于没说。
- 工具定义。这一块最有用,因为模型必须知道有哪些工具、怎么调用、参数是什么。
- 输出格式约束。这个也关键,尤其当你要求模型输出结构化结果时。
- 项目特定规则。比如“本项目使用 Python 3.11、依赖用 uv 管理、函数注释用中文”,这是真正值钱的上下文。
我建议做一次“保留、删除、外置”三分类。能删除的直接删除,例如所有情绪化修辞和重复表述;需要保留的压缩成最简表述;还有一部分不适合放进系统提示词的,比如项目背景、代码规范全文,挪到外部上下文或检索文件里。
2.2 压缩策略:按“每次请求是否真正用到”筛选
我做压缩时只问一个问题:这一条指令在 90% 的请求里,真的会改变模型的行为吗?如果答案是否,就删掉。如果只是偶尔用到,就把它从系统提示词里挪到专门的指令模板里,需要时再注入。
比如“遇到权限问题不要随便给方案”这类规则,对代码生成任务几乎没用,但对运维排查任务非常关键。放在系统提示词里就是白烧 Token,放进按需模板才合理。再比如“输出代码块时要标明语言种类”,这条在大多数任务里都适用,留着;而“代码风格参考某具体项目里的命名规范”只在处理那个项目时才有用,那就改成变量,在调用时传入。
这个策略执行到最后,你会发现原来 1.4W 字符的系统提示词,真正高频且必要的只有几条:工具调用方式、输出格式、极少数全局约束。剩下的全是可以按需加载的内容。
2.3 200 字符的系统提示词长什么样
压缩后的系统提示词可以只有几行。我这里提供一个参照模板,具体内容需要按你自己的业务调整:
你是开发助手。只输出必要内容。 当且仅当需要调用工具时,输出 JSON:{"tool":"工具名","params":{...}}。 不调用工具时,直接输出代码或文本,不要包 XML。 回答默认使用中文。这段内容换算成字符大概是 100 到 200 左右,Token 不过 50 上下。有人会担心这么短会不会让模型失去“人设”?实测下来不会。模型的代码能力来自底座模型的训练,系统提示词只是给它一个工作边界。你把边界划清楚了,它反而不会在无关的位置绕来绕去。
这里要补一个底层逻辑:系统提示词越长,模型的注意力就越分散。你不希望它花心思去理解“你是顶尖专家”这种废话,你希望它一进门就看到工具 JSON 格式和输出规范。压缩系统提示词,本质上是减少无关噪声,让模型把注意力放在你的真实请求上。
3. 迁移实操:从 Claude Code 切换到 Pi 的完整步骤
3.1 迁移前的准备与评估
动手之前我先做了一次工作流盘点,把现有 AI 辅助场景列成四类:
- 代码自动补全和生成,例如写一个分页函数、生成迁移脚本。
- Code Review,审查提交差异,指出潜在 bug 和改进点。
- 单测补全,基于已有功能代码生成测试用例。
- 跨文件重构,需要模型理解项目结构并改动多个文件。
前两类对系统提示词依赖不大,我们自己的任务指令占了主导,迁移风险低。第三类中等。第四类最麻烦,因为 Claude Code 在跨文件场景里依赖内置的仓库地图和工具串联能力,Pi 这边需要自己搭工具链。
盘点完我会建议你记录每个场景的平均单次请求 Token、响应质量、耗时。没有基线数据,迁移后你根本说不清楚是变好了还是变差了。
3.2 环境搭建:安装 Pi 与配置模型接入
Pi 的安装比较简单,我这里以命令行工具为例:
pip install pi-cli pi init初始化之后会生成一个配置文件,通常放在当前项目目录的.pi/config.yaml。你需要在这里填入模型接入信息。因为 Pi 本身不绑定模型,我用的是兼容标准 API 的方式:
model: provider: openai-compatible base_url: https://your-endpoint.example.com/v1 api_key: ${PI_API_KEY} model_name: your-model-name temperature: 0.2这里需要说明一点,模型选择会影响效果和价格。如果追求极致成本,可以先用更便宜的小模型;如果追求代码质量,保留原来的强模型,靠砍提示词来省钱。我自己是先用原来的模型做对比,确认提示词压缩后效果没问题,再考虑要不要换更便宜的模型。
3.3 系统提示词迁移:把工作习惯写进去
Pi 默认会读取系统提示词文件,你在.pi/system_prompt.txt里写什么,请求就带什么。迁移时千万不要生搬硬套,直接把 Claude Code 里的角色设定复制过来,那没意义。你要做的是把“自己团队的工作约定”压缩进去。
我在.pi/system_prompt.txt里最终留下的是真正的约束:
你是开发助手。只输出必要内容。 当且仅当需要调用工具时,输出 JSON:{"tool":"工具名","params":{...}}。 不调用工具时,直接输出代码或文本,不要包 XML。 回答默认使用中文。项目特有的规范,例如“函数注释必须写清参数含义”“数据库迁移脚本要放在指定目录”,我放在外部项目规则文件里,需要时通过任务指令注入。这样做既保证了系统提示词短,又没有丢掉业务上下文。
3.4 工具调用与格式适配
两边工具调用格式不一样,这是迁移里最费时间的部分。Claude Code 有自己固定的工具调用格式,Pi 则可以让工具返回结果成为上下文的一部分,再让模型根据结果生成下一步动作。
我用一个简单的 Python 工具示例来说明:
# tools/run_tests.py def run_tests(test_pattern: str) -> dict: """运行匹配指定模式的测试并返回结果""" import subprocess result = subprocess.run( ["pytest", test_pattern, "-q"], capture_output=True, text=True ) return { "stdout": result.stdout, "stderr": result.stderr, "code": result.returncode }在 Pi 里注册工具时,我会给工具写一句清晰描述,例如“运行测试并返回输出,参数 test_pattern 是测试文件路径或 pytest 表达式”。这句描述很重要,模型看到 JSON 格式的系统提示词后,会根据描述自动决定何时调用工具,也会自动按 JSON 格式输出参数。
关键区别在于,Pi 不会替你塞一堆工具说明。你有多少个工具,它只发多少条描述,没有隐藏工具。如果你只注册了三个工具,系统提示词里就只出现这三条描述,Token 自然省。
3.5 从代码审查场景看迁移前后差异
拿一个实际场景举例。迁移前,我们发起的代码审查请求一般是:
请审查以下代码变更,重点关注潜在 bug、边界条件、性能问题,并给出改进建议。然后 Claude Code 会系统性地先分析变更,再按内置格式组织 review 意见。效果不差,但那 1.4W 字符的系统提示词也在同步发送。迁移后,同样的任务在 Pi 下的指令是:
审查这个补丁,输出 markdown 检查清单:bug、边界、性能、测试建议。系统提示词只给了 200 字符的底线约束,具体的审查要求由本次任务指令承担。实测下来审查结果并没有明显缩水,反而由于模型不需要在冗长指令里找重点,输出更直接,废话变少了。
4. 成本实测与效果复盘
4.1 Token 消耗的对比数据
迁移完我跑了整整两周,记录同一工作负载下的 Token 消耗。这里用日均 200 次请求的保守模型来算,结果如下:
| 指标 | 迁移前 | 迁移后 |
|---|---|---|
| 单次请求系统提示词 | 约 3500 Token | 约 50 Token |
| 单次请求总输入 Token | 约 4000 Token | 约 700 Token |
| 日均输入 Token | 约 80 万 | 约 14 万 |
| 单日成本指数 | 100% | 约 17% |
| 平均响应首 Token 延迟 | 约 3 到 5 秒 | 约 1 到 2 秒 |
注意一个细节:迁移后单次总输入 Token 并不是只减了系统提示词那部分。因为系统提示词短了,多轮对话里上下文里被反复重复的“固定负担”也少了。再加上 Pi 支持对历史消息做摘要压缩,所以整体降幅超过了 85%。
延迟下降也很明显。发送内容少了,模型首 Token 生成时间自然变快。对代码生成这种长输出任务来说,首 Token 快意味着你更早看到代码开头,体感会好不少。
4.2 质量不是简单下降,而是“重活变轻”
成本降这么多,质量到底有没有缩水?我先说结论:没有出现大家担心的“模型变傻”现象,但确实有场景分化。
适合迁移的场景:
- 单文件代码生成。
- Code Review 和检查清单输出。
- 根据提交信息生成说明。
- 单元测试和 mock 数据生成。
- 简单脚本批量处理任务。
这些任务的特点是目标清晰、上下文要求不高。你给一个具体任务,模型直接输出,系统提示词短反而更合适。
不太适合直接迁移的场景:
- 大型跨文件 Agent 重构,例如“把整个项目的数据库访问层替换为新的 ORM”。
- 复杂的多工具链编排,需要模型自主决定连续调用多个工具。
- 对项目上下文依赖极高的长期任务,例如理解一个历史包袱很重的服务拆分方案。
遇到这些场景,我会在 Pi 里额外注入项目结构摘要或者检索结果,而不是指望 200 字符的系统提示词解决所有问题。适应期过后,这类复杂任务也能跑到七八十分的水平,关键是你要接受“提示词只是边界,知识要靠外部给”。
5. 迁移中的坑与排查实录
5.1 最容易被坑的三个地方
第一个坑:系统提示词压得太狠,工具调用描述被砍掉了。我第一版压缩时只保留了一句话“你可以使用工具”,结果模型在需要读取文件的时候完全不调用工具,直接凭印象编代码。排查之后发现,模型根本不知道有哪些工具可选,必须明确告诉它工具名和参数格式。工具描述不能省,但每个工具的描述要短,一般一句话交代清楚。
第二个坑:输出格式约束太硬,导致多步推理被切断。我原本在系统提示词里写了“只输出最终代码,不要解释”,结果遇到复杂的调试请求时,模型直接略过分析步骤,输出一个错得离谱的方案。后来我改成“先简短分析,再输出代码”,问题解决。格式约束不是越强越好,要给模型留出推理空间。
第三个坑:多轮对话历史摘要过头了。为了进一步省 Token,我把摘要窗口调得很激进,结果模型经常忘记上一轮已经确认过的技术方案,来回重复问同样的问题。后来我把摘要调成保留最近两轮的完整原文,更早的才做摘要,效果好很多。省 Token 要省在固定负担上,不能省在有效信息上。
5.2 排查与恢复策略
迁移后如果觉得效果不对,我推荐从系统提示词和工具描述两个方向回溯,而不是直接怀疑模型不行。先看日志里这次请求实际发送了多少 Token,确认系统提示词是否生效;再看工具是否被正确注册,检查函数签名和描述是否匹配;最后对比同一任务在迁移前和迁移后的输出,找出具体的劣化点。
这里有一条非常实用的经验:渐进式压缩。不要一上来就砍到 200 字符。先砍到 5000,跑两天;再砍到 3000,跑两天;最后才缩到 200。每次压缩后都拿同一批测试问题去验证,确认输出质量没有明显滑坡再继续。我在这个过程里发现,很多提示词内容看起来没用,实际却在兜底某些边界情况。渐进式压缩让你能找到那条“还能保住底线”的边界线。
5.3 重新拿回控制感的意外收获
迁移本身是成本优化,但过程中我最大的收益反而不是省了多少钱。Claude Code 的系统提示词长期处于黑盒状态,出了问题你只能猜“模型今天状态不好”。迁移到 Pi 之后,一旦回答风格不对,我可以直接打开系统提示词文件检查,是工具描述有问题,还是格式约束太强,全部一目了然。对你每天依赖的工具,你应该有这种程度的掌控力。
再分享一个小技巧:压缩后的系统提示词不要写得像编程语言规范那么干,适当用“当且仅当”“除非必要”这类条件化说法,模型理解和遵循起来会更稳。200 字符不是配额,是思考的边界。
给准备动手的朋友一个建议:先别急着删光一切,按照我前面说的渐进式压缩走,同时保留一份完整版提示词作为备用。等你在 Pi 上跑通一两个核心场景,确认输出质量稳定,再逐步把长尾任务也迁过来。迁移不是非黑即白,完全可以先并行跑一段时间,用真实账单和代码 Review 数据说话。哪天你打开后台,看到 Token 消耗曲线掉了一个量级,就会觉得这趟折腾非常值得。