This commit is contained in:
aruo
2026-05-31 21:45:14 +08:00
parent d4b5015beb
commit ac08345369
67 changed files with 11120 additions and 387 deletions
@@ -0,0 +1,42 @@
# ChatModel + Embedding 解耦 Design
## 架构摘要
当前代码直接使用 DashScope 具体实现类 → 改为面向 Spring AI 抽象接口编程,通过 Spring Boot 自动注入切换实现。
## 关键决策
- ChatModel:Spring Boot Starter 自动注册 Bean,通过 `@Autowired ChatModel` 注入,不再手动工厂创建
- EmbeddingModel:Spring Boot Starter 自动注册 Bean,通过 `@Autowired EmbeddingModel` 注入,替代 DashScope TextEmbedding SDK
- RagService 流式对话:用 `ChatModel.stream(Prompt)` 返回 `Flux<ChatResponse>` 替代 DashScope Generation
- VECTOR_DIM:从 `application.yml` 配置读取,替代 `MilvusConstants.VECTOR_DIM` 常量
## 模块地图
| 模块 | 职责 | 改动 |
| --- | --- | --- |
| ChatService | 封装 ChatModel + ReactAgent | 删除工厂方法,注入 ChatModel |
| ChatController | HTTP API 入口 | 删除 DashScope import,使用注入 ChatModel |
| AiOpsService | 多 Agent 协作 | DashScopeChatModel → ChatModel |
| VectorEmbeddingService | 向量化 | DashScope SDK → EmbeddingModel 接口 |
| RagService | RAG 流式对话 | DashScope Generation → ChatModel.stream() |
| MilvusConstants | Milvus 常量 | VECTOR_DIM 改为配置化 |
| MilvusProperties | Milvus 配置 | 新增 vectorDim 字段 |
| ModelRoutingConfig | 模型路由 | 新增:yml 关键字驱动的 @Primary 路由(Bean 名 > 类名 > 回退) |
| SiliconFlowEmbeddingConfig | Embedding | 新增:独立 OpenAiApi → SiliconFlow, BGE-M3 |
| application.yml | 配置 | 新增 vector-dim 配置项 |
## 接口影响
- 级别:L2 内部接口(所有消费者在同一实现范围内)
- 判级原因:方法签名从具体类改为接口,调用方需同步修改,但都在本项目内
- 不改变外部 API(/api/chat, /api/chat_stream, /api/ai_ops 的 HTTP 响应不变)
## 架构风险
- RagService 流式适配最复杂:DashScope Generation 返回 Flowable<GenerationResult>,Spring AI ChatModel.stream() 返回 Flux<ChatResponse>,需适配 StreamCallback 接口
- 缓解:Spring AI 的 Flux 与项目已有的 SSE 推送逻辑天然兼容
- ChatModel Bean 冲突:多 starter 并存时需 @Primary 或条件注解区分默认实现
- 缓解:通过 ModelRoutingConfig 集中管理,@Primary 声明默认 Bean;跨厂商时只改 `@Qualifier` 名
- DashScopeConfig 通用性:`spring.ai.dashscope.chat.options.timeout` 是厂商绑定配置键
- 缓解:本次保留该配置(只做解耦不换实现);换模型时改配置键
@@ -0,0 +1,50 @@
# ChatModel + Embedding 解耦 Proposal
## 问题
项目 5 个 Java 文件硬编码 DashScope 具体实现类,而非 Spring AI 抽象接口:
- ChatService/ChatController/AiOpsService:方法签名用 `DashScopeChatModel` 而非 `ChatModel`
- VectorEmbeddingService:完全绕过 Spring AI,直接用 DashScope SDK 的 `TextEmbedding`
- RagService:完全绕过 Spring AI,直接用 DashScope SDK 的 `Generation`(流式对话)
导致替换 LLM 或 Embedding 模型需要改代码而非改配置。
## 建议方案
**面向 Spring AI 报表接口编程**:
- Chat 部分:`DashScopeChatModel` → `ChatModel` 接口,通过 Spring Boot 自动注入
- Embedding 部分:DashScope SDK `TextEmbedding` → Spring AI `EmbeddingModel` 接口
- RagService 流式对话:DashScope SDK `Generation` → Spring AI `ChatModel` 流式接口 (`stream()`)
通过 Spring Boot Starter + `application.yml` 配置切换模型实现,无需改代码。
## 范围
- 本次要做:
- ChatService:删除 `createDashScopeApi()` / `createChatModel()` 工厂方法,改为注入 `ChatModel`
- ChatController:删除 DashScope import 和手动构建,改为使用注入的 `ChatModel`
- AiOpsService:方法签名 `DashScopeChatModel` → `ChatModel`
- VectorEmbeddingService:DashScope SDK → Spring AI `EmbeddingModel`
- RagService:DashScope SDK `Generation` → Spring AI `ChatModel` stream
- DashScopeConfig:通用化配置(保留 DashScope starter 配置,但代码层不再硬编码 DashScope 类)
- application.yml:保持现有 DashScope 配置,增加模型切换说明
- ModelRoutingConfig:新增 `@Configuration` + `@Primary` 集中路由,支持 Chat/Embedding 跨厂商混合
- 本次不做:
- 不替换 DashScope 为其他提供商(只做解耦,不换实现)
- 不修改 Agent Framework 本身
- 不改 Milvus 相关代码
- 不改 MCP 客户端配置
## 关键约束
- ReactAgent.builder().model() 已接受 ChatModel 接口(已验证)
- Spring AI 的 EmbeddingModel 接口可替代 DashScope TextEmbedding
- Spring AI 的 ChatModel.stream() 可替代 DashScope Generation 流式接口
- DashScope starter 仍需保留作为默认实现(通过 pom 依赖 + yml 配置)
## 风险
- RagService 流式对话的迁移可能最复杂:DashScope SDK 返回 RxJava Flowable,Spring AI ChatModel.stream() 返回 Flux,需要适配 SSE 推送逻辑
- VectorEmbeddingService 维度可能变化:DashScope text-embedding-v4 输出 1024 维,替换模型后维度不同,需要同步修改 Milvus VECTOR_DIM 常量
@@ -0,0 +1,30 @@
# ChatModel + Embedding 解耦 Specs
## 可观察行为规格
### S1: Chat 接口不变
- `/api/chat`, `/api/chat_stream`, `/api/ai_ops` 的 HTTP 入参/出参/响应结构完全不变
- 功能行为不变:工具调用、Agent 协作、SSE 流式推送照旧工作
### S2: 模型切换只需改配置
- 替换 DashScope starter 为 OpenAI starter + 改 yml 配置 → ChatModel 自动注入不同实现
- 替换 embedding 模型只需改 yml 的 `dashscope.embedding.model` 和 `milvus.vector-dim`
- 不需要改任何 Java 代码
### S3: VECTOR_DIM 从配置读取
- `MilvusClientFactory.createBizCollection()` 使用 MilvusProperties.getVectorDim() 而非 MilvusConstants.VECTOR_DIM
- 切换 embedding 模型后改 yml 的 `milvus.vector-dim` 即可适配新维度
### S4: VectorEmbeddingService 行为不变
- generateEmbedding/generateEmbeddings/generateQueryVector 的签名和返回类型不变
- 内部实现从 DashScope SDK 切换到 Spring AI EmbeddingModel
### S5: RagService 流式对话行为不变
- queryStream 方法签名和 StreamCallback 接口不变
- 内部实现从 DashScope Generation 切换到 Spring AI ChatModel.stream()
### S6: 混合厂商路由支持(yml 驱动)
- `model-routing.chat` / `model-routing.embedding` 声明启用哪个模型
- ModelRoutingConfig 按关键字匹配 Bean:Bean 名优先 → 类名兜底 → 回退第一个
- 切换示例:`chat: deepseek` → `chat: openai`,只改 yml
- Service 代码零改动
@@ -0,0 +1,38 @@
# ChatModel + Embedding 解耦 Tasks
## 需求追踪
| 需求 | 状态 | 备注 |
| --- | --- | --- |
| ChatService 解耦 DashScopeChatModel | ✅ 已完成 | 改为注入 ChatModel |
| ChatController 解耦 DashScope | ✅ 已完成 | 删除手动构建逻辑 |
| AiOpsService 解耦 DashScopeChatModel | ✅ 已完成 | 方法签名改为 ChatModel |
| VectorEmbeddingService 解耦 DashScope SDK | ✅ 已完成 | 改为注入 EmbeddingModel |
| RagService 解耦 DashScope Generation | ✅ 已完成 | 改为 ChatModel.stream() |
| VECTOR_DIM 配置化 | ✅ 已完成 | 从 yml 读取 |
| 混合厂商路由 | ✅ 已完成 | ModelRoutingConfig + @Primary |
| SiliconFlow Embedding | ✅ 已完成 | SiliconFlowEmbeddingConfig + BGE-M3 |
## 实现任务
- [x] T1: MilvusProperties 新增 vectorDim 字段 + getter/setter,application.yml 新增 `milvus.vector-dim: 1024`
- [x] T2: MilvusConstants.VECTOR_DIM 改为从 MilvusProperties 动态读取(MilvusClientFactory 传入)
- [x] T3: ChatService — 删除 createDashScopeApi/createChatModel/createStandardChatModel,新增 @Autowired ChatModel;createReactAgent 参数改为 ChatModel
- [x] T4: ChatController — 删除 DashScope import 和手动构建(行83-84, 171-172, 292-301),改为使用注入 ChatModel 或 ChatService 传入
- [x] T5: AiOpsService — executeAiOpsAnalysis/buildPlannerAgent/buildExecutorAgent 参数类型 DashScopeChatModel → ChatModel
- [x] T6: VectorEmbeddingService — 删除 DashScope SDK import + TextEmbedding 字段 + @PostConstruct init(),改为 @Autowired EmbeddingModel;generateEmbedding 改为调用 EmbeddingModel.embed()
- [x] T7: RagService — 删除 DashScope SDK import + Generation 字段 + Constants.apiKey,改为 @Autowired ChatModel;generateAnswerStream 改为 ChatModel.stream(Prompt) + Flux 适配 StreamCallback
- [x] T8: 新增 ModelRoutingConfig — @Configuration + @Primary ChatModel / EmbeddingModel Bean,集中管理模型路由(List<T> 自检 + 类名筛选)
- [x] T9: 新增 SiliconFlowEmbeddingConfig — 独立 OpenAiApi → SiliconFlow,BGE-M3 1024 维
## 最终状态
| 模型 | 厂商 | Spring AI 实现 | Bean |
|---|---|---|---|
| Chat | DeepSeek V4 Flash | `DeepSeekChatModel` (原生) | `deepSeekChatModel` |
| Embedding | BGE-M3 | `OpenAiEmbeddingModel` → SiliconFlow | `siliconFlowEmbeddingModel` |
| 路由 | — | `ModelRoutingConfig` | `chatModel` + `embeddingModel` @Primary |
### 验证
- `ChatAndEmbeddingSmokeTest`: 5/5 ✅
- `FullPipelineSmokeTest`: 5/5 ✅ (Chat + Embedding + Milvus 全链路)