☰
AI应用Token节约策略:系统提示词、上下文与RAG优化实战
2026/10/14 22:53:12 网站建设 项目流程

1. 这套策略到底在解决什么问题

做过AI应用开发的人都有一个共同感受:模型能力越来越强,但账单也越来越吓人。尤其是把大模型接入到数据分析、报表生成、智能问答这类高频场景之后,token消耗就像开了水龙头,月底一看账单直接傻眼。我所在的团队去年做过一个内部数据分析助手,日活不到两百人,结果一个月token费用顶得上半个服务器的预算。后来我们花了两周时间专门做了一轮token节约优化,硬生生把消耗压到了原来的三分之一,效果立竿见影。

所谓Skill节约token策略,说白了就是在调用大模型完成特定技能任务时,通过一系列工程手段减少输入输出token的总量,同时尽量不牺牲结果质量。这里的"Skill"可以理解为一个封装好的能力单元,比如"根据SQL查询结果生成分析结论""把用户自然语言转成查询语句""对异常数据做归因解释"等等。每一个Skill在运行时都会消耗token,而节约策略就是围绕这些Skill的调用链路做文章。

这套东西适合谁看?如果你正在做AI应用开发、数据分析平台、智能客服、RAG系统,或者任何需要频繁调用大模型的工程项目,那这篇内容对你直接有用。哪怕你只是个人开发者,用API做一些小工具,看完也能省下不少真金白银。我不打算讲空泛的理论,而是把我们实际踩过的坑、试过的方案、量化的效果都摊开来说,你能直接抄作业。

2. 先搞清楚token到底花在哪里

2.1 token消耗的四个主要来源

很多人一提到省token,第一反应就是"把prompt写短一点"。这个方向没错,但只盯着prompt是远远不够的。在实际项目里,token消耗主要来自四个地方,我按占比从高到低排一下:

  • 系统提示词(System Prompt):这是每次调用都要带上的固定内容,包括角色设定、输出格式要求、few-shot示例等。如果系统提示词写了三千字,那每次调用都烧三千token的输入,调用一万次就是三千万token,非常恐怖。
  • 上下文历史(Conversation History):多轮对话场景下,历史消息会不断累积。用户聊到第十轮的时候,前面九轮的内容还在往模型里塞,token量呈线性甚至指数增长。
  • 检索增强内容(RAG Context):如果接了知识库,每次检索回来的文档片段都会拼进prompt。检索条数设多了、片段切大了,token就哗哗地流。
  • 模型输出(Completion):输出token通常比输入token贵,而且模型有时候会啰嗦,明明一句话能说清楚,非要写三段。

我做过一个粗略统计,在一个典型的数据分析问答场景里,这四部分的token占比大概是:系统提示词30%、上下文历史25%、RAG内容30%、模型输出15%。当然不同场景比例会变,但这个结构能说明一个问题——省token是个系统工程,不能只盯一个点。

2.2 为什么"无脑截断"不是好办法

有些团队为了省token,直接粗暴地截断历史、砍掉检索内容、把系统提示词删到只剩一句话。这么做token是省了,但模型的表现会断崖式下跌。用户问"上个月那个异常怎么回事",你把历史截了,模型根本不知道"那个异常"指的是什么,回答就是胡扯。

所以节约token的核心原则是:在保证任务可完成的前提下,去掉冗余信息,保留关键信息。这需要你对每个Skill的任务边界有清晰认识,知道哪些信息是模型真正需要的,哪些只是"看起来有用"。

3. 系统提示词的瘦身与结构化

3.1 把长提示词拆成"常驻+按需"两层

我们最开始的做法是把所有规则都写在一个巨大的系统提示词里,包括角色设定、输出格式、各种边界情况的处理方式、十几个few-shot示例。结果这个提示词有四千多token,每次调用都带着。

后来我们做了拆分:常驻层只保留最核心的角色设定和输出格式要求,控制在300 token以内;按需层根据当前Skill的类型动态加载。比如做SQL生成的时候才加载SQL相关的示例和规则,做归因分析的时候才加载归因的示例。这样平均下来,系统提示词的token消耗降了大概60%。

具体怎么拆?我给你一个实际的结构参考:

[常驻层 - 约250 token] 你是一个数据分析助手,负责根据给定的数据回答用户问题。 输出要求: 1. 结论先行,不超过3句话 2. 如需展示数据,用简洁的表格 3. 不确定的地方明确说明,不要编造 [按需层 - SQL生成Skill - 约400 token] 当用户需要查询数据时,将自然语言转为SQL。 数据库表结构如下:{schema} 注意事项: - 只使用SELECT语句 - 时间字段统一用date格式 - 示例:...

这样拆的好处是,常驻层永远精简,按需层只在对应场景加载,不会互相污染。

3.2 few-shot示例的压缩技巧

few-shot示例是系统提示词里最占token的部分。一个完整的示例可能包含输入、输出、解释说明,动辄两三百token。如果你放了十个示例,那就是两三千token。

