二哥项目资料

求职派:大模型接入+模型路由+运行时切换

正文 17,098 字 #07 原文
本文目录 · 21 节

星球:Java进阶之路&二哥编程星球 | 专栏:求职派 OpenClaw 架构 | 作者:沉默王二 | 发布:2026-07-13

求职派:大模型接入+模型路由+运行时切换

求职派:大模型接入+模型路由+运行时切换

Spring AI 给 OpenAI、Anthropic 这些主流模型做了官方 Starter,加个依赖就能调用。

但往往模型的更新速度会超过SpringAI的迭代速度。

求职派同时接入了智谱、硅基流动、DeepSeek、阿里通义等多家供应商。有些供应商SpringAI是不支持的。技术派: https://paicoding.com/jobclaw-llm-integration

图片.png

所以求职派把模型接入抽象成了一个接口。

只要实现了这个接口,新模型就能被系统自动发现和调用。

这篇就从这个接口出发,拆解多个模型接入的完整架构,从接口设计到自动发现,从模型解析到 OpenAI 兼容协议的复用,再到运行时不重启服务就能切换模型。

01、为什么需要自定义接入

Spring AI 官方维护了一批 Starter,比如 spring-ai-starter-model-openai、 spring-ai-starter-model-zhipuai,加到 Maven 依赖里配上 API Key 就能用。

求职派目前接入的供应商有五六家,而且不同的用户可能喜好不同的模型,有人喜欢用智谱的免费模型,有人愿意付费用 DeepSeek。

图片.png

如果每接入一个新厂商就在核心模块里加一堆 if-else,改调用逻辑,几轮下来代码就没法维护了。

更麻烦的是,模型的增减是运营行为,不是开发行为。今天某个免费模型下线了,明天某家厂商发布了性价比更高的新模型,这些调整不应该每次都走开发、测试、部署的流程。

求职派需要的是插件式的方案。

02、一个接口搞定所有供应商

求职派模型供应商的核心接口定义在 core 模块里。

Java

public interface ModelProvider {
    String apiStyle();
    Model model(ModelConfig.ModelInfo info);
}

就两个方法。

apiStyle() 返回一个标识字符串,比如 "openai"、"zhipu"、"anthropic"、"ali",用来区分不同的 API 协议风格。

model() 是工厂方法,根据配置信息构建 Spring AI 的 Model 实例。

图片.png

以阿里通义的实现为例,它支持六种模型,包括文本对话、视觉理解、图像生成、向量嵌入、语音识别、语音合成。

Java

public Model model(ModelConfig.ModelInfo info) {
    return switch (info.getType()) {
        case TEXT, VISION -> buildChatModel(info);
        case IMAGE -> buildImageModel(info);
        case EMBEDDING -> buildEmbeddingModel(info);
        // ASR、TTS 等音频类型同理
    };
}

switch 按模型类型分发到不同的构建方法。

每个分支内部负责三件事,创建 HTTP 客户端(RestClient 或 WebClient)、设置认证方式(Bearer Token、API Key Header 等)、把配置参数映射到 Spring AI 对应的 Options 对象上。

以文本对话模型为例, buildChatModel 方法里会根据配置信息设置 base URL、超时时间、重试策略,然后把这些参数传给 Spring AI 的 ChatModel 构造方法。

如果供应商支持工具调用(Function Calling),还会注入 Spring AI 的 ToolCallingManager,让上层 Agent 可以直接挂载自定义工具。

对外只暴露一个统一的 Model 实例,上层调用者不需要知道底层用的是 SDK 还是 HTTP 请求。

那系统是怎么发现这些供应商呢?

每个供应商模块需要写一个 Spring Boot 自动配置类(标注 @AutoConfiguration),把自己的实现注册为 Bean,再在模块的 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件里声明配置类的全限定名。

Spring Boot 启动时扫描 classpath,发现声明文件就加载对应的配置类,供应商 Bean 自动注册进容器。

