跳到内容

AI 模型

受众:开发者 摘要:spring-open-starter-ai-model 提供统一 AI 模型调用抽象,负责把模型请求、配置解析和 Provider SPI 收敛到 starter 边界内。

定位

spring-open-starter-ai-model 是 AI 模型调用底座,不承载平台运营、用户 API Key、Token 计量、扣费、套餐和后台管理逻辑。这些业务能力由独立的 spring-open-module-ai 负责。

第一版包名统一为:

text
com.springopen.starter.ai.model

这个命名表示 ai 能力域下的 model 子能力,后续可以自然扩展 com.springopen.starter.ai.gatewaycom.springopen.starter.ai.embedding 等独立边界。

设计结构

AI 模型 starter 遵循项目统一 Provider 模型:

text
Facade -> Manager -> ConfigResolver -> Provider SPI
组件说明
AiModel静态 Facade,提供简洁调用入口
AiModelManager能力主入口,负责选择 Provider 并执行调用
AiModelConfigResolver解析请求级配置、默认模型和 Provider 配置
AiModelProvider可替换实现 SPI,隐藏第三方模型服务差异
AiModelProviderConfigProvider 执行配置快照
AiModelMetadata模型元数据,承载展示名、能力、上下文窗口和输出上限
AiModelCapabilities模型能力常量,如 chatstreamvision
AiModelUsage模型用量统计,统一承载输入、输出和总 token 数
AiModelTokenEstimatorToken 预估入口,进入 Provider 前用于预检、预占和成本估算
AiModelStreamChunk流式响应片段,承载增量内容、结束标记和 token 统计
AiModelEmbeddingRequest / AiModelEmbeddingResponse向量生成 contract,承载 OpenAI Compatible inputencoding_formatdimensionsuser 和 embedding 数据列表
AiModelError统一错误信息,承载错误类型、Provider、模型、上游状态和是否可重试
AiModelProviderNamesProvider 名称常量

当前已内置 mocklogsimulatedopenai-compatiblenewapiaccount-poolopenai-officialanthropic-officialspring-ai Provider:

  • mock:用于本地验证普通响应、流式响应和 embeddings 调用链。
  • log:用于网关 contract、计量、审计和联调链路冒烟验证;默认只记录调用元信息,不记录 prompt 内容,并提供确定性 embeddings。
  • simulated:用于低成本模拟模型服务机制,支持普通响应、流式响应、embeddings、usage、延迟、限流、超时、上游错误和空响应,不访问外部模型服务。
  • openai-compatible:适配 OpenAI Chat Completions、Embeddings 和 Models 兼容协议,适合 OpenAI、DeepSeek、通义千问兼容模式、Ollama OpenAI endpoint 和企业自建兼容网关等服务。
  • newapi:面向 NewAPI 聚合网关的快速接入 Provider,内置默认关闭的本地预设,默认地址为 http://127.0.0.1:3000/v1,协议处理复用 OpenAI Compatible HTTP / SSE / /models 实现。
  • account-pool:面向本地或私有 OpenAI Compatible HTTP 服务入口,Provider 自身只接收 base-url / api-key 并转发请求;凭证健康、调度和冷却由 AI 模块运行时治理层完成。
  • openai-official / anthropic-official:官方 SDK 可选桥接 Provider;默认不引入官方 SDK 依赖,只有应用或可选 starter 提供 AiModelOfficialSdkClient 时参与路由。
  • spring-ai:基于 Spring AI 2.0.0 的 OpenAI ChatModel 做最小接入,适合验证 Spring AI 生态能力;默认关闭,需要显式启用。

DeepSeek 第一阶段作为正式供应商优先支持,但不单独新增 Java Provider 类。推荐把 deepseek 作为 provider 配置实例名,内部通过 provider: openai-compatible 复用公共底座。

anthropic-compatiblecodex-compatible 等协议适配仍在 AI Gateway 模块承接;真实官方 SDK adapter 和外部工具联调放 P2 外部验收。

源码机制骨架

AI Model starter 的核心调用链如下:

text
AiModel / AiModelManager
  -> AiModelConfigResolver
  -> AiModelRouteSelector
  -> AiModelResilienceExecutor
  -> AiModelProvider
入口源码机制边界
FacadeAiModel静态入口,委托当前 Spring 容器内的 AiModelManager
ManagerDefaultAiModelManager校验请求、选择 Provider、展开 fallback、调用韧性执行器并写回路由元数据
配置解析DefaultAiModelConfigResolver合并默认 Provider、请求 Provider、请求模型和 Provider 实例配置,生成调用快照
路由选择AiModelRouteSelector未显式指定 Provider 时按健康状态、priority、weight 和 preferred Provider 选路
韧性执行AiModelResilienceExecutor按 Provider + model 维护 retry、circuit breaker、bulkhead 和 timeout
Provider SPIAiModelProvider只负责上游协议转换、模型列表、流式片段和错误映射,不处理平台业务数据
HTTP 兼容实现OpenAiCompatibleAiModelProvider使用标准 HTTP / Jackson 访问 Chat Completions、SSE 和 /models
Spring AI 实现SpringAiModelProvider通过 Spring AI OpenAI ChatModel 接入兼容上游,仍隐藏在统一 SPI 后

路由元数据会写入普通响应和流式片段的 metadata,包含 primaryProvideractualProviderfallbackUsedrouteStrategyrouteReason 和候选 Provider 顺序。AI 模块控制面和 AI Gateway 可以用这些字段做审计、计量、排障和运维展示。

DefaultAiModelManager 会先按本次操作需要的能力过滤候选 Provider,再进入 priority、weight、health 和 fallback 选择。chat / stream / embeddings 分别要求 chatstreamembedding 能力;通用 relay 会通过 AiModelOperationCapabilities 把 endpoint 映射到 completionresponserealtimeimageaudiorerankfilebatchfine-tuningassistantvector-storeeval 等能力。历史轻量 Provider 如果没有声明 capabilities,只保留 chat / stream 兼容,不会被 embeddings 或非对话 relay 误选。

fallback 只处理可恢复的调用失败。认证失败、Provider 禁用、请求参数错误等不可重试错误不会被 fallback 掩盖;模型不存在或模型不可用只有在 model-unavailable-fallback-enabled=true 时才允许切到后备 Provider。

OpenAI Compatible(含 NewAPI、Account Pool)和 Anthropic Compatible Provider 收到上游非 2xx HTTP 响应时,会在映射为 AiModelException 前输出 warn 日志。日志包含协议、operation、Provider 配置名、实现名、凭证名称、模型、HTTP 状态、请求方法、去除 query 和 user-info 的上游 URI,以及最多 4KB 的上游错误体;错误体中的常见密钥字段、Bearer token 和 sk-* 片段会脱敏,正常 2xx 响应不输出该告警。

Spring AI 接入状态

