LLM Provider 管理与模型工厂.md 38 KB

LLM Provider 管理与模型工厂

本文引用的文件

  • pom.xml
  • ai-server/pom.xml
  • AI_AGENT.md
  • AgentEntity.java
  • AgentModel.java
  • AgentModelProvider.java
  • ModelTypeEnum.java
  • AgentModelService.java
  • AgentModelServiceImpl.java
  • AgentModelFactory.java
  • ModelConnectivityTester.java
  • EmbeddingModelFactory.java
  • AgentModelController.java
  • application-dev.yaml

目录

  1. 引言
  2. 项目结构与定位
  3. 依赖与扩展边界
  4. 核心组件总览
  5. 架构与数据流
  6. 详细组件分析
  7. 模型配置项与枚举
  8. 可用性与健康检查策略
  9. 操作示例
  10. 依赖关系分析
  11. 性能与可观测性
  12. 问题排查指南
  13. 结论

引言

本文围绕 ai-server 模块中的 LLM Provider 管理 与 模型工厂 展开,目标是帮助开发者理解:

  • Maven 依赖中 agentscope-harness、DashScope/Ollama/OpenAI 扩展、mem0、redis 等扩展的作用;
  • 数据库实体 AgentModel、服务 AgentModelService、工厂 AgentModelFactory 如何协作;
  • 如何通过 AgentScope SPI 将 DB 中的模型配置注册为 DashScope、Ollama、OpenAI 三种 Provider;
  • 模型配置项、用途类型枚举、默认模型隔离规则;
  • 连通性测试与健康检查机制;
  • 新增一个 LLM Provider、切换默认模型、通过控制器查询模型列表和状态的完整流程。

本项目的 Agent 子系统基于 AgentScope 2.0.4,后端是 Spring Boot 3 + MyBatis-Plus,模型配置不写 YAML,而是持久化到平台库的 agent_model / agent_model_provider 表,由前端「模型管理」界面维护。

章节来源

  • AI_AGENT.md:1-60
  • AI_AGENT.md:160-180

项目结构与定位

仓库根 pom.xml 是一个聚合 POM,打包类型为 pom,包含 ai-server 与 ai-gateway 两个子模块。LLM Provider 管理与模型工厂全部位于 ai-server 模块的 com.zsjz.ai.module.agent 包下。

graph TB
    Root["根 POM<br/>zsjz-ai"] --> Server["ai-server<br/>Spring Boot 3 + AgentScope"]
    Root --> Gateway["ai-gateway<br/>Spring Cloud Gateway"]
    Server --> Controller["AgentModelController<br/>/models/*"]
    Server --> Service["AgentModelService<br/>模型配置服务"]
    Server --> Factory["AgentModelFactory<br/>AgentScope Model 工厂"]
    Server --> Tester["ModelConnectivityTester<br/>连通性测试"]
    Server --> Entities["AgentModel / AgentModelProvider"]
    Server --> EnumType["ModelTypeEnum<br/>llm / embedding"]

图表来源

  • pom.xml:1-23
  • AgentModelController.java:1-91
  • AgentModelService.java:1-70
  • AgentModelFactory.java:1-131
  • AgentModel.java:1-63
  • AgentModelProvider.java:1-43
  • ModelTypeEnum.java:1-54

章节来源

  • pom.xml:1-23
  • AI_AGENT.md:20-60

依赖与扩展边界

ai-server/pom.xml 集中声明了 AgentScope 及其扩展依赖。它们不是业务逻辑代码,而是让 Spring Boot 应用能接入不同大模型厂商或本地推理服务的运行时扩展。