03、模型路由

供应商注册进来后,下一个问题是解决的,就是某个用户的某次请求该用哪个模型?

这个工作由模型解析器完成。

它在启动时通过 Spring 的依赖注入收集所有供应商实例,按 apiStyle() 建了一张索引表。

Java

this.providerMap = list.stream()
    .collect(Collectors.toMap(
        ModelProvider::apiStyle, it -> it));

模型选择用的是 provider#modelName 这个格式。

图片.png

zhipu#glm-4.7-flash 表示用智谱供应商的 glm-4.7-flash 模型, openai#gpt-5.5 表示用 OpenAI 的 GPT-5.5。

解析时按 # 拆分,前半段在索引表里找到供应商,后半段作为模型名传给 model() 方法。

构建出来的 Model 实例会被缓存。同一个用户请求同一个模型时,不会重复创建 HTTP 客户端和认证信息,直接复用已有的实例。

用户级别的模型偏好在 application.yml 的 agent.ai.preference 下维护。

每条记录绑定一个用户 ID,指定该用户的文本模型和视觉模型分别用哪个。比如 text: zhipu#glm-4.7-flash 表示文本对话用智谱的 glm-4.7-flash, vision: zhipu#glm-4.6v-flash 表示图片理解用智谱的视觉模型。

有一个特殊的用户 ID 叫 total,作为全局默认配置。

所有没有单独设置的用户都走这个。系统也支持按用户 ID 指定不同的偏好,A 用户用智谱的免费模型,B 用户用 DeepSeek,互不影响。

上层 Agent 调用大模型时,只需要传入用户 ID 和模型类型,解析器自动找到对应的供应商和模型名,返回可用的 Model 实例。

模型是谁家的、走什么协议,Agent 完全不需要感知。

Agent 怎么调用模型

模型解析器解决了"找到哪个模型"的问题,但 Agent 并不是直接拿着解析器去调用的。

中间还有一层调用抽象,求职派设计了三级调用器,从简到繁。

图片.png

第一级是简单调用器,拿到用户 ID 后,从解析器获取模型,发送 Prompt,返回结果。没有历史记忆,没有工具,适合一次性的分类、摘要等场景。

第二级是带记忆的调用器,在第一级的基础上接入了聊天记忆组件,能记住用户的上下文。同时支持挂载自定义工具(比如搜索岗位、查询简历),让模型具备调用外部能力的本事。这是大部分业务 Agent 日常使用的调用层级。

第三级是带身份的调用器,在第二级之上还会加载用户的个人画像(教育背景、工作经历、求职意向),把这些信息注入到系统提示词中。这样模型不仅能记住对话上下文,还能根据用户的具体情况给出个性化的回答。

三级调用器共用同一个模型解析器,区别只在于"给模型附加了多少上下文信息"。

Agent 根据业务场景选择合适的层级,不需要关心底层的模型选择和 HTTP 调用。

另外还有一个自动检测的细节。

调用器会判断用户消息里是否包含图片等多媒体内容,如果有,就会自动把模型类型从 TEXT 切换到 VISION,不需要调用方手动指定。

04、OpenAI 兼容协议的复用

智谱、硅基流动、DeepSeek 三家供应商的 api-style 都填的是 openai。

YAML

zhipu:
  api-style: openai
  base-url: https://open.bigmodel.cn/api/paas/v4
deepseek:
  api-style: openai
  base-url: https://api.deepseek.com

智谱、硅基流动、DeepSeek 三家都实现了 OpenAI 兼容的 HTTP 接口。

请求体的 JSON 结构、返回体的字段命名,跟 OpenAI 一模一样,区别只在于服务地址不同。

OpenAI 的供应商实现在构建模型时,检查配置里有没有自定义的 base URL,有的话就覆盖默认的 api.openai.com。

