第四篇:AI 模块架构设计:多 Provider 切换、RAG 知识库与 Agent 编排

0 阅读14分钟

前言

本文是 SeaPack 项目技术系列的第四篇,聚焦 AI 模块的整体架构设计与功能全景。这篇文章的目标是介绍 AI 模块「做了什么」——有哪些核心能力、各部分如何协作、解决了哪些问题。具体的实现细节会拆分到后续每篇文章中逐一展开。

访问地址http://124.222.194.201/

前端代码github.com/seapack-hub…

后端代码github.com/seapack-hub…

一、为什么需要一个 AI 模块架构

在很多 AI 项目中,最常见的做法是「对着一个模型硬编码」——用 DeepSeek 就写死 DeepSeek 的调用,想换成通义千问就得改代码、改配置、重新部署。这在原型阶段没问题,但在生产环境会遇到几个致命问题:

痛点硬编码一个模型的表现
模型切换成本高换一个 Provider 就要改代码、改配置、重新部署
向量化和文本模型混用文本对话用 A 厂商,向量化用 B 厂商,代码里到处 if-else
知识库数据散落文档解析、分片、向量化、检索各写一套,没有统一流程
Agent 扩展困难想给 Agent 加个技能,要改一堆硬编码逻辑
可观测性差不知道每次调用花了多少 Token、耗时多久、走了哪条链路

SeaPack 的 AI 模块设计目标非常明确:

一套配置切换所有 Provider,一套流程管理知识库全生命周期,一个流水线编排 Agent 执行,一条 SSE 管道流式输出所有结果。

目前是后端动态设置切换AI模型,之后可以前后端联动,由前端动态设置使用哪个大模型。

二、整体架构:一张图看懂全貌

                        ┌─────────────────────────────────────────────┐
                        │            前端 SSE 通信层                   │
                        │  useChatExecution.ts → chatExecute.ts       │
                        │  统一 Composable,根据 session.mode 自动路由 │
                        └──────────────────┬──────────────────────────┘
                                           │ fetch + ReadableStream
                                           ▼
┌──────────────────────────────────────────────────────────────────────────────────────┐
│                          AiDialogService(统一对话调度)                              │
│                                                                                      │
│   mode: streaming_llm ──→ 直接调用 LLM(通用对话)                                    │
│   mode: agent_stream ──→ Agent 四步流水线                                            │
│   mode: orchestration ─→ LLM 智能路由 → 编排 / Agent / 通用 LLM                       │
└──────────────────────────────────────────────────────────────────────────────────────┘
                                           │
              ┌────────────────────────────┼────────────────────────────┐
              ▼                            ▼                            ▼
   ┌──────────────────┐       ┌──────────────────────┐      ┌──────────────────────┐
   │ 多 Provider 配置  │      │   Agent 四步流水线    │      │   编排执行引擎        │
   │                   │      │   1. 提示词组装      │      │                       │
   │ activeProvider    │      │   2. 知识库检索      │      │ sequential / parallel │
   │ embeddingProvider │      │   3. 技能调用        │      │ dynamic orchestration │
   │ providers{}       │      │   4. LLM 流式调用    │      │                       │
   └──────────────────┘       └──────────┬───────────┘      └──────────────────────┘
              │                           │
              ▼                           ▼
   ┌──────────────────┐       ┌──────────────────────────────────────┐
   │ LangChain4j      │       │          ChromaDB 向量数据库          │
   │ 模型实例化        │       │  文档解析 → 分片 → 向量化 → 语义检索   │
   └──────────────────┘       └──────────────────────────────────────┘

三层职责划分:

层级核心组件职责
调度层AiDialogService按 mode 分发对话请求,统一取消标志和 Token 额度校验
执行层AgentTestChatService / OrchestrationExecuteServiceAgent 四步流水线 / 编排步骤执行
基础层AIProperties / AiConfig / ChromaDbConfig多 Provider 配置、模型实例化、向量存储

三、核心能力一:多 Provider 动态切换

