diff --git a/mvp/engineering/harness/Harness 整体架构学习笔记-从装配到入口到记忆到知识库写入.md b/mvp/engineering/harness/Harness 整体架构学习笔记-从装配到入口到记忆到知识库写入.md new file mode 100644 index 0000000..b3f7108 --- /dev/null +++ b/mvp/engineering/harness/Harness 整体架构学习笔记-从装配到入口到记忆到知识库写入.md @@ -0,0 +1,223 @@ +# Harness 整体架构学习笔记:从装配到入口到记忆到知识库写入 + +**更新日期**:2026-08-04 +**主题**:整体架构五块补充(了解层面)——配置装配中心 / HTTP 入口层 / 会话系统与记忆体系 / 知识库写入链路 +**配套**:九域主线笔记(core/retry/progress/tool/guard/release/agent/audit/contract 全 ✅) + +## 1. 配置装配中心(整体怎么搭起来) + +### 1.1 装配全景(Bean 拓扑) + +```mermaid +flowchart LR + C["ChatHarnessProperties
配置集中(yml)"] --> K["DiagnosisHarnessCore
总闸门:超时/预算/重试/收敛"] + K --> B["ToolBoundary
工具底座:canonical/门禁/投影"] + B --> A1["RagToolAdapter"] + B --> A2["QueryLogsToolAdapter"] + B --> A3["MysqlToolAdapter
(可选装配)"] + A1 --> E["HarnessEvidenceTools
组装注册"] + A2 --> E + A3 --> E + K --> G["GuardModelCall
(守卫/修复/路由共用底座)"] + G --> SG["SemanticGuard"] + G --> ER["EvidenceRepair"] + G --> R["IntentRouter"] + E --> F["DiagnosisAgentFactory"] + F --> UC["DiagnosisAgentUseCase"] + UC --> D["DiagnosisChatExecutor"] + R --> D + R --> S["SystemChatExecutor"] + R --> KQ["KnowledgeQueryExecutor"] + D --> A["ChatApplicationUseCase
应用入口"] + S --> A + KQ --> A +``` + +### 1.2 三层组织(话术版) + +```text +① 总闸门(core):能花多少钱/跑多久/怎么重试/何时停——配置集中,改一处全局生效 +② 工具底座:所有工具统一留痕(canonical)/拦截(ToolBoundary)/裁剪(投影)——行为整齐划一 +③ 具体工具:RAG/Logs/MySQL 按需装配(没配数据源不装死工具)→ 组装注册给 Agent + +串联:先判意图(路由)→ 走对应分支 → 全程在总闸门管辖下 +一句话:边界集中、执行统一、工具可插拔 +``` + +### 1.3 关键设计点 + +| 设计 | 为什么 | +|---|---| +| 单一装配入口(HarnessChatConfiguration) | 读 Bean 签名 = 读架构拓扑 | +| 一切围绕 core | 所有链路共享同一套门禁(超时/预算/重试/收敛) | +| 配置属性集中(@EnableConfigurationProperties) | 一处改全局生效,不会有的环节漏管 | +| 工具可选装配(mysqlEnabled 判断) | 没配置不装死工具;ObjectProvider 可选后端 | +| 守卫/修复/路由共用 GuardModelCall | LLM judge 模式:同一轻量模型底座 | +| Redis 存 canonical | 跨实例共享 + TTL 过期 | +| 线程池 AbortPolicy | 队列满直接拒绝(fail fast) | + +## 2. HTTP 入口层(薄协议适配) + +### 2.1 请求流时序 + +```text +POST /api/chat {Id, Question} + → 校验 → new SseEmitter + ChatSseSession(= ChatApplicationObserver) + → chatWorkerExecutor.execute(...) ← 异步:HTTP 线程不跑模型 + → 立即返回 200 + TEXT_EVENT_STREAM + → worker 线程执行编排,经 session 推事件 + → 队列满 → 503(RejectedExecutionException) +``` + +### 2.2 SSE 状态机 + 五类事件 + +```text +状态机:NEW → OPEN → TERMINAL(收尾)/ DISCONNECTED(断连) + 每个方法 requireState 校验顺序——防乱序推送 + +事件协议: + metadata → {session_id, run_id}(首推) + status → 编排进度(ROUTING / DIAGNOSIS_RUNNING / SAFETY_VALIDATING…) + content → 最终内容(content_type + payload) + failure → 失败码 + 消息 + done → 终态(SUCCESS/FALLBACK/FAILED)★ CANCELLED 对外不可见 +``` + +### 2.3 断连取消链路(贯穿到 Harness) + +```text +客户端断开 → emitter.onTimeout/onError/onCompletion → session.disconnect() + → 状态 DISCONNECTED → runControl.cancelClientDisconnect() + → Harness 取消机制接管(checkActive / 拦截器 / 线程池 cancel) +onStarted 时若已断连:直接取消——不白跑 +``` + +### 2.4 失败两层出口 + +```text +SSE 通道:ChatApplicationException → session.fail(failure + done(FAILED)) + 其他 RuntimeException → INTERNAL_FAILURE 通用信息(不泄露细节) +REST 通道:GlobalExceptionHandler → 404(SessionNotFound)/ 400(参数/文档/文件超限)/ 500(兜底) + +→ 编排异常走 SSE failure,REST 异常走 HTTP 状态码——都不暴露内部细节 +``` + +## 3. 会话系统与记忆体系(术语精确校准) + +### 3.1 会话存储:不存历史,存「可重放的发布结果」 + +```text +ChatSession(chat_session 表):只存元数据(status/messagePairCount/时间戳) + ——「message history is not persisted here」 +DiagnosisSession:诊断快照(query/answer/selfEvaluation/feedback) +真正的历史:DiagnosisRun(每次运行一行)+ PublishedResult(JSON 落库) +``` + +### 3.2 PreviousTurn 注入链路(短期记忆) + +```text +ChatApplicationUseCase 开头读 findPreviousTurn(sessionId) + → 查最近 SUCCESS+DIAGNOSIS+publishedResult 非空的 Run + → 反序列化 PublishedResult → PublishedResultPolicy 生成【有界】摘要 + (limitations 10 条×500 字 / 源文档 10 个 / 字段限长——有界在生成时) + → 传 executePath → DiagnosisChatExecutor + → new DiagnosisAgentInput(query, previous_turn) + → 序列化成输入 JSON → agent.call(inputJson) → 模型从输入读到 + +设计三决策(话术版): + 诊断短流程 → 只取上一轮(更早记忆靠多轮逐层传递) + 非 SUCCESS 误导 → SUCCESS 才准入(且非 SUCCESS 轮次根本没写 PublishedResult) + token 爆炸 → 有界摘要(PreviousTurnLimits) +补充:可回放——模型看有界摘要,审计看全量 JSON(两层分离) +``` + +### 3.3 记忆术语校准(重要认知) + +```text +判定标准:记忆 = 会被【注入 prompt/上下文】的东西(不是存了什么) + + PreviousTurn → 注入输入 JSON(user message)→ ✅ 短期记忆(当前会话) + lookup_knowledge → 工具调用动态获取(tool result)→ ❌ 记忆,是检索增强(RAG) + 知识库 → 检索源,规模太大无法全量注入 → 归检索侧(工具检索是正确形态) + 案例库 → 有结构有写入、缺检索注入 → 长期记忆的【候选原料】 + 运行档案 → 元数据层永不注入 → 审计数据 + +项目真实情况:只有短期记忆(PreviousTurn)+ 检索增强(RAG),【没有】长期记忆层 +``` + +### 3.4 长期记忆设计路径(如果要做) + +```text +筛选标准:规模可控 + 跨会话价值 + 可注入形态 + +案例库最符合:root_cause+solution 结构化摘要、注入 top 2-3 条、相似故障复用解法 +PreviousTurn 扩展:最近 N 轮结论摘要(短期 → 中期记忆) +Feedback 偏好:用户偏好摘要 +知识库不符合:全量太大 → 保持工具检索 + +案例 → skill 提炼(项目已实现): + 6 个 SKILL.md(diagnose-mysql-connection-pool 等) + 结构:Workflow / Required Evidence / Stop Conditions / Report Rules / Eval Anchor + 注入:ClasspathSkillRegistry → SystemPromptTemplate → system prompt(程序性长期记忆) + 情景记忆(案例)→ 程序记忆(skill)→ 常驻注入 ✅ 长期记忆的正确形态 +现有缺口:单技能激活(只放行 1 个)/ 静态加载(无按 query 自动匹配)/ skill 与案例库断开 +``` + +## 4. 知识库写入链路(RAG 写半边) + +```text +上传(/api/documents/upload) + → TextExtractorService(文本提取) + → DocumentChunkService.chunkDocument(分块)★ + → VectorEmbeddingService(dense embedding) + → VectorIndexService.indexDocumentChunks(写 Milvus)★ + → 检索侧(lookup_knowledge)读同一份索引 +``` + +### 关键设计 + +```text +① 分块:按章节分块(非定长硬切)+ 相邻 chunk 保留 overlap(减轻边界断裂) + 双条件限制:maxSize(字符)+ maxTokens(token) +② hybrid 写入:dense(应用侧 embedding → vector 字段) + + BM25(buildSearchText → search_text 字段) + ★ 关键:dense embedding 输入 与 BM25 search_text 【同源】—— + 同一个「增强文本」既喂 embedding 又写 BM25 字段 + → 两路召回看到完全一致的文档内容,混合检索才公平 +③ 弃用:legacy MilvusServiceClient(旧 SDK)/ Spring AI VectorStore#add(无 hybrid schema) + 唯一后端:MilvusHybridKnowledgeStore(Milvus SDK v2) +``` + +## 5. 易错点 + +| 易错 | 正确 | +|---|---| +| Controller 做业务编排 | 薄适配层:校验+开 SSE+异步+写回,编排在 Application | +| SSE 顺序不重要 | requireState 状态机校验——防乱序推送 | +| 取消对外可见 | Done 拒绝 CANCELLED——客户端只看到 SUCCESS/FALLBACK/FAILED | +| 知识库 = 长期记忆 | 是检索源(工具动态获取);记忆 = prompt 注入——项目无长期记忆层 | +| 案例 = 长期记忆 | 是候选原料——缺检索注入;skill 才是程序性长期记忆(已实现) | +| 工具预算在工具层 | maxToolCalls/收敛参数都在 core(总闸门) | +| 分块定长硬切 | 按章节 + overlap + 双条件限制 | + +## 6. 面试话术(30 秒) + +### 6.1 整体架构怎么组织 + +> "整个系统从下往上三层:最底层一套全局规则(超时/预算/重试/收敛,配置集中改一处全局生效);中间一层工具共用的底座(调用留痕、统一拦截、结果裁剪);上层按需装配具体工具(知识库/日志/数据库,配了才装)。最后串成应用入口——先判意图再走分支,全程在总闸门管辖下。一句话:边界集中、执行统一、工具可插拔。" + +### 6.2 记忆体系 + +> "记忆的判定标准是会不会被注入上下文:PreviousTurn 是短期记忆(注入输入 JSON,上一轮 SUCCESS 的有界摘要);知识库是检索增强不是记忆(工具动态获取);项目没有长期记忆层——skill(案例提炼的诊断方法)注入 system prompt 是程序性长期记忆的正确形态;案例库是候选原料,缺检索注入。" + +## 7. 代码位置索引 + +| 块 | 文件 | +|---|---| +| 装配中心 | `config/HarnessChatConfiguration.java`(+ `config/ChatHarnessProperties.java`) | +| HTTP 入口 | `controller/ChatController.java` + `controller/sse/ChatSseSession.java` / `ChatSseEvent.java` / `SseEmitterChatSink.java` | +| 异常映射 | `exception/GlobalExceptionHandler.java` | +| 会话存储 | `harness/application/persistence/JpaChatRunStore.java` / `PreviousTurnLimits.java` / `PublishedResultPolicy.java` | +| 记忆注入 | `harness/application/ChatApplicationUseCase.java` + `harness/application/executor/DiagnosisChatExecutor.java` + `harness/agent/DiagnosisAgentUseCase.java` | +| skill 机制 | `config/SkillConfig.java` + `src/main/resources/skills/*/SKILL.md` | +| 知识库写入 | `service/DocumentChunkService.java` / `VectorIndexService.java` / `VectorEmbeddingService.java` / `KnowledgeBaseInitService.java` + `controller/DocumentController.java` / `KnowledgeBaseController.java` | diff --git a/mvp/engineering/harness/Harness组件学习路线-进度追踪.md b/mvp/engineering/harness/Harness组件学习路线-进度追踪.md index 361ab99..da6dcae 100644 --- a/mvp/engineering/harness/Harness组件学习路线-进度追踪.md +++ b/mvp/engineering/harness/Harness组件学习路线-进度追踪.md @@ -112,6 +112,7 @@ | [Harness 面试复习笔记-五步复习与白板图沉淀](Harness%20面试复习笔记-五步复习与白板图沉淀.md) | **详细版**:30 秒陈述展开/三张白板图/九域五段式讲法(动机→决策→实现→边界→话术)/六易错点带原因/追问应对大全/支付超时案例/纠正认知清单/面试 Checklist | ✅ 已沉淀 | | [Harness agent 域学习笔记-从框架 ReAct 接入到受控停止](Harness%20agent%20域学习笔记-从框架%20ReAct%20接入到受控停止.md) | agent 域:装配(Factory 粘合点)/双拦截器(Model 预算+Token 审计、Tool 五道门)/UseCase 循环外壳/受控停止/双视图投影/串行工具 | ✅ 已沉淀 | | [Harness LLM Judge 设计笔记-从不可信判定到可信裁决](Harness%20LLM%20Judge%20设计笔记-从不可信判定到可信裁决.md) | LLM-as-a-judge 模式:SemanticGuard(判支持度)+ EvidenceRepair(修引用)+ GuardModelCall(受控底座);面试五段式回答稿 + 六追问应对 + 通用要素 | ✅ 已沉淀 | +| [Harness 整体架构学习笔记-从装配到入口到记忆到知识库写入](Harness%20整体架构学习笔记-从装配到入口到记忆到知识库写入.md) | 整体架构补充:配置装配中心(三层组织)/ HTTP 入口层(薄 Controller + SSE 状态机 + 断连取消)/ 会话与记忆体系(PreviousTurn 注入 + 术语校准 + skill 长期记忆)/ 知识库写入链路(分块 + hybrid 同源) | ✅ 已沉淀 | ## 3. 一次请求的完整学习主线 @@ -141,7 +142,7 @@ flowchart LR 可选深化(不阻塞面试): 1. audit 域深化:RagLookupAuditEnricher 检索审计明细(已覆盖大半) 2. LLM Judge 设计(已沉淀:面试问答 + 追问应对) - 3. 按需深入:模型步 hook 细节 / DiagnosisChatExecutor 恢复路径 / SSE 序列化 + 3. 整体架构补充(已沉淀:装配/入口/记忆体系/知识库写入) ``` ## 5. 建议每次学完一个域后更新