所以接入一个 OpenAI 兼容的新厂商,根本不需要写 Java 代码——在配置文件里加几行,填上地址和 API Key 就完事了。

图片.png

国内大部分模型厂商都在往 OpenAI 兼容方向靠拢,这个趋势短期内不会变。

api-style 这个字段的设计让求职派不需要为每个兼容厂商单独写模块,一个 OpenAI 供应商实现就覆盖了大半个国内市场。

真正需要单独写模块的,只有协议不兼容的厂商。

比如 Anthropic 的 Claude 系列,用的是自己的 Messages API 格式,请求体结构和返回字段跟 OpenAI 完全不同。

求职派为它单独写了一个供应商模块,里面还实现了一个自定义的认证后端,专门处理 Claude Code 的 OAuth 令牌注入和提示词缓存。这种"协议级别的差异"是配置解决不了的。

05、运行时切换模型

配置文件改了要重启服务,生产环境里不太现实。

求职派在管理后台做了 LLM 供应商的完整配置页面,可以在线完成增删供应商、修改 API Key 和服务地址、调整全局默认模型、为特定用户指定模型偏好。

保存配置后,系统通过事件驱动机制通知模型缓存刷新。

缓存被清空,下一次模型调用时解析器会用新的配置重新构建 Model 实例。整个过程不需要重启服务,对正在进行的对话也没有影响。

图片.png

管理后台还做了一个模型连通性测试的功能。

填完 API Key 和服务地址后,先点"测试"按钮验证能否正常通信,确认没问题再保存。API Key 在页面上做了脱敏处理,只显示首尾几位字符,避免在共享屏幕或截图时泄露。

06、求职派如何写到简历上?

项目名称:求职派(JobClaw)

项目简介:基于 Spring AI 的多 Agent 求职助手系统,支持微信/钉钉/飞书多渠道接入,通过意图识别自动路由到身份采集、岗位检索、智能推荐等业务 Agent。

技术栈:Java 21、Spring Boot 4.0、Spring AI 2.0、LangGraph4J、JPA/Hibernate、React 19/Next.js 15

核心职责:

  • 基于 AutoConfiguration 机制实现模型供应商的插件化接入,新增供应商无需修改核心代码,Maven 依赖加载即自动生效

  • 设计 provider#modelName 格式的模型选择协议,支持按用户维度配置模型偏好,实现多租户场景下的模型隔离

  • 利用 OpenAI 兼容协议,通过配置变更即可接入智谱、硅基流动、DeepSeek 等国产大模型

  • 实现模型配置的热更新机制,管理后台修改供应商配置后通过事件驱动刷新缓存,无需重启服务

  • 构建三层调用抽象(简单调用、有记忆调用、带身份调用),业务 Agent 对底层模型供应商完全透明

【自定义模型接入的重点不在怎么发 HTTP 请求,重点在怎么让系统在不改代码的前提下,随时接纳新的模型。】

我们下期见。

Spring AI 给 OpenAI、Anthropic 这些主流模型做了官方 Starter,加个依赖就能调用。

但往往模型的更新速度会超过SpringAI的迭代速度。

求职派同时接入了智谱、硅基流动、DeepSeek、阿里通义等多家供应商。有些供应商SpringAI是不支持的。技术派: https://paicoding.com/jobclaw-llm-integration

图片.png

所以求职派把模型接入抽象成了一个接口。

只要实现了这个接口,新模型就能被系统自动发现和调用。

这篇就从这个接口出发,拆解多个模型接入的完整架构,从接口设计到自动发现,从模型解析到 OpenAI 兼容协议的复用,再到运行时不重启服务就能切换模型。

01、为什么需要自定义接入

Spring AI 官方维护了一批 Starter,比如 spring-ai-starter-model-openai、 spring-ai-starter-model-zhipuai,加到 Maven 依赖里配上 API Key 就能用。

求职派目前接入的供应商有五六家,而且不同的用户可能喜好不同的模型,有人喜欢用智谱的免费模型,有人愿意付费用 DeepSeek。

