你有没有算过,调一次GPT-4o要花多少钱?

输入2.5美元/M tokens,输出10美元/M tokens。一个简单的情感分类任务,用GPT-4o跑一遍,大概0.05美元——5毛钱。一天跑1000次就是500块,一个月15000块。

而同样的任务,用Qwen3-8B跑,成本不到十分之一。

问题来了:不是所有任务都需要最贵的模型。简单分类用大模型就是浪费,复杂推理用小模型就是翻车。怎么让每次调用都花在刀刃上?

今天手敲了5个Demo,搭了一套省钱三件套:模型路由(Router)+ 自动降级(Fallback)+ 请求缓存(Cache)。三个设计模式,三条省钱路线,拼起来就是生产级LLM应用的成本优化骨架。

说白了:路由省钱、降级保命、缓存省时间。三者组合,API调用成本砍掉60-80%,服务可靠性还不掉。

一、模型路由:不是所有任务都值得花5毛钱

策略模式,你肯定写过

ModelRouter的本质就是策略模式——根据任务类型选不同的"策略"(模型)。

简单任务(分类、提取、翻译)用小模型,快且便宜;复杂任务(推理、代码生成)用大模型,贵但质量有保障。

enum TaskType {
    // 简单任务:分类、提取、翻译
    CLASSIFICATION, EXTRACTION, TRANSLATION,
    // 复杂任务:推理、代码生成、创意写作
    REASONING, CODE_GENERATION, CREATIVE_WRITING
}

static String routeModel(TaskType taskType) {
    return switch (taskType) {
        // 简单 → 小模型(省钱+快)
        case CLASSIFICATION, EXTRACTION, TRANSLATION -> "Qwen/Qwen3-8B";
        // 复杂 → 大模型(质量优先)
        case REASONING, CODE_GENERATION, CREATIVE_WRITING -> "Pro/zai-org/GLM-5.1";
    };
}

对比实验:小模型做复杂任务会翻车

我故意做了一个对比——让Qwen3-8B写"线程安全的LRU缓存+过期时间支持"这种复杂代码任务。

结果?代码不完整,逻辑有漏洞,关键方法漏了实现。同一个问题用GLM-5.1,完整代码直接给出来,注释清楚,逻辑正确。

铁律:简单任务用小模型省钱,复杂任务必须大模型保质量。路由错了,省钱变翻车。

生产环境怎么路由?

Demo里是手动标注TaskType,生产环境不会这么干。真实场景有三种路由方式:

1. 按业务场景硬编码(最简单,最常见)

  • 客服闲聊 → 小模型
  • 合同审查 → 大模型
  • 代码生成 → 大模型
  • 产品FAQ提取 → 小模型
  • 这就是策略模式,每个业务入口写死路由规则,简单直接

2. 按Prompt长度/复杂度自动判断(中等难度)

  • Prompt < 100字 + 无代码块 → 小模型
  • Prompt > 500字 + 包含"分析/设计/实现" → 大模型
  • 用规则引擎或简单的if-else判断,不需要额外LLM调用

3. 用LLM判断LLM(最智能,但有额外成本)

  • 先用极小模型(如GPT-4o-mini)快速判断任务复杂度
  • 返回"simple/complex"标签 → 路由到对应模型
  • Anthropic官方推荐这种"路由器模型"方案,但要注意路由器本身的调用成本
  • 路由器模型的成本要远低于被路由的模型,否则得不偿失

真实案例:

  • OpenAI官方在API文档里推荐用GPT-4o-mini做路由判断,成本$0.15/M tokens,比GPT-4o便宜17倍
  • 很多企业用本地Ollama跑Qwen2.5-3B做路由判断,成本为零(本地模型不花钱)
  • 关键指标:路由准确率 > 95%,否则错误路由的损失远超路由器本身的省钱效果

二、自动降级:模型挂了用户无感知

责任链模式,跟Spring Interceptor一模一样

生产环境模型一定会挂——网络抖动、API限流、模型维护、服务过载。这时候如果没有降级机制,用户直接看到500错误。