Spring AI 是项目优先复用的上游模型调用生态。当前主线已按开发决策接入 Spring AI 2.0.0,并提供 spring-ai Provider。该 Provider 仍隐藏在 AiModelProvider SPI 后面,业务模块和 Open Platform 网关只调用 AiModelManager,不直接依赖 Spring AI API。

当前 spring-ai Provider 属于最小接入:

  • 底层使用 Spring AI OpenAI ChatModel。
  • 支持普通响应、流式响应和 usage 转换。
  • 支持 base-urlapi-keymodeltimeoutorganizationprojectmax-retriesstream-usage
  • 模型列表仍返回本地配置的 AiModelMetadata,因为 Spring AI ChatModel 不提供统一 /models 抽象;需要动态同步官网模型列表时,继续使用 openai-compatible Provider。

后续升级 Spring AI 2.x 小版本时,只需要升级 spring-ai.version 并复跑 AI Model starter 与 Open Platform Gateway 测试,不改变业务调用 contract。

官方 SDK Provider 接入状态

OpenAI 和 Anthropic / Claude 都已有官方 Java SDK。当前默认 starter 暂不引入这些 SDK 依赖,原因是第一阶段 openai-compatible Provider 已覆盖 DeepSeek、OpenAI Compatible、自建兼容网关和开发者工具常用调用路径。

AI Model starter 已提供 openai-official / anthropic-official 桥接 Provider 和 AiModelOfficialSdkClient SPI。应用或后续可选 provider starter 可以自行引入官方 SDK,并把 SDK 调用适配为统一的 AiModelResponseAiModelStreamChunkAiModelMetadata。没有匹配客户端时,桥接 Provider 会保持 supports=false,Manager 会在 fallback 链中自动跳过它并继续尝试后续 Provider。

官方 SDK adapter 只建议用于这些场景:

  • 官方新 API 或特殊字段无法通过兼容 HTTP Provider 稳定表达。
  • 需要官方 SDK 特有认证、分页、流式事件或错误类型。
  • 开发者显式引入可选 Provider 依赖。

即使接入官方 SDK,业务模块也只调用 AiModelManager / AiModelProvider,不直接依赖官方 SDK API。

快速开始

默认启用:

yaml
spring:
  open:
    ai:
      enabled: true
      platform:
        enabled: true
      gateway:
        enabled: true
      model:
        enabled: true
        default-provider: ${SPRING_OPEN_AI_MODEL_DEFAULT_PROVIDER:openai-compatible}

应用默认配置已经内置 simulatedmocklogdeepseekopenaiopenai-compatiblenewapigeminilocal-account-pool 这几类 Provider 实例模板。AI Model starter 还会默认注册一批关闭状态的 OpenAI Compatible 渠道预设,用于后台快速启用常见聚合网关、官方兼容接口和本地自托管端点。默认 Provider 名称是 openai-compatible,面向生产时优先接入真实兼容入口;该 Provider 的地址、模型和密钥默认留空,必须由管理员通过后台配置或环境变量显式启用后才会访问真实上游。simulated 默认启用,只用于 Knowledge 等内部能力的低成本降级兜底和本地联调,不作为生产主路由。

兼容渠道预设矩阵

AI Model starter 默认注册的渠道预设都处于 enabled=false,只作为后台 Provider 列表和快速配置模板,不会在启动时访问真实上游。

配置实例名实际 Provider默认地址类型能力画像Relay 画像
newapinewapihttp://127.0.0.1:3000/v1聚合网关aggregated-openai-compatiblefull-relay
openaiopenai-compatiblehttps://api.openai.com/v1官方兼容接口full-openai-compatiblefull-relay
azure-openaiopenai-compatiblehttps://example.openai.azure.com官方兼容接口deployment-openai-compatibledeployment-relay
deepseekopenai-compatiblehttps://api.deepseek.com官方兼容接口official-openai-compatiblecore-relay
openrouteropenai-compatiblehttps://openrouter.ai/api/v1聚合网关aggregated-openai-compatiblefull-relay
groqopenai-compatiblehttps://api.groq.com/openai/v1官方兼容接口official-openai-compatiblecore-relay
mistralopenai-compatiblehttps://api.mistral.ai/v1官方兼容接口official-openai-compatiblecore-relay
togetheropenai-compatiblehttps://api.together.xyz/v1官方兼容接口official-openai-compatiblecore-relay
xaiopenai-compatiblehttps://api.x.ai/v1官方兼容接口official-openai-compatiblecore-relay
perplexityopenai-compatiblehttps://api.perplexity.ai官方兼容接口official-openai-compatiblecore-relay
geminiopenai-compatiblehttps://generativelanguage.googleapis.com/v1beta/openai官方兼容接口official-openai-compatiblecore-relay
cerebrasopenai-compatiblehttps://api.cerebras.ai/v1官方兼容接口official-openai-compatiblecore-relay
fireworksopenai-compatiblehttps://api.fireworks.ai/inference/v1官方兼容接口official-openai-compatiblecore-relay
sambanovaopenai-compatiblehttps://api.sambanova.ai/v1官方兼容接口official-openai-compatiblecore-relay
ollamaopenai-compatiblehttp://127.0.0.1:11434/v1本地自托管self-hosted-openai-compatiblefull-relay
lm-studioopenai-compatiblehttp://127.0.0.1:1234/v1本地自托管self-hosted-openai-compatiblefull-relay
vllmopenai-compatiblehttp://127.0.0.1:8000/v1本地自托管self-hosted-openai-compatiblefull-relay
local-account-poolaccount-poolhttp://127.0.0.1:8000/v1本地凭证池入口self-hosted-openai-compatiblefull-relay

这些预设统一声明 chatcompletionresponseconversationevalrealtimestreamembeddingmoderationimageaudiorerankfilebatchfine-tuningvector-storeassistant 能力,并默认配置 /chat/completions/embeddings/models/models/{model_id}/responses/responses/input_tokens/responses/compact/conversations/conversations/{conversation_id}/items/evals/evals/{eval_id}/runs/evals/{eval_id}/runs/{run_id}/output_items 等 OpenAI Compatible 路径。azure-openai 预设按 Azure OpenAI 传统 data plane 入口使用 /openai/deployments/{deployment}/... 路径模板、api-version query 参数和 api-key Header。capability-profilerelay-profile 是运营展示和路由治理画像,后台 Provider 列表、路由清单和候选排序都会透出这些字段;运行时真正进入候选集前还会按 operation 能力过滤,避免只支持 chat 的 Provider 承接 embeddings、rerank、file、assistant 等 endpoint。实际是否启用某个 endpoint 仍由管理员的 Provider 配置、模型目录和上游能力共同决定。管理员可以在后台启用任意预设,也可以在 YAML 中覆盖 base-urlapi-keymodelcapabilitiesoptions.* 和 metadata。

