省 Token 实战手册:从提示词到架构,开发中真正有效的降本策略

0 阅读17分钟

上一篇已经拆解了大模型计费的底层逻辑: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

加权平均输出单价:从 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

优化后的日均成本估算

应用以下策略组合:

  1. 提示词精简:2000 → 800 Token
  2. 滑动窗口(保留 3 轮):平均历史从 1500 降到 600 Token
  3. 缓存命中(前缀稳定):800 Token 系统提示 90% 命中缓存
  4. 模型路由:85% 简单任务用 GPT-4o-mini
  5. 输出结构化:输出从 300 降到 120 Token
  6. 规则层拦截:30% 对话不进模型
  7. 语义缓存:额外命中 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 年,一起进步。