依赖 作用 在本项目中的意义
agentscope-harness AgentScope 运行期入口,提供 HarnessAgent、Toolkit、中间件等基础设施 本项目不引入外部 MCP SDK(显式排除 io.modelcontextprotocol.sdk:mcp),只使用其 Agent 编排能力
agentscope-extensions-model-dashscope DashScope 原生协议的 LLM 与 Embedding 扩展 用于阿里通义 DashScope 对话与向量模型
agentscope-extensions-model-ollama Ollama 本地推理服务的扩展 用于本地 llama.cpp / Ollama 兼容端点
agentscope-extensions-model-openai OpenAI 兼容协议的扩展 作为兜底协议前缀,覆盖 OpenAI、DeepSeek、GLM、Kimi、Ollama 兼容服务等
agentscope-extensions-mem0 Agent 记忆扩展 与 Redis 配合实现会话级或用户级记忆存储
agentscope-extensions-rag-simple 简易 RAG 扩展 配合 pgvector 做模板元数据语义检索
agentscope-extensions-redis Redis 扩展 用于 mem0、缓存与会话相关能力

注意:Provider 名称不等于模型用途类型。

  • agent_model.type 表示用途:llm(对话)或 embedding(向量)。
  • agent_model_provider.type 表示厂商协议:如 OLLAMA、OPENAI、DASHSCOPE、DEEPSEEK。

章节来源

  • ai-server/pom.xml:1-200
  • AI_AGENT.md:140-180
  • ModelTypeEnum.java:1-54

核心组件总览

组件 职责 关键行为
AgentModel 持久化单个模型配置 保存 provider、modelId、apiKey、baseUrl、type、config、headersJson、extraJson、status
AgentModelProvider 持久化厂商元信息 保存 name、baseUrl、config、status、modelsEndpoint、headersJson、extraJson、type
AgentModelService 模型配置的 CRUD、默认模型、连通性测试 按 type 隔离默认模型,删除采用软删除
AgentModelFactory DB 配置 → AgentScope Model 实例 根据 provider 归一化为 dashscope: 或 openai: 前缀,构造 ModelCreationContext
ModelConnectivityTester 最小化真实调用验证连通性 对话模型 ping 首个流式分片,向量模型做一次嵌入
EmbeddingModelFactory RAG 用向量模型构建 按 provider 选择 Ollama / DashScope / OpenAI 嵌入实现
AgentModelController REST API 暴露模型管理能力 /models/providers、/models、/{id}/default、/{id}/test
AgentEntity 用户自定义 Agent 定义 携带 model、tools、skills、sandboxMode、sandboxScope 等业务字段,但不直接承载 LLM Provider 配置
classDiagram
    class AgentModel {
        +Long id
        +String provider
        +String modelId
        +String name
        +String type
        +String apiKey
        +String baseUrl
        +Boolean defaultModel
        +String config
        +String headersJson
        +String extraJson
        +StatusEnum status
    }

    class AgentModelProvider {
        +Long id
        +String name
        +String baseUrl
        +String config
        +String status
        +String modelsEndpoint
        +String headersJson
        +String extraJson
        +String type
    }

    class AgentModelService {
        +listActiveModels()
        +createModel(dto)
        +updateModel(id, dto)
        +deleteModel(id)
        +setDefaultModel(id)
        +testModel(id)
        +getDefaultModelId()
        +getDefaultModelId(type)
    }

    class AgentModelFactory {
        +create(config)
        +create(config, enableThinkingOverride)
        -resolvePrefix(provider)
        -readEnableThinking(config)
    }

    class ModelConnectivityTester {
        +test(config)
        -testChat(config)
        -testEmbedding(config)
        -describeFailure(e)
    }

    class EmbeddingModelFactory {
        +create(config)
        -buildOllama(...)
        -buildDashScope(...)
        -buildOpenAI(...)
    }

    class AgentModelController {
        +listProviders()
        +listModels()
        +createModel(dto)
        +updateModel(id, dto)
        +deleteModel(id)
        +setDefaultModel(id)
        +testModel(id)
    }

    AgentModelService --> AgentModel : "读写"
    AgentModelService --> ModelConnectivityTester : "委托测试"
    ModelConnectivityTester --> AgentModelFactory : "创建 LLM Model"
    ModelConnectivityTester --> EmbeddingModelFactory : "创建向量模型"
    AgentModelController --> AgentModelService : "调用"
    AgentModelController --> AgentModelProviderService : "读取厂商"

