|
|
@@ -11,11 +11,12 @@
|
|
|
1. [背景与现状](#1-背景与现状)
|
|
|
2. [Dify 依赖全景](#2-dify-依赖全景)
|
|
|
3. [替代方案评估矩阵](#3-替代方案评估矩阵)
|
|
|
-4. [推荐方案:模块化混合替换](#4-推荐方案模块化混合替换)
|
|
|
-5. [分阶段实施计划](#5-分阶段实施计划)
|
|
|
-6. [风险评估与应对](#6-风险评估与应对)
|
|
|
-7. [成本收益分析](#7-成本收益分析)
|
|
|
-8. [决策树](#8-决策树)
|
|
|
+4. [推荐方案:Spring AI + AxonHub 分层替换](#4-推荐方案spring-ai--axonhub-分层替换)
|
|
|
+5. [Dify 全功能可替代性结论](#5-dify-全功能可替代性结论)
|
|
|
+6. [分阶段实施计划](#6-分阶段实施计划)
|
|
|
+7. [风险评估与应对](#7-风险评估与应对)
|
|
|
+8. [成本收益分析](#8-成本收益分析)
|
|
|
+9. [决策树](#9-决策树)
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -180,56 +181,114 @@ OpenClaw 的流行不代表它适合替换 Dify。两者定位完全不同:
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 4. 推荐方案:模块化混合替换
|
|
|
+## 4. 推荐方案:Spring AI + AxonHub 分层替换
|
|
|
|
|
|
-### 4.1 架构演进
|
|
|
+### 4.1 最终架构(2026-07-20 决策)
|
|
|
|
|
|
```
|
|
|
-当前架构:
|
|
|
-┌─────────────────────────────────────────────────────────────┐
|
|
|
-│ Frontend │
|
|
|
-│ chat.vue → AIChatController → AIService → Dify → LLM API │
|
|
|
-└─────────────────────────────────────────────────────────────┘
|
|
|
-
|
|
|
-目标架构:
|
|
|
-┌─────────────────────────────────────────────────────────────┐
|
|
|
-│ Frontend │
|
|
|
-│ chat.vue → AIChatController → LLMService │
|
|
|
-│ ├─ DeepSeekLLMService │
|
|
|
-│ ├─ RAGService (pgvector) │
|
|
|
-│ └─ ContextStrategy │
|
|
|
-│
|
|
|
-│ 本地持久化:ChatMirrorService (转正) │
|
|
|
-│ 本地记忆:AiConversationSummary + AiUserFact (来源替换) │
|
|
|
-│ 本地推荐:RecommendationService (已有) │
|
|
|
-└─────────────────────────────────────────────────────────────┘
|
|
|
+升级前:
|
|
|
+┌──────────────────────────────────────────────────────────────┐
|
|
|
+│ Frontend │
|
|
|
+│ chat.vue → AIChatController → AIService → Dify → LLM API │
|
|
|
+│ (应用层+路由层一体) │
|
|
|
+└──────────────────────────────────────────────────────────────┘
|
|
|
+
|
|
|
+升级后:
|
|
|
+┌──────────────────────────────────────────────────────────────┐
|
|
|
+│ Frontend │
|
|
|
+│ chat.vue → AIChatController → LLMService (Spring AI) │
|
|
|
+│ ├─ ChatClient (Chat) │
|
|
|
+│ ├─ @Tool (Function Calling) │
|
|
|
+│ ├─ VectorStore (RAG) │
|
|
|
+│ └─ MemoryAdvisor (记忆) │
|
|
|
+│ │ │
|
|
|
+│ ▼ │
|
|
|
+│ AxonHub (模型路由层) │
|
|
|
+│ axonhub.iwintrue.com │
|
|
|
+│ ├─ 模型分发 / 自动降级 │
|
|
|
+│ ├─ 用量计费 / 密钥管理 │
|
|
|
+│ └─ 多模型统一网关 │
|
|
|
+│ │ │
|
|
|
+│ ┌────────────────────┼──────────────────┐ │
|
|
|
+│ ▼ ▼ ▼ │
|
|
|
+│ DeepSeek Qwen 本地模型 │
|
|
|
+│ │
|
|
|
+│ 本地持久化: │
|
|
|
+│ ├─ ChatMirrorService (对话缓存,转正) │
|
|
|
+│ ├─ ChatMemory (JDBC/Redis 持久化) │
|
|
|
+│ ├─ sqlite-vec (知识库向量存储) │
|
|
|
+│ └─ docling / unstructured (复杂PDF预处理,Python脚本) │
|
|
|
+└──────────────────────────────────────────────────────────────┘
|
|
|
+
|
|
|
+分层职责:
|
|
|
+┌──────────────┬──────────────────┬──────────────────────────────┐
|
|
|
+│ 层 │ 技术 │ 职责 │
|
|
|
+├──────────────┼──────────────────┼──────────────────────────────┤
|
|
|
+│ AI 应用层 │ Spring AI │ 对话、RAG、Tool Calling、 │
|
|
|
+│ │ │ 记忆管理、多模型编排、MCP │
|
|
|
+├──────────────┼──────────────────┼──────────────────────────────┤
|
|
|
+│ 模型路由层 │ AxonHub │ 模型分发、自动降级、 │
|
|
|
+│ │ (axonhub.iwintrue.com) │ 用量计费、统一网关 │
|
|
|
+├──────────────┼──────────────────┼──────────────────────────────┤
|
|
|
+│ 文档预处理 │ docling / │ 复杂PDF/表格/多栏布局解析 │
|
|
|
+│ │ unstructured │ │
|
|
|
+└──────────────┴──────────────────┴──────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 4.2 核心替换策略
|
|
|
|
|
|
-#### 4.2.1 新增接口层
|
|
|
+#### 4.2.1 Spring AI ChatClient 封装(替代手写 LLMService)
|
|
|
|
|
|
```java
|
|
|
-// 新增抽象接口,AIService 改为其中一个实现
|
|
|
-public interface LLMService {
|
|
|
- ChatResult sendChat(ChatRequest request);
|
|
|
- ChatResult sendChatWithStream(ChatRequest request);
|
|
|
- String getProviderName();
|
|
|
- boolean isAvailable();
|
|
|
-}
|
|
|
-
|
|
|
-// Dify 实现(保留作降级通道)
|
|
|
-@Component
|
|
|
-public class DifyLLMService implements LLMService { ... }
|
|
|
-
|
|
|
-// 直接 LLM API 实现(主通道)
|
|
|
-@Component
|
|
|
-@Primary
|
|
|
-public class DirectLLMService implements LLMService {
|
|
|
- // 调用 DeepSeek / Qwen / GLM 的 /v1/chat/completions
|
|
|
+@Service
|
|
|
+public class LLMService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ChatClient chatClient; // Spring AI 自动配置
|
|
|
+
|
|
|
+ @Resource @Qualifier("openAiChatModel")
|
|
|
+ private ChatModel deepSeekModel; // → AxonHub → DeepSeek
|
|
|
+
|
|
|
+ @Resource @Qualifier("dashScopeChatModel")
|
|
|
+ private ChatModel qwenModel; // → AxonHub → Qwen
|
|
|
+
|
|
|
+ // 默认聊天
|
|
|
+ public String chat(String query, String systemPrompt, String conversationId) {
|
|
|
+ return chatClient.prompt()
|
|
|
+ .system(systemPrompt)
|
|
|
+ .user(query)
|
|
|
+ .advisors(new MessageChatMemoryAdvisor(chatMemory, conversationId, 10))
|
|
|
+ .call()
|
|
|
+ .content();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 工作流各节点可用不同模型
|
|
|
+ public String chatWithModel(String query, String systemPrompt,
|
|
|
+ String conversationId, ChatModel model) {
|
|
|
+ return ChatClient.builder(model).build()
|
|
|
+ .prompt()
|
|
|
+ .system(systemPrompt)
|
|
|
+ .user(query)
|
|
|
+ .call()
|
|
|
+ .content();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 多模型编排
|
|
|
+ public String executeWorkflow(String input) {
|
|
|
+ String intent = ChatClient.builder(deepSeekModel).build()
|
|
|
+ .prompt().user("分类: " + input).call().content();
|
|
|
+ return ChatClient.builder(qwenModel).build()
|
|
|
+ .prompt().system("分析专家").user(intent).call().content();
|
|
|
+ }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
+对比原方案的手写 `DirectLLMService`,Spring AI 省去了:
|
|
|
+- 自己维护 HTTP 调用(Spring AI 内置)
|
|
|
+- 自己解析 JSON 响应(`StructuredOutput` 直接转 POJO)
|
|
|
+- 自己处理流式(`Flux<String>` 原生)
|
|
|
+- 自己实现重试/降级(Advisors 链式扩展)
|
|
|
+
|
|
|
#### 4.2.2 System Prompt 外部化
|
|
|
|
|
|
从 Dify 应用配置迁移到本地:
|
|
|
@@ -254,7 +313,36 @@ ai:
|
|
|
temperature: 0.3
|
|
|
```
|
|
|
|
|
|
-#### 4.2.3 Workflow 拆解
|
|
|
+#### 4.2.3 AxonHub 模型路由配置
|
|
|
+
|
|
|
+所有模型调用统一经 AxonHub 网关,不直连任何 Provider:
|
|
|
+
|
|
|
+```yaml
|
|
|
+# application.yml
|
|
|
+spring:
|
|
|
+ ai:
|
|
|
+ openai: # 默认模型 → AxonHub → DeepSeek
|
|
|
+ base-url: https://axonhub.iwintrue.com/v1
|
|
|
+ api-key: ${AXONHUB_API_KEY}
|
|
|
+ chat:
|
|
|
+ options:
|
|
|
+ model: deepseek-chat
|
|
|
+ temperature: 0.7
|
|
|
+ dashscope: # 第二模型 → AxonHub → Qwen
|
|
|
+ api-key: ${AXONHUB_API_KEY}
|
|
|
+ chat:
|
|
|
+ options:
|
|
|
+ model: qwen-max
|
|
|
+ ollama: # 本地模型 (不经过 AxonHub)
|
|
|
+ base-url: http://localhost:11434
|
|
|
+ chat:
|
|
|
+ options:
|
|
|
+ model: qwen2.5:7b
|
|
|
+```
|
|
|
+
|
|
|
+AxonHub 接管原 Dify 的模型路由职责:自动分发请求到对应模型、故障时降级到备用模型、统一计费和密钥管理。Spring AI 只需指定 model 参数。
|
|
|
+
|
|
|
+#### 4.2.4 Workflow 拆解
|
|
|
|
|
|
| 当前 Dify Workflow | 替换方式 | 工作量 |
|
|
|
|--------------------|---------|--------|
|
|
|
@@ -264,11 +352,11 @@ ai:
|
|
|
| 数学判题 | 已有 Eval 兜底,永久化 | 0 天 |
|
|
|
| 食谱推荐 | 直接调 LLM API + `MealRecommendService` 聚合上下文 | 0.5 天 |
|
|
|
|
|
|
-#### 4.2.4 知识库 RAG 本地化
|
|
|
+#### 4.2.5 知识库 RAG 本地化
|
|
|
|
|
|
```
|
|
|
当前:管理端创建知识点 → DifySyncService → Dify Datasets → Dify 检索
|
|
|
-替换后:管理端创建知识点 → TextEmbeddingService → pgvector (或 sqlite-vec) → 相似度检索
|
|
|
+替换后:管理端创建知识点 → TextEmbeddingService → sqlite-vec → 相似度检索
|
|
|
```
|
|
|
|
|
|
**向量方案选择:**
|
|
|
@@ -282,9 +370,84 @@ ai:
|
|
|
|
|
|
**推荐 sqlite-vec 理由**:项目当前使用 MySQL,无法做向量检索。sqlite-vec 作为一个零配置的 SQLite 扩展,可以独立运行,不需要额外部署服务。适合当前几千条知识库的规模。
|
|
|
|
|
|
+#### 4.2.6 文档预处理(PDF 复杂解析)
|
|
|
+
|
|
|
+Dify 内置的 PDF 解析对简单文档足够,但复杂 PDF(表格、多栏布局)效果一般。可用 Python 专有工具替代:
|
|
|
+
|
|
|
+| 工具 | 说明 | 推荐度 |
|
|
|
+|------|------|--------|
|
|
|
+| **docling** (IBM) | 开源 PDF 解析,表格/多栏布局强,输出 Markdown/JSON | ⭐⭐⭐ 首选 |
|
|
|
+| unstructured.io | 商业级文档解析,多格式支持 | ⭐⭐ 次选 |
|
|
|
+| Marker | 开源 PDF 转 Markdown,精度好 | ⭐⭐ 备选 |
|
|
|
+
|
|
|
+Spring AI ETL Pipeline 处理简单文档,复杂文档走 Python 预处理脚本。
|
|
|
+
|
|
|
---
|
|
|
|
|
|
-## 5. 分阶段实施计划
|
|
|
+## 5. Dify 全功能可替代性结论
|
|
|
+
|
|
|
+### 5.1 功能对照表
|
|
|
+
|
|
|
+| 编号 | Dify 功能 | Spring AI | AxonHub | 其他工具 | 可替代? | 本项目需要? |
|
|
|
+|------|----------|-----------|---------|---------|---------|------------|
|
|
|
+| 1 | 聊天机器人 (Chatbot) | ChatClient + MemoryAdvisor | — | — | ✅ | ✅ |
|
|
|
+| 2 | 流式聊天响应 | Flux<String> | — | — | ✅ | ✅ |
|
|
|
+| 3 | 对话记忆管理 | MessageChatMemoryAdvisor | — | — | ✅ | ✅ |
|
|
|
+| 4 | 文本生成 (Completion) | ChatClient.call() | — | — | ✅ | ✅ |
|
|
|
+| 5 | **可视化工作流画布** | ❌ 无 | — | 代码编排 | ❌ **不可替代** | ❌ **不需要(只调API)** |
|
|
|
+| 6 | 工作流: LLM 节点 | ChatClient | AxonHub 路由 | — | ✅ | ✅ |
|
|
|
+| 7 | 工作流: 条件分支 | Java if/switch | — | — | ✅ | ✅ |
|
|
|
+| 8 | 工作流: 循环/迭代 | Java for/while | — | — | ✅ | ✅ |
|
|
|
+| 9 | 工作流: 代码节点 | Java 方法 | — | — | ✅ **更好** | ✅ |
|
|
|
+| 10 | 工作流: HTTP 请求 | RestTemplate/WebClient | — | — | ✅ **更好** | ✅ |
|
|
|
+| 11 | **工作流: 各节点不同模型** | @Qualifier 多 ChatModel | ✅ 统一网关 | — | ✅ **更灵活** | ✅ |
|
|
|
+| 12 | RAG: 文档分块/向量化 | ETL Pipeline | — | — | ✅ | ✅ |
|
|
|
+| 13 | RAG: 混合搜索 | 依赖 VectorStore | — | — | ⚠️ 部分 | ⚠️ 未来 |
|
|
|
+| 14 | RAG: 重排序 (Rerank) | 需手动实现 | — | — | ⚠️ 需手动 | ⚠️ 未来 |
|
|
|
+| 15 | **RAG: 复杂PDF/表格解析** | ❌ 较弱 | — | docling/unstructured | ✅ **第三方更强** | ⚠️ 未来 |
|
|
|
+| 16 | **模型路由/自动降级** | ❌ 无 | ✅ **AxonHub** | — | ✅ **更专业** | ✅ |
|
|
|
+| 17 | **模型用量计费** | ❌ 无 | ✅ **AxonHub** | — | ✅ **更专业** | ⚠️ 可选项 |
|
|
|
+| 18 | 50+ 内置工具 | @Tool 手动封装 | — | — | ⚠️ 需手动 | ❌ 不需要 |
|
|
|
+| 19 | **Prompt IDE/版本管理** | ❌ 无 | — | Git 管理 | ❌ **不可替代** | ❌ **不需要** |
|
|
|
+| 20 | **LLMOps 仪表盘** | Micrometer + Grafana | AxonHub 计费 | — | ✅ **标准化更强** | ✅ |
|
|
|
+| 21 | Token 用量追踪 | gen_ai.client.token.usage | AxonHub | — | ✅ | ✅ |
|
|
|
+| 22 | 用户反馈/标注 | 需手动实现 | — | — | ⚠️ 需手动 | ❌ 不需要 |
|
|
|
+| 23 | A/B Prompt 测试 | ❌ 无 | — | — | ❌ 不可替代 | ❌ 不需要 |
|
|
|
+| 24 | 函数调用 (Function Calling) | @Tool 注解 | — | — | ✅ **类型安全** | ✅ |
|
|
|
+| 25 | 多 Agent 协作 | Advisors + @Tool | — | — | ✅ | ❌ 不需要 |
|
|
|
+| 26 | 语音转文字 (STT) | AudioTranscription | — | — | ✅ | ❌ 不需要 |
|
|
|
+| 27 | 文字转语音 (TTS) | TextToSpeech | — | — | ✅ | ❌ 不需要 |
|
|
|
+| 28 | 图片生成 | ImageModel | — | — | ✅ | ❌ 不需要 |
|
|
|
+| 29 | 图片理解 (Vision) | ChatClient 多模态 | — | — | ✅ | ✅ |
|
|
|
+| 30 | 内容审核 | ModerationModel | — | — | ✅ | ❌ 不需要 |
|
|
|
+| 31 | SSO/RBAC | Spring Security | — | — | ✅ **更成熟** | ❌ 不需要 |
|
|
|
+| 32 | API 限流 | Spring Cloud Gateway | AxonHub | — | ✅ | ❌ 不需要 |
|
|
|
+| 33 | MCP 集成 | MCP Boot Starter | — | — | ✅ **一级支持** | ⚠️ 未来 |
|
|
|
+| 34 | 批处理 | Spring Batch | — | — | ✅ | ❌ 不需要 |
|
|
|
+
|
|
|
+### 5.2 结论
|
|
|
+
|
|
|
+```
|
|
|
+不可替代且本项目需要的功能:0 个
|
|
|
+不可替代但不需要的功能: 3 个(可视化画布、Prompt IDE、A/B 测试—因为只调 API 不需要 UI)
|
|
|
+可替代且更好的功能: 大多数(类型安全、零网络跳、Spring 原生)
|
|
|
+```
|
|
|
+
|
|
|
+## 7. 分阶段实施计划(详见独立文档)
|
|
|
+
|
|
|
+> 完整的 5 阶段 Task 级计划见 `docs/architecture/2026-07-20-SB3-upgrade-plan.md`
|
|
|
+> 设计概览见 `docs/architecture/SpringBoot3升级+Dify替代实施计划.md`
|
|
|
+
|
|
|
+### 总览
|
|
|
+
|
|
|
+| 阶段 | 内容 | 时间 |
|
|
|
+|------|------|------|
|
|
|
+| Phase 0 | 前置准备(JDK 21、依赖对齐) | 3 天 |
|
|
|
+| Phase 1 | javax → jakarta 迁移 | 5 天 |
|
|
|
+| Phase 2 | 行为适配 + Nashorn 替换 | 4 天 |
|
|
|
+| Phase 3 | Spring AI + AxonHub + Dify 替换 | 5 天 |
|
|
|
+| Phase 4 | 回归验证 + 灰度上线 | 3 天 |
|
|
|
+| **合计** | | **20 人天** |
|
|
|
|
|
|
### 阶段 1:基础设施(1 周)
|
|
|
|
|
|
@@ -409,9 +572,9 @@ Week 4
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 6. 风险评估与应对
|
|
|
+## 8. 风险评估与应对
|
|
|
|
|
|
-### 6.1 风险矩阵
|
|
|
+### 8.1 风险矩阵
|
|
|
|
|
|
| 风险 | 概率 | 影响 | 应对措施 |
|
|
|
|------|------|------|---------|
|
|
|
@@ -440,7 +603,7 @@ Week 4
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 7. 成本收益分析
|
|
|
+## 9. 成本收益分析
|
|
|
|
|
|
### 7.1 开发成本
|
|
|
|
|
|
@@ -475,7 +638,7 @@ Week 4
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 8. 决策树
|
|
|
+## 10. 决策树
|
|
|
|
|
|
```
|
|
|
需要替换 Dify?
|