图片.png

如果每接入一个新厂商就在核心模块里加一堆 if-else,改调用逻辑,几轮下来代码就没法维护了。

更麻烦的是,模型的增减是运营行为,不是开发行为。今天某个免费模型下线了,明天某家厂商发布了性价比更高的新模型,这些调整不应该每次都走开发、测试、部署的流程。

求职派需要的是插件式的方案。

02、一个接口搞定所有供应商

求职派模型供应商的核心接口定义在 core 模块里。

Java

public interface ModelProvider {
    String apiStyle();
    Model model(ModelConfig.ModelInfo info);
}

就两个方法。

apiStyle() 返回一个标识字符串,比如 "openai"、"zhipu"、"anthropic"、"ali",用来区分不同的 API 协议风格。

model() 是工厂方法,根据配置信息构建 Spring AI 的 Model 实例。

图片.png

以阿里通义的实现为例,它支持六种模型,包括文本对话、视觉理解、图像生成、向量嵌入、语音识别、语音合成。

Java

public Model model(ModelConfig.ModelInfo info) {
    return switch (info.getType()) {
        case TEXT, VISION -> buildChatModel(info);
        case IMAGE -> buildImageModel(info);
        case EMBEDDING -> buildEmbeddingModel(info);
        // ASR、TTS 等音频类型同理
    };
}

switch 按模型类型分发到不同的构建方法。

每个分支内部负责三件事,创建 HTTP 客户端(RestClient 或 WebClient)、设置认证方式(Bearer Token、API Key Header 等)、把配置参数映射到 Spring AI 对应的 Options 对象上。

以文本对话模型为例, buildChatModel 方法里会根据配置信息设置 base URL、超时时间、重试策略,然后把这些参数传给 Spring AI 的 ChatModel 构造方法。

如果供应商支持工具调用(Function Calling),还会注入 Spring AI 的 ToolCallingManager,让上层 Agent 可以直接挂载自定义工具。

对外只暴露一个统一的 Model 实例,上层调用者不需要知道底层用的是 SDK 还是 HTTP 请求。

那系统是怎么发现这些供应商呢?

每个供应商模块需要写一个 Spring Boot 自动配置类(标注 @AutoConfiguration),把自己的实现注册为 Bean,再在模块的 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件里声明配置类的全限定名。

Spring Boot 启动时扫描 classpath,发现声明文件就加载对应的配置类,供应商 Bean 自动注册进容器。

03、模型路由

供应商注册进来后,下一个问题是解决的,就是某个用户的某次请求该用哪个模型?

这个工作由模型解析器完成。

它在启动时通过 Spring 的依赖注入收集所有供应商实例,按 apiStyle() 建了一张索引表。

Java

this.providerMap = list.stream()
    .collect(Collectors.toMap(
        ModelProvider::apiStyle, it -> it));

模型选择用的是 provider#modelName 这个格式。

图片.png

zhipu#glm-4.7-flash 表示用智谱供应商的 glm-4.7-flash 模型, openai#gpt-5.5 表示用 OpenAI 的 GPT-5.5。

解析时按 # 拆分,前半段在索引表里找到供应商,后半段作为模型名传给 model() 方法。

构建出来的 Model 实例会被缓存。同一个用户请求同一个模型时,不会重复创建 HTTP 客户端和认证信息,直接复用已有的实例。

用户级别的模型偏好在 application.yml 的 agent.ai.preference 下维护。

每条记录绑定一个用户 ID,指定该用户的文本模型和视觉模型分别用哪个。比如 text: zhipu#glm-4.7-flash 表示文本对话用智谱的 glm-4.7-flash, vision: zhipu#glm-4.6v-flash 表示图片理解用智谱的视觉模型。

有一个特殊的用户 ID 叫 total,作为全局默认配置。