NewAPI 快速接入

NewAPI 对外提供 OpenAI Compatible API。框架内置 newapi Provider 和后台 Provider 预设,管理员只需要在后台启用 newapi、填写 NewAPI 实例的 baseUrlapiKey,再配置模型目录即可作为上游 Provider 使用;也可以通过 YAML 固化配置:

yaml
spring:
  open:
    ai:
      model:
        default-provider: ${SPRING_OPEN_AI_MODEL_DEFAULT_PROVIDER:newapi}
        providers:
          newapi:
            provider: newapi
            enabled: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_ENABLED:true}
            model: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_MODEL:gpt-4.1}
            display-name: NewAPI
            base-url: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_BASE_URL:${NEWAPI_BASE_URL:http://127.0.0.1:3000/v1}}
            api-key: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_API_KEY:${NEWAPI_API_KEY:}}
            timeout: 30s
            capabilities:
              - chat
              - stream
              - embedding
              - eval
            options:
              chat-completions-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_CHAT_COMPLETIONS_PATH:/chat/completions}
              embeddings-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_EMBEDDINGS_PATH:/embeddings}
              models-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_MODELS_PATH:/models}
              model-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_MODEL_PATH:/models/{model_id}}
              response-input-tokens-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_RESPONSE_INPUT_TOKENS_PATH:/responses/input_tokens}
              responses-compact-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_RESPONSES_COMPACT_PATH:/responses/compact}
              conversations-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_CONVERSATIONS_PATH:/conversations}
              conversation-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_CONVERSATION_PATH:/conversations/{conversation_id}}
              conversation-items-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_CONVERSATION_ITEMS_PATH:/conversations/{conversation_id}/items}
              conversation-item-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_CONVERSATION_ITEM_PATH:/conversations/{conversation_id}/items/{item_id}}
              evals-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_EVALS_PATH:/evals}
              eval-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_EVAL_PATH:/evals/{eval_id}}
              eval-runs-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_EVAL_RUNS_PATH:/evals/{eval_id}/runs}
              eval-run-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_EVAL_RUN_PATH:/evals/{eval_id}/runs/{run_id}}
              eval-run-output-items-path: ${SPRING_OPEN_AI_MODEL_PROVIDERS_NEWAPI_EVAL_RUN_OUTPUT_ITEMS_PATH:/evals/{eval_id}/runs/{run_id}/output_items}
            metadata:
              vendor: newapi

配置要点:

  • base-url 使用 NewAPI 实例地址,通常以 /v1 结尾。
  • api-key 使用 NewAPI 控制台颁发的令牌。
  • model 填 NewAPI 中可用的模型 ID;也可以先调用 AiModel.models()/v1/models 读取列表。
  • models-path 用于模型列表,model-path 用于 models.retrieve / models.delete relay,默认 /models/{model_id}
  • Responses 辅助子资源默认使用 /responses/input_tokens/responses/compact;Conversation 生命周期默认使用 /conversations/conversations/{conversation_id}/conversations/{conversation_id}/items/conversations/{conversation_id}/items/{item_id};Eval 生命周期默认使用 /evals/evals/{eval_id}/evals/{eval_id}/runs/evals/{eval_id}/runs/{run_id}/evals/{eval_id}/runs/{run_id}/output_items
  • 流式调用使用 OpenAI Compatible SSE 实时 relay,Provider 会边读取上游 data: 事件边输出 AiModelStreamChunk,不会等待上游整段响应结束后再返回。
  • embeddings 调用默认走 /embeddings,可用 options.embeddings-path 覆盖;inputencoding_formatdimensionsuser 会按 OpenAI Compatible 结构发送。
  • 需要保留低成本默认行为时,不要把 default-provider 改成 newapi,只在后台 Provider 配置中启用 newapi,按业务场景显式指定 Provider。

OpenAI Compatible 参数模板与覆盖

openai-compatiblenewapiaccount-pool 都复用 OpenAI Compatible HTTP 实现,支持通过 Provider 或凭证 options.parameter-template / options.parameter-override 在发送上游请求前调整 JSON payload。该能力只用于合法授权上游之间的接口兼容、企业网络适配和请求归一化,不处理计费、凭证调度或后台运营逻辑。

模板模式用于声明渠道默认参数,会先于覆盖规则执行,只补齐缺失或 null 字段,不替换调用方已经传入的值;嵌套对象会递归补齐。兼容别名为 request-template

yaml
spring:
  open:
    ai:
      model:
        providers:
          newapi:
            options:
              parameter-template: >
                {
                  "top_p": 0.9,
                  "extra_body": {
                    "reasoning_effort": "medium"
                  }
                }

覆盖模式用于强制归一化,会在模板之后执行。简单覆盖会把 JSON 对象直接合并到原始请求;兼容别名为 request-override

yaml
spring:
  open:
    ai:
      model:
        providers:
          newapi:
            options:
              parameter-override: >
                {
                  "temperature": 0.3,
                  "max_tokens": 2000
                }

模板和覆盖都支持 operations 高级模式,按顺序执行 setdeletemovecopyappendprependtrim_prefixtrim_suffixensure_prefixensure_suffixtrim_spaceto_lowerto_upperreplaceregex_replace。模板中的 set 默认等价于 keep_origin: true,只在目标字段缺失时写入;确需覆盖可显式设置 keep_origin: false

yaml
spring:
  open:
    ai:
      model:
        providers:
          newapi:
            options:
              parameter-template: >
                {
                  "operations": [
                    {"path": "top_p", "mode": "set", "value": 0.9}
                  ]
                }
              parameter-override: >
                {
                  "operations": [
                    {
                      "path": "messages",
                      "mode": "prepend",
                      "value": [
                        {"role": "system", "content": "请保持专业、简洁。"}
                      ]
                    },
                    {
                      "path": "temperature",
                      "mode": "set",
                      "value": 0.2,
                      "conditions": [
                        {"path": "messages.-1.content", "mode": "contains", "value": "代码"}
                      ]
                    },
                    {"path": "model", "mode": "trim_prefix", "value": "openai/"}
                  ]
                }

路径使用点号语法,例如 temperaturemessages.0.contentmessages.-1.content。条件支持 fullprefixsuffixcontainsgtgteltlte,并可使用 logic: "AND"invert: truepass_missing_key: true。数据库态凭证池也可以在单个凭证的 options 中配置同名规则,运行时选中凭证后会覆盖 Provider 级同名 option。

代码调用:

java
List<AiModelMetadata> models = AiModel.models();
AiModelResponse response = AiModel.chat("你好");
String content = response.getContent();

也可以注入 AiModelManager

java
AiModelRequest request = AiModelRequest.ofUserMessage("请总结这段内容");
AiModelResponse response = aiModelManager.chat(request);
long totalTokens = response.getUsage().getTotalTokens();