图表来源

  • AgentModel.java:1-63
  • AgentModelProvider.java:1-43
  • AgentModelService.java:1-70
  • AgentModelServiceImpl.java:1-198
  • AgentModelFactory.java:1-131
  • ModelConnectivityTester.java:1-139
  • EmbeddingModelFactory.java:1-144
  • AgentModelController.java:1-91

章节来源

  • AgentModel.java:1-63
  • AgentModelProvider.java:1-43
  • AgentModelService.java:1-70
  • AgentModelController.java:1-91

架构与数据流

模型管理的整体流程可以拆成两条主线:

  1. 配置主线:前端 → AgentModelController → AgentModelService → AgentModelMapper → PostgreSQL agent_model 表。
  2. 推理主线:上层业务 → AgentModelFactory → AgentScope ModelRegistry.resolve(...) → 具体 Provider(DashScope / OpenAI 兼容 / Ollama)。

    sequenceDiagram
    participant FE as "前端"
    participant C as "AgentModelController"
    participant S as "AgentModelService"
    participant M as "AgentModelMapper"
    participant DB as "PostgreSQL"
    participant F as "AgentModelFactory"
    participant MS as "ModelRegistry"
    participant P as "DashScope / OpenAI / Ollama"
    
    FE->>C: GET /models
    C->>S: listActiveModels()
    S->>M: 查询未删除模型
    M->>DB: SELECT agent_model
    DB-->>M: 模型列表
    M-->>S: 实体列表
    S-->>C: VO 列表
    C-->>FE: Result<List<ModelVO>>
    
    FE->>C: GET /models/{id}/test
    C->>S: testModel(id)
    S->>F: create(config)
    F->>MS: resolve("dashscope:"|"openai:"+modelId, ctx)
    MS->>P: 初始化 Provider
    P-->>MS: Model 实例
    MS-->>F: Model
    F-->>S: Model
    S->>S: 发起最小化调用
    S-->>C: ModelTestResultVO
    C-->>FE: Result<ModelTestResultVO>
    

图表来源

  • AgentModelController.java:32-91
  • AgentModelServiceImpl.java:40-198
  • AgentModelFactory.java:56-113
  • ModelConnectivityTester.java:66-139

章节来源

  • AgentModelController.java:32-91
  • AgentModelServiceImpl.java:40-198
  • AgentModelFactory.java:56-113

详细组件分析

AgentEntity:Agent 定义实体

AgentEntity 是用户自定义 Agent 的持久化实体,对应数据库 agent 表。它负责保存 Agent 的业务配置,例如:

  • ownerId、userId:用户归属;
  • isBuiltin:是否内置专家;
  • workspacePath:Agent 工作区路径;
  • name、description、sysPrompt:名称、描述、系统提示词;
  • model:绑定的模型标识;
  • maxIters:最大迭代次数;
  • toolsAllowJson、toolsDenyJson:工具白名单/黑名单;
  • toolPacksJson:方案绑定的工具包;
  • knowledgeBaseId:知识库 ID;
  • skillsAllowJson、skillsDenyJson:技能白名单/黑名单;
  • runAs、forkOf:执行身份与 Fork 来源;
  • skillRepositoriesJson:技能仓库配置;
  • sandboxMode、sandboxScope:沙箱模式与隔离范围。

需要特别注意:AgentEntity 并不等同于 LLM Provider 配置。它只是引用某个模型,真正的 Provider、API Key、Base URL、模型 ID 等保存在 AgentModel 表中。

章节来源

  • AgentEntity.java:1-137

AgentModel:模型配置实体

AgentModel 是 LLM Provider 管理的核心数据对象,对应 agent_model 表。关键字段如下:

字段 含义 约束与行为
provider 用户填写的 Provider 名称 会被 AgentModelFactory 归一化为 DashScope 或 OpenAI 兼容前缀
modelId 模型 ID 必填;缺失时工厂抛 400
name 模型展示名 日志与调试用
type 用途类型 llm 或 embedding;历史空值按 llm 处理
apiKey API 密钥 必填;缺失时工厂抛 400
baseUrl 基础地址 可选;DashScope 通常为空,OpenAI 兼容或 Ollama 常填本地或代理地址
defaultModel 是否默认模型 同类型互斥,设置时清除其他同类型默认
config JSON 扩展配置 支持 enableThinking 控制思考模式
headersJson 请求头扩展 JSON 字符串
extraJson 扩展字段 JSON 字符串
status 状态 使用 StatusEnum,删除为软删除

章节来源

  • AgentModel.java:1-63

AgentModelProvider:厂商实体

AgentModelProvider 对应 agent_model_provider 表,主要用于前端展示可用的厂商选项。它不是 AgentScope 的 Provider 注册中心,而是平台侧的厂商元数据表。

字段 含义
name 厂商名称
baseUrl 厂商默认 Base URL
config 厂商级 JSON 配置
status 启用状态,查询时使用 "active"
modelsEndpoint 厂商模型列表接口地址
headersJson 厂商级请求头
extraJson 厂商级扩展字段
type 厂商协议类型,如 OLLAMA、OPENAI、DASHSCOPE、DEEPSEEK

章节来源

  • AgentModelProvider.java:1-43
  • AgentModelProviderServiceImpl.java:23-42

AgentModelService:模型配置服务

AgentModelService 是模型管理的业务门面,提供以下能力:

  1. 列出启用模型:过滤已删除记录,按默认模型和创建人排序。
  2. 创建模型:生成 ID、填充默认值、写入 DB;若设为默认,则清除同类型其它默认。
  3. 更新模型:按 ID 更新;若表单标记为默认,同样清理同类型其它默认。
  4. 删除模型:软删除,将状态改为 DELETED。
  5. 设置默认模型:按 type 隔离,llm 与 embedding 各自独立默认。
  6. 测试连通性:委托 ModelConnectivityTester 对已保存配置发起真实调用。
  7. 获取默认模型 ID:优先返回 llm 类型默认;也可按传入 type 查询。

默认模型的隔离规则非常关键:

  • 历史数据中 type 可能为空;
  • 空值在查询和清除默认时都视为 llm;
  • 因此设置一个 embedding 默认不会清掉 llm 默认,反之亦然。

章节来源

  • AgentModelService.java:1-70
  • AgentModelServiceImpl.java:40-198

AgentModelFactory:AgentScope 模型工厂

AgentModelFactory 是连接平台模型配置与 AgentScope 运行时的重要桥梁。它的核心职责是:

  1. 校验 AgentModel 配置是否完整;
  2. 将 provider 归一化为 AgentScope SPI 前缀;
  3. 构造 ModelCreationContext,携带 apiKey、baseUrl、stream、结构化输出选项、思考模式;
  4. 调用 ModelRegistry.resolve(modelRef, ctx) 创建实际 Model 实例。

Provider 归一化规则:

输入 provider 结果前缀 说明
包含 dashscope 或 阿里(忽略大小写) dashscope: 使用 DashScope 原生协议
其余任何值 openai: 使用 OpenAI 兼容协议,通过 baseUrl 指向各厂商

这意味着:

  • DashScope 走原生 Provider;
  • OpenAI、DeepSeek、GLM、Kimi、Ollama 兼容端点都可以通过 openai: 前缀 + baseUrl 接入;
  • 不需要为每个兼容厂商新增 Java 类,只要其 API 符合 OpenAI 兼容协议即可。

思考模式开关:

  • 如果调用方显式传 enableThinkingOverride,优先使用该值;
  • 否则从 config JSON 中读取 enableThinking;
  • 都没有则交给各 Provider 的默认行为;
  • 该设计避免推理模型 reasoning 吃光 maxTokens,导致正文为空。

章节来源

  • AgentModelFactory.java:1-131

ModelConnectivityTester:连通性测试器

ModelConnectivityTester 不负责业务推理,只负责“这个模型配置能不能用”。

测试策略:

