账单别先爆:AI 工具降本实战与网关源码分享
AI工具 如何降低成本|附源码
在过去几年里,AI 工具从“新鲜玩具”逐渐变成了企业和个人提升效率的生产力基础设施。无论是内容创作、客服答疑、数据分析、代码开发,还是合同审查、知识库问答、流程自动化,AI 都正在改变工作方式。
但很多团队在真正使用 AI 工具后,很快会遇到一个现实问题:成本越来越高。
一开始只是几个人试用,每月几十美元;后来接入业务系统,调用量上升,模型费用、服务器费用、向量数据库费用、存储费用、人工维护费用叠加起来,成本可能迅速失控。尤其是当企业把 AI 能力嵌入到客服、办公系统、SaaS 产品或内部知识库中时,如果没有良好的成本控制机制,很容易出现“效果还没稳定,账单先爆炸”的情况。
本文将从实际落地角度,系统讲解 AI 工具如何降低成本,并提供一套可直接参考的源码示例,帮助你搭建一个具备缓存、模型路由、费用统计、限流控制能力的 AI 调用网关。
一、AI 工具成本主要来自哪里?
想要降低成本,首先要知道成本从哪里来。AI 工具的成本通常可以分为以下几类。
1. 模型调用费用
这是最直接的成本。
大语言模型通常按照 Token 收费,包括:
- 输入 Token
- 输出 Token
- 上下文长度
- 模型类型
- 调用次数
例如,同样是一次问答,如果使用高性能模型,成本可能是轻量模型的数倍甚至数十倍。很多团队在早期开发时,为了追求效果,所有请求都使用最强模型,结果造成了大量不必要的浪费。
事实上,并不是所有任务都需要最贵的模型。
例如:
| 场景 | 推荐模型策略 |
|---|---|
| 简单分类 | 小模型即可 |
| 文本摘要 | 中等模型 |
| 复杂推理 | 高性能模型 |
| 代码生成 | 专用代码模型或高性能模型 |
| FAQ 问答 | RAG + 小模型 |
| 敏感合同审查 | 高性能模型 + 人工复核 |
2. 长上下文带来的费用
很多 AI 应用为了“让模型知道更多”,会把大量上下文直接塞进 Prompt 中。例如一次客服对话,把用户历史记录、产品文档、FAQ、系统规则全部拼进去。
这种做法虽然简单,但成本很高。
因为每次调用模型,都要重新计算这些输入 Token。假设一个请求包含 20,000 个输入 Token,一天调用 10,000 次,那么成本会非常可观。
更合理的方式是:
- 使用向量检索,只取相关内容;
- 对长文档做摘要;
- 使用上下文缓存;
- 对历史对话进行压缩;
- 避免重复传递固定系统提示词。
3. 重复请求造成浪费
在真实业务中,很多用户问题其实高度重复。
例如:
- “怎么退款?”
- “发票在哪里开?”
- “会员怎么取消?”
- “这个功能怎么用?”
- “忘记密码怎么办?”
如果每次都调用大模型生成答案,就会产生重复成本。对于高频、标准化问题,可以使用缓存或知识库直接返回答案。
4. 错误重试和无效调用
一些 AI 应用在接口失败时会自动重试,但如果没有控制策略,可能造成重复调用。
常见问题包括:
- 超时后重复发起请求;
- 前端用户连续点击导致重复请求;
- 后端任务异常循环调用;
- Prompt 写得不清晰导致模型反复补救;
- 输出格式不稳定导致多次解析失败。
这些都会产生额外费用。
5. 人工维护成本
AI 成本不只是 API 费用,还包括人工成本。
如果系统没有日志、监控、评估、回放能力,出现问题后工程师需要手动排查 Prompt、输入、输出和模型参数,维护成本会越来越高。
所以,降低 AI 成本并不是单纯换一个便宜模型,而是要建立一套完整的工程化机制。
二、降低 AI 工具成本的核心思路
降低 AI 成本可以从以下几个方向入手。
1. 建立模型分层策略
不要让所有请求都走最贵模型。
可以把模型分为三层:
轻量模型
适合:
- 意图识别
- 文本分类
- 标签提取
- 简单问答
- 格式转换
- 简单摘要
特点是速度快、价格低。
中等模型
适合:
- 普通内容生成
- 文档摘要
- 客服回复
- 结构化抽取
- 知识库问答
这是日常业务中使用频率最高的一层。
高性能模型
适合:
- 复杂推理
- 多步骤规划
- 代码生成
- 法务、金融、医疗等高风险场景
- 高价值用户请求
高性能模型成本较高,应当只在真正需要时调用。
示例策略
如果用户问题长度 < 100 且属于 FAQ:使用缓存或小模型
如果需要知识库检索:使用中等模型 + RAG
如果涉及复杂推理或代码:使用高性能模型
如果模型置信度低:升级到更强模型
这种模型路由机制可以显著降低平均调用成本。
2. 使用缓存减少重复调用
缓存是降低 AI 成本最直接有效的方法之一。
适合缓存的内容包括:
- 高频 FAQ;
- 标准客服回答;
- 文档摘要;
- 翻译结果;
- 分类结果;
- 相同 Prompt 的输出;
- RAG 检索结果。
缓存要注意什么?
AI 输出存在一定随机性,因此缓存不适合所有场景。
适合缓存的任务通常有以下特点:
- 用户对答案一致性要求高;
- 问题重复率高;
- 输出不需要强个性化;
- Prompt 和参数相对稳定;
- 业务允许返回历史答案。
为了提升缓存命中率,可以对用户输入进行标准化,例如:
- 去掉多余空格;
- 转为小写;
- 去除无意义标点;
- 进行同义句归一;
- 对 Prompt 做 Hash。
3. 使用 RAG 替代超长 Prompt
RAG,全称 Retrieval-Augmented Generation,即检索增强生成。
它的核心思路是:
不要把所有知识都塞给模型,而是先检索出最相关的几段内容,再交给模型生成答案。
这样可以大幅减少输入 Token。
例如,原来你可能会把 50 页产品文档全部放入 Prompt,现在只需要检索出最相关的 3 到 5 段内容。
这不仅降低成本,还能提高答案准确性。
RAG 的成本优化技巧
- 文档切片不要太大;
- 检索结果数量不要过多;
- 对文档提前做摘要;
- 高频问题直接缓存;
- 使用便宜的 Embedding 模型;
- 对向量检索结果做重排序;
- 避免把无关内容放入 Prompt。
4. 压缩历史对话上下文
聊天机器人常见的成本黑洞就是历史上下文无限增长。
用户聊得越久,每次请求携带的历史消息越多,输入 Token 成本越来越高。
可以采用以下方法:
最近消息保留
只保留最近 5 到 10 轮对话。
摘要压缩
把较早的历史对话压缩成一段摘要。
例如:
用户之前询问过退款政策、发票申请和会员取消方式。
系统已经告知用户退款需要在订单页申请,发票可在账户中心开具。
用户当前主要关注会员取消后是否还能使用剩余权益。
重要信息抽取
只保存关键信息,例如:
{
"user_plan": "高级会员",
"order_status": "已支付",
"main_intent": "取消会员",
"previous_issue": "申请退款"
}
这种方法比保存完整对话更省 Token。
5. 控制输出长度
很多团队只关注输入 Token,却忽略输出 Token。实际上,输出越长,费用也越高。
可以通过 Prompt 明确要求:
- 回答不超过 300 字;
- 使用三条要点;
- 只输出 JSON;
- 不要解释过程;
- 不要重复问题;
- 不要输出无关内容。
例如:
请用不超过 150 字回答用户问题,只给出可执行步骤,不要输出寒暄内容。
对于客服、FAQ、分类、抽取等场景,限制输出长度非常有效。
6. 做好限流与预算控制
AI 系统一定要有预算意识。
建议设置以下限制:
- 单用户每日调用次数;
- 单用户每日 Token 上限;
- 单接口 QPS;
- 单业务线月度预算;
- 高价模型调用审批;
- 异常调用报警;
- 失败重试次数限制。
如果没有限流机制,一次 Bug、一次爬虫攻击或一次异常循环任务,都可能造成巨大费用。
7. 监控每一次调用成本
很多 AI 成本失控,本质上是因为“不知道钱花在哪里”。
至少要记录以下信息:
- 用户 ID;
- 业务场景;
- 使用模型;
- 输入 Token;
- 输出 Token;
- 总费用;
- 响应时间;
- 是否命中缓存;
- 是否触发重试;
- 请求状态;
- Prompt 版本。
当这些数据积累起来后,你就能回答几个关键问题:
- 哪个业务线最费钱?
- 哪类问题最常出现?
- 哪个 Prompt 成本最高?
- 哪个模型性价比最好?
- 缓存命中率是多少?
- 高价模型是否被滥用?
只有可观测,才能可优化。
三、AI 成本优化网关源码示例
下面提供一个简化版 AI 调用网关示例,使用 Node.js + Express 实现,具备以下功能:
- AI 请求统一入口;
- 简单模型路由;
- Prompt Hash 缓存;
- 费用估算;
- 用户限流;
- 调用日志记录;
- 可替换为真实大模型 API。
说明:以下代码为教学示例,实际生产环境建议使用 Redis、数据库、消息队列、监控系统和更完善的鉴权机制。
1. 项目结构
ai-cost-gateway/
├── package.json
├── server.js
├── aiClient.js
├── cache.js
├── rateLimiter.js
├── cost.js
└── logger.js
2. package.json
{
"name": "ai-cost-gateway",
"version": "1.0.0",
"description": "AI cost optimization gateway demo",
"main": "server.js",
"type": "commonjs",
"scripts": {
"start": "node server.js",
"dev": "node server.js"
},
"dependencies": {
"express": "^4.18.3",
"crypto-js": "^4.2.0"
}
}
安装依赖:
npm install
3. cache.js:简单内存缓存
const CryptoJS = require("crypto-js");
const cacheStore = new Map();
/**
* 对输入内容生成稳定 Hash
*/
function createCacheKey(payload) {
const raw = JSON.stringify(payload);
return CryptoJS.SHA256(raw).toString();
}
/**
* 获取缓存
*/
function getCache(key) {
const item = cacheStore.get(key);
if (!item) return null;
const now = Date.now();
if (item.expireAt && item.expireAt < now) {
cacheStore.delete(key);
return null;
}
return item.value;
}
/**
* 设置缓存
*/
function setCache(key, value, ttlSeconds = 3600) {
const expireAt = Date.now() + ttlSeconds * 1000;
cacheStore.set(key, {
value,
expireAt
});
}
module.exports = {
createCacheKey,
getCache,
setCache
};
4. rateLimiter.js:用户限流
const userUsage = new Map();
const DAILY_LIMIT = {
requests: 100,
tokens: 50000
};
function getTodayKey() {
return new Date().toISOString().slice(0, 10);
}
function checkRateLimit(userId) {
const today = getTodayKey();
const key = `${userId}:${today}`;
if (!userUsage.has(key)) {
userUsage.set(key, {
requests: 0,
tokens: 0
});
}
const usage = userUsage.get(key);
if (usage.requests >= DAILY_LIMIT.requests) {
return {
allowed: false,
reason: "今日请求次数已达上限"
};
}
if (usage.tokens >= DAILY_LIMIT.tokens) {
return {
allowed: false,
reason: "今日 Token 使用量已达上限"
};
}
return {
allowed: true,
usage
};
}
function updateUsage(userId, tokens) {
const today = getTodayKey();
const key = `${userId}:${today}`;
if (!userUsage.has(key)) {
userUsage.set(key, {
requests: 0,
tokens: 0
});
}
const usage = userUsage.get(key);
usage.requests += 1;
usage.tokens += tokens;
}
module.exports = {
checkRateLimit,
updateUsage
};
5. cost.js:费用估算
这里使用示例价格,并不代表真实价格。你可以根据实际模型供应商价格修改。
const MODEL_PRICE = {
small: {
input: 0.000001,
output: 0.000002
},
medium: {
input: 0.000005,
output: 0.00001
},
large: {
input: 0.00002,
output: 0.00006
}
};
/**
* 简化 Token 估算:
* 中文场景可以粗略按字符数估算;
* 生产环境建议使用模型对应 tokenizer。
*/
function estimateTokens(text) {
if (!text) return 0;
return Math.ceil(String(text).length * 0.8);
}
function estimateCost(model, inputTokens, outputTokens) {
const price = MODEL_PRICE[model] || MODEL_PRICE.medium;
return inputTokens * price.input + outputTokens * price.output;
}
module.exports = {
estimateTokens,
estimateCost
};
6. aiClient.js:模型路由与模拟调用
const { estimateTokens } = require("./cost");
/**
* 根据任务复杂度选择模型
*/
function selectModel({ prompt, taskType }) {
const textLength = prompt.length;
if (taskType === "classify" || taskType === "extract") {
return "small";
}
if (taskType === "code" || taskType === "reasoning") {
return "large";
}
if (textLength < 200) {
return "small";
}
if (textLength < 2000) {
return "medium";
}
return "large";
}
/**
* 模拟 AI 调用
* 生产环境中可以替换为 OpenAI、Claude、Gemini、通义、智谱等 API。
*/
async function callAI({ model, prompt, maxOutputTokens = 500 }) {
const inputTokens = estimateTokens(prompt);
// 模拟输出
const answer = `这是由 ${model} 模型生成的回答。已根据你的问题进行处理:${prompt.slice(
0,
80
)}...`;
const outputTokens = Math.min(
estimateTokens(answer),
maxOutputTokens
);
await new Promise(resolve => setTimeout(resolve, 200));
return {
answer,
usage: {
inputTokens,
outputTokens,
totalTokens: inputTokens + outputTokens
}
};
}
module.exports = {
selectModel,
callAI
};
7. logger.js:调用日志
function logAIRequest(data) {
const log = {
time: new Date().toISOString(),
...data
};
console.log(JSON.stringify(log, null, 2));
}
module.exports = {
logAIRequest
};
8. server.js:统一 AI 网关入口
const express = require("express");
const {
createCacheKey,
getCache,
setCache
} = require("./cache");
const {
checkRateLimit,
updateUsage
} = require("./rateLimiter");
const {
estimateCost
} = require("./cost");
const {
selectModel,
callAI
} = require("./aiClient");
const {
logAIRequest
} = require("./logger");
const app = express();
app.use(express.json());
app.post("/api/ai", async (req, res) => {
const startTime = Date.now();
try {
const {
userId = "anonymous",
prompt,
taskType = "chat",
cache = true,
maxOutputTokens = 500
} = req.body;
if (!prompt) {
return res.status(400).json({
error: "prompt 不能为空"
});
}
// 1. 用户限流检查
const limitResult = checkRateLimit(userId);
if (!limitResult.allowed) {
return res.status(429).json({
error: limitResult.reason
});
}
// 2. 模型路由
const model = selectModel({
prompt,
taskType
});
// 3. 生成缓存 Key
const cacheKey = createCacheKey({
prompt,
taskType,
model,
maxOutputTokens
});
// 4. 查询缓存
if (cache) {
const cached = getCache(cacheKey);
if (cached) {
logAIRequest({
userId,
taskType,
model,
cacheHit: true,
inputTokens: 0,
outputTokens: 0,
cost: 0,
latencyMs: Date.now() - startTime
});
return res.json({
fromCache: true,
model,
answer: cached.answer,
usage: {
inputTokens: 0,
outputTokens: 0,
totalTokens: 0
},
cost: 0
});
}
}
// 5. 调用 AI
const result = await callAI({
model,
prompt,
maxOutputTokens
});
const {
inputTokens,
outputTokens,
totalTokens
} = result.usage;
// 6. 费用估算
const cost = estimateCost(
model,
inputTokens,
outputTokens
);
// 7. 更新用户使用量
updateUsage(userId, totalTokens);
// 8. 写入缓存
if (cache) {
setCache(cacheKey, {
answer: result.answer
}, 3600);
}
// 9. 记录日志
logAIRequest({
userId,
taskType,
model,
cacheHit: false,
inputTokens,
outputTokens,
totalTokens,
cost,
latencyMs: Date.now() - startTime
});
return res.json({
fromCache: false,
model,
answer: result.answer,
usage: result.usage,
cost
});
} catch (error) {
console.error(error);
return res.status(500).json({
error: "服务器内部错误"
});
}
});
app.listen(3000, () => {
console.log("AI cost gateway running at http://localhost:3000");
});
9. 启动服务
node server.js
测试请求:
curl -X POST http://localhost:3000/api/ai \
-H "Content-Type: application/json" \
-d '{
"userId": "user_001",
"prompt": "请总结一下 AI 工具如何帮助企业降低运营成本",
"taskType": "summary",
"cache": true,
"maxOutputTokens": 300
}'
第一次请求会调用模型,第二次相同请求会命中缓存。
返回示例:
{
"fromCache": false,
"model": "small",
"answer": "这是由 small 模型生成的回答。已根据你的问题进行处理:请总结一下 AI 工具如何帮助企业降低运营成本...",
"usage": {
"inputTokens": 22,
"outputTokens": 57,
"totalTokens": 79
},
"cost": 0.000136
}
四、生产环境如何继续优化?
上面的源码只是一个最小可用示例。如果要用于真实业务,还可以继续增强。
1. 使用 Redis 替代内存缓存
内存缓存的问题是服务重启后数据会丢失,而且多实例之间无法共享。
生产环境建议使用 Redis:
- 支持 TTL;
- 支持分布式共享;
- 性能高;
- 适合缓存高频问答;
- 可统计缓存命中率。
2. 使用数据库记录调用明细
建议将每次调用写入数据库,例如 MySQL、PostgreSQL 或 ClickHouse。
数据表可以包含:
CREATE TABLE ai_call_logs (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id VARCHAR(100),
task_type VARCHAR(50),
model VARCHAR(50),
prompt_hash VARCHAR(128),
input_tokens INT,
output_tokens INT,
total_tokens INT,
cost DECIMAL(12, 8),
cache_hit BOOLEAN,
latency_ms INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
有了这些数据,就可以做成本报表、异常分析和模型效果评估。
3. 增加 Prompt 版本管理
Prompt 一旦上线,就不应该随意修改。因为 Prompt 改动会影响:
- 输出质量;
- 成本;
- 缓存命中率;
- 评估结果;
- 业务稳定性。
建议给每个 Prompt 增加版本号:
{
"promptName": "customer_service_reply",
"version": "v3",
"model": "medium"
}
这样可以对比不同版本的成本和效果。
4. 引入语义缓存
普通缓存只能命中完全相同的问题,而语义缓存可以命中意思相近的问题。
例如:
怎么退款?
如何申请退款?
订单能退吗?
我想退钱怎么办?
这些问题语义相似,可以复用同一个答案。
实现方式一般是:
- 对用户问题生成 Embedding;
- 在向量数据库中查找相似问题;
- 如果相似度超过阈值,直接返回缓存答案;
- 否则调用模型并写入语义缓存。
语义缓存对客服和知识库问答非常有效。
5. 对高价模型增加审批或降级策略
高价模型不应该被无节制调用。
可以设计策略:
- 普通用户默认不能调用高价模型;
- 只有复杂任务才自动升级;
- 低价值请求使用小模型;
- 超出预算后自动降级;
- 高价模型失败时降级到中等模型;
- 对内部员工开放更高额度。
6. 建立离线评估集
成本优化不能只看价格,还要看效果。
如果一味使用便宜模型,可能导致回答质量下降,最终增加人工客服压力,反而总成本更高。
建议准备一批真实问题作为评估集,例如:
- 100 条客服问题;
- 100 条摘要任务;
- 100 条分类任务;
- 100 条代码任务。
每次调整模型、Prompt 或参数后,自动跑评估,比较:
- 准确率;
- 用户满意度;
- 平均 Token;
- 平均成本;
- 响应时间;
- 人工接管率。
真正的优化目标应该是:在满足业务质量的前提下,让单位任务成本最低。
五、AI 成本优化的实战清单
下面是一份可以直接执行的检查清单。
模型选择
- [ ] 是否所有任务都在使用最贵模型?
- [ ] 是否区分了分类、摘要、问答、推理、代码等任务?
- [ ] 是否有模型路由机制?
- [ ] 是否统计了不同模型的成本和效果?
Prompt 优化
- [ ] Prompt 是否过长?
- [ ] 是否包含无关上下文?
- [ ] 是否限制输出长度?
- [ ] 是否存在重复说明?
- [ ] 是否有 Prompt 版本管理?
缓存机制
- [ ] 高频问题是否缓存?
- [ ] 是否使用 Redis?
- [ ] 是否统计缓存命中率?
- [ ] 是否考虑语义缓存?
- [ ] 缓存是否设置合理过期时间?
RAG 知识库
- [ ] 是否把整篇文档都塞进 Prompt?
- [ ] 是否只检索相关片段?
- [ ] 文档切片是否合理?
- [ ] 是否对长文档做摘要?
- [ ] 是否过滤低相关内容?
限流与预算
- [ ] 是否限制单用户每日调用次数?
- [ ] 是否限制 Token 使用量?
- [ ] 是否设置业务线预算?
- [ ] 是否对异常调用报警?
- [ ] 是否限制失败重试次数?
日志与监控
- [ ] 是否记录每次调用成本?
- [ ] 是否记录输入输出 Token?
- [ ] 是否记录模型、场景、用户?
- [ ] 是否可以按业务线统计费用?
- [ ] 是否能发现成本异常增长?
六、总结
AI 工具降低成本的关键,不是简单地“换便宜模型”,而是建立系统化的成本控制能力。
真正有效的做法包括:
- 模型分层:不同任务使用不同模型;
- 缓存复用:高频问题不重复调用;
- RAG 检索:减少无效上下文;
- 上下文压缩:避免历史对话无限增长;
- 输出限制:控制生成长度;
- 限流预算:防止异常消耗;
- 日志监控:知道钱花在哪里;
- 持续评估:平衡成本与效果。
对于企业来说,AI 的价值不只是“能不能用”,而是“能否稳定、低成本、可规模化地用”。当你的 AI 系统具备缓存、路由、限流、监控和评估能力后,成本通常可以下降 30% 到 80%,同时系统稳定性和可维护性也会显著提升。
如果你正在做 AI 应用,不建议一开始就追求复杂架构,而是可以先搭建一个统一的 AI 网关,把所有模型调用集中管理起来。只要入口统一,后续无论是切换模型、统计费用、做缓存、加限流,都会变得容易很多。
上文提供的源码就是一个最小版本的 AI 成本优化网关。你可以基于它继续扩展 Redis 缓存、数据库日志、语义缓存、RAG 检索和可视化报表,从而逐步构建一套适合自己业务的 AI 成本控制体系。