所有没有单独设置的用户都走这个。系统也支持按用户 ID 指定不同的偏好,A 用户用智谱的免费模型,B 用户用 DeepSeek,互不影响。

上层 Agent 调用大模型时,只需要传入用户 ID 和模型类型,解析器自动找到对应的供应商和模型名,返回可用的 Model 实例。

模型是谁家的、走什么协议,Agent 完全不需要感知。

Agent 怎么调用模型

模型解析器解决了"找到哪个模型"的问题,但 Agent 并不是直接拿着解析器去调用的。

中间还有一层调用抽象,求职派设计了三级调用器,从简到繁。

图片.png

第一级是简单调用器,拿到用户 ID 后,从解析器获取模型,发送 Prompt,返回结果。没有历史记忆,没有工具,适合一次性的分类、摘要等场景。

第二级是带记忆的调用器,在第一级的基础上接入了聊天记忆组件,能记住用户的上下文。同时支持挂载自定义工具(比如搜索岗位、查询简历),让模型具备调用外部能力的本事。这是大部分业务 Agent 日常使用的调用层级。

第三级是带身份的调用器,在第二级之上还会加载用户的个人画像(教育背景、工作经历、求职意向),把这些信息注入到系统提示词中。这样模型不仅能记住对话上下文,还能根据用户的具体情况给出个性化的回答。

三级调用器共用同一个模型解析器,区别只在于"给模型附加了多少上下文信息"。

Agent 根据业务场景选择合适的层级,不需要关心底层的模型选择和 HTTP 调用。

另外还有一个自动检测的细节。

调用器会判断用户消息里是否包含图片等多媒体内容,如果有,就会自动把模型类型从 TEXT 切换到 VISION,不需要调用方手动指定。

04、OpenAI 兼容协议的复用

智谱、硅基流动、DeepSeek 三家供应商的 api-style 都填的是 openai。

YAML

zhipu:
  api-style: openai
  base-url: https://open.bigmodel.cn/api/paas/v4
deepseek:
  api-style: openai
  base-url: https://api.deepseek.com

智谱、硅基流动、DeepSeek 三家都实现了 OpenAI 兼容的 HTTP 接口。

请求体的 JSON 结构、返回体的字段命名,跟 OpenAI 一模一样,区别只在于服务地址不同。

OpenAI 的供应商实现在构建模型时,检查配置里有没有自定义的 base URL,有的话就覆盖默认的 api.openai.com。

所以接入一个 OpenAI 兼容的新厂商,根本不需要写 Java 代码——在配置文件里加几行,填上地址和 API Key 就完事了。

图片.png

国内大部分模型厂商都在往 OpenAI 兼容方向靠拢,这个趋势短期内不会变。

api-style 这个字段的设计让求职派不需要为每个兼容厂商单独写模块,一个 OpenAI 供应商实现就覆盖了大半个国内市场。

真正需要单独写模块的,只有协议不兼容的厂商。

比如 Anthropic 的 Claude 系列,用的是自己的 Messages API 格式,请求体结构和返回字段跟 OpenAI 完全不同。

求职派为它单独写了一个供应商模块,里面还实现了一个自定义的认证后端,专门处理 Claude Code 的 OAuth 令牌注入和提示词缓存。这种"协议级别的差异"是配置解决不了的。

05、运行时切换模型

配置文件改了要重启服务,生产环境里不太现实。

求职派在管理后台做了 LLM 供应商的完整配置页面,可以在线完成增删供应商、修改 API Key 和服务地址、调整全局默认模型、为特定用户指定模型偏好。

保存配置后,系统通过事件驱动机制通知模型缓存刷新。

缓存被清空,下一次模型调用时解析器会用新的配置重新构建 Model 实例。整个过程不需要重启服务,对正在进行的对话也没有影响。

图片.png

管理后台还做了一个模型连通性测试的功能。

