Administrator
发布于 2026-07-03 / 551 阅读
12

Spring 与 DeepSeek 战略合作后的生态变化

周会上被问住了

6 月底的架构周会,组里一个同学问:"Spring 官方和 DeepSeek 合作之后,我们要不要把模型调用层切到官方 starter?"

我当时答不上来。这两年"XX 与 XX 达成合作"的新闻太多了,大部分最后落在 PPT 上。我没有花时间验证过,就不能在会上拍板,于是给自己派了三天活:把官方文档、starter 源码和我们的实际调用链路过一遍。

这篇是那三天的结果,以及我们最后做的决策。

先搞清楚"官方集成"集成了什么

我把变化拆成了三层,只有第一层是新闻里说的那个。

层次具体是什么对我们的价值
模型接入Spring AI 提供官方 DeepSeek starter,配置即可用
能力对齐函数调用、结构化输出、思考链在 starter 里对齐
生态位国内模型进入 Spring 官方支持矩阵,不再是"社区维护"

第一层其实一直有社区实现,差别不大。真正有分量的是第二层和第三层。

我们之前接 DeepSeek 是自己写的 ChatModel 实现,因为早期官方版本对 tool calling 的支持不完整,特别是并行工具调用(parallel tool calls)返回的结构社区版解析有 bug,我们被迫在业务侧做了一层兼容。这类兼容代码是纯负债。

接入官方 starter 之后:

<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-starter-model-deepseek</artifactId>
</dependency>
spring:
  ai:
    deepseek:
      api-key: ${DEEPSEEK_KEY}
      base-url: https://api.deepseek.com
      chat:
        options:
          model: deepseek-chat
          temperature: 0.2
          # 关键:官方 starter 支持这个开关,我们之前的自研实现不支持
          internal-tool-execution-enabled: false

删掉了 640 行兼容代码。internal-tool-execution-enabled: false 这一项对我们是刚需——工具执行必须由我们自己的编排层控制,而不是让框架内部自动回调,因为要接幂等和审计。

三天的 POC 数据

光看功能不够,我们跑了一轮对比。测试集是我们自己的 640 条客服问答 + 180 条工具调用用例。

指标现网模型(某闭源)DeepSeek(官方 starter)
问答准确率89.4%87.2%
工具调用正确率94.1%91.8%
P99 首 token 延迟860ms1,420ms
P99 完整响应延迟3.4s4.9s
输入单价(每百万 token)¥16¥4
月成本(日均 300 万次)¥18.6 万¥4.9 万

结论一目了然:能力差 2~3 个百分点,成本差 3.8 倍。但延迟也确实更差,完整响应 P99 从 3.4s 涨到 4.9s,这对客服场景是有感知的。

我们没打算全切,而是按场景拆。这里就引出了真正的重点。

真正值钱的不是 starter,是抽象层的可用性

如果只接一个模型,starter 的意义有限。它的价值在于:换模型的成本被压到了一行配置

我们之前的教训是深刻的。去年从模型 A 切到模型 B,因为业务代码里散落着各种 provider 特有的参数(topPresponseFormat、自定义 header),改了 47 个文件,回归了两周。

这次我们借升级 Spring AI 2.0 的机会,强制加了一层自己的门面。所有业务代码只依赖业务语义,不依赖任何模型厂商:

public interface LlmPort {
    /** 场景而非模型:业务方只说"我要做意图识别",不关心跑在哪个模型上 */
    LlmReply complete(Task task, List<Message> messages, List<ToolSpec> tools);
}

public enum Task {
    INTENT_CLASSIFY,   // 轻量,走便宜模型
    RAG_ANSWER,        // 主力
    TOOL_PLANNING,     // 需要强推理,走最好的模型
    SUMMARIZE,         // 轻量
    SAFETY_GUARD       // 本地小模型优先
}

路由配置集中在一张表里,改模型不用发版:

@Bean
TaskRouter taskRouter(ChatModelRegistry reg) {
    return TaskRouter.builder()
        .route(INTENT_CLASSIFY, reg.get("deepseek-chat"))
        .route(RAG_ANSWER,     reg.get("deepseek-chat"))
        .route(TOOL_PLANNING,  reg.get("claude-sonnet"))
        .route(SUMMARIZE,      reg.get("qwen-turbo"))
        .route(SAFETY_GUARD,   reg.get("local-guard"))
        .fallback(RAG_ANSWER,  reg.get("qwen-plus"))     // 主模型不可用时降级
        .build();
}

这层做了之后,7 月 12 日 DeepSeek 那边出了一次 40 分钟的限流故障,我们把 RAG_ANSWER 的路由改到备用模型,改的是配置中心的一个值,30 秒生效,没有发版。

对选型的影响:三句话

这是我在周会上给出的结论。

如果你是新项目,直接用 Spring AI 2.0 + 官方 DeepSeek starter,别自己写适配层了。两年前自己写是无奈之举,现在是浪费时间。

如果你已经有自研适配层,评估一下维护成本。我们那 640 行代码里,真正有业务价值的是 0 行,全是协议兼容。删掉它本身就是收益。

别把"官方合作"当成能力背书。它只意味着"这条路走得通、有人维护",不意味着"这个模型适合你的场景"。我们的 POC 显示准确率差了 2.2 个百分点,这个差距对有些业务是致命的,对另一些业务无所谓。

我们的决策:跟进,但不绑定

最终方案是分层跟进:

  1. 框架层全量跟进。Spring AI 2.0 已 GA,我们从 1.x 升上来了,所有模型调用走官方 starter,删掉全部自研适配代码;
  2. 模型层按场景分。意图识别、摘要、RAG 问答切 DeepSeek,工具编排(TOOL_PLANNING)保留原来的模型,因为 91.8% vs 94.1% 在涉及写操作的场景里风险太大;
  3. 数据层不跟进。训练数据、微调语料、评测集全部留在自己手里,这是我们唯一的护城河,不会交给任何厂商。

成本结果:月支出从 ¥18.6 万降到 ¥9.7 万,降幅 48%。延迟方面,因为只有部分场景切换,整体 P99 从 3.4s 变成 3.9s,涨了 0.5 秒。业务方能接受,我们给了他们一个开关,投诉多的时候切回去。

观望清单

有几件事我暂时不动,列一下理由。

  • 厂商专属特性。DeepSeek 的一些特有参数(比如思考链预算控制)官方 starter 支持了,但用了就绑死。我们目前一个都没用;
  • 微调能力。我们没有足够的标注数据,微调的投入产出比算不过来,先观察一个季度;
  • 私有化部署。合规上我们有诉求,但现在的推理服务成本还没压到能接受的水平。这块我在跟另一个项目一起看,有结论了再写。

小结

三天 POC 换来最大的收获不是省下的 8.9 万,是把"换模型"这件事从两周的项目变成了一个配置项。技术新闻会一波接一波,明年可能又是别的厂商、别的合作,但只要这层抽象在,我们面对任何合作都可以用三天验证完再决定跟不跟。

至于那 2.2 个百分点的准确率差距,我目前的判断是:它会随模型迭代快速收敛,不值得为它锁死供应商。这个判断对不对,年底再看。

参考