流式调用:

java
AiModelRequest request = AiModelRequest.ofUserMessage("请流式回答");
try (Stream<AiModelStreamChunk> stream = aiModelManager.stream(request)) {
    stream.forEach(chunk -> {
        if (!chunk.isDone()) {
            String delta = chunk.getDelta();
            // 将 delta 写入 SSE / WebSocket / HTTP chunk。
        }
    });
}

stream(...) 会自动把请求标记为流式请求。Provider 可以直接实现 stream(...),也可以复用默认实现,把普通响应包装为一个增量片段和一个结束片段。

结束片段会携带 AiModelUsage,调用方可以在普通响应和流式响应中使用同一个 usage contract 读取 token 用量:

java
if (chunk.isDone()) {
    long totalTokens = chunk.getUsage().getTotalTokens();
}

向量生成调用:

java
AiModelEmbeddingRequest request = AiModelEmbeddingRequest.of(List.of("hello", "world"));
request.setModel("text-embedding-3-small");
AiModelEmbeddingResponse response = aiModelManager.embeddings(request);
Object firstVector = response.getData().get(0).getEmbedding();

input 保持 OpenAI Compatible 语义,可传字符串、字符串列表或 token 数组;encodingFormatdimensionsuser 会在兼容 Provider 中映射为 encoding_formatdimensionsuser。默认 mock / log / simulated Provider 会返回本地确定性向量,便于本地测试和 Knowledge 向量化链路联调;真实 Provider 的向量维度和格式以对应上游模型能力为准。

配置项

配置默认值说明
spring.open.ai.model.enabledtrue是否启用 AI 模型 starter
spring.open.ai.model.default-provideropenai-compatible默认 Provider 名称;真实调用前需要启用并配置对应 Provider,simulated 默认启用用于内部降级兜底
spring.open.ai.model.fallback-providers[]全局 fallback Provider 顺序
spring.open.ai.model.timeout30s默认调用超时时间
spring.open.ai.model.model-discovery-timeout5s默认模型发现超时时间,仅用于上游 /models 控制面探测
spring.open.ai.model.resilience.enabledtrue是否启用 Provider 调用韧性封装
spring.open.ai.model.resilience.retry.enabledtrue是否启用重试
spring.open.ai.model.resilience.retry.max-attempts2最大尝试次数,包含首次调用
spring.open.ai.model.resilience.retry.wait-duration200ms重试间隔
spring.open.ai.model.resilience.circuit-breaker.enabledtrue是否启用熔断
spring.open.ai.model.resilience.circuit-breaker.sliding-window-size20熔断滑动窗口大小
spring.open.ai.model.resilience.circuit-breaker.minimum-number-of-calls10计算失败率前的最小调用次数
spring.open.ai.model.resilience.circuit-breaker.failure-rate-threshold50熔断失败率阈值
spring.open.ai.model.resilience.circuit-breaker.wait-duration-in-open-state30s熔断打开后的等待时间
spring.open.ai.model.resilience.bulkhead.enabledtrue是否启用并发隔离
spring.open.ai.model.resilience.bulkhead.max-concurrent-calls50单个 Provider / model 的最大并发调用数
spring.open.ai.model.resilience.bulkhead.max-wait-duration0s等待并发槽位的最长时间
spring.open.ai.model.resilience.time-limiter.enabledtrue是否启用调用超时保护
spring.open.ai.model.resilience.time-limiter.cancel-running-futuretrue超时后是否取消底层调用
spring.open.ai.model.tokenizer.enabledtrue是否启用 jtokkit Token 预估
spring.open.ai.model.tokenizer.fallback-encodingcl100k_base模型无法匹配时使用的 tokenizer encoding
spring.open.ai.model.tokenizer.fallback-chars-per-token4tokenizer 不可用时的字符数兜底估算比例
spring.open.ai.model.tokenizer.tokens-per-message3Chat 消息结构额外 token 预估
spring.open.ai.model.tokenizer.tokens-per-name1消息 name 字段额外 token 预估
spring.open.ai.model.tokenizer.assistant-primer-tokens3Assistant 回复起始额外 token 预估
spring.open.ai.model.providers.<name>.provider-实际 Provider 名称
spring.open.ai.model.providers.<name>.enabledtrue是否启用该 Provider
spring.open.ai.model.providers.<name>.model-Provider 默认模型
spring.open.ai.model.providers.<name>.display-name-模型展示名称
spring.open.ai.model.providers.<name>.capabilities[]模型能力,未配置时 Provider 可给出默认能力
spring.open.ai.model.providers.<name>.context-window-上下文窗口 token 数
spring.open.ai.model.providers.<name>.max-output-tokens-最大输出 token 数
spring.open.ai.model.providers.<name>.metadata-模型扩展元数据
spring.open.ai.model.providers.<name>.fallback-providers[]当前 Provider 失败后的 fallback Provider 顺序;优先级高于全局配置
spring.open.ai.model.providers.<name>.model-unavailable-fallback-enabledtrue当前模型不存在或不可用时是否允许切换到 fallback Provider
spring.open.ai.model.providers.<name>.upstream-error-passthrough-enabledtrue是否允许向调用方透传上游错误码和错误摘要
spring.open.ai.model.providers.<name>.base-url-Provider 服务地址
spring.open.ai.model.providers.<name>.api-key-Provider API Key
spring.open.ai.model.providers.<name>.timeout-Provider 调用超时时间
spring.open.ai.model.providers.<name>.model-discovery-timeout-Provider 模型发现超时时间;未配置时使用全局 model-discovery-timeout
spring.open.ai.model.providers.<name>.options-Provider 扩展选项
spring.open.ai.model.providers.<name>.credential-pool.enabledfalse是否启用 Provider 内上游凭证池;关闭时继续使用 Provider 级 base-url / api-key
spring.open.ai.model.providers.<name>.credential-pool.strategypriority凭证池选择策略,当前支持 priorityweighted 和平台侧 health-weighted
spring.open.ai.model.providers.<name>.credential-pool.credentials[].name-凭证名称,只用于路由观测和审计,不返回密钥明文
spring.open.ai.model.providers.<name>.credential-pool.credentials[].source-typeapi-key凭证来源类型,当前面向 api-keybyokcompatible-endpoint 等可授权来源
spring.open.ai.model.providers.<name>.credential-pool.credentials[].base-url-凭证级服务地址;为空时沿用 Provider 级 base-url
spring.open.ai.model.providers.<name>.credential-pool.credentials[].api-key-凭证级 API Key;为空时沿用 Provider 级 api-key
spring.open.ai.model.providers.<name>.credential-pool.credentials[].priority0凭证优先级,数值越大越优先
spring.open.ai.model.providers.<name>.credential-pool.credentials[].weight1凭证权重,weighted 策略下使用
spring.open.ai.model.providers.<name>.credential-pool.credentials[].options-凭证级 Provider 扩展选项,会覆盖同名 Provider 级选项
spring.open.ai.model.providers.<name>.credential-pool.credentials[].metadata-凭证级公开元数据,只放可审计的非敏感字段