FallbackChain就是责任链模式:主模型 → 备用模型 → 兜底响应,依次尝试,直到成功。

static FallbackResult executeWithFallback(List<ModelNode> chain, String prompt) {
    for (int i = 0; i < chain.size(); i++) {
        ModelNode node = chain.get(i);
        try {
            ChatModel model = node.createModel();
            String response = model.chat(prompt);
            if (response != null && !response.isBlank()) {
                return new FallbackResult(node.name, response, i, null);
            }
        } catch (Exception e) {
            // 这个挂了,试下一个
        }
    }
    // 全挂了 → 兜底响应(比500好太多)
    return new FallbackResult("none", "服务暂时不可用,请稍后重试。", chain.size(), "all models failed");
}

四个场景实测

场景主模型备用模型结果
正常GLM-5.1 ✅Qwen3-8B主模型直接成功
主模型配错❌ 不存在Qwen3-8B ✅自动降级到备用
主模型超时(1s)❌ 超时Qwen3-8B ✅超时降级
全挂❌❌兜底响应保底

关键设计:超时时间递增。主模型timeout短一点(5-10秒),快速fail快速降级;备用模型timeout长一点(30-60秒),确保能接住请求。别让主模型超时30秒还在等,用户早就跑了。

生产环境怎么做降级?

1. 多云多供应商策略(最常见)

  • 主:OpenAI GPT-4o(贵但强)
  • 备:Anthropic Claude Sonnet(同等质量但可能更便宜)
  • 兜底:本地Ollama Qwen(零成本但质量差)
  • 三个不同供应商,一个挂了另外两个不受影响

2. 同供应商不同规格

  • 主:GPT-4o(贵)
  • 备:GPT-4o-mini(便宜,快)
  • 兜底:静态响应模板
  • 优点:API调用方式相同,切换成本最低

3. 降级后自动恢复(高级)

  • 主模型挂了 → 切到备用 → 后台定时ping主模型
  • 主模型恢复 → 自动切回(不要永远用备用,贵)
  • 实现方式:健康检查线程每隔30秒尝试一次轻量级请求,成功就切回

真实案例:

  • Klarna的AI助手同时对接OpenAI和Azure OpenAI,OpenAI挂了自动切Azure,用户无感知
  • 很多国内企业用「硅基流动 + 本地Ollama」做双链,云端挂了切本地
  • 关键指标:降级切换延迟 < 10秒,用户几乎无感知

三、请求缓存:相同问题零调用

装饰器模式,透明包装

CachedChatModel就是装饰器模式——包装一个ChatModel,外面加一层缓存,内部模型不知道自己被缓存了。

static class CachedChatModel {
    private final ChatModel delegate;        // 被装饰的真实模型
    private final Map<String, CacheEntry> cache = new HashMap<>();
    private final long ttlMs;                 // 缓存过期时间

    String chat(String prompt) {
        String cacheKey = buildCacheKey(prompt);
        // 1. 查缓存
        CacheEntry entry = cache.get(cacheKey);
        if (entry != null && !entry.isExpired(ttlMs)) {
            return entry.response;  // 命中!直接返回
        }
        // 2. 未命中 → 调API
        String response = delegate.chat(prompt);
        // 3. 存入缓存
        cache.put(cacheKey, new CacheEntry(response));
        return response;
    }
}

实测:缓存命中瞬间返回

场景结果耗时
首次提问未命中,调API2-3秒
完全相同的问题再问💚命中缓存<1毫秒
问题加了个"请"字🔴未命中(精确匹配)2-3秒
清空缓存后再问未命中2-3秒

注意——"什么是RAG?"和"什么是RAG?请"只差一个字,缓存就不命中。这是精确匹配的死板之处。

生产环境怎么做缓存?

1. 本地内存缓存(Caffeine)——最快最简单

  • 适合单机部署,命中率极高(用户重复提问很常见)
  • Caffeine是Java世界里最高性能的缓存库,比Guava Cache快2倍
  • 配置:最大容量10000条 + TTL 5分钟 + LRU淘汰