模型类型 测试方式 超时 失败处理
llm 发送文本 "ping",取第一个流式分片后取消 20 秒 返回 success=false,不抛异常
embedding 对固定短文本做一次向量化 20 秒 返回空向量时报错

重要特性:

  • 失败是预期结果,HTTP 返回 200,错误信息放在返回值中;
  • 超时异常被识别并翻译为“连接超时(N s),请检查网络与 Base URL”;
  • 非超时异常会提取根因消息,并限制最大长度;
  • 向量模型返回空向量被视为失败;
  • 测试耗时会记录到 latencyMs。

章节来源

  • ModelConnectivityTester.java:1-139

EmbeddingModelFactory:RAG 向量模型工厂

EmbeddingModelFactory 面向 RAG 场景,根据 provider 选择具体嵌入实现:

provider 嵌入实现 特点
ollama OllamaTextEmbedding 本地端点,无需 apiKey
dashscope DashScopeTextEmbedding 原生 DashScope 向量模型
其他 OpenAITextEmbedding OpenAI 兼容协议,靠 baseUrl 指向

它与 AgentModelFactory 的区别在于:

  • AgentModelFactory 用于 LLM 对话;
  • EmbeddingModelFactory 用于向量嵌入;
  • 两者共用 AgentModel 配置,但构造的对象不同。

章节来源

  • EmbeddingModelFactory.java:1-144

AgentModelController:REST API

控制器暴露 /models 下的模型管理能力:

方法 路径 功能 返回
GET /models/providers 查询启用的厂商列表 Result<List<ModelProviderVO>>
GET /models 查询启用的模型列表 Result<List<ModelVO>>
POST /models 创建模型 Result<ModelVO>
PUT /models/{id} 更新模型 Result<Void>
GET /models/{id} 删除模型(软删除) Result<Void>
GET /models/{id}/default 设置默认模型 Result<Void>
GET /models/{id}/test 测试模型连通性 Result<ModelTestResultVO>

章节来源

  • AgentModelController.java:1-91

模型配置项与枚举

模型配置项

配置项 所属实体 是否必填 说明
provider AgentModel 建议填写 用户自由填写;工厂按规则归一化为 DashScope 或 OpenAI 兼容
modelId AgentModel 是 模型 ID;缺失时 AgentModelFactory 抛 400
name AgentModel 否 展示名称
type AgentModel 建议填写 llm 或 embedding;空值按 llm 处理
apiKey AgentModel 是 API Key;缺失时 AgentModelFactory 抛 400
baseUrl AgentModel 否 Base URL;DashScope 通常留空,OpenAI 兼容或 Ollama 常用
defaultModel AgentModel 否 默认模型开关,同类型唯一
config AgentModel 否 JSON;支持 enableThinking
headersJson AgentModel 否 JSON;额外请求头
extraJson AgentModel 否 JSON;扩展字段
status AgentModel 自动 使用 StatusEnum,删除为软删除

用途类型枚举

ModelTypeEnum 描述模型用途,不是厂商协议:

枚举值 code 含义
LLM llm 对话模型,可用于 AI 对话与分析推理
EMBEDDING embedding 向量模型,仅供 RAG 表结构语义检索,不能用于对话

fromCode 的容错规则:

  • null、空串、未知值一律按 LLM 处理;
  • 只有严格等于 embedding(忽略大小写)才按向量模型处理;
  • 这是为了兼容历史数据和前端把空 type 视为对话模型的约定。

章节来源

  • ModelTypeEnum.java:1-54
  • AgentModel.java:1-63
  • AgentModelServiceImpl.java:114-198

可用性与健康检查策略

