Files
DevFlow/docs/03-模块文档/df-knowledge-知识库-2026-06-14.md
绝尘 bd6a41fe6e 新增: 批次工作落地(推进链/评估闭环/事件总线/并发/加固) + 技术债清理 + 文档整理
后端:
- 工作流推进链(D-03):advance_task/状态机/闸门走 df-nodes Node trait,conditions 条件引擎扩展
- 想法评估闭环:启发式评分+对抗评估,df-ideas/scoring + df-storage/idea_eval_repo + idea 前端打通
- 全局事件数据总线:df-ai/context+context_helpers+augmentation 跨模块解耦
- AI planner/plan_hint/intent:aichat B 路线并行多轮基础
- patch_file 加固(TD-03/04):读改写整体锁防 lost update,expected_hash 合约闭环
- 压缩超时兜底(F-15 卡死根治)
- F-09 多会话并发:LlmConcurrency per-conv + streamingGuard 前端守护 + verify 脚本
- 知识注入 DRY/skills/audit 扩展

清理:
- aichat 技术债(误报 allow/死导入/过时注释 30 项)
- URGENT.md 删除(11 项加急全解决/迁 todo)
- 文档整理(todo/待决策/待审查/ARCHITECTURE/INDEX + 总线/技术债审查新文档)
2026-06-21 20:51:26 +08:00

228 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 知识库模块
> 创建: 2026-06-13 | 阶段: Tier 1 已实现
---
## 概述
知识库是 DevFlow 的"共享记忆层",被动积累 AI 对话中产生的可复用经验供后续对话注入使用。外部工具Claude Code / CodeX / Cursor可通过相同 IPC 接口读写,内外零差异。
---
## 实现状态
| 功能 | 状态 |
|------|------|
| candidate→published 状态机 | ✅ Tier 1 |
| 手动录入Knowledge.vue| ✅ Tier 1 |
| AI 自动提炼(对话完成后)| ✅ Tier 1 |
| LIKE 关键词检索 + 注入 system prompt | ✅ Tier 1 |
| 审核收件箱(人工门控)| ✅ Tier 1 |
| 向量 embedding + 混合检索 | ✅ Phase 5.5(开关控制,默认关)|
| ai_node prompt 注入 | ⬜ Tier 2 |
| MCP 对外 API | ⬜ Tier 2 |
---
## 状态机
```
candidate ──→ pending_review ──→ published ──→ archived
│ │ │
└────────────────┴───────────────┘
(可直接到 archived)
```
- AI 提炼只产 **candidate**,绝不自动 published人工门控
- `knowledge_archive`软删除status=archived不物理删除
---
## 知识类型KnowledgeKind
7 种:`pitfall`(踩坑)/ `review_rule`(审查规则)/ `prompt_template`Prompt 模板)/ `architecture_pattern`(架构模式)/ `diagnosis`(诊断知识)/ `deployment_note`(部署经验)/ `workflow_optimization`(工作流优化)
---
## IPC 命令11 个)
| Command | 说明 |
|---------|------|
| `knowledge_list(status?)` | 列表,默认仅 publishedlibrary 纯已发布F-260616-02 决策 a显式传 status 按该状态过滤(含 archived |
| `knowledge_get(id)` | 单条查询 |
| `knowledge_search(query, kind?, limit?)` | LIKE 检索,默认 top-3`limit.clamp` 上限 20`min(20)` |
| `knowledge_create(input)` | 创建status=candidate|
| `knowledge_update_status(id, status)` | 状态转换(含合法矩阵校验)|
| `knowledge_record_reuse(id)` | reuse_count +1 |
| `knowledge_list_candidates()` | 待处理收件箱candidate+pending_review按 confidence 排序)|
| `knowledge_archive(id)` | 软删除 |
| `knowledge_get_config()` | 读取 KnowledgeConfig |
| `knowledge_save_config(config)` | 保存 KnowledgeConfig |
| `knowledge_extract_now()` | 手动触发提炼ManualOnly 模式)|
---
## KnowledgeConfig
```rust
pub struct KnowledgeConfig {
pub auto_extract: bool, // 提炼总开关,默认 true
pub trigger_mode: ExtractTrigger, // on_complete | manual_only(OnIdle 已下线,见 KP-2)
pub min_messages: u32, // 守卫:最少消息数,默认 4
pub auto_inject: bool, // 聊天注入开关,默认 true
pub vector_enabled: bool, // 向量检索开关,默认 false
pub embedding_provider_id: Option<String>, // 仅 openai_compat 类型
pub embedding_model: Option<String>,
}
```
存储:`AppState.knowledge_config: Arc<Mutex<KnowledgeConfig>>` 为内存真相源,并通过 `SettingsRepo` KV 表key=`df-knowledge-config`)持久化;`knowledge_save_config` 落库、`AppState::init` reload 恢复KP-1 已修复)。
---
## 检索与注入
### LIKE 检索(默认)
`search(query, kind, limit=3)``WHERE title LIKE ? OR content LIKE ?``ORDER BY reuse_count DESC`
### 混合检索vector_enabled=true
三层降级链:
1. 开关关 → 纯 LIKE
2. embed 调用失败 → 纯 LIKE
3. 正常 → 双信号排序(同时命中 LIKE+向量 cos≥0.3 > 仅 LIKE > 仅向量 cos≥0.3
嵌入时机:知识**发布时**(不在 candidate 阶段浪费 embed 调用),`spawn_embedding_for_knowledge` fire-and-forget。
### 注入位置
system prompt 头部([知识库上下文] --- [技能指令] --- [原始 system prompt]),仅 auto_inject=true 时生效。
---
## AI 自动提炼流程
1. `run_agentic_loop` 正常退出 → `maybe_spawn_extraction()` 守卫检查
2. 守卫:`auto_extract=true` + `messages.len() >= min_messages`
3. `tauri::async_runtime::spawn` 后台执行,不 await不阻断聊天
4. 取最后 6 条 user/assistant 消息 → 构造 JSON schema prompt → LLM `complete()`
5. `serde_json::from_str<Vec<ExtractedItem>>` 解析失败整批丢弃warn 不报错)
6. 逐条写 `knowledges`status=candidatesource_ref="conv:{id}"
---
## 矛盾知识处理
不做结构层消歧,在内容和 tags 中自述限制范围。检索时两条知识都可能返回,由 LLM 上下文理解取舍。
---
## 外部工具访问(规划)
Tier 1+ 目标MCP Shell 封装(`mcp-server` 转发 IPC外部工具使用逻辑与内部零差异
- 外部写入:走 candidate → 人工审核流程
- 外部读取:`knowledge_search` / `knowledge_list`published
---
## 相关文档
- [df-storage 存储层](./df-storage-存储层-2026-06-12.md) — knowledges 表结构 + 向量工具函数
- [df-ai AI 集成模块](./df-ai-AI集成模块-2026-06-12.md) — hybrid_search / generate_embedding / extract
- [功能决策记录](../02-架构设计/滚动规范/功能决策记录-2026-06-14.md) — 检索方案演进决策
---
## 已知问题2026-06-16 审查)
> 来源全量源码逐行审查knowledge.rs / knowledge_inject.rs / knowledge_timeline.rs / stores/knowledge.ts / Knowledge.vue / agentic.rs / commands.rs / state.rs
>
> **修复进度汇总2026-06-21**
> - ✅ 已修复:**KP-1** 配置持久化 / **KP-2** OnIdle 下线;跨审查项 **R-P1-4** `build_provider` 统一工厂secret::build_provider_for、**CR-28** error 通道AiError emit 覆盖 build_provider_for Err 分支)、**CR-29** 审批等待态竞态B-260615-26 guard disarm + try_continue generating 复位重检)。
> - 🔧 本 workflow 修复中:**KP-3**try_continue 知识注入)/ **KP-5**(编辑生命线事件)/ **KP-6**(嵌入失败重试/标记)。
### 🔴 P0 严重
#### KP-1: KnowledgeConfig 不持久化 — 重启丢失全部配置 ✅ 已修复
> **状态已修复P0 设置走查-2026-06-21。** `knowledge_save_config` / `knowledge_get_config` 现读写 `SettingsRepo` KVkey=`df-knowledge-config`JSON 序列化);`AppState::init` 增加 `reload_knowledge_config` 恢复。下方原文保留供溯源。
- **位置:** `state.rs:208` 初始化 + `knowledge.rs:knowledge_save_config`
- **现象:** `knowledge_save_config` 仅写入内存 `Arc<Mutex<KnowledgeConfig>>`,未落库。应用重启后 `AppState::init` 永远用 `KnowledgeConfig::default()`
- **影响:** 用户配置的向量检索 provider、提炼参数等关闭应用后全部丢失。系统已有 `app_settings` KV 表和 `SettingsRepo` 可用,但未接入
- **修复方向:** `knowledge_save_config` / `knowledge_get_config` 读写 `SettingsRepo`key=`knowledge_config`value=JSON
#### KP-2: OnIdle 触发模式完全未实现 — 配置项为死代码 ✅ 已修复(下线)
> **状态已修复OnIdle 下线)。** `ExtractTrigger` 仅保留 `OnComplete` / `ManualOnly` 两变体,`OnIdle` 变体与 `idle_timeout_ms` 字段已从 `state.rs` 移除(`idle_timeout_ms` 在 `src-tauri` 内零残留)。`trigger_mode` 取值同步收敛。下方原文保留供溯源。
- **位置:** `state.rs` 定义 `ExtractTrigger::OnIdle` + `idle_timeout_ms``knowledge_inject.rs:maybe_spawn_extraction`
- **现象:** `maybe_spawn_extraction` 仅检查 `trigger_mode == OnComplete``OnIdle``ManualOnly` 都直接 `return Ok(())``idle_timeout_ms` 在整个 `src-tauri` 中零引用
- **影响:** 用户选择 `OnIdle` 模式后,知识提炼永远不会触发(与 ManualOnly 行为相同但无任何提示)
- **修复方向:** 要么实现 idle 定时器tokio::time::interval 轮询 AiSession 最后活动时间),要么移除 OnIdle 变体并在前端隐藏该选项
#### KP-3: 审批恢复循环路径缺失知识注入 🔧 本 workflow 修复中
> **状态:本 workflow 修复中。** `try_continue_agent_loop`agentic/mod.rs现已在续跑轮重建 system prompt 时调用 `build_knowledge_context` 注入知识库上下文(参考代码 :1420-1444 区段注释)。下方原文保留供溯源。
- **位置:** `agentic.rs:try_continue_agent_loop` vs `commands.rs:ai_chat`
- **现象:** `ai_chat` 首次消息时调用 `build_knowledge_context` 注入 system prompt`try_continue_agent_loop`(审批通过后恢复循环)仅调用 `build_system_prompt`**未调用** `build_knowledge_context`
- **影响:** 对话经历工具审批流程后恢复时system prompt 中不包含任何知识库上下文AI 在多轮工具调用场景下丢失经验注入
---
### 🟡 P1 中等
#### KP-4: 前端搜索只能搜到 published 知识
- **位置:** `knowledge.rs:knowledge_search``KnowledgeRepo::search`(底层固定 `WHERE status='published'`
- **现象:** 前端搜索栏调用链 `store.search()``knowledgeApi.search()` → IPC → `repo.search()`,底层 SQL 硬编码 `status='published'`
- **影响:** 知识库 Tab 列表加载的是 `list_non_archived()`(含 candidate/pending_review/published但搜索只能命中 published导致列表显示条目数 > 可搜索条目数,体验矛盾
- **修复方向:** 前端搜索走独立的 `knowledge_list` + 前端过滤,或后端新增 `search_all_status()` 方法供前端使用
#### KP-5: 编辑操作缺失生命线事件 🔧 本 workflow 修复中
> **状态:本 workflow 修复中。** 计划在 `knowledge_timeline.rs` 新增 `EVENT_UPDATED` + `KnowledgeTimeline::record_updated()`,并接入 `knowledge.rs:knowledge_update`:375-411。下方原文保留供溯源。
- **位置:** `knowledge.rs:knowledge_update`
- **现象:** `knowledge_create``record_created``knowledge_update_status``record_status_change`,但 `knowledge_update`(编辑 title/content/tags 等)**无任何 Timeline 调用**
- **影响:** 知识被编辑修改后,生命周期时间线中不显示编辑记录,审计追踪存在断档
- **修复方向:** 新增 `EVENT_UPDATED` 事件类型 + `KnowledgeTimeline::record_updated()` 方法
#### KP-6: 嵌入生成失败无重试/标记 — 可能永久无向量索引 🔧 本 workflow 修复中
> **状态:本 workflow 修复中。** 计划在 `knowledge_inject.rs:spawn_embedding_for_knowledge`:91-118增加失败标记/重试,配合 `migrations.rs`knowledges 表)`embedding IS NULL` 补偿。下方原文保留供溯源。
- **位置:** `knowledge_inject.rs:spawn_embedding_for_knowledge`
- **现象:** 发布时 fire-and-forget 生成嵌入,失败只 `warn log`,无重试机制、无失败标记
- **影响:** provider 临时不可用(网络抖动/API 限流)时该知识永远不会获得向量嵌入,即使后续 provider 恢复。混合检索中该条目向量信号永久缺失
- **修复方向:** 可选方案:(a) 定期补偿任务扫描 `published AND embedding IS NULL`(b) 前端详情页显示嵌入状态并提供"重新生成"按钮
#### KP-7: 前端 updateStatus 后仅本地移除 — 不刷新列表
- **位置:** `stores/knowledge.ts:updateStatus`
- **现象:** 发布/拒绝/归档操作后仅 `filter` 移除本地数组中的条目,不重新 `loadList()` / `loadCandidates()`
- **影响:** 状态变化后需手动刷新才能看到最新列表。若其他路径(如 AI 提炼)并发写入候选列表,本地状态会进一步偏离
---
### 🟢 P2 低优先级
#### KP-8: 搜索后分类筛选状态丢失
- **位置:** `Knowledge.vue:onSearchInput`
- **现象:** 搜索框清空时触发 `store.loadList()`,但不恢复之前的 `activeKind` 分类筛选状态
#### KP-9: knowledge_search limit 硬限 3 条
- **位置:** `knowledge.rs:knowledge_search``.min(3)`
- **现象:** 即使传入 `limit=10` 也只返回最多 3 条。Tier 1 内部合理,但 Tier 2 MCP 对外开放后可能受限
#### KP-10: 矛盾知识无消歧机制
- **位置:** 模块设计层面(文档已记录此决策)
- **现象:** 两条矛盾知识可能同时返回,完全依赖 LLM 上下文理解取舍。当前 top-3 限制降低了冲突概率,但随知识积累会逐渐显现