Cache<String, String> cache = Caffeine.newBuilder()
    .maximumSize(10_000)
    .expireAfterWrite(Duration.ofMinutes(5))
    .recordStats()           // 开启统计(命中率/淘汰率)
    .build();

2. Redis分布式缓存——多实例共享

  • 适合K8s多Pod部署,所有实例共享同一份缓存
  • 优点:多实例缓存一致,容量大
  • 缺点:每次查缓存多一次Redis网络调用(1-3ms),比本地慢但比调API快1000倍

3. 语义缓存(Semantic Cache)——最智能但最复杂

  • 不是精确匹配,而是用Embedding算语义相似度
  • "什么是RAG?"和"RAG是什么意思?"措辞不同但语义相同 → 命中
  • 工具:GPTCache(Python)、LangChain SemanticCache
  • 缺点:每次查缓存要先调Embedding模型(有成本),阈值设不好会返回错误答案

真实案例:

  • 企业客服系统60-70%的提问是重复问题,缓存命中率极高
  • 关键指标:缓存命中率 > 30%就有价值,> 50%就是优秀

四、Token精简:三招砍掉一半Token

缓存和路由是结构层面的优化,Token精简是内容层面的优化——同样的信息,用更少的字表达。

第一招:Prompt瘦身

// 冗长版(啰嗦+重复)——约200 tokens
String verbose = "你是专业的Java代码审查专家,拥有20年经验。" +
    "请仔细审查以下代码,从多个角度分析:" +
    "首先检查语法错误,其次检查逻辑错误," +
    "然后检查安全问题,接着检查性能问题," +
    "最后检查编码规范。" +
    "请给出详细报告,包括问题描述、严重程度和修改建议。" +
    "请用中文回答。";

// 精简版(结构化模板)——约80 tokens
String lean = "审查以下Java代码,按格式输出:\n" +
    "[类型] 问题描述 → 修改建议\n" +
    "类型:语法/逻辑/安全/性能/规范";

实测对比:冗长版约200 tokens,精简版约80 tokens,省了60%。效果呢?精简版的回答更结构化,因为模板本身就在引导输出格式。

第二招:历史消息裁剪

多轮对话的Token消耗是线性增长——每轮对话加4条消息(User+AI+可能还有System),10轮对话就是40条消息。

// 全量历史:10条消息 ≈ 800 tokens
// 裁剪后:System + 最近2轮 + 当前问题 ≈ 200 tokens
// 省了75%
String trimmed = systemMsg + "...(更早对话已省略)...\n"
    + recentMessages + currentQuestion;

生产环境裁剪策略:

  • 客服场景:只保留最近3轮(用户通常只关心当前问题)
  • 代码助手:保留最近5轮(上下文对代码理解很重要)
  • 写作助手:保留最近2轮+摘要(前面聊的内容压缩成摘要,不丢关键信息)
  • 摘要压缩可以参考Claude Code的四级压缩架构(我们昨天学的):Snip→MicroCompact→Collapse→AutoCompact

第三招:输出长度限制

输出Token通常比输入Token贵4倍(GPT-4o:输入$2.5 vs 输出$10/M tokens)。控制输出长度是最直接的省钱手段。

ChatModel limitedModel = OpenAiChatModel.builder()
    .modelName("Pro/zai-org/GLM-5.1")
    .maxTokens(50)  // 只允许50个Token输出
    .build();

实测:问"详细介绍Java垃圾回收",maxTokens=50时输出约30-40个中文字,刚好够一句话总结。如果你只需要一句话答案,不设上限模型可能写500字废话。

五、三件套整合:完整请求链路

把Router + Fallback + Cache组装到一起,完整的请求链路是这样的:

请求进来 → ① 查缓存(命中?直接返回,0 API调用)
              ↓ 未命中
           ② Router选模型(简单→小模型,复杂→大模型)
              ↓
           ③ Fallback链调用(主模型挂了→备用→兜底)
              ↓ 成功
           ④ 存入缓存 → 返回
              ↓ 全挂
           ⑤ 兜底响应

