后端: - 工作流推进链(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 + 总线/技术债审查新文档)
228 lines
12 KiB
Markdown
228 lines
12 KiB
Markdown
# 知识库模块
|
||
|
||
> 创建: 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?)` | 列表,默认仅 published(library 纯已发布,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=candidate,source_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` KV(key=`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 限制降低了冲突概率,但随知识积累会逐渐显现
|