diff --git a/CLAUDE.md b/CLAUDE.md
index 196d9ba..1e144f8 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -179,6 +179,26 @@ catch (e) { toast(e.message || '操作失败', 'error') }
catch (e) { toast('操作失败', 'error') }
```
+### 前后端:AI 执行链示意图与代码保持同步
+
+**规则**: 对 `app/`、`rag/`、`advisor/` 包中核心编排类的**结构性变更**(新增/删除管道阶段、调整调用链、引入新组件),**必须同步更新以下两处架构图**,否则示意图与实际代码会不一致:
+
+| 文件 | 内容 | 说明 |
+|------|------|------|
+| `frontend/src/views/PipelineFlow.vue` | Mermaid 流程图 DSL(`GRAPH_DEFINITION` 常量) | 管理后台「AI 执行链」页面的可视化图表 |
+| `CLAUDE.md` 中的 ASCII 管道图 | 文本流程描述("统一对话管道"章节) | 供 AI 和开发者快速了解架构 |
+
+**触发条件**(满足任一即需更新):
+- `ChatPipeline.buildRequest()` 的决策分支(意图路由、FAQ、RAG、纯对话路径)发生变更
+- `RagPipeline.retrieve()` 的检索流程(查询重写策略、检索方式、资料拼装)发生变更
+- `AssistantApp` 的 Advisor 链成员或顺序发生变更(如新增/移除 Advisor)
+- 新增管道阶段组件(如 `IntentRouter`、`SuggestionGenerator`、`SimpleCircuitBreaker` 等)或移除现有组件
+- 组件间调用关系调整(如原来 A→B 改为 A→C→B)
+
+**图表元数据**: `PipelineFlow.vue` 中 DSL 首行有 `%%graph-meta` 注释标记最后更新时间,修改图表时必须更新该日期。
+
+**反面案例**: commit `527d9e7` 创建的流程图展示了 RAG 子图中 `VECTOR → RRF | KEYWORD → RRF | HYBRID → RRF → Reranker` 的三模式检索流程,但实际 `RagPipeline.similaritySearch()` 仅做纯向量检索,`HybridSearchService`/`RrfFusion`/`RerankerService` 尚未接入主对话流程,导致图表与代码事实不符。
+
## API 路由约定
- AI 对话: `/ai/*`(`AiController`)
diff --git a/frontend/src/views/PipelineFlow.vue b/frontend/src/views/PipelineFlow.vue
index 8760c43..345bc8b 100644
--- a/frontend/src/views/PipelineFlow.vue
+++ b/frontend/src/views/PipelineFlow.vue
@@ -3,8 +3,8 @@
🔀 AI 执行链
- 下图展示从用户请求到 AI 回复的完整处理流程,包含意图路由、RAG 检索和 Advisor 链。
- 菱形节点 = 决策分支 · 虚线框 = 独立子系统 · 蓝/绿/黄色高亮 = 入口/出口/LLM。
+ 下图展示从用户请求到 AI 回复的完整处理流程,包含意图路由、RAG 检索、熔断保护和 Advisor 链。
+ 菱形节点 = 决策分支 · 虚线框 = 独立子系统 · 虚线箭头 = 降级/异步路径。
message + roleId + accountId + chatId"]
- A --> B{"Controller
鉴权 / 角色解析
构建 ChatContext"}
+ A --> B{"Controller
鉴权 / 角色解析 / KB 隔离判断
构建 ChatContext"}
B --> C["ChatPipeline.buildRequest
编排决策入口"]
C --> D{"enableRag ?"}
- D -- "❌ false" --> E["模式: 纯对话
systemPrompt(角色人设)
不检索知识库"]
+ D -- "❌ false" --> E["模式: 纯对话
systemPrompt(角色人设 + 全局配置)
不检索知识库"]
- D -- "✅ true" --> F["IntentRouter
LLM 意图识别
FAQ / RAG / CHITCHAT"]
+ D -- "✅ true" --> F["IntentRouter
🔹 寒暄词快速路径: 本地列表精确匹配(零 LLM)
🔹 未命中则 LLM 意图分类
FAQ / RAG / CHITCHAT"]
F --> G{"意图分类结果"}
@@ -81,26 +82,27 @@ flowchart TD
G -- "RAG / 降级
其余情况" --> J["RagPipeline.retrieve
RAG 检索流水线入口"]
- subgraph RAG["📚 RAG 检索流水线"]
- J --> K["1. FAQ 优先匹配
FaqMatchEngine 三级匹配
命中则短路返回"]
+ H -- "✅ 命中标准答案" --> T
+ H -. "❌ 未命中 → 降级 RAG" .-> J
+
+ subgraph RAG["📚 RAG 检索流水线(当前: 纯向量检索)"]
+ J --> K["1. FAQ 优先匹配(二次兜底)
FaqMatchEngine 三级匹配
命中则短路返回"]
K --> L["2. 查询重写
REWRITE / TRANSLATION
COMPRESSION / MULTI_QUERY"]
- L --> M{"3. 检索模式"}
- M --> N["VECTOR
向量语义检索"]
- M --> O["KEYWORD
全文关键词检索
PostgreSQL tsvector"]
- M --> P["HYBRID
向量 + 关键词
双路检索"]
- N --> Q["4. RRF 融合排序
Reciprocal Rank Fusion
k=60"]
- O --> Q
- P --> Q
- Q --> R["5. Reranker 重排序
DashScope / OpenAI 兼容
超时 3s 自动 fallback"]
- R --> S["6. 构建资料块
拼接检索文档
注入 system prompt 末尾"]
+ L --> M["3. 向量检索
PGVector similaritySearch
topK=4 + 分类过滤"]
+ M --> S["4. 构建资料块
拼接检索文档
注入 system prompt 末尾"]
end
- H --> T["组装 ChatRequest
finalMessage + finalSystemPrompt
+ faqAnswer (可选)"]
I --> T
S --> T
E --> T
- T --> U["AssistantApp
chat / chatStream
构建 ChatClient + MCP 工具"]
+ T["组装 ChatRequest
finalMessage + finalSystemPrompt
+ faqAnswer (可选)"]
+
+ T --> CB{"🔌 AI 熔断检查
SimpleCircuitBreaker
阈值: 连续 3 次失败 / 恢复: 5 分钟"}
+
+ CB -- "熔断中" --> FALLBACK["返回降级提示
「AI 服务暂时不可用
请稍后重试」"]
+
+ CB -- "正常" --> U["AssistantApp
chat / chatStream
构建 ChatClient + MCP 工具"]
subgraph ADVISOR["🛡️ Advisor 链(环绕 LLM 调用)"]
U --> V["ContentSafetyAdvisor
🔽 before: DFA 敏感词检测
用户输入 BLOCK/MASK"]
@@ -113,9 +115,21 @@ flowchart TD
AA --> AB["返回 AI 回复
SSE 流式输出
+ MCP 工具调用事件"]
+ FALLBACK --> AB
+
+ AB -. "异步按需触发" .-> SG
+
+ subgraph SUGGEST["💡 推荐问题(异步)"]
+ SG["SuggestionGenerator
独立 ChatClient(无 MCP 工具)
基于最近 10 条历史
生成 3 条推荐问题
超时 15s · 结果缓存"]
+ end
+
style A fill:#dbeafe,stroke:#3b82f6,stroke-width:2px
style AB fill:#d1fae5,stroke:#10b981,stroke-width:2px
style Y fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
+ style CB fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
+ style FALLBACK fill:#fee2e2,stroke:#ef4444,stroke-width:2px,stroke-dasharray:5
+ style M fill:#e0e7ff,stroke:#a5b4fc,stroke-width:2px
+ style S fill:#e0e7ff,stroke:#a5b4fc,stroke-width:2px
`
const svg = ref('')
diff --git a/src/main/java/com/wok/supportbot/app/AssistantApp.java b/src/main/java/com/wok/supportbot/app/AssistantApp.java
index 876cbd2..8be4ec6 100644
--- a/src/main/java/com/wok/supportbot/app/AssistantApp.java
+++ b/src/main/java/com/wok/supportbot/app/AssistantApp.java
@@ -29,11 +29,28 @@ import java.util.Map;
import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;
/**
- * @Classname AssistantApp
- * @Description
- * @Version 1.0.0
- * @Date 2025/06/27 14:11
- * @Author lyx
+ * AI 对话执行层 —— ChatClient 构建、缓存管理与 LLM 调用执行。
+ *
+ * 本类负责 ChatClient 生命周期(按 appType + allowedMcpTools 缓存,LRU 淘汰), + * Advisor 链装配(ContentSafetyAdvisor → MessageChatMemoryAdvisor → MyLoggerAdvisor), + * 以及同步/流式对话执行(含熔断保护)。对话编排决策由 {@link ChatPipeline} 完成。 + *
+ * 核心方法: + *
+ * {@code @pipeline} execution-layer order=2
+ * {@code @pipeline-step} 熔断检查: SimpleCircuitBreaker(3次失败/5分钟恢复) → 熔断时返回降级提示
+ * {@code @pipeline-step} Advisor链: ContentSafetyAdvisor(HIGHEST) → MessageChatMemoryAdvisor → MyLoggerAdvisor
+ * {@code @pipeline-step} ChatClient.call/stream: LLM 大模型调用 → 成功/失败记录到熔断器
+ * 同步至: frontend/src/views/PipelineFlow.vue Advisor 子图 & 熔断节点
+ *
+ * @author lyx
+ * @version 1.0.0
+ * @date 2025/06/27 14:11
*/
@Component
@Slf4j
diff --git a/src/main/java/com/wok/supportbot/app/ChatPipeline.java b/src/main/java/com/wok/supportbot/app/ChatPipeline.java
index 2a1df6f..466b204 100644
--- a/src/main/java/com/wok/supportbot/app/ChatPipeline.java
+++ b/src/main/java/com/wok/supportbot/app/ChatPipeline.java
@@ -27,6 +27,12 @@ import java.util.Optional;
*
* 接入 {@link IntentRouter} 替代原 {@code AiController.shouldBypassKnowledgeRetrieval} 的硬编码寒暄词判断: * 寒暄词列表保留为快速路径与兜底,IntentRouter 负责细粒度意图分类,二者命中其一即跳过 KB 检索。 + *
+ * {@code @pipeline} orchestration-layer order=0
+ * {@code @pipeline-step} buildRequest: 意图路由 → FAQ优先 → RAG检索 → 提示词组装
+ * {@code @pipeline-step} routeIntent: 寒暄词快速路径 → IntentRouter LLM分类 → 降级RAG
+ * {@code @pipeline-step} effectiveSystem: DB全局提示词 + 角色人设 动态组合
+ * 同步至: frontend/src/views/PipelineFlow.vue, CLAUDE.md ASCII管道图
*/
@Component
@Slf4j
diff --git a/src/main/java/com/wok/supportbot/rag/RagPipeline.java b/src/main/java/com/wok/supportbot/rag/RagPipeline.java
index 1dbc7aa..0fb20c0 100644
--- a/src/main/java/com/wok/supportbot/rag/RagPipeline.java
+++ b/src/main/java/com/wok/supportbot/rag/RagPipeline.java
@@ -44,6 +44,12 @@ import java.util.stream.Collectors;
* 消除上下文注入位置随策略不同而不同的不一致。
*
* 阶段一作为旁路组件存在,旧 {@code AssistantApp} RAG 路径未改动;阶段二由 {@code ChatPipeline} 接入。 + *
+ * {@code @pipeline} rag-layer order=1
+ * {@code @pipeline-step} retrieve: FAQ优先匹配 → 查询重写/扩展 → similaritySearch(PGVector) → 资料拼接
+ * {@code @pipeline-step} similaritySearch: 纯向量检索 topK=4 + CategoryFilter 分类过滤
+ * 注意: HybridSearchService/RrfFusion/RerankerService 尚未接入本管道,当前仅单路向量检索。
+ * 同步至: frontend/src/views/PipelineFlow.vue RAG 子图
*/
@Component
@Slf4j