基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-10-29 22:30

从用量日志入手控制 Spring AI 成本

dev.to · AI#Spring AI#成本优化#可观测性
Editor brief · 编辑速览

文章讨论智能体在生产环境中因小规模低效累积而出现的 API 成本增长。示例通过 Spring AI 读取每次请求的输入、输出及总令牌数,再用 SQL 聚合分析消耗。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

AI Agent 的账单,往往不是被某一次复杂推理拉高的,而是被每次请求都重复发送的系统提示词、历史消息和工具结果慢慢堆起来的。原文围绕 Spring AI 旅行助手,提出了一套成本优化顺序:先记录 token 用量,再压缩上下文、分配模型、减少重复调用。

这套思路值得借鉴,但文中的节省比例大多没有附测试数据,部分示例也有信息丢失和因果解释不严谨的问题。读它最有用的方式,是拿走排查路径,同时把「省钱且质量不变」当成需要验证的目标。

先查每次发送了什么,再决定从哪里省

作者认为,多数 Agent 的输出 token 只占总量的 10–20%,输入才是主要消耗来源。这个比例没有给出样本范围,不能直接套到代码生成、长文写作等场景,但它提醒了一个容易忽略的事实:用户只输入一句话,模型收到的可能是一大包上下文。

系统提示词、工具定义、历史对话和工具返回值,都可能随请求反复发送。

作者首先用 Spring AI 记录每次调用的用量:

ChatResponse chatResponse = chatClient.prompt()
    .user(request.message())
    .call()
    .chatResponse();

Usage usage = chatResponse.getMetadata().getUsage();
log.info("[cost] conversationId={} inputTokens={} outputTokens={} totalTokens={}",
    request.conversationId(),
    usage.getPromptTokens(),
    usage.getGenerationTokens(),
    usage.getTotalTokens());

关键是 chatResponse.getMetadata().getUsage():它把讨论从「感觉上下文太长」变成了可以统计的输入、输出和总 token 数。不过,这段代码只演示日志记录,没有展示如何写入后面查询使用的 request_usage 表。

原文接着查询最近 INTERVAL '7 days' 的 AVG(input_tokens)、AVG(output_tokens)、AVG(total_tokens) 和 MAX(total_tokens)。平均值用来找日常消耗,最大值用来发现异常长对话。

还要区分 token 数和费用。不同模型的单价不同,输入与输出也不能默认按同一价格计算。原文给的是用量排查入口,尚不是完整的费用核算方案。

上下文每重复一次,冗余就多收一次钱

系统提示词是最容易检查的固定开销。作者举例:500-token 的提示词,每天调用 10,000 次,仅指令就要消耗 500 万 token。他把印度旅行助手的长段角色说明压缩为三句,保留服务范围、工具用途和事实来源约束,称 token 减少约 40%。

这里真正可复用的方法,是删掉重复表达,同时保留行为边界。压缩后是否仍能正确调用工具、拒绝编造,需要评测,不能只看文字更短。

历史消息的影响更大。原文用一段 20 轮对话举例:历史约 2,000 tokens,加上新消息 25、系统提示词 80、工具定义 200,单次输入约 2,300 tokens。用户的新问题只占很小一部分。

作者通过 MessageChatMemoryAdvisor,传入 redisChatMemory、AbstractChatMemoryAdvisor.DEFAULT_CHAT_MEMORY_CONVERSATION_ID,把窗口设为最后 10 条消息,而非 20 条。他认为旅行规划通常保留 8–12 条消息就够了,因为用户很少追问 5 轮之前的内容。

这里要看清单位:10 条消息不等于 10 轮对话。 原文也没有交代工具消息在这套配置中的具体计数方式,更没有注明 Spring AI 版本,接入时需要核对项目实际 API。

工具返回值同样会进入历史。作者把景点 JSON 改成简短字符串,声称减少约 60% token。但示例同时删掉了评分、开放时间和 lastUpdated: "2026-09-27",所以不能称为保留了相同信息。若用户接着问几点关门,压缩后的上下文已经无法回答。

应当先决定哪些字段必须保留,再比较 JSON 与文本格式的开销。

模型分流、缓存和批处理,分别省不同的钱

原文把模型分流视为影响最大的手段:查 Mysore 天气只需要简单判断和一次工具调用,规划 Karnataka 的 7 天预算旅行则需要多步推理,不必都使用同一档模型。

下面的代码用简单规则选择模型:

@PostMapping("/chat")
public ResponseEntity<String> chat(@RequestBody ChatRequest request) {
    String model = selectModel(request.message());
    String response = callAgentWithModel(request, model);
    return ResponseEntity.ok(response);
}

private String selectModel(String message) {
    // 简单启发式规则,需要根据流量特征继续调整
    boolean isComplex = message.length() > 200
        || message.contains("plan")
        || message.contains("itinerary")
        || message.contains("compare")
        || message.toLowerCase().contains("week");

    return isComplex ? "gemini-1.5-pro" : "gemini-1.5-flash";
}

最需要审视的是 isComplex:字符数大于 200,或者出现几个英文关键词,并不能稳定代表推理难度。中文请求不会命中这些英文词,而且只有 week 做了小写转换。这段代码适合说明分流思路,不能直接承担通用路由策略。

作者称 Flash 类模型通常便宜 10–20 倍;若简单请求占 70%、复杂请求占 30%,模型费用可下降 60–70%。这些数字依赖价格和流量结构,也隐含两类请求用量相近等条件。原文没有提供实际账单或分类评测结果,示例模型名也不能当作当前选型结论。

缓存解决的是另一部分成本。原文给 getWeather("Mysore") 加上 @Cacheable(value = "weather", key = "#city"),并保留 @Tool 和 @ToolParam,让相同城市查询复用结果。

这能减少天气服务调用,但原文所说的「缓存会让工具回复更短」没有从代码中得到支持。若缓存返回相同字符串,模型仍会收到相同长度的内容,直接节省的是外部工具 API 费用。缓存有效期也没交代,而天气结果显然有时效要求。

作者还建议在系统提示词里禁止重复调用历史中已有结果的工具,声称可减少 20–30% 工具调用。这个比例同样缺少实测依据,规则也需要考虑结果是否过期。

最后是 Batch API。原文将 100 次独立调用作为对照,称批处理约省 50%,结果在 24 小时内返回,适用于文档处理、摘要和夜间评测。它没有指定供应商,也没有给出可运行的批处理接口,因此这些条件需要按实际服务确认,不能套到实时聊天。

我的判断

我认可作者把优化建立在评测之上的顺序:先记录基线通过率,每次只改一项,重新评测,上线后继续观察一周。这比同时缩提示词、砍历史、换模型更容易定位质量变化。

但「不影响质量」在原文中更多是目标,而非已经证明的结论。提示词减少约 40%、工具结果减少约 60%、重复调用减少 20–30%,都没有展示测试集、样本量或对照结果,应当作为经验参考。

最该优先削减的是重复传输,最该谨慎削减的是任务所需信息。

与简单截断历史相比,保留摘要或关键状态也是可比较的做法,但原文没有提供这些方案的成本与质量对照。不能仅凭旅行助手的 8–12 条消息经验,就决定其他 Agent 的窗口。

工具格式也没有统一答案。短文本适合直接交给模型阅读;结构化结果方便程序校验和后续处理。原文的景点示例证明了删字段能变短,却没有证明自然语言一定比同等信息的 JSON 更合适。

能拿来做什么

  • 给现有 AI 接口补上用量记录,先观察一周的输入、输出、平均值和最大值,再结合模型单价判断费用集中在哪里。Node 服务也可以沿用这套记录思路,具体用量字段按 SDK 返回值处理。
  • 为长对话准备回归样例,覆盖早期约束、连续追问和工具结果复用。逐步缩小历史窗口,确认预算、日期等条件仍能保留,再决定窗口大小。
  • 把简单查询和多步规划分组评测,再考虑模型分流。中文业务应使用实际中文请求验证规则,不能照搬 plan、itinerary 等关键词。
  • 检查工具返回字段和重复调用日志,分别处理无用字段、相同参数重复请求和过期数据。离线摘要、文档处理及评测任务,再单独核对供应商 Batch API 的价格与时限。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
Clover 开源 MoE 扩散语言模型
下一篇
让编程智能体建库,同时隔离数据库密码

资讯速览

dev.to · AI · 2026-10-29 22:30

AI 评分 8.0 / 10

相关标签

#Spring AI#成本优化#可观测性

继续阅读

  • 给编程助手补上落地页设计流程
  • Clover 开源 MoE 扩散语言模型
  • 让编程智能体建库,同时隔离数据库密码
  • 给桌面编码 Agent 加上分阶段验收
  • 让 Claude Code 先写规格再动手