3.1 设计目标

改一行配置,所有 AI 调用自动切换到新模型——零代码改动。

系统同时对接了三家大模型厂商(DeepSeek、阿里云通义千问、小米 MiMo),通过配置文件中的 ai.active-provider 字段决定当前使用哪个。更重要的是,文本对话模型和向量化模型可以来自不同厂商——文本追求推理能力用 MiMo,向量化追求语义表达用阿里云,两者独立配置互不干扰。

3.2 配置结构

# 当前激活的 Provider(文本对话用)
ai.active-provider=mimo

# 向量化服务使用的 Provider(可以和文本对话不同)
ai.embedding-provider=aliyun

# 各 Provider 的具体配置
ai.providers.deepseek.api-key=sk-xxx
ai.providers.deepseek.base-url=https://api.deepseek.com/v1
ai.providers.deepseek.chat-model=deepseek-chat
ai.providers.deepseek.embedding-model=text-embedding-ada-002

ai.providers.aliyun.api-key=sk-xxx
ai.providers.aliyun.base-url=https://dashscope.aliyuncs.com/compatible-mode/v1
ai.providers.aliyun.chat-model=qwen-plus
ai.providers.aliyun.embedding-model=text-embedding-v3

ai.providers.mimo.api-key=sk-xxx
ai.providers.mimo.base-url=https://api.xiaomi.com/v1
ai.providers.mimo.chat-model=mimo-v2.5

3.3 已实现的功能

功能说明
Provider 动态切换通过AIProperties + @ConfigurationProperties 自动映射配置,AiConfig 根据 activeProvider 动态创建 LangChain4j 模型 Bean
文本/向量模型分离activeProvider 控制文本对话,embeddingProvider 控制向量化,各自独立
OpenAI 协议兼容所有厂商都使用 OpenAI 兼容协议,LangChain4j 的OpenAiChatModel 一套代码通吃
Provider 身份注入自动在消息头部注入模型身份提示词,避免模型「自报错误身份」

3.4 涉及的关键类

职责
AIProperties配置属性类,映射ai.* 前缀,管理所有 Provider 配置
AiConfigSpring 配置类,根据activeProvider 创建 ChatLanguageModel / StreamingChatLanguageModel Bean
ChromaDbConfigChromaDB 配置,创建EmbeddingModel Bean,按知识库 ID 提供 EmbeddingStore
AiProviderIdentities各 Provider 的身份提示词常量

四、核心能力二:RAG 知识库

4.1 设计目标

上传文档,自动解析、分片、向量化、入库;对话时自动检索相关知识,让 Agent 拥有「领域记忆」。

RAG(Retrieval-Augmented Generation)是让大模型「知道你私有数据」的关键技术。SeaPack 实现了完整的 RAG 链路:从文档上传到语义检索,全流程异步处理,前端实时展示进度。

4.2 完整流程

用户上传文档
    │
    ▼
保存文件 → 创建文档记录 → 生成 taskToken → 触发异步向量化
                                                   │
    ┌────────────────────────────────────────────────┘
    │  异步线程 (@Async)
    │
    ├── 1. 解析文档 ──── FileParserUtil(支持 PDF / Word / TXT / Markdown)
    │
    ├── 2. 文档分片 ──── 按段落分片,可配置分片大小和重叠字符
    │
    ├── 3. 向量化 ────── 调用 EmbeddingModel 生成每个分片的向量
    │
    ├── 4. 向量入库 ──── 存入 ChromaDB(每个知识库独立 Collection)
    │                    同时写入 MySQL(记录 vectorId,支持回溯和删除)
    │
    └── 5. 更新统计 ──── 文档数、分片数、向量数等统计信息

4.3 已实现的功能