填完 API Key 和服务地址后,先点"测试"按钮验证能否正常通信,确认没问题再保存。API Key 在页面上做了脱敏处理,只显示首尾几位字符,避免在共享屏幕或截图时泄露。

06、求职派如何写到简历上?

项目名称:求职派(JobClaw)

项目简介:基于 Spring AI 的多 Agent 求职助手系统,支持微信/钉钉/飞书多渠道接入,通过意图识别自动路由到身份采集、岗位检索、智能推荐等业务 Agent。

技术栈:Java 21、Spring Boot 4.0、Spring AI 2.0、LangGraph4J、JPA/Hibernate、React 19/Next.js 15

核心职责:

  • 基于 AutoConfiguration 机制实现模型供应商的插件化接入,新增供应商无需修改核心代码,Maven 依赖加载即自动生效

  • 设计 provider#modelName 格式的模型选择协议,支持按用户维度配置模型偏好,实现多租户场景下的模型隔离

  • 利用 OpenAI 兼容协议,通过配置变更即可接入智谱、硅基流动、DeepSeek 等国产大模型

  • 实现模型配置的热更新机制,管理后台修改供应商配置后通过事件驱动刷新缓存,无需重启服务

  • 构建三层调用抽象(简单调用、有记忆调用、带身份调用),业务 Agent 对底层模型供应商完全透明

【自定义模型接入的重点不在怎么发 HTTP 请求,重点在怎么让系统在不改代码的前提下,随时接纳新的模型。】

我们下期见。

Spring AI 给 OpenAI、Anthropic 这些主流模型做了官方 Starter,加个依赖就能调用。

但往往模型的更新速度会超过SpringAI的迭代速度。

求职派同时接入了智谱、硅基流动、DeepSeek、阿里通义等多家供应商。有些供应商SpringAI是不支持的。技术派: https://paicoding.com/jobclaw-llm-integration

图片.png

所以求职派把模型接入抽象成了一个接口。

只要实现了这个接口,新模型就能被系统自动发现和调用。

这篇就从这个接口出发,拆解多个模型接入的完整架构,从接口设计到自动发现,从模型解析到 OpenAI 兼容协议的复用,再到运行时不重启服务就能切换模型。

01、为什么需要自定义接入

Spring AI 官方维护了一批 Starter,比如 spring-ai-starter-model-openai、 spring-ai-starter-model-zhipuai,加到 Maven 依赖里配上 API Key 就能用。

求职派目前接入的供应商有五六家,而且不同的用户可能喜好不同的模型,有人喜欢用智谱的免费模型,有人愿意付费用 DeepSeek。

图片.png

如果每接入一个新厂商就在核心模块里加一堆 if-else,改调用逻辑,几轮下来代码就没法维护了。

更麻烦的是,模型的增减是运营行为,不是开发行为。今天某个免费模型下线了,明天某家厂商发布了性价比更高的新模型,这些调整不应该每次都走开发、测试、部署的流程。

求职派需要的是插件式的方案。

02、一个接口搞定所有供应商

求职派模型供应商的核心接口定义在 core 模块里。

Java

public interface ModelProvider {
    String apiStyle();
    Model model(ModelConfig.ModelInfo info);
}

就两个方法。

apiStyle() 返回一个标识字符串,比如 "openai"、"zhipu"、"anthropic"、"ali",用来区分不同的 API 协议风格。

model() 是工厂方法,根据配置信息构建 Spring AI 的 Model 实例。

图片.png

以阿里通义的实现为例,它支持六种模型,包括文本对话、视觉理解、图像生成、向量嵌入、语音识别、语音合成。

Java

public Model model(ModelConfig.ModelInfo info) {
    return switch (info.getType()) {
        case TEXT, VISION -> buildChatModel(info);
        case IMAGE -> buildImageModel(info);
        case EMBEDDING -> buildEmbeddingModel(info);
        // ASR、TTS 等音频类型同理
    };
}

switch 按模型类型分发到不同的构建方法。