系统没有全局 Provider 启动时自动探测,也没有硬编码的 Provider 白名单。可用性保障主要通过三层完成:

  1. 配置完整性校验:AgentModelFactory.create 要求 modelId 和 apiKey 非空。
  2. 默认模型隔离:AgentModelService 保证同一用途类型只有一个默认模型。
  3. 连通性测试:ModelConnectivityTester 对已保存配置发起真实最小调用。

    flowchart TD
    Start(["开始测试"]) --> CheckType{"模型类型"}
    CheckType -->|llm| CreateLLM["AgentModelFactory.create(config)"]
    CheckType -->|embedding| CreateEmbed["EmbeddingModelFactory.create(config)"]
    CreateLLM --> Ping["发送 'ping',取首个流式分片"]
    CreateEmbed --> Embed["对固定文本做向量化"]
    Ping --> Timeout{"是否超时?"}
    Embed --> VectorValid{"是否返回非空向量?"}
    Timeout -->|是| FailTimeout["返回超时原因"]
    Timeout -->|否| Success["返回 success=true"]
    VectorValid -->|否| FailEmpty["返回嵌入为空"]
    VectorValid -->|是| Success
    FailTimeout --> End(["结束"])
    FailEmpty --> End
    Success --> End
    

图表来源

  • ModelConnectivityTester.java:66-139
  • AgentModelFactory.java:56-113
  • EmbeddingModelFactory.java:108-144

章节来源

  • ModelConnectivityTester.java:1-139
  • AgentModelFactory.java:56-113

操作示例

示例一:新增一个 LLM Provider

步骤:

  1. 确保后端已引入对应 AgentScope 扩展(DashScope、Ollama、OpenAI 已引入)。
  2. 打开前端「模型管理」页面或通过 /models 接口创建模型。
  3. 填写 provider、modelId、name、type=llm、apiKey。
  4. 如果是 DashScope,baseUrl 通常留空;如果是 Ollama 或 OpenAI 兼容代理,填写对应 Base URL。
  5. 点击“测试”,确认 ModelTestResultVO.success=true。
  6. 如需设为默认,调用 /models/{id}/default。

注意事项:

  • provider 只要包含 dashscope 或 阿里,就会走 DashScope 原生协议;
  • 其它值都会走 openai: 兼容协议;
  • 新增模型默认就是启用状态;
  • 如果同时勾选“设为默认”,系统会清除同类型其它默认。

章节来源

  • AgentModelController.java:32-91
  • AgentModelServiceImpl.java:60-113
  • AgentModelFactory.java:56-113

示例二:切换默认模型

调用:

GET /models/{id}/default

行为:

  • 先根据当前模型记录的 type 确定用途类型;
  • 清除该类型下其它模型的 defaultModel=true;
  • 将目标模型设为默认;
  • 另一个用途类型的默认不受影响。

典型场景:

  • 将 embedding 默认模型切换到新向量模型;
  • 将 llm 默认模型切换到新对话模型;
  • 两者互不干扰。

章节来源

  • AgentModelServiceImpl.java:114-150
  • ModelTypeEnum.java:20-54

示例三:通过 AgentModelController 查询模型列表和状态

查询模型列表:

GET /models

返回所有未被软删除的模型,并按默认模型和创建人排序。

查询厂商列表:

GET /models/providers

返回 agent_model_provider 表中 status="active" 的厂商。

测试模型连通性:

GET /models/{id}/test

返回结构体包含:

字段 含义
success 是否连通
latencyMs 测试耗时毫秒
message 失败原因摘要

章节来源

  • AgentModelController.java:32-91
  • AgentModelServiceImpl.java:40-58
  • ModelConnectivityTester.java:66-139

依赖关系分析

graph LR
    POM["ai-server/pom.xml"] --> Harness["agentscope-harness"]
    POM --> DashScope["agentscope-extensions-model-dashscope"]
    POM --> OllamaExt["agentscope-extensions-model-ollama"]
    POM --> OpenAIExt["agentscope-extensions-model-openai"]
    POM --> Mem0["agentscope-extensions-mem0"]
    POM --> RAGSimple["agentscope-extensions-rag-simple"]
    POM --> RedisExt["agentscope-extensions-redis"]

    Controller["AgentModelController"] --> Service["AgentModelService"]
    Controller --> ProviderService["AgentModelProviderService"]
    Service --> Mapper["AgentModelMapper"]
    Service --> Tester["ModelConnectivityTester"]
    Tester --> Factory["AgentModelFactory"]
    Tester --> EmbedFactory["EmbeddingModelFactory"]
    Factory --> Registry["AgentScope ModelRegistry"]