Spring AI Provider

spring-ai Provider 用于通过 Spring AI 调用 OpenAI Compatible 上游。它不替代 openai-compatible Provider 的动态模型列表能力,也不改变 AI Gateway 对外协议。

yaml
spring:
  open:
    ai:
      model:
        default-provider: spring-ai
        providers:
          spring-ai:
            provider: spring-ai
            enabled: true
            model: ${SPRING_OPEN_AI_MODEL_PROVIDERS_SPRING_AI_MODEL:${OPENAI_MODEL:}}
            base-url: ${SPRING_OPEN_AI_MODEL_PROVIDERS_SPRING_AI_BASE_URL:https://api.openai.com/v1}
            api-key: ${SPRING_OPEN_AI_MODEL_PROVIDERS_SPRING_AI_API_KEY:${OPENAI_API_KEY:}}
            timeout: 30s
            capabilities:
              - chat
              - stream
            options:
              max-retries: 0
              stream-usage: true
              organization: ${OPENAI_ORGANIZATION:}
              project: ${OPENAI_PROJECT:}

常用扩展选项:

配置默认值说明
options.max-retries0Spring AI / OpenAI Java client 层重试次数;框架自身已在 Manager 层使用 Resilience4j,默认避免双层重试放大请求
options.stream-usagetrue流式响应是否请求 usage,便于网关计量扣费
options.organization-OpenAI Organization
options.project-OpenAI Project

如果目标是“官网支持什么模型,平台就默认开放什么模型”,仍建议使用 openai-compatible Provider 的 /models 同步能力;spring-ai Provider 更适合作为 Spring AI 生态兼容验证和后续高级能力接入口。

调用韧性

AI Model starter 在 Provider 调用层接入 Resilience4j,默认提供:

  • retry:只重试结构化错误中 retryable=true 的异常,例如上游限流、超时和临时不可用。
  • circuit breaker:按 Provider + model 维度维护熔断状态,避免持续打爆异常上游。
  • bulkhead:按 Provider + model 维度限制并发,保护应用线程资源。
  • time limiter:正式模型调用使用 Provider 自身 timeout,未配置时使用全局 spring.open.ai.model.timeout;模型发现 /models 使用 model-discovery-timeout,避免控制面状态页被慢上游长时间拖住。

fallback 顺序仍由 fallback-providers 决定。某个 Provider 经过重试后仍失败,Manager 才会尝试下一个 fallback Provider;认证失败、Provider 禁用、请求参数错误等不可重试错误不会被 retry 放大,也不会被 fallback 掩盖。模型不存在或模型不可用属于单独策略,只有 model-unavailable-fallback-enabled=true 时才会切换到 fallback Provider。

upstream-error-passthrough-enabled 控制错误响应是否透传上游错误码和错误摘要。关闭后,网关仍会保留结构化错误类型和状态码,但对外返回框架统一错误摘要,适合隐藏供应商原始错误内容或密钥类提示。

OpenAI Compatible Provider 会解析常见上游错误体,包括 errorerror_response 和根级错误对象中的 codetypemessagedetail 等字段。错误映射会优先参考上游错误码和摘要,再回退 HTTP 状态码,因此 model_not_foundrate_limit_errorinvalid_api_keyservice_unavailable 等错误可以稳定归一为框架内部结构化错误类型。

AiModelManager.resilienceSnapshots()AiModel.resilienceSnapshots() 可读取当前进程内的 Provider + model 韧性快照,包含熔断器状态、失败率、慢调用率、成功 / 失败调用数和熔断拒绝调用数。该接口不暴露 Resilience4j 原生类型,方便 Open Platform、Admin 运维页或后续观测模块复用。

工具网关(受治理工具执行)

模型协议层的 tool_calls / function_call 是透传:Provider 把模型的函数调用在调用方与上游模型之间中转,不做服务端治理。tool 包在其之上补一层受治理工具执行,让模型只能调用显式授权、安全可审计的业务工具。

核心类型(com.springopen.starter.ai.model.tool):

  • ToolDefinition:工具定义,含工具名、参数 JSON Schema、所需 scope、风险等级(LOW / MEDIUM / HIGH)、是否幂等、超时、是否要求二次确认和审计元数据。
  • ToolRegistry(默认 DefaultToolRegistry):显式注册工具,重复名 fail-fast;toModelToolSpecs() 把已注册工具渲染成 OpenAI tools 规格,供 AiModelRequest 携带。
  • ToolGateway(默认 DefaultToolGateway):受治理执行入口。
    • parseToolCalls(AiModelResponse):解析模型响应中的 tool_calls(协议透传层 → 执行层的接缝),输出 ToolCall
    • execute(ToolExecutionRequest):治理顺序为「定位定义 → 解析参数 → scope 校验 → 高风险二次确认 → 幂等复用 → 限时执行 → 审计」,返回带 ToolExecutionStatusSUCCESS / NOT_FOUND / INVALID_ARGUMENTS / DENIED / CONFIRMATION_REQUIRED / TIMEOUT / ERROR)的结果。
    • toToolMessage(ToolExecutionResult):把结果回灌为 tool 角色消息,喂回下一轮模型对话。
  • ToolAuditSink(默认 LoggingToolAuditSink):执行审计 SPI,可替换为落库 / 上报实现。

安全边界:

  • 只执行显式注册的工具,不把任意 Spring Bean 自动暴露成工具。
  • HIGH 风险工具默认要求二次确认:未确认时返回 CONFIRMATION_REQUIREDToolConfirmationRequest,调用方确认后必须携 confirmed=true 和本次返回的 confirmationToken 重试;确认令牌会绑定工具名、toolCallId、风险等级和参数快照,过期或参数变化都会被拒绝。
  • 不经工具网关执行真实支付、退款、钱包、Web3 出款、删除数据等不可逆高风险动作。
  • 幂等复用为单实例尽力而为的有界缓存;跨实例持久幂等由 ToolHandler 基于 idempotencyKey 自行落库实现。

注册与执行示例:

java
toolRegistry.register(
        ToolDefinition.builder()
                .name("get_order_status")
                .description("查询订单状态")
                .scope("tool:order:read")
                .riskLevel(ToolRiskLevel.LOW)
                .idempotent(true)
                .build(),
        context -> orderQueryService.status((String) context.getArguments().get("orderNo")));

// 模型返回 tool_calls 后:
for (ToolCall call : toolGateway.parseToolCalls(response)) {
    ToolExecutionResult result = toolGateway.execute(ToolExecutionRequest.builder()
            .toolName(call.toolName())
            .toolCallId(call.toolCallId())
            .rawArguments(call.rawArguments())
            .grantedScope("tool:order:read")
            .build());
    AiModelMessage toolMessage = toolGateway.toToolMessage(result);
    // 把 toolMessage 追加进下一轮请求 messages
}

Token 预估

AI Model starter 默认通过 AiModelTokenEstimator 提供输入 token 预估能力。内置实现基于 jtokkit,会优先根据请求中的 model 选择匹配 encoding;无法匹配时使用 spring.open.ai.model.tokenizer.fallback-encoding,仍失败时再按 fallback-chars-per-token 做保守兜底。

预估只用于进入 Provider 前的配额预检、账务预占和成本估算。真正的用量仍以 Provider 返回的 AiModelUsage 为准;成功实扣和用量报表不依赖预估值。

开发者可以通过覆盖 AiModelTokenEstimator Bean 接入自定义 tokenizer,例如面向特定国产模型、私有模型或企业网关的专用估算规则:

java
@Bean
AiModelTokenEstimator aiModelTokenEstimator() {
    return request -> 1L;
}

DeepSeek 配置实例

DeepSeek 是 AI 模型供应商平台第一阶段优先支持的正式供应商。DeepSeek 采用 OpenAI Compatible 协议,第一版不单独实现 DeepSeekAiModelProvider,而是通过 openai-compatible 公共 Provider 接入:

yaml
spring:
  open:
    ai:
      model:
        default-provider: deepseek
        providers:
          deepseek:
            provider: openai-compatible
            enabled: ${SPRING_OPEN_AI_MODEL_PROVIDERS_DEEPSEEK_ENABLED:true}
            model: ${SPRING_OPEN_AI_MODEL_PROVIDERS_DEEPSEEK_MODEL:${DEEPSEEK_MODEL:}}
            base-url: ${SPRING_OPEN_AI_MODEL_PROVIDERS_DEEPSEEK_BASE_URL:${DEEPSEEK_BASE_URL:https://api.deepseek.com}}
            api-key: ${SPRING_OPEN_AI_MODEL_PROVIDERS_DEEPSEEK_API_KEY:${DEEPSEEK_API_KEY:}}
            capabilities:
              - chat
              - stream
              - embedding
            context-window: 128000
            max-output-tokens: 8192

deepseek 是配置实例名,provider: openai-compatible 才是实际 Provider 实现。默认调用 /chat/completions,模型列表调用 /models。如果使用企业网关、代理或私有转发入口,可以通过 base-url 覆盖。

第一阶段不在文档里虚构或改写 DeepSeek 模型名称。平台会优先通过上游 /models 同步官方模型列表,用户在 CC Switch、Claude Code 或 OpenAI Compatible 请求里填写官网返回的 id。如果希望服务端有兜底默认模型,可以通过 DEEPSEEK_MODEL 配置一个官方模型名;没有配置默认模型时,请求侧必须显式传 model

OpenAI Compatible Provider

OpenAI Compatible Provider 不要求业务模块直接依赖 OpenAI SDK,而是用标准 HTTP 调用 Chat Completions 兼容接口:

yaml
spring:
  open:
    ai:
      model:
        default-provider: deepseek
        providers:
          deepseek:
            provider: openai-compatible
            enabled: ${SPRING_OPEN_AI_MODEL_PROVIDERS_DEEPSEEK_ENABLED:true}
            model: ${SPRING_OPEN_AI_MODEL_PROVIDERS_DEEPSEEK_MODEL:${DEEPSEEK_MODEL:}}
            base-url: ${SPRING_OPEN_AI_MODEL_PROVIDERS_DEEPSEEK_BASE_URL:${DEEPSEEK_BASE_URL:https://api.deepseek.com}}
            api-key: ${SPRING_OPEN_AI_MODEL_PROVIDERS_DEEPSEEK_API_KEY:${DEEPSEEK_API_KEY:}}
            capabilities:
              - chat
              - stream
              - embedding
            context-window: 64000
            max-output-tokens: 8192

如果需要通过通用兼容 Provider 接入其他 OpenAI Compatible 服务商,可以直接启用应用配置中的 openai-compatible 实例,并显式配置 base-urlapi-key 和可选路径。

OpenAI 官方接口可以启用应用配置中的 openai 实例:

yaml
spring:
  open:
    ai:
      model:
        default-provider: openai
        providers:
          openai:
            provider: openai-compatible
            enabled: ${SPRING_OPEN_AI_MODEL_PROVIDERS_OPENAI_ENABLED:true}
            model: ${SPRING_OPEN_AI_MODEL_PROVIDERS_OPENAI_MODEL:${OPENAI_MODEL:}}
            base-url: ${SPRING_OPEN_AI_MODEL_PROVIDERS_OPENAI_BASE_URL:https://api.openai.com/v1}
            api-key: ${SPRING_OPEN_AI_MODEL_PROVIDERS_OPENAI_API_KEY:${OPENAI_API_KEY:}}

常用扩展选项:

配置默认值说明
options.chat-completions-path/chat/completionsChat Completions 兼容接口路径
options.embeddings-path/embeddingsEmbeddings 兼容接口路径
options.models-path/models模型列表接口路径
options.model-path/models/{model_id}单模型查询 / 删除接口路径
options.responses-path/responsesResponses 创建接口路径
options.response-path/responses/{response_id}Response 详情 / 删除接口路径
options.response-input-tokens-path/responses/input_tokensResponses 输入 token 统计接口路径
options.responses-compact-path/responses/compactResponses 上下文压缩接口路径
options.conversations-path/conversationsConversation 创建接口路径
options.conversation-path/conversations/{conversation_id}Conversation 详情 / 更新 / 删除接口路径
options.conversation-items-path/conversations/{conversation_id}/itemsConversation Item 创建 / 列表接口路径
options.conversation-item-path/conversations/{conversation_id}/items/{item_id}Conversation Item 详情 / 删除接口路径
options.evals-path/evalsEval 创建 / 列表接口路径
options.eval-path/evals/{eval_id}Eval 详情 / 更新 / 删除接口路径
options.eval-runs-path/evals/{eval_id}/runsEval Run 创建 / 列表接口路径
options.eval-run-path/evals/{eval_id}/runs/{run_id}Eval Run 详情 / 删除接口路径
options.eval-run-output-items-path/evals/{eval_id}/runs/{run_id}/output_itemsEval Run 输出项列表接口路径
options.organization-OpenAI Organization Header
options.project-OpenAI Project Header
options.extra-headers-额外 HTTP Header,可用 JSON 对象或 Header=value,Header2=value;不会覆盖 AuthorizationContent-TypeAccept
options.auth-typebearer鉴权方式,支持 bearerapi-key-headernone
options.api-key-headerapi-keyauth-type=api-key-header 时 API Key 使用的 Header 名称
options.api-version-追加到 URL query 的 api-version,适合 Azure OpenAI
options.query-parameters-额外 query 参数,可用 JSON 对象或 a=b,c=d
options.deployment / options.deployment-id-路径模板 {deployment} / {deployment-id} 的值;未配置时使用当前模型名
options.parameter-template / options.request-template-上游请求 payload 默认模板,只补齐缺失字段,支持简单 JSON 和 operations 高级操作
options.parameter-override / options.request-override-上游请求 payload 覆盖规则,支持简单 JSON 合并和 operations 高级操作

兼容路径支持 {model}{deployment}{deployment-id} 变量。变量会按 URL path segment 编码后替换,避免模型名或部署名里的特殊字符破坏路径结构。

需要为 OpenRouter 等上游追加公开请求头时,可以使用 extra-headers

yaml
spring:
  open:
    ai:
      model:
        providers:
          openrouter:
            provider: openai-compatible
            enabled: true
            base-url: https://openrouter.ai/api/v1
            api-key: ${OPENROUTER_API_KEY:}
            options:
              extra-headers: >
                {
                  "HTTP-Referer": "https://example.com",
                  "X-Title": "AI Gateway"
                }

Azure OpenAI 传统部署路径可以直接启用 azure-openai 预设,或按下面的 YAML 固化:

yaml
spring:
  open:
    ai:
      model:
        providers:
          azure-openai:
            provider: openai-compatible
            enabled: true
            model: ${AZURE_OPENAI_DEPLOYMENT:gpt-4o-prod}
            display-name: Azure OpenAI
            base-url: ${AZURE_OPENAI_ENDPOINT:https://example.openai.azure.com}
            api-key: ${AZURE_OPENAI_API_KEY:}
            capabilities:
              - chat
              - stream
              - embedding
            options:
              auth-type: api-key-header
              api-key-header: api-key
              api-version: ${AZURE_OPENAI_API_VERSION:2024-10-21}
              deployment: ${AZURE_OPENAI_DEPLOYMENT:gpt-4o-prod}
              chat-completions-path: /openai/deployments/{deployment}/chat/completions
              embeddings-path: /openai/deployments/{deployment}/embeddings
              models-path: /openai/deployments

Provider 会把框架的 AiModelRequest 转成 OpenAI 兼容 JSON:

  • model
  • messages
  • stream
  • temperature
  • max_tokens
  • max_completion_tokens
  • top_p
  • tools
  • tool_choice

messages[].content 支持文本和 OpenAI Compatible 复杂 content 数组;tool_call_idtool_calls 和旧版 function_call 会被原样转发到上游。AI 网关入口未显式建模的 OpenAI Compatible 扩展字段会放入 request_parameters,Provider 会在不覆盖显式核心字段的前提下合并到最终 payload,例如 response_formatseedlogprobstop_logprobsparallel_tool_callsstream_optionsmetadata。普通响应会解析 choices[0].message.contenttool_callsfunction_callfinish_reasonusage;流式响应会实时解析 data: {...} SSE 片段,输出文本 delta、delta.tool_calls / delta.function_call 和结束片段。

Provider 也会把 AiModelEmbeddingRequest 转成 OpenAI Compatible /embeddings 请求:

  • model
  • input
  • encoding_format
  • dimensions
  • user

响应会解析 objectmodeldata[].objectdata[].indexdata[].embeddingusageembedding 可以是浮点数组,也可以是上游按 base64 返回的字符串;starter 会保留原始结构,由调用方或向量库适配层决定后续转换方式。

模型列表会在配置了 base-urlapi-key 时请求兼容服务的 /models 接口,并把返回的 data[].id 转成 AiModelMetadata。未配置远程地址和密钥时,Provider 会回退到本地配置中的模型元数据,避免默认启动时误访问外部服务。

AI 模型供应商平台的模型目录默认开放上游 /models 可同步到的全部模型:官网支持什么,平台默认就允许进入可用模型目录。默认模型名称必须保持上游官网原名,用户配置 model 时优先填写官网模型名,避免平台自行改名造成疑惑。AI 模块的数据库模型目录可给这些模型补充展示描述、价格、能力标签、上下文窗口、限流、fallback、下架状态和可选平台别名;平台别名只在 AI 网关入口解析,starter 和上游 Provider 调用仍使用官网模型名。

Account Pool Provider

account-pool Provider 是一个协议中立的 OpenAI Compatible HTTP Provider,适合把框架接到本地或私有模型服务入口。它不读取数据库、不计算健康分、不做冷却和调度,只负责把 AiModelRequest 转成兼容 Chat Completions 请求,再把普通响应或 SSE 片段转回 starter 统一响应对象。

应用默认提供 local-account-pool 配置实例,默认关闭。启用时只需要指向本地兼容服务地址:

yaml
spring:
  open:
    ai:
      model:
        default-provider: local-account-pool
        providers:
          local-account-pool:
            provider: account-pool
            enabled: true
            model: private-chat
            base-url: http://127.0.0.1:8000/v1
            api-key: ${LOCAL_ACCOUNT_POOL_API_KEY:}
            options:
              chat-completions-path: /chat/completions
              embeddings-path: /embeddings
              models-path: /models
              evals-path: /evals
              eval-path: /evals/{eval_id}
              eval-runs-path: /evals/{eval_id}/runs
              eval-run-path: /evals/{eval_id}/runs/{run_id}
              eval-run-output-items-path: /evals/{eval_id}/runs/{run_id}/output_items

如果需要在多个已授权凭证或多个兼容端点之间治理流量,把凭证放到 AI 模块的数据库态凭证池,并把 Provider 配置实例的 credential-pool.strategy 设置为 health-weighted。运行时 AiModelConfigResolverAdapter 会在调用前选出本次凭证并注入 baseUrl / apiKey / optionsAccountPoolAiModelProvider 仍保持纯 HTTP 转发边界。

上游凭证池

Provider 可以启用上游凭证池,在同一个 Provider 配置实例下维护多组已授权 API Key、BYOK 或自建兼容端点。凭证池用于快速实现多 Key 容量分摊、供应商额度隔离、企业专属入口和后续后台运营接入;它只面向可授权、可审计的服务端 API 凭证与兼容端点。

yaml
spring:
  open:
    ai:
      model:
        providers:
          deepseek:
            provider: openai-compatible
            model: deepseek-chat
            credential-pool:
              enabled: true
              strategy: priority
              credentials:
                - name: deepseek-main
                  source-type: api-key
                  base-url: https://api.deepseek.com
                  api-key: ${DEEPSEEK_API_KEY_MAIN:}
                  priority: 10
                  weight: 5
                - name: deepseek-backup
                  source-type: api-key
                  base-url: https://api.deepseek.com
                  api-key: ${DEEPSEEK_API_KEY_BACKUP:}
                  priority: 20
                  weight: 1

选择策略:

  • priority:优先选择 priority 最大的启用凭证;优先级相同时权重更大的排前,再按名称稳定排序。
  • weighted:先锁定最高 priority 分层,再按该分层内启用凭证的正权重做稳定哈希分配,避免每次调用随机跳动,便于审计和复现;权重为 0 的凭证不会被分配流量。
  • health-weighted:Open Platform 运行时治理策略,按凭证健康分计算有效权重并做加权随机调度;冷却中或低于最低健康分的凭证不会进入候选集合。

选中的凭证会覆盖本次调用的 baseUrlapiKey 和同名 options,并把 credentialNamecredentialSourceTypecredentialSelectionStrategy 写入 Provider metadata,供 Open Platform / AI Gateway 后续用量事件、成本分析和故障排查复用。

AI 模块也提供数据库态凭证池,适合在 Admin 运营台动态管理上游 API Key、BYOK 或自建兼容端点。后台接口位于 /api/v1/admin/ai/platform/providers/{providerName}/credentials,支持查询、保存和删除 Provider 下的多组凭证;API Key 使用 spring.open.ai.secret.encryption-key 加密落库到 ai_provider_credential,列表响应只返回 apiKeyConfigured、凭证名称、来源类型、baseURL、优先级、权重、配置 key 和公开 metadata,不返回密钥明文。

运行时 AiModelConfigResolverAdapter 会在本地 Provider 配置和 ai_provider_config 覆盖之上叠加已启用的数据库凭证。Provider 配置中的 credentialSelectionStrategy 决定数据库凭证池使用 priorityweighted 还是 health-weighted 策略;选中的凭证会覆盖本次调用的 baseURL / API Key / options,并把 upstreamCredentialNameupstreamCredentialSourceTypecredentialSelectionStrategy 固化到 AI Gateway usage event。启用 health-weighted 时,响应 metadata 还会携带 credentialHealthScorecredentialScheduleReason 和候选摘要,方便后续审计和排障。

Log Provider

Log Provider 面向本地联调、网关 contract、计量和审计链路冒烟验证,不依赖任何外部模型服务:

yaml
spring:
  open:
    ai:
      model:
        default-provider: log
        providers:
          log:
            provider: log
            model: log-chat
            options:
              response-content: "[log] request accepted"
              include-prompt-in-response: false
              log-prompt: false

常用扩展选项:

配置默认值说明
options.response-content[log] request accepted固定响应内容
options.include-prompt-in-responsefalse是否把最后一条用户消息拼到响应里,仅建议测试时开启
options.log-promptfalse是否记录 prompt 内容,默认关闭,避免日志泄露敏感输入

Simulated Provider

Simulated Provider 面向低成本联调和故障演练。它不访问外部模型服务,不消耗真实 token,也不读取 Knowledge 或业务数据;调用方仍然通过标准 AiModelManager.chat(...) / stream(...) 消费它,因此可以用于 Knowledge Chat、AI Gateway、前端流式展示、usage 记录、fallback 和审计链路的完整联调。

yaml
spring:
  open:
    ai:
      model:
        default-provider: simulated
        providers:
          simulated:
            provider: simulated
            enabled: true
            model: simulated-chat
            options:
              mode: echo
              response-content: "[simulated] request accepted"
              include-prompt-in-response: false
              latency-ms: 0
              failure-type:
              stream-chunk-size: 12

常用扩展选项:

配置默认值说明
options.modeecho响应模式:echo 回显最后一条用户消息,template 使用固定模板并拼接用户消息,empty 返回空内容
options.response-content[simulated] request acceptedtemplate 模式或显式拼接时使用的固定响应内容
options.include-prompt-in-responsefalseecho 模式下是否把最后一条用户消息拼到响应中
options.latency-ms0模拟调用延迟,适合验证前端 loading、超时和并发隔离
options.failure-type模拟失败类型:rate-limittimeoutprovider-unavailableupstream-error
options.stream-chunk-size12流式响应每个 delta 的最大字符数

Fallback

Provider fallback 用于上游模型服务短时失败、限流或不可用时切换到备用 Provider:

yaml
spring:
  open:
    ai:
      model:
        default-provider: primary
        fallback-providers:
          - mock
        providers:
          primary:
            provider: openai-compatible
            model: chat-fast
            display-name: Chat Fast
            capabilities:
              - chat
              - stream
            context-window: 128000
            max-output-tokens: 8192
            fallback-providers:
              - mock
          mock:
            provider: mock
            model: mock-chat

执行顺序:

  1. 优先使用请求指定 Provider 或 default-provider
  2. 如果当前 Provider 配置了 fallback-providers,优先使用当前 Provider 的 fallback 顺序。
  3. 如果当前 Provider 没有配置 fallback,则使用全局 fallback-providers
  4. fallback 只切换 Provider 配置,不复用主 Provider 的密钥、地址和扩展选项。

错误映射

AI Model starter 会把 Provider 运行时异常映射为统一的 AiModelError,并通过 AiModelException#getError() 暴露给上层网关。

AiModelError 主要字段:

字段说明
type错误类型,如 rate_limittimeoutauthenticationprovider_unavailable
provider发生错误的 Provider
model发生错误的模型
status上游 HTTP 状态码,适合 HTTP Provider 填充
upstreamCode上游错误码
upstreamMessage上游错误摘要
retryable是否适合 fallback 或稍后重试

常见 HTTP 状态会被归一为稳定错误类型:

HTTP 状态错误类型
400 / 422invalid_request
401authentication
403authorization
404model_not_found
408timeout
429rate_limit
5xxprovider_unavailable

后续 OpenAI Compatible、Claude / Anthropic Messages、Codex / Responses API 网关应基于这个错误 contract 转换各自协议的错误响应,不在 Controller 中重复判断第三方异常。

和 AI 模型平台的关系

spring-open-starter-ai-model 只负责“怎么调用模型”。spring-open-module-ai 负责“怎么运营平台”:

  • 供应商管理
  • 模型目录和模型别名
  • 用户 API Key
  • OpenAI Compatible 网关
  • Claude Code / Anthropic Messages 网关
  • Codex / Responses API 网关
  • Token 计量
  • 余额 / 套餐扣费
  • 成本、售价和毛利
  • Admin / App / PC 控制台

业务模块通过 starter 的 Manager / Provider contract 调用模型,不直接依赖第三方 SDK。

Translate starter 的 ai-model Provider 也是这个边界的一个消费方:Translate 负责文本、语言、格式提示和占位符保护,AI Model starter 负责模型路由、Provider 调用和 token usage 返回。翻译结果会把实际 Provider、模型、结束原因和 token 用量写入 TranslateResult.metadata(),方便后台预览、审计和后续计量归集。

验证

bash
./mvnw -pl spring-open-starters/spring-open-starter-ai-model -am test -DskipITs

Released under the Apache License 2.0.