每个分支内部负责三件事,创建 HTTP 客户端(RestClient 或 WebClient)、设置认证方式(Bearer Token、API Key Header 等)、把配置参数映射到 Spring AI 对应的 Options 对象上。

以文本对话模型为例, buildChatModel 方法里会根据配置信息设置 base URL、超时时间、重试策略,然后把这些参数传给 Spring AI 的 ChatModel 构造方法。

如果供应商支持工具调用(Function Calling),还会注入 Spring AI 的 ToolCallingManager,让上层 Agent 可以直接挂载自定义工具。

对外只暴露一个统一的 Model 实例,上层调用者不需要知道底层用的是 SDK 还是 HTTP 请求。

那系统是怎么发现这些供应商呢?

每个供应商模块需要写一个 Spring Boot 自动配置类(标注 @AutoConfiguration),把自己的实现注册为 Bean,再在模块的 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件里声明配置类的全限定名。

Spring Boot 启动时扫描 classpath,发现声明文件就加载对应的配置类,供应商 Bean 自动注册进容器。

03、模型路由

供应商注册进来后,下一个问题是解决的,就是某个用户的某次请求该用哪个模型?

这个工作由模型解析器完成。

它在启动时通过 Spring 的依赖注入收集所有供应商实例,按 apiStyle() 建了一张索引表。

Java

this.providerMap = list.stream()
    .collect(Collectors.toMap(
        ModelProvider::apiStyle, it -> it));

模型选择用的是 provider#modelName 这个格式。

图片.png

zhipu#glm-4.7-flash 表示用智谱供应商的 glm-4.7-flash 模型, openai#gpt-5.5 表示用 OpenAI 的 GPT-5.5。

解析时按 # 拆分,前半段在索引表里找到供应商,后半段作为模型名传给 model() 方法。

构建出来的 Model 实例会被缓存。同一个用户请求同一个模型时,不会重复创建 HTTP 客户端和认证信息,直接复用已有的实例。

用户级别的模型偏好在 application.yml 的 agent.ai.preference 下维护。

每条记录绑定一个用户 ID,指定该用户的文本模型和视觉模型分别用哪个。比如 text: zhipu#glm-4.7-flash 表示文本对话用智谱的 glm-4.7-flash, vision: zhipu#glm-4.6v-flash 表示图片理解用智谱的视觉模型。

有一个特殊的用户 ID 叫 total,作为全局默认配置。

所有没有单独设置的用户都走这个。系统也支持按用户 ID 指定不同的偏好,A 用户用智谱的免费模型,B 用户用 DeepSeek,互不影响。

上层 Agent 调用大模型时,只需要传入用户 ID 和模型类型,解析器自动找到对应的供应商和模型名,返回可用的 Model 实例。

模型是谁家的、走什么协议,Agent 完全不需要感知。

Agent 怎么调用模型

模型解析器解决了"找到哪个模型"的问题,但 Agent 并不是直接拿着解析器去调用的。

中间还有一层调用抽象,求职派设计了三级调用器,从简到繁。

图片.png

第一级是简单调用器,拿到用户 ID 后,从解析器获取模型,发送 Prompt,返回结果。没有历史记忆,没有工具,适合一次性的分类、摘要等场景。

第二级是带记忆的调用器,在第一级的基础上接入了聊天记忆组件,能记住用户的上下文。同时支持挂载自定义工具(比如搜索岗位、查询简历),让模型具备调用外部能力的本事。这是大部分业务 Agent 日常使用的调用层级。

第三级是带身份的调用器,在第二级之上还会加载用户的个人画像(教育背景、工作经历、求职意向),把这些信息注入到系统提示词中。这样模型不仅能记住对话上下文,还能根据用户的具体情况给出个性化的回答。

三级调用器共用同一个模型解析器,区别只在于"给模型附加了多少上下文信息"。