我们的做法是:示例只保留输入和输出,去掉解释说明。模型看示例是为了学格式和模式,不需要你告诉它"这个示例展示了什么"。另外,示例的数量也要控制,通常每个Skill保留2到3个高质量示例就够了,多了边际收益很低。

还有一个技巧是用占位符代替具体内容。比如你要教模型输出JSON格式,不需要给一个完整的真实数据示例,可以用简化版的占位数据:

{"conclusion": "结论文本", "confidence": 0.85, "evidence": ["要点1", "要点2"]}

这比塞一段真实数据省得多,模型照样能学会格式。

注意:压缩示例的时候一定要测试模型表现。我们有一次把示例压得太狠,结果模型输出的格式开始飘,后来补回了一个关键示例才稳定。压缩和效果之间要找平衡点,不能一味求省。

4. 上下文历史的智能管理

4.1 滑动窗口不是唯一解

最常见的上下文管理方式是滑动窗口,就是只保留最近N轮对话。这个方法简单,但有个明显问题:如果用户在前面提到过一个关键信息,后面几轮没提,滑动窗口一滑就把它丢了。

我们试过几种改进方案,最后落地的是一个分层记忆的结构:

  • 最近3轮:完整保留,一字不删
  • 3到10轮:只保留用户的关键提问和模型的结论,去掉中间的推理过程和寒暄
  • 10轮以上:做一次摘要压缩,把多轮内容浓缩成一段话

这个分层策略让上下文token消耗降了大概45%,同时关键信息丢失的情况明显减少。

4.2 摘要压缩的具体做法

摘要压缩听起来简单,做起来有讲究。你不能随便让模型"总结一下前面的对话",因为那样可能把关键数字和条件丢掉。

我们的做法是结构化摘要,让模型按固定模板提取信息:

请从以下对话中提取关键信息,按以下格式输出: - 用户关注的核心指标:[填写] - 涉及的时间范围:[填写] - 已确认的筛选条件:[填写] - 尚未解决的问题:[填写] 对话内容: {history}

这样压缩出来的摘要既短又保留了关键要素,通常能把十轮对话压到100 token以内。

4.3 什么时候该清空历史

不是所有场景都需要保留历史。我们给每个Skill定义了"是否需要上下文"的标记。比如"把这段文字翻译成英文"这种任务,完全不需要历史,每次调用都是独立的。对于这类Skill,我们直接不传历史,token消耗直接归零。

判断标准很简单:如果这个任务单独拿出来也能完成,就不需要历史。这个判断在Skill设计阶段就要做好,不要等到运行时才纠结。

5. RAG检索内容的精准控制

5.1 检索条数不是越多越好

很多人做RAG有个误区,觉得检索回来的文档越多,模型回答越准。实际上,检索条数超过一定数量后,边际收益急剧下降,而且会引入噪声。我们做过对比测试,检索3条和检索10条,回答质量差异很小,但token消耗差了三倍多。

我们最终把默认检索条数定在3到5条,具体根据Skill类型调整。事实查询类用3条,分析归因类用5条。这个数字不是拍脑袋定的,是做了A/B测试之后选的。

5.2 片段切分与重排

文档切分的粒度直接影响token。切得太细,检索回来的片段信息不完整,模型需要更多片段才能拼出全貌;切得太粗,一个片段里一半是无关内容,浪费token。

我们的经验是:按语义段落切分,每段控制在200到400字。这个粒度既能保证信息完整,又不会太冗长。切分之后,再用重排模型对检索结果做一次精排,只把最相关的片段送进prompt。

重排这一步很关键。向量检索的召回结果里,排第一的不一定最相关。加一个轻量级重排模型,能把真正有用的片段提到前面,这样你甚至可以只取前2条就够用。

5.3 用引用代替全文

还有一个省token的狠招:不把文档全文塞进prompt,只塞关键句和引用编号。模型回答的时候引用编号,前端再把编号映射回原文展示给用户。

比如检索回来的片段是:

2024年第三季度,华东区域销售额为1.2亿元,同比增长15%,主要驱动因素是新产品线的铺开和渠道下沉策略的推进。

我们可以压缩成:

[1] 华东Q3销售额1.2亿,同比+15%,驱动:新品+渠道下沉

这样一段200字的内容压到30字左右,信息密度大幅提升。当然这需要做一些预处理,但一次处理可以反复使用,长期看非常划算。

6. 输出token的控制

6.1 用格式约束代替自然语言

模型输出啰嗦是token浪费的大头。你问"这个月销售额多少",它可能回答"根据您提供的数据,本月销售额为人民币1,234,567元,相比上月增长了8.3%,增长主要来自于..."。其实你只需要"1,234,567元,环比+8.3%"。

控制输出的核心手段是在系统提示词里明确格式要求。我们给每个Skill都定义了输出模板,比如:

输出格式(严格遵守,不要添加额外说明): 结论:{一句话结论} 数据:{关键数字} 建议:{可选,不超过一句话}

有了明确的格式约束,模型输出的token能减少40%以上,而且前端解析起来也更方便。

