本文引用的文件
本文围绕 ai-server 模块中的 LLM Provider 管理 与 模型工厂 展开,目标是帮助开发者理解:
agentscope-harness、DashScope/Ollama/OpenAI 扩展、mem0、redis 等扩展的作用;AgentModel、服务 AgentModelService、工厂 AgentModelFactory 如何协作;本项目的 Agent 子系统基于 AgentScope 2.0.4,后端是 Spring Boot 3 + MyBatis-Plus,模型配置不写 YAML,而是持久化到平台库的 agent_model / agent_model_provider 表,由前端「模型管理」界面维护。
章节来源
仓库根 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"]
图表来源
章节来源
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。章节来源
| 组件 | 职责 | 关键行为 |
|---|---|---|
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 : "读取厂商"
图表来源
章节来源
模型管理的整体流程可以拆成两条主线:
AgentModelController → AgentModelService → AgentModelMapper → PostgreSQL agent_model 表。推理主线:上层业务 → 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>
图表来源
章节来源
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 表中。
章节来源
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,删除为软删除 |
章节来源
AgentModelProvider 对应 agent_model_provider 表,主要用于前端展示可用的厂商选项。它不是 AgentScope 的 Provider 注册中心,而是平台侧的厂商元数据表。
| 字段 | 含义 |
|---|---|
name |
厂商名称 |
baseUrl |
厂商默认 Base URL |
config |
厂商级 JSON 配置 |
status |
启用状态,查询时使用 "active" |
modelsEndpoint |
厂商模型列表接口地址 |
headersJson |
厂商级请求头 |
extraJson |
厂商级扩展字段 |
type |
厂商协议类型,如 OLLAMA、OPENAI、DASHSCOPE、DEEPSEEK |
章节来源
AgentModelService 是模型管理的业务门面,提供以下能力:
DELETED。type 隔离,llm 与 embedding 各自独立默认。ModelConnectivityTester 对已保存配置发起真实调用。llm 类型默认;也可按传入 type 查询。默认模型的隔离规则非常关键:
type 可能为空;llm;embedding 默认不会清掉 llm 默认,反之亦然。章节来源
AgentModelFactory 是连接平台模型配置与 AgentScope 运行时的重要桥梁。它的核心职责是:
AgentModel 配置是否完整;provider 归一化为 AgentScope SPI 前缀;ModelCreationContext,携带 apiKey、baseUrl、stream、结构化输出选项、思考模式;ModelRegistry.resolve(modelRef, ctx) 创建实际 Model 实例。Provider 归一化规则:
| 输入 provider | 结果前缀 | 说明 |
|---|---|---|
包含 dashscope 或 阿里(忽略大小写) |
dashscope: |
使用 DashScope 原生协议 |
| 其余任何值 | openai: |
使用 OpenAI 兼容协议,通过 baseUrl 指向各厂商 |
这意味着:
openai: 前缀 + baseUrl 接入;思考模式开关:
enableThinkingOverride,优先使用该值;config JSON 中读取 enableThinking;章节来源
ModelConnectivityTester 不负责业务推理,只负责“这个模型配置能不能用”。
测试策略:
| 模型类型 | 测试方式 | 超时 | 失败处理 |
|---|---|---|---|
llm |
发送文本 "ping",取第一个流式分片后取消 |
20 秒 | 返回 success=false,不抛异常 |
embedding |
对固定短文本做一次向量化 | 20 秒 | 返回空向量时报错 |
重要特性:
latencyMs。章节来源
EmbeddingModelFactory 面向 RAG 场景,根据 provider 选择具体嵌入实现:
| provider | 嵌入实现 | 特点 |
|---|---|---|
ollama |
OllamaTextEmbedding |
本地端点,无需 apiKey |
dashscope |
DashScopeTextEmbedding |
原生 DashScope 向量模型 |
| 其他 | OpenAITextEmbedding |
OpenAI 兼容协议,靠 baseUrl 指向 |
它与 AgentModelFactory 的区别在于:
AgentModelFactory 用于 LLM 对话;EmbeddingModelFactory 用于向量嵌入;AgentModel 配置,但构造的对象不同。章节来源
控制器暴露 /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> |
章节来源
| 配置项 | 所属实体 | 是否必填 | 说明 |
|---|---|---|---|
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 的容错规则:
LLM 处理;embedding(忽略大小写)才按向量模型处理;章节来源
系统没有全局 Provider 启动时自动探测,也没有硬编码的 Provider 白名单。可用性保障主要通过三层完成:
AgentModelFactory.create 要求 modelId 和 apiKey 非空。AgentModelService 保证同一用途类型只有一个默认模型。连通性测试: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
图表来源
章节来源
步骤:
/models 接口创建模型。provider、modelId、name、type=llm、apiKey。baseUrl 通常留空;如果是 Ollama 或 OpenAI 兼容代理,填写对应 Base URL。ModelTestResultVO.success=true。/models/{id}/default。注意事项:
provider 只要包含 dashscope 或 阿里,就会走 DashScope 原生协议;openai: 兼容协议;章节来源
调用:
GET /models/{id}/default
行为:
type 确定用途类型;defaultModel=true;典型场景:
embedding 默认模型切换到新向量模型;llm 默认模型切换到新对话模型;章节来源
查询模型列表:
GET /models
返回所有未被软删除的模型,并按默认模型和创建人排序。
查询厂商列表:
GET /models/providers
返回 agent_model_provider 表中 status="active" 的厂商。
测试模型连通性:
GET /models/{id}/test
返回结构体包含:
| 字段 | 含义 |
|---|---|
success |
是否连通 |
latencyMs |
测试耗时毫秒 |
message |
失败原因摘要 |
章节来源
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"]
图表来源
章节来源
AgentModelFactory.create 都会新建轻量 Model 配置对象,不做跨请求缓存;章节来源
现象:
success=false;排查步骤:
agent_model.api_key 是否正确复制,无多余空格;agent_model.provider 包含 dashscope 或 阿里,否则会误走 openai: 前缀;/models/{id}/test 查看失败原因;根因映射:
AgentModelFactory.create 会把 apiKey 放入 ModelCreationContext;章节来源
现象:
排查步骤:
baseUrl 指向正确的 Ollama HTTP 地址;/models/{id}/test 观察耗时和错误信息。根因映射:
openai: 兼容协议接入;章节来源
现象:
排查步骤:
TimeoutException。根因映射:
openai:;describeFailure 会遍历异常链查找 TimeoutException。章节来源
现象:
embedding 默认模型,却影响了 llm 默认;type 为空,行为不符合预期。排查步骤:
agent_model.type 是 llm 还是 embedding;type 与 agent_model_provider.type;ModelTypeEnum.fromCode 判断:只有严格 embedding 才按向量模型处理;isNull(type) 分支。根因映射:
ModelTypeEnum.fromCode 将空值和未知值归一为 LLM;clearDefaultOfType 对 LLM 包含 isNull(type),对 EMBEDDING 严格按 type 匹配;buildDefaultQueryWrapper 也有相同区分。章节来源
现象:
排查步骤:
modelId 非空;apiKey 非空;provider 能被正确归一化;AgentModelFactory.create 日志和异常信息。根因映射:
ServerException(400, ...);ServerException(500, ...);章节来源
虽然 Redis 不属于 LLM Provider 本身,但文档中明确说明:
StpUtil.* 抛异常;排查步骤:
spring.data.redis.host 和 port;/models/{id}/test。章节来源
本项目将 LLM Provider 管理分为两层:
AgentModel、AgentModelProvider、AgentModelService、AgentModelController 负责持久化、CRUD、默认模型隔离和连通性测试;AgentModelFactory 借助 AgentScope SPI 将 DB 配置转换为 DashScope、OpenAI 兼容、Ollama 三类 Provider 实例。这种设计的好处是:
扩展建议:
openai: + baseUrl 接入;dashscope 或 阿里;/models/{id}/test。