Agent 根据业务场景选择合适的层级,不需要关心底层的模型选择和 HTTP 调用。

另外还有一个自动检测的细节。

调用器会判断用户消息里是否包含图片等多媒体内容,如果有,就会自动把模型类型从 TEXT 切换到 VISION,不需要调用方手动指定。

04、OpenAI 兼容协议的复用

智谱、硅基流动、DeepSeek 三家供应商的 api-style 都填的是 openai。

YAML

zhipu:
  api-style: openai
  base-url: https://open.bigmodel.cn/api/paas/v4
deepseek:
  api-style: openai
  base-url: https://api.deepseek.com

智谱、硅基流动、DeepSeek 三家都实现了 OpenAI 兼容的 HTTP 接口。

请求体的 JSON 结构、返回体的字段命名,跟 OpenAI 一模一样,区别只在于服务地址不同。

OpenAI 的供应商实现在构建模型时,检查配置里有没有自定义的 base URL,有的话就覆盖默认的 api.openai.com。

所以接入一个 OpenAI 兼容的新厂商,根本不需要写 Java 代码——在配置文件里加几行,填上地址和 API Key 就完事了。

图片.png

国内大部分模型厂商都在往 OpenAI 兼容方向靠拢,这个趋势短期内不会变。

api-style 这个字段的设计让求职派不需要为每个兼容厂商单独写模块,一个 OpenAI 供应商实现就覆盖了大半个国内市场。

真正需要单独写模块的,只有协议不兼容的厂商。

比如 Anthropic 的 Claude 系列,用的是自己的 Messages API 格式,请求体结构和返回字段跟 OpenAI 完全不同。

求职派为它单独写了一个供应商模块,里面还实现了一个自定义的认证后端,专门处理 Claude Code 的 OAuth 令牌注入和提示词缓存。这种"协议级别的差异"是配置解决不了的。

05、运行时切换模型

配置文件改了要重启服务,生产环境里不太现实。

求职派在管理后台做了 LLM 供应商的完整配置页面,可以在线完成增删供应商、修改 API Key 和服务地址、调整全局默认模型、为特定用户指定模型偏好。

保存配置后,系统通过事件驱动机制通知模型缓存刷新。

缓存被清空,下一次模型调用时解析器会用新的配置重新构建 Model 实例。整个过程不需要重启服务,对正在进行的对话也没有影响。

图片.png

管理后台还做了一个模型连通性测试的功能。

填完 API Key 和服务地址后,先点"测试"按钮验证能否正常通信,确认没问题再保存。API Key 在页面上做了脱敏处理,只显示首尾几位字符,避免在共享屏幕或截图时泄露。

06、求职派如何写到简历上?

项目名称:求职派(JobClaw)

项目简介:基于 Spring AI 的多 Agent 求职助手系统,支持微信/钉钉/飞书多渠道接入,通过意图识别自动路由到身份采集、岗位检索、智能推荐等业务 Agent。

技术栈:Java 21、Spring Boot 4.0、Spring AI 2.0、LangGraph4J、JPA/Hibernate、React 19/Next.js 15

核心职责:

  • 基于 AutoConfiguration 机制实现模型供应商的插件化接入,新增供应商无需修改核心代码,Maven 依赖加载即自动生效

  • 设计 provider#modelName 格式的模型选择协议,支持按用户维度配置模型偏好,实现多租户场景下的模型隔离

  • 利用 OpenAI 兼容协议,通过配置变更即可接入智谱、硅基流动、DeepSeek 等国产大模型

  • 实现模型配置的热更新机制,管理后台修改供应商配置后通过事件驱动刷新缓存,无需重启服务

  • 构建三层调用抽象(简单调用、有记忆调用、带身份调用),业务 Agent 对底层模型供应商完全透明

【自定义模型接入的重点不在怎么发 HTTP 请求,重点在怎么让系统在不改代码的前提下,随时接纳新的模型。】

我们下期见。