6.2 设置max_tokens上限

这个是最直接的。每个Skill根据任务类型设置合理的max_tokens。分类任务给50就够了,摘要任务给200,分析报告给500。不要图省事统一设一个很大的值,那样模型可能会"话痨"。

我们踩过一个坑:有个Skill的max_tokens设了2000,结果模型每次都要写满才停,其实前200 token就已经把话说完了。后来把上限调到300,输出质量没变,token省了85%。

6.3 让模型学会"不知道就说不知道"

这个听起来跟省token没关系,但其实很相关。如果模型不确定的时候硬要编一段话,既浪费token又误导用户。我们在提示词里明确要求:"如果信息不足以回答,直接输出'信息不足',不要推测。"这一条规则让无效输出的比例降了不少。

7. 缓存与复用:被低估的省钱利器

7.1 相同请求直接命中缓存

数据分析场景有个特点:很多查询是重复的。比如每天早上都有人问"昨天的销售额是多少",这种请求的结果在当天内是固定的。我们加了一层缓存,key是"Skill类型+关键参数",命中缓存直接返回,token消耗为零。

缓存的有效期根据数据更新频率设定。日报类数据缓存24小时,实时看板类缓存5分钟。这一层缓存帮我们省了大概20%的token。

7.2 前缀缓存

现在很多模型服务支持前缀缓存(Prompt Caching),就是如果多次请求的prompt前缀相同,这部分可以复用,不计费或打折计费。我们的系统提示词常驻层正好符合这个特点,把它放在prompt最前面,就能吃到前缀缓存的红利。

要用好前缀缓存,关键是保持前缀稳定。不要把动态内容(比如时间戳、用户ID)放在prompt开头,那样每次前缀都变,缓存就失效了。把动态内容放到后面,固定内容放前面。

7.3 结果模板化复用

对于一些高频的、结构固定的分析任务,我们干脆做了模板化处理。比如"周报生成"这个Skill,模型只需要填充几个关键数字和结论,大部分文字框架是预置好的。这样模型输出的token量大幅减少,因为大部分内容不需要它生成。

8. 常见问题与排查实录

8.1 token消耗突然飙升怎么排查

这是最常见的问题。我们的排查顺序是这样的:

排查项检查方法常见原因
系统提示词打印实际发送的prompt按需层加载逻辑出错,加载了不该加载的内容
上下文历史统计历史消息条数和长度某轮对话异常长,或者摘要压缩失败
RAG内容检查检索条数和片段长度检索条数配置被改,或者文档切分粒度变了
输出长度统计completion token分布某个Skill的max_tokens设置过大
缓存命中率查看缓存日志缓存key设计有问题,导致命中率下降

按这个顺序查,基本能定位到问题。

8.2 省了token但效果变差怎么办

这是另一个常见困境。我们的原则是先保效果,再省token。如果压缩之后效果下降明显,说明压到了关键信息。这时候要做的是精细化,而不是一刀切。

具体做法:把压缩前后的prompt都拿出来对比,看模型在哪些case上表现变差了,然后针对这些case补回必要信息。通常只需要补一小部分,就能把效果拉回来,同时token还是比原来省很多。

8.3 不同模型的token计费差异

不同模型的token计费方式不一样,有的按输入输出分别计价,有的有缓存折扣,有的对长上下文有阶梯定价。做优化的时候要针对具体模型来。比如某个模型的前缀缓存折扣很大,那你就重点优化前缀稳定性;另一个模型输出token特别贵,那你就重点控制输出长度。

我们内部做了一个简单的成本计算表,每次调整策略都算一下预期节省,避免做无用功。

9. 一套可落地的Skill节约token检查清单

最后给你一份我们团队实际在用的检查清单,每次新增或修改Skill的时候都过一遍:

  • 系统提示词是否拆分了常驻层和按需层?常驻层是否控制在300 token以内?
  • few-shot示例是否只保留了输入输出,去掉了冗余说明?数量是否控制在3个以内?
  • 上下文历史是否做了分层管理?是否明确了哪些Skill不需要历史?
  • RAG检索条数是否经过测试确定?是否加了重排?
  • 输出格式是否有明确约束?max_tokens是否按任务类型设置?
  • 是否加了缓存层?缓存key和有效期是否合理?
  • 前缀是否保持稳定,能否吃到前缀缓存?
  • 是否定期统计各Skill的token消耗,发现异常及时排查?

这套清单看起来简单,但真正每条都做到位,token消耗能降一半以上。我们团队从最初的"月底看账单心疼"到现在"token成本可控",靠的就是把这些细节一个个抠出来。

我个人在实际操作中的体会是,省token这件事没有一招制敌的银弹,它是一堆小优化的叠加。每一条单独看可能只省5%、10%,但十条加起来就是质变。而且这些优化做完之后,系统的响应速度也会变快,因为传输和处理的数据量小了,用户体验反而更好。所以别把省token当成纯粹的省钱手段,它同时也是性能优化的一部分。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询