功能说明
知识库 CRUD创建、编辑、删除、复制、启停控制,支持分页查询
文档上传与解析支持 PDF、Word、TXT、Markdown,通过FileParserUtil 统一解析
异步向量化@Async 异步线程处理,不阻塞用户请求,前端实时展示进度
可配置分片每个知识库可独立设置分片大小(chunkSize)和重叠字符(chunkOverlap)
ChromaDB 向量存储每个知识库对应独立 Collectionknowledge_{id}),数据完全隔离
语义检索基于向量相似度的 top-K 检索,返回最相关的分片内容
关键词降级ChromaDB 不可用时自动降级到 MySQL 关键词匹配,保障可用性
进度追踪taskToken + VectorProgressManager,前端实时展示解析→分片→向量化进度
文档重新处理清理旧向量,重置状态,从磁盘重新读取并向量化
级联删除删除知识库时自动清理文档、分片、向量数据和磁盘文件

4.4 涉及的关键类

职责
KnowledgeBaseService知识库 CRUD、文档上传、语义检索入口
KnowledgeVectorService异步向量化核心,文档解析→分片→向量化→入库
ChromaDbConfigEmbeddingModel 创建 + EmbeddingStore 动态获取
VectorProgressManager向量化进度管理,通过 taskToken 推送实时进度
FileParserUtil多格式文档解析工具(PDF / Word / TXT / Markdown)

五、核心能力三:Agent 四步编排流水线

5.1 设计目标

Agent 不是「带 System Prompt 的聊天机器人」,而是一个完整的任务执行流水线——自动组装提示词检索知识调用技能生成回答

每个 Agent 可以关联多个提示词模板、多个知识库、多个技能。对话时系统自动完成四个步骤的编排,每步执行前用户都可以取消。

5.2 四步流水线

用户消息: "帮我查一下最近一周的股票行情"
    │
    ▼
┌─────────────────────────────────────────────────────────────────┐
│                 Agent 四步编排流水线                             │
│                                                                 │
│  Step 1: 提示词组装 (prompt_assembly)                            │
│  ├── 加载 Agent 基础 system_prompt                               │
│  ├── LLM 动态选择相关模板(从 Agent 关联的模板池中)               │
│  └── 拼接: system_prompt + selected_templates                    │
│                                                                 │
│  Step 2: 知识库检索 (knowledge_retrieval)                        │
│  ├── 遍历 Agent 关联的知识库列表                                  │
│  ├── 对每个知识库执行 ChromaDB 向量检索 top-K                     │
│  └── 拼接: system_prompt + 【参考知识】                          │
│                                                                 │
│  Step 3: 技能调用 (skill_execution)                              │
│  ├── LLM 智能选择技能(从 Agent 关联的技能池中)                   │
│  ├── LLM 提取参数(根据 inputSchema + 用户消息)                  │
│  ├── HTTP 调用技能 endpoint                                      │
│  └── 拼接: system_prompt + 【技能执行结果】                       │
│                                                                 │
│  Step 4: LLM 流式调用 (llm_call)                                 │
│  ├── 组装完整 messages(system + history + user)                │
│  ├── 流式调用 LLM API                                            │
│  └── 逐 token 通过 SSE 推送给前端                                │
│                                                                 │
│  完成后: 组装 TraceSnapshot → 保存会话记录 → 统计 Token           │
└─────────────────────────────────────────────────────────────────┘

5.3 已实现的功能

功能说明
LLM 动态选择模板不是全部加载,而是让** LLM 根据用户意图从模板池中选择最相关的模板**
LLM 动态选择技能LLM 从 Agent 关联的技能池中选择最匹配的技能,避免全部执行
LLM 智能参数提取根据技能的 inputSchema,LLM 自动从用户消息中提取结构化参数
知识库检索集成自动遍历 Agent 关联的所有知识库,向量检索后拼接到提示词中
技能策略模式SkillHandler 接口 + Spring 自动注册,支持 LLM / HTTP / 文件生成等多种技能类型
Step 间取消检查每个步骤执行前检查 cancelFlag,用户可随时终止
链路追踪(Trace Snapshot)完整记录每步的输入、输出、耗时、Token 消耗,存入数据库
场景级配置覆盖Agent 在不同场景下可覆盖模型、temperature、maxTokens 等参数
对话记忆支持滑动窗口记忆,保留最近 N 轮对话上下文