整合Demo的核心引擎——CostAwareChatEngine,把三步串到一起:

static class CostAwareChatEngine {
    String chat(String prompt, TaskType taskType) {
        // ① 查缓存
        CacheEntry cached = cache.get(cacheKey);
        if (cached != null && !cached.isExpired(cacheTtlMs)) {
            return cached.response;  // 命中!
        }

        // ② Router选模型
        String primaryModel = taskType == TaskType.SIMPLE ? SMALL_MODEL : LARGE_MODEL;
        String fallbackModel = taskType == TaskType.SIMPLE ? LARGE_MODEL : SMALL_MODEL;

        // ③ Fallback链
        for (String model : Arrays.asList(primaryModel, fallbackModel)) {
            try {
                String response = createModel(model).chat(prompt);
                if (response != null && !response.isBlank()) {
                    cache.put(cacheKey, new CacheEntry(response));  // ④ 存缓存
                    return response;
                }
            } catch (Exception e) {
                // 降级
            }
        }
        return "服务暂时不可用";  // ⑤ 兜底
    }
}

六个场景测试的最终统计报告:

  • 6次请求,3次缓存命中,1次大模型调用,2次小模型调用
  • 缓存命中率50%,省了3次API调用
  • 无降级,无失败——说明链路可靠

六、生产环境成本优化全景

把今天学的三件套放到真实生产环境,还需要补充这些:

监控层

  • Token计数追踪:每次调用记录input/output tokens,按模型/业务/用户维度聚合
  • 成本Dashboard:实时展示每日/每周成本趋势,异常飙升自动告警
  • 质量监控:缓存命中率过低→说明缓存策略有问题;降级率过高→说明主模型不稳定

配置层

  • 动态路由规则:不在代码里硬编码,放在配置中心(Nacos/Apollo),随时调整
  • 模型版本管理:模型升级后(如GPT-4o→GPT-5),自动切换+灰度验证
  • 缓存策略调整:不同业务不同TTL,热门问题TTL长,时效性问题TTL短

安全层

  • 缓存隔离:不同用户/租户的缓存不能交叉(避免数据泄露)
  • 降级审计:每次降级记录原因和持续时间,事后分析
  • 成本上限:设置每日/每月API调用预算上限,超限自动降级到免费模型

推荐技术栈

组件推荐方案理由
路由引擎自写策略模式 + Nacos配置简单够用,不需要额外框架
降级框架自写责任链 + Resilience4jResilience4j做熔断限流,责任链做模型降级
本地缓存CaffeineJava最强本地缓存,比Guava快2倍
分布式缓存Redis + Redisson多实例共享,Redisson封装好用
语义缓存GPTCache / LangChain SemanticCache智能匹配,但需调阈值
Token统计MLflow Tracking / 自写Interceptor每次调用拦截记录token数
成本告警Prometheus + Grafana实时监控成本曲线,异常告警

写在最后

总结一下,今天学了三个设计模式,搭了三件套,但最核心的不是代码,而是思维转变:

  1. 不是所有任务都需要最贵的模型——这是成本优化的起点
  2. 模型一定会挂——这是降级机制的必要性
  3. 用户会重复问同样的问题——这是缓存的价值所在
  4. 省钱不是偷工减料——是在正确的地方花正确的钱

三个设计模式的映射:

  • 策略模式 = Router 选模型
  • 责任链模式 = Fallback 降级
  • 装饰器模式 = Cache 加缓存

你之前肯定写过这三模式,只是应用场景变成了LLM。核心逻辑一模一样。

下次聊安全防护——Prompt注入检测、输出审查、越狱防御。这三件事做好,成本优化才不会变成安全灾难。


欢迎关注,一起从Java后端转型LLM应用开发。下周预告:安全防护实战——让你的Agent不被黑客玩弄。

更多推荐