省 Token 实战手册:从提示词到架构,开发中真正有效的降本策略
上一篇已经拆解了大模型计费的底层逻辑:Token 是什么、官方如何收费,以及中转站倍率体系如何影响成本。但理解计费只是第一步,开发中更关键的问题是:知道它贵之后,如何把成本真正降下来。
需要先说明的是,本文中的案例将主要使用电商与客服场景来演示节省 Token 的方法。这样做是为了让成本结构更直观、优化路径更清晰;这些方法本身同样适用于多数具备多轮对话、工具调用、知识检索特征的 LLM 应用。
本文聚焦的问题是:在实际项目开发中,有哪些真正有效的策略可以减少 Token 消耗? 文章不会停留在“少写点字”这类笼统建议上,而是从提示词工程、上下文管理、缓存策略、模型选择、架构设计五个维度,给出可直接落地的对比案例。
每个策略都会附上"优化前 vs 优化后"的对比,让你直观看到 Token 消耗的变化。
一、提示词精简:最直接的降本入口
![]()
提示词(System Prompt + User Prompt)是每次请求都会重复发送的内容。它的冗余程度,直接决定了你的输入 Token 基线。
1. 去除冗余描述和重复指令
很多开发者习惯在系统提示词里写得非常详细,甚至同一个意思用不同方式说了两三遍。模型并不需要这种"重复强调"。
❌ 优化前(约 180 Token)
你是一个非常专业的客服助手。你的任务是帮助用户解决问题。
你需要始终保持礼貌和专业。你回答问题时要简洁明了。
请不要回答与产品无关的问题。如果用户问了与产品无关的问题,
请礼貌地告诉用户你只能回答产品相关的问题。
你应该尽量用中文回答。回答时不要太长,保持简洁。
记住,你是客服助手,不是通用聊天机器人。
✅ 优化后(约 60 Token)
角色:产品客服助手
规则:
- 仅回答产品相关问题,其余礼貌拒绝
- 中文回答,简洁专业
节省效果:约 67% 的系统提示词 Token。 如果你的应用每天处理 1 万次请求,仅这一项优化每天就能减少约 120 万输入 Token。
许多提示词中的补充性表述并不会显著提升效果。除非场景确实需要多轮强调或额外约束,否则没有必要用面向人的沟通方式去“安抚”模型;从成本控制角度看,简洁明确往往更有效。
2. 使用结构化格式代替自然语言描述
模型对结构化指令的理解能力很强。与其用长段落描述规则,不如用 YAML、Markdown 列表或 JSON 格式。
❌ 优化前(约 250 Token)
当用户询问退款政策时,你需要告诉他们:如果商品在购买后7天内
且未拆封,可以全额退款。如果商品已拆封但在7天内,可以退款
但需要扣除15%的手续费。如果超过7天但在30天内,只能换货不
能退款。超过30天则不支持任何退款或换货服务。你需要根据用户
描述的情况判断属于哪种,然后给出对应的回答。
✅ 优化后(约 100 Token)
退款政策查找表:
| 条件 | 处理方式 |
|---|---|
| ≤7天 + 未拆封 | 全额退款 |
| ≤7天 + 已拆封 | 退款扣15%手续费 |
| 8-30天 | 仅换货 |
| >30天 | 不支持 |
根据用户情况匹配对应行回复。
节省效果:约 60% Token。 而且结构化格式还能提升模型的准确率,一举两得。
3. 用变量占位代替静态长文本
如果你的提示词里有大量静态内容(如产品说明、FAQ 列表),每次都原样发送会非常浪费。
❌ 优化前:把完整 FAQ 塞进每次请求(约 2000 Token)
System: 你是XX产品客服。以下是完整FAQ:
Q1: 如何注册?A: 打开官网点击注册...(200字)
Q2: 如何修改密码?A: 进入设置页面...(150字)
Q3: 支持哪些支付方式?A: 支持微信、支付宝...(180字)
...(共20条FAQ,总计约1800 Token)
请根据以上FAQ回答用户问题。
✅ 优化后:先分类再检索,只注入相关条目(约 300 Token)
System: 你是XX产品客服。根据以下相关FAQ回答:
{retrieved_faq}
如FAQ未覆盖,回复"我需要转接人工客服为您处理"。
其中 {retrieved_faq} 只包含与当前问题最相关的 1-3 条 FAQ。
节省效果:约 85% 的 FAQ 相关 Token。 这就是最基础的 RAG(检索增强生成)思路:不是把所有知识一次性塞给模型,而是只注入当前问题真正需要的内容。
二、上下文管理:控制多轮对话的隐形成本
![]()
上一篇已经提到,多轮对话中历史消息会在后续请求中被反复带入输入侧。这意味着对话越长,每一轮的输入 Token 成本就越高。
1. 滑动窗口:只保留最近 N 轮
最简单的策略是限制上下文长度,只把最近的几轮对话发给模型。
❌ 优化前:完整历史(第 10 轮时约 8000 Token 输入)
messages: [
{ role: "system", content: "..." },
{ role: "user", content: "第1轮问题" },
{ role: "assistant", content: "第1轮回答" },
{ role: "user", content: "第2轮问题" },
{ role: "assistant", content: "第2轮回答" },
// ... 一直到第10轮
{ role: "user", content: "第10轮问题" }
]
✅ 优化后:滑动窗口保留最近 3 轮(约 2500 Token 输入)
messages: [
{ role: "system", content: "..." },
{ role: "user", content: "第8轮问题" },
{ role: "assistant", content: "第8轮回答" },
{ role: "user", content: "第9轮问题" },
{ role: "assistant", content: "第9轮回答" },
{ role: "user", content: "第10轮问题" }
]
节省效果:约 69% 的输入 Token。 对于大多数客服与问答场景,保留最近 3-5 轮通常已经足够。
2. 摘要压缩:用模型总结历史
如果业务需要更长的上下文记忆,可以用一次廉价的模型调用把历史压缩成摘要。
❌ 优化前:20 轮完整历史(约 15000 Token)
完整保留所有对话消息。
✅ 优化后:摘要 + 最近 3 轮(约 3500 Token)
messages: [
{ role: "system", content: "..." },
{ role: "system", content: "对话摘要:用户咨询了A产品的退款流程,
已确认购买日期在7天内且未拆封,正在等待退款地址。" },
{ role: "user", content: "第18轮问题" },
{ role: "assistant", content: "第18轮回答" },
{ role: "user", content: "第19轮问题" },
{ role: "assistant", content: "第19轮回答" },
{ role: "user", content: "第20轮问题" }
]
节省效果:约 77%。 虽然生成摘要本身也会消耗 Token,但如果使用小模型(如 GPT-4o-mini)完成摘要,整体成本仍然远低于每一轮都携带完整历史。
3. 按需加载上下文而非全量注入
这是上下文管理中最容易被忽视的一点:不是所有上下文在每次请求时都需要。
❌ 优化前:每次请求都注入完整工具定义(约 3000 Token)
tools: [
{ name: "search_products", description: "...", parameters: {...} },
{ name: "check_order", description: "...", parameters: {...} },
{ name: "process_refund", description: "...", parameters: {...} },
{ name: "update_address", description: "...", parameters: {...} },
{ name: "send_email", description: "...", parameters: {...} },
{ name: "create_ticket", description: "...", parameters: {...} },
// ... 共15个工具
]
✅ 优化后:根据意图分类,只注入相关工具(约 600 Token)
先用一次轻量分类(或规则匹配)判断用户意图,再只注入对应的工具子集:
// 用户意图: "退款"
tools: [
{ name: "check_order", description: "...", parameters: {...} },
{ name: "process_refund", description: "...", parameters: {...} }
]
节省效果:约 80%。 这一思路不只适用于工具定义,也适用于知识库片段、Schema 描述等所有“上下文素材”。
三、缓存策略:让重复内容只付一次全价
![]()
上一篇讲过,缓存命中的输入 Token 通常只按原价的 1/10 计费。所以,合理利用缓存机制是降本的重要手段。
1. 稳定前缀原则
缓存命中的前提是:请求的前缀部分和上次请求一致。所以,把不变的内容放前面,变化的内容放后面。
❌ 优化前:动态内容在前(缓存几乎无法命中)
messages: [
{ role: "user", content: "今天天气真好,我想问一下..." },
{ role: "system", content: "你是XX产品客服...(2000 Token 系统提示)" }
]
✅ 优化后:系统提示在前、动态内容在后(前缀可被缓存)
messages: [
{ role: "system", content: "你是XX产品客服...(2000 Token 系统提示)" },
{ role: "user", content: "今天天气真好,我想问一下..." }
]
节省效果: 假设系统提示 2000 Token,命中缓存后这部分从 2000 × Pin 降到 2000 × 0.1 × Pin,输入侧这部分节省 90%。
2. 批量请求共享前缀
如果你有一批类似任务(如批量翻译、批量分类),把它们组织成共享相同 system prompt 的连续请求,可以最大化缓存命中。
❌ 优化前:随机交替发送不同任务
请求1: [翻译系统提示] + 翻译任务A
请求2: [分类系统提示] + 分类任务B
请求3: [翻译系统提示] + 翻译任务C ← 提示可能已被清出缓存
请求4: [分类系统提示] + 分类任务D ← 提示可能已被清出缓存
✅ 优化后:同类任务集中发送
请求1: [翻译系统提示] + 翻译任务A
请求2: [翻译系统提示] + 翻译任务C ← 缓存命中
请求3: [翻译系统提示] + 翻译任务E ← 缓存命中
...
请求N: [分类系统提示] + 分类任务B
请求N+1: [分类系统提示] + 分类任务D ← 缓存命中
节省效果: 如果批量处理 100 个翻译任务,系统提示为 1500 Token,那么第一个请求按原价计费,后 99 个请求命中缓存后按缓存价计费,可节省约 89% 的系统提示输入成本。
四、模型选择:不是所有任务都需要最强模型
![]()
这可能是最容易被忽视、但收益最显著的策略之一:不同任务使用不同模型。
1. 任务分级路由
❌ 优化前:所有任务统一用 Claude 3.5 Sonnet
意图识别 → Claude 3.5 Sonnet($3/1M 输入,$15/1M 输出)
简单问答 → Claude 3.5 Sonnet
复杂推理 → Claude 3.5 Sonnet
文本分类 → Claude 3.5 Sonnet
✅ 优化后:按任务复杂度路由
意图识别 → GPT-4o-mini($0.15/1M 输入,$0.6/1M 输出)
简单问答 → GPT-4o-mini
复杂推理 → Claude 3.5 Sonnet
文本分类 → GPT-4o-mini
假设流量分布是:60% 简单任务 + 25% 中等任务 + 15% 复杂任务:
| 任务类型 | 流量占比 | 优化前单价(输出) | 优化后单价(输出) |
|---|---|---|---|
| 简单任务 | 60% | $15/1M | $0.6/1M |
| 中等任务 | 25% | $15/1M | $0.6/1M |
| 复杂任务 | 15% | $15/1M | $15/1M |
加权平均输出单价:从 2.76/1M,节省约 82%。
2. Thinking 模式的精准使用
上一篇说过,thinking 模式会额外产生大量推理 Token。所以它只应该在真正需要复杂推理时开启。
❌ 优化前:所有请求都开 thinking
一个简单的格式转换任务:
输入 Token: 500
可见输出 Token: 200
thinking Token: 2000 ← 模型"想"了很多但完全没必要
总输出计费: 2200 Token
✅ 优化后:仅对复杂推理任务开启 thinking
同一个格式转换任务:
输入 Token: 500
可见输出 Token: 200
thinking Token: 0
总输出计费: 200 Token
节省效果:输出侧 Token 减少约 91%。 对于简单任务,thinking 不仅会抬高成本,也会显著增加延迟。
五、输出控制:减少模型的"废话"
输出 Token 通常比输入贵 3-6 倍。控制输出长度是降本的高杠杆点。
1. 限定输出格式
❌ 优化前:自由格式回答(约 300 Token 输出)
User: 这个订单的状态是什么?
Assistant: 您好!感谢您的询问。我来帮您查看一下订单状态。
经过查询,您的订单号为 #12345 的订单目前处于"已发货"状态。
该订单已于2024年3月15日从我们的仓库发出,预计将在3-5个
工作日内送达。您可以使用快递单号 SF1234567890 在顺丰官网
查询物流信息。如果您还有其他问题,请随时告诉我!
✅ 优化后:要求结构化输出(约 60 Token 输出)
系统提示中增加:输出JSON格式: {status, shipped_date, tracking_no, eta}
{"status":"已发货","shipped_date":"2024-03-15",
"tracking_no":"SF1234567890","eta":"3-5工作日"}
节省效果:输出 Token 减少约 80%。 结构化输出不仅能减少 Token 消耗,也更便于程序稳定解析。
2. 设置 max_tokens 防止超长输出
即使提示词已经要求简洁,模型有时仍会"发挥过度"。设置 max_tokens 是最后一道防线。
// 分类任务:输出不应超过 20 Token
await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [...],
max_tokens: 20
});
这通常不会影响模型质量——如果任务本身只需要短输出,max_tokens 只是防止回答意外拉长。
六、架构设计:从系统层面控制成本
![]()
多层架构:规则拦截 → 语义缓存 → 模型兜底
以上是单次请求层面的优化。到了系统架构层面,还有几个影响更大的设计决策。
1. 结果缓存:相同问题不重复调用
❌ 优化前:每次相同问题都调用模型
用户A问: "你们的营业时间是?" → 调用模型 → 消耗 Token
用户B问: "营业时间几点?" → 调用模型 → 消耗 Token
用户C问: "什么时候开门?" → 调用模型 → 消耗 Token
✅ 优化后:语义缓存 + TTL
用户A问: "你们的营业时间是?"
→ embedding相似度搜索 → 未命中 → 调用模型 → 缓存结果
用户B问: "营业时间几点?"
→ embedding相似度搜索 → 命中 → 直接返回缓存 → 0 Token
用户C问: "什么时候开门?"
→ embedding相似度搜索 → 命中 → 直接返回缓存 → 0 Token
节省效果: 如果 30% 的问题可以通过语义缓存命中,整体模型调用量就能直接减少 30%。而 Embedding 的成本通常远低于生成式模型调用。
2. 预处理层:能不用模型就不用模型
❌ 优化前:所有请求都进模型
"你好" → 模型处理 → "你好!有什么可以帮助您的?"
"谢谢" → 模型处理 → "不客气!还有其他问题吗?"
"#@!$%" → 模型处理 → "抱歉,我没有理解您的意思"
✅ 优化后:规则层拦截 + 模型兜底
"你好" → 规则匹配 → 固定回复(0 Token)
"谢谢" → 规则匹配 → 固定回复(0 Token)
"#@!$%" → 规则拦截 → 固定回复(0 Token)
"我想退款" → 规则未匹配 → 进入模型处理
节省效果: 实际业务中,20%-40% 的对话可以被规则层直接处理,完全不消耗模型 Token。
3. 异步批处理 vs 实时调用
如果你的任务不要求实时返回(如数据标注、内容审核、批量翻译),使用 Batch API 通常可以获得 50% 的价格折扣。
| 调用方式 | 延迟 | 价格 |
|---|---|---|
| 实时 API | 秒级 | 标准价格 |
| Batch API | 小时级(通常 24h 内) | 标准价格的 50% |
七、综合案例:一个客服系统的全链路优化
把上面的策略组合起来,看一个完整的案例。
假设一个电商客服系统:
- 日均 10,000 次对话
- 平均每次对话 5 轮
- 系统提示词 2000 Token
- 每轮用户输入约 100 Token,模型输出约 300 Token
优化前的日均成本估算
每轮输入 ≈ 2000(系统提示)+ 累积历史(平均约 1500)+ 100(用户输入)= 3600 Token
每轮输出 ≈ 300 Token
每次对话 5 轮总输入 ≈ 18,000 Token
每次对话 5 轮总输出 ≈ 1,500 Token
日均总输入 = 10,000 × 18,000 = 1.8 亿 Token
日均总输出 = 10,000 × 1,500 = 1,500 万 Token
使用 GPT-4o($2.5/1M 输入,$10/1M 输出):
日均成本 = 180 × 2.5 + 15 × 10 = $450 + $150 = $600
优化后的日均成本估算
应用以下策略组合:
- 提示词精简:2000 → 800 Token
- 滑动窗口(保留 3 轮):平均历史从 1500 降到 600 Token
- 缓存命中(前缀稳定):800 Token 系统提示 90% 命中缓存
- 模型路由:85% 简单任务用 GPT-4o-mini
- 输出结构化:输出从 300 降到 120 Token
- 规则层拦截:30% 对话不进模型
- 语义缓存:额外命中 15%
实际进入模型的对话 = 10,000 × (1 - 0.30 - 0.15) = 5,500 次
每轮输入 ≈ 80(未缓存提示)+ 720(缓存提示,按0.1计)+ 600 + 100 = 852 等效 Token
每轮输出 ≈ 120 Token
每次对话 5 轮总等效输入 ≈ 4,260 Token
每次对话 5 轮总输出 ≈ 600 Token
其中 85% 用 GPT-4o-mini,15% 用 GPT-4o:
mini 部分:
输入 = 5,500 × 0.85 × 4,260 = 约 2,000 万 Token × $0.15/1M = $3
输出 = 5,500 × 0.85 × 600 = 约 280 万 Token × $0.6/1M = $1.7
4o 部分:
输入 = 5,500 × 0.15 × 4,260 = 约 350 万 Token × $2.5/1M = $8.8
输出 = 5,500 × 0.15 × 600 = 约 50 万 Token × $10/1M = $5
日均总成本 ≈ $3 + $1.7 + $8.8 + $5 = $18.5
📊 优化效果汇总
- 优化前日均成本:$600
- 优化后日均成本:$18.5
- 节省比例:约 97%
- 月度节省:约 $17,445
以上数字是基于电商客服场景的理想化综合估算,实际效果仍取决于业务形态、流量结构与实现质量。但即使只达到其中一部分优化收益,节省幅度也往往足够可观。
八、策略选择优先级
不同策略的实施难度和收益差异很大。如果你不确定从哪里开始,可以参考这个优先级:
| 优先级 | 策略 | 实施难度 | 预期收益 |
|---|---|---|---|
| 🥇 最先做 | 模型路由(大小模型分流) | 低 | 非常高 |
| 🥇 最先做 | 提示词精简 | 低 | 高 |
| 🥈 其次做 | 输出格式控制 | 低 | 高 |
| 🥈 其次做 | 缓存前缀优化 | 低 | 中-高 |
| 🥉 然后做 | 上下文滑动窗口 | 中 | 高 |
| 🥉 然后做 | 规则层拦截 | 中 | 中 |
| 🏅 长期建设 | 语义缓存 | 高 | 中-高 |
| 🏅 长期建设 | 历史摘要压缩 | 高 | 中 |
九、结论:省 Token 的本质是工程能力
回顾整篇文章,所有优化策略本质上都在做同一件事:
让模型只处理它真正需要处理的信息,只生成你真正需要的输出。
这不是某个神奇的参数配置,而是一整套工程实践:
- 提示词工程解决的是"少说废话";
- 上下文管理解决的是"别重复带货";
- 缓存策略解决的是"重复的东西别全价付";
- 模型路由解决的是"杀鸡别用牛刀";
- 架构设计解决的是"能不调模型就别调"。
上一篇讨论的是“钱是如何花出去的”,这一篇讨论的是“成本如何系统地降下来”。两篇结合起来,基本可以构成对大模型成本问题的完整认知闭环。
需要强调的是:省 Token 本身不是目的,在可接受的质量前提下降低 Token 成本,才有实际意义。 任何优化都不应以明显牺牲用户体验或输出质量为代价。在推进每一项优化时,都应该同步监控质量指标,确保成本下降不是以服务质量下滑换来的。
附:一个可实际体验的中转站选择
如果你想把本文的策略(提示词精简、上下文裁剪、缓存命中、模型路由、输出控制)真正落到工程里,最有效的办法之一是找一个计费透明、统计清晰、便于切模型与观察缓存的平台,做几组小实验把“优化前 vs 优化后”的差异跑出来。
如果你最近刚好在找可用的中转站,也可以参考我朋友超哥在做的 Amux API。它更适合用来做这些验证:
- 多模型统一接入:便于做“大小模型分流”的对比;
- 成本与用量更直观:方便核对输入、输出、缓存命中后的计费差异;
- 更贴近真实账单:用同一套业务请求去验证“前缀稳定”“输出变短”等策略的实际收益。
选平台时,建议仍按本文标准做取舍:不仅看倍率,也要看充值口径、缓存表现、计费透明度和稳定性。
写在最后🧪
这里是言萧凡的 AI 编程实验室。 我会在这里持续记录和分享 AI 工具、编程实践,以及那些值得沉淀下来的高效工作方法。 不只聊概念,也尽量分享能直接上手、能够复用的经验。 希望这间小小的实验室,能陪你一起探索、实践和成长。2026 年,一起进步。