5.4 涉及的关键类

职责
AgentTestChatServiceAgent 四步流水线编排核心,管理完整的对话执行链路
AgentSkillExecutor技能执行引擎:LLM 选择技能 → LLM 提取参数 → HTTP 调用 endpoint
SkillHandler技能执行器策略接口,各类型技能实现各自的 Handler
AgentAgent 实体,包含 system_prompt、模型参数、记忆配置等

六、核心能力四:编排模式与 LLM 智能路由

6.1 设计目标

不需要预先定义流程,让 LLM 根据用户消息实时决定——该用哪个 Agent、按什么顺序执行、甚至是否需要 Agent

编排模式是整个 AI 模块最灵活的能力。它把「编排决策」本身也交给了 LLM。

6.2 路由决策流程

用户消息: "帮我分析一下茅台的财务数据并生成报告"
    │
    ▼
┌─── 编排路由 ───────────────────────────────——┐
│                                             │
│  1. 收集候选 Agent                           │
│     └── 从场景关联的 Agent 列表中获取         │
│                                             │
│  2. 决策分支                                 │
│     ├── 有预定义编排步骤 → 按步骤执行         │
│     ├── 仅 1 个候选 Agent → 直接使用          │
│     ├── 多个候选 Agent → LLM 动态选择         │
│     │   ├── 选中 1 个 → Agent 对话            │
│     │   ├── 选中多个 → 动态编排(顺序/并行)   │
│     │   └── 选 0 个 → 降级到通用 LLM          │
│     └── 无候选 Agent → 降级到通用 LLM         │
│                                              │
│  每个分支都通过 SSE 事件向前端实时反馈路由结果  │
└─────────────────────────────────────────────——┘

6.3 已实现的功能