图表来源

  • ai-server/pom.xml:1-200
  • AgentModelController.java:1-91
  • AgentModelService.java:1-70
  • ModelConnectivityTester.java:1-139
  • AgentModelFactory.java:1-131
  • EmbeddingModelFactory.java:1-144

章节来源

  • ai-server/pom.xml:1-200
  • AgentModelController.java:1-91
  • AgentModelFactory.java:1-131

性能与可观测性

性能特征

  • 每次调用 AgentModelFactory.create 都会新建轻量 Model 配置对象,不做跨请求缓存;
  • 连通性测试对话模型只取首个流式分片,不等完整回复,减少 token 消耗和网络等待;
  • 连通性测试向量模型对固定短文本做一次嵌入;
  • 测试超时统一为 20 秒,既允许 Ollama 冷启动加载模型,又避免长时间阻塞;
  • 测试失败的消息长度被限制为 200 字符,便于前端展示。

可观测性

  • 模型创建成功、更新成功、删除成功、设置默认成功均有日志;
  • 模型实例构造成功记录 modelRef、name、enableThinking;
  • 连通性测试成功记录 name 和耗时;
  • 连通性测试失败记录 name、耗时、原因;
  • 思考模式 JSON 解析失败会记录警告日志,不影响主流程。

章节来源

  • AgentModelServiceImpl.java:60-198
  • AgentModelFactory.java:56-131
  • ModelConnectivityTester.java:66-139

问题排查指南

问题一:DashScope Key 无效

现象:

  • 模型创建成功;
  • 连通性测试返回 success=false;
  • 消息中包含鉴权失败、Key 无效、免费额度不足等底层 Provider 错误。

排查步骤:

  1. 确认 agent_model.api_key 是否正确复制,无多余空格;
  2. 确认 agent_model.provider 包含 dashscope 或 阿里,否则会误走 openai: 前缀;
  3. 确认 DashScope 账号权限和免费额度;
  4. 使用 /models/{id}/test 查看失败原因;
  5. 检查后端日志中“模型连通性测试失败”的 message。

根因映射:

  • AgentModelFactory.create 会把 apiKey 放入 ModelCreationContext;
  • DashScope Provider 会在首次调用时校验 Key;
  • 连通性测试捕获异常并转为结构化失败结果。

章节来源

  • AgentModelFactory.java:56-113
  • ModelConnectivityTester.java:66-139

问题二:Ollama 服务不可达

现象:

  • baseUrl 指向本地 Ollama;
  • 连通性测试超时或连接失败;
  • 本地 Ollama 进程未启动,或端口不一致。

排查步骤:

  1. 确认 Ollama 进程正在运行;
  2. 确认 baseUrl 指向正确的 Ollama HTTP 地址;
  3. 确认防火墙或容器网络允许访问该端口;
  4. 首次加载本地模型可能较慢,20 秒超时可能不够长;
  5. 使用 /models/{id}/test 观察耗时和错误信息。

根因映射:

  • Ollama 通过 openai: 兼容协议接入;
  • 连通性测试对 Ollama 也使用 20 秒超时;
  • 超时异常会被识别为“连接超时(20s),请检查网络与 Base URL”。

章节来源

  • ModelConnectivityTester.java:30-45
  • ModelConnectivityTester.java:90-139
  • AgentModelFactory.java:98-113

问题三:OpenAI 代理超时

现象:

  • baseUrl 指向第三方代理;
  • 连通性测试返回超时;
  • 网络延迟高或代理限流。

排查步骤:

  1. 确认代理地址可达;
  2. 确认代理未限流或拒绝请求;
  3. 确认代理支持 OpenAI 兼容协议;
  4. 如果代理响应慢,考虑调整连通性测试超时逻辑;
  5. 检查底层异常链中是否有 TimeoutException。

根因映射:

  • 非 DashScope provider 统一走 openai:;
  • 连通性测试使用 20 秒超时;
  • describeFailure 会遍历异常链查找 TimeoutException。

章节来源

  • AgentModelFactory.java:98-113
  • ModelConnectivityTester.java:108-139

问题四:模型枚举不生效

现象:

  • 设置了一个 embedding 默认模型,却影响了 llm 默认;
  • 或者反过来;
  • 旧数据 type 为空,行为不符合预期。

排查步骤:

  1. 确认 agent_model.type 是 llm 还是 embedding;
  2. 不要混淆 type 与 agent_model_provider.type;
  3. 检查历史数据是否为空;
  4. 使用 ModelTypeEnum.fromCode 判断:只有严格 embedding 才按向量模型处理;
  5. 默认模型清除逻辑会根据 type 决定是否包含 isNull(type) 分支。

根因映射:

  • ModelTypeEnum.fromCode 将空值和未知值归一为 LLM;
  • clearDefaultOfType 对 LLM 包含 isNull(type),对 EMBEDDING 严格按 type 匹配;
  • buildDefaultQueryWrapper 也有相同区分。

章节来源

  • ModelTypeEnum.java:20-54
  • AgentModelServiceImpl.java:114-198

问题五:新增 Provider 后模型无法创建

现象:

  • 创建模型时抛 400;
  • 提示缺少模型 ID 或 API Key;
  • 或构造 Model 时抛 500。

排查步骤:

  1. 确认 modelId 非空;
  2. 确认 apiKey 非空;
  3. 确认 provider 能被正确归一化;
  4. 确认 AgentScope 扩展已引入;
  5. 查看 AgentModelFactory.create 日志和异常信息。

根因映射:

  • 配置不完整直接抛 ServerException(400, ...);
  • ModelRegistry 解析失败抛 ServerException(500, ...);
  • pom 中必须引入对应 extension,否则 SPI 找不到前缀。

章节来源

  • AgentModelFactory.java:56-113
  • ai-server/pom.xml:1-200

问题六:Redis 不可用导致登录或会话异常

虽然 Redis 不属于 LLM Provider 本身,但文档中明确说明:

  • Redis 是 Sa-Token 的硬依赖;
  • Redis 不可用则所有 StpUtil.* 抛异常;
  • 本项目没有降级实现;
  • mem0 也依赖 Redis。

排查步骤:

  1. 检查 spring.data.redis.host 和 port;
  2. 确认 Redis 服务可连接;
  3. 检查网络、密码、ACL;
  4. 不要误以为 LLM 不通是 Redis 问题——LLM 不通主要看 /models/{id}/test。

章节来源

  • application-dev.yaml:1-87
  • AI_AGENT.md:120-160

结论

本项目将 LLM Provider 管理分为两层:

  • 平台层:AgentModel、AgentModelProvider、AgentModelService、AgentModelController 负责持久化、CRUD、默认模型隔离和连通性测试;
  • 运行时层:AgentModelFactory 借助 AgentScope SPI 将 DB 配置转换为 DashScope、OpenAI 兼容、Ollama 三类 Provider 实例。

这种设计的好处是:

  • Provider 扩展集中在 pom 中,新增 Provider 主要依赖 AgentScope 扩展,而不必大量改动业务代码;
  • 模型配置可动态管理,不需要重启服务;
  • 默认模型按用途隔离,避免对话模型和向量模型互相污染;
  • 连通性测试以结构化结果返回,适合前端展示诊断信息。

扩展建议:

  • 新增 LLM Provider 时,优先确认其是否遵循 OpenAI 兼容协议;若是,可通过 openai: + baseUrl 接入;
  • 若需 DashScope 原生能力,则确保 provider 名称命中 dashscope 或 阿里;
  • 对本地 Ollama 场景,适当评估连通性测试超时是否足够;
  • 对生产环境,建议补充更细粒度的 Provider 健康检查定时任务,而不仅依赖用户手动触发 /models/{id}/test。