功能说明
LLM Agent 选择LLM 分析用户意图,从候选 Agent 中选择合适的,返回选择原因
sequential / parallel 策略LLM 判断 Agent 之间是否有依赖,决定顺序执行还是并行执行
动态步骤构建LLM 选中多个 Agent 时,动态编排步骤(上一步输出作为下一步输入)
多级降级LLM 选择失败 → 默认 Agent → 通用 LLM,三级 fallback
SSE 路由事件前端实时展示路由分析过程(routingroute_resultagent_select
预定义编排执行支持预先配置好的编排步骤,按顺序逐步执行

6.4 涉及的关键类

职责
AiDialogService统一对话调度,编排模式的路由决策核心
OrchestrationExecuteService编排步骤执行引擎,支持顺序/并行/动态编排

七、核心能力五:SSE 流式通信

7.1 设计目标

后端逐 token 输出,前端实时渲染——用户看到的不是「等待 5 秒出一堆文字」,而是「像打字一样一个字一个字蹦出来」。

SSE(Server-Sent Events)是整套 AI 模块的通信基础。不仅用于最终的文本输出,还用于传递步骤进度、路由决策、Token 统计等结构化信息。

7.2 SSE 事件协议

所有对话模式共享统一的事件协议:

事件类型用途关键字段
routing编排模式路由开始message
route_result路由结果route, agents, strategy
agent_selectAgent 选择结果agents, strategy, fallback
step_start步骤开始stepIndex, stepType, stepName
step_progress步骤进度stepIndex, message
step_detail步骤详情stepIndex, detailType, + 各类详情
step_done步骤完成stepIndex, status, durationMs
content流式文本输出text
done对话完成tokens, durationMs, traceSnapshot
stop用户终止message, durationMs
error错误message

7.3 已实现的功能

功能说明
后端 SseEmitterSpringSseEmitter 作为 SSE 发射器,LlmSseHelper 封装通用 LLM 流式调用
前端 readSseStream基于fetch + ReadableStream 的通用 SSE 读取器,行缓冲处理不完整数据
useChatExecution统一 Composable,根据 session.mode 自动选择 LLM/场景模式的 SSE 处理
步骤进度可视化每个步骤实时推送step_startstep_progressstep_detailstep_done
取消机制前端AbortController + 后端 AtomicBoolean cancelFlag,用户可随时终止
请求中断新请求自动中断上一次进行中的 SSE 流

传送门:LLM 流式调用工具类 LlmSseHelper解析这篇文章深入剖析了 LlmSseHelper 类,一个专为大语言模 - 掘金 (juejin.cn)

八、核心能力六:Token 统计与额度管理

8.1 设计目标

每次 LLM 调用都可追踪——谁调的、用了什么模型、花了多少 Token、耗时多久、走了哪条链路。

8.2 已实现的功能

功能说明
Token 消耗记录每次 LLM 调用(包括模板选择、技能选择等辅助调用)都记录到token_usage_log
额度校验每次对话前**检查用户剩余额度**,超限则拒绝并提示
多维度统计按用户、模型、场景、业务类型等维度统计 Token 消耗
链路追踪快照Agent 对话生成TraceSnapshot,完整记录每步输入输出和耗时
前端用量展示对话完成后展示 Token 消耗,支持查看完整执行链路

九、模块全景:前端 AI 管理界面

AI 模块不仅有后端能力,还配套了完整的前端管理界面:

模块功能
Agent 管理Agent 的创建、编辑、配置(提示词、知识库、技能、记忆),支持详情查看与编辑双态模式
知识库管理知识库的创建、文档上传、分片预览、向量化进度追踪、检索测试
技能管理技能的创建、分类管理、参数 Schema 编辑、技能测试
提示词模板模板的创建、编辑、预览,支持 Agent 关联
场景管理场景创建、Agent 关联、编排步骤配置、部署管理
Token 统计Token 消耗趋势图、模型分布饼图、用户排行、场景消耗
Token 额度用户额度设置、用量进度条、超限告警
AI 对话统一对话界面,支持 LLM 直聊和场景编排两种模式

十、设计总结

设计点实现方式解决的问题
多 Provider 切换AIProperties + AiConfig + activeProvider一行配置切换大模型,零代码改动
文本/向量模型分离activeProvider + embeddingProvider不同场景用不同模型
RAG 全链路解析→分片→向量化→ChromaDB→检索+降级完整的知识库生命周期管理
Collection 隔离每个知识库独立 ChromaDB Collection知识库数据互不干扰
LLM 智能路由LLM 选择模板/技能/Agent动态决策,避免硬编码
SSE 流式通信统一事件协议 + 前端 Composable逐 token 输出 + 步骤进度可视化
取消机制前端 AbortController + 后端 AtomicBoolean用户可随时终止对话
Token 统计每次调用记录 + 额度校验可观测、可控制
链路追踪AgentTraceSnapshot完整记录执行链路
多级降级向量→关键词、POST→GET、LLM选择失败→默认Agent系统鲁棒性保障

十一、写在最后

AI 模块的架构设计核心思想是配置驱动 + LLM 智能路由 + 降级保障

多 Provider 切换让模型选择变得灵活,RAG 知识库让 Agent 拥有了「领域知识」,四步编排流水线让 Agent 从「聊天机器人」升级为「可执行任务的智能体」,SSE 流式通信让用户能实时看到每一步的执行过程。

整套架构的一个重要原则是:LLM 能做的事让 LLM 做,LLM 做不了的事有降级方案。模板选择失败就加载全部,技能选择失败就全部执行,向量检索失败就关键词匹配,Agent 选择失败就用默认 Agent。

这种「智能 + 兜底」的设计让系统在各种异常场景下都能正常工作。

后续文章计划:本文只做架构总览,每个核心能力的实现细节(多 Provider 切换的具体配置方式、RAG 知识库的向量化实现、Agent 编排流水线的代码结构、SSE 流式通信的前后端对接)将在后续文章中逐一展开。