新增: 知识库图召回激活扩散与治理续批
- 阶段2 图召回: list_neighbors_for_seeds(多种子 1-hop 展开,排除种子与 archived)+knowledge_search 结果附 related 段(权重降序限 5) - 蒸馏合并: knowledge_distill.rs(archived 按 kind 分组 LLM 合订本+merges 边连组) - V54 knowledge_edges 边表与渐进披露批配套迁移/模型字段 - 提炼链 related_ids 协议+检索补 id 字段
This commit is contained in:
@@ -7,7 +7,7 @@ use serde::Deserialize;
|
||||
use tauri::State;
|
||||
|
||||
use df_types::types::new_id;
|
||||
use df_storage::models::{KnowledgeEventRecord, KnowledgeRecord};
|
||||
use df_storage::models::{KnowledgeEventRecord, KnowledgeRecord, RelatedKnowledge};
|
||||
|
||||
use crate::state::{AppState, KnowledgeConfig};
|
||||
|
||||
@@ -303,6 +303,80 @@ pub async fn knowledge_retry_embedding(
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
/// 淘汰批:零复用 + low 置信 + 超龄条目批量归档(P0 淘汰机制,2026-10-23)
|
||||
///
|
||||
/// 背景(知识库治理审查 2026-10-23):71% 条目零复用长尾稀释检索排序,检索面是
|
||||
/// status 白名单,archived 天然出池。逐条留痕(status_changed,source_ref=archive_stale)
|
||||
/// 可审计可回滚。默认阈值 90 天/批 500——从生产画像看 low 置信存量极少(实测 1 条),
|
||||
/// 阈值偏保守,宁可分批多跑不误伤。
|
||||
///
|
||||
/// 归档不可逆性:archived 条目退出检索面,可通过 knowledge_update_status 手动转回
|
||||
/// published(状态机合法迁移),留痕链完整。
|
||||
#[tauri::command]
|
||||
pub async fn knowledge_archive_stale(
|
||||
state: State<'_, AppState>,
|
||||
older_than_days: Option<i64>,
|
||||
limit: Option<i64>,
|
||||
) -> Result<Vec<String>, String> {
|
||||
let days = older_than_days.unwrap_or(90).clamp(1, 3650);
|
||||
let limit = limit.unwrap_or(500).clamp(1, 5000);
|
||||
let ids = state
|
||||
.knowledge
|
||||
.archive_stale(days, limit)
|
||||
.await
|
||||
.map_err(err_str)?;
|
||||
// 逐条留痕 fire-and-forget(与晋升留痕同风格,吞错只 warn)。
|
||||
// from 记 "stale" 而非逐条旧值(批量 UPDATE 已合并原状态,淘汰批标记便于审计回滚)
|
||||
let timeline = KnowledgeTimeline::new(&state.db);
|
||||
for id in &ids {
|
||||
timeline.record_status_change(id, "stale", "archived").await;
|
||||
}
|
||||
if !ids.is_empty() {
|
||||
tracing::info!("[knowledge] 淘汰批: {} 条零复用低置信超龄条目归档(>{days}天)", ids.len());
|
||||
}
|
||||
Ok(ids)
|
||||
}
|
||||
|
||||
/// 关联知识列表(知识中枢阶段1:详情页「关联知识」区块数据源)
|
||||
///
|
||||
/// 双向读边表 + 对端条目展开,archived 对端不展示(与检索面口径一致)。
|
||||
#[tauri::command]
|
||||
pub async fn knowledge_list_related(
|
||||
state: State<'_, AppState>,
|
||||
id: String,
|
||||
limit: Option<i64>,
|
||||
) -> Result<Vec<RelatedKnowledge>, String> {
|
||||
let limit = limit.unwrap_or(10).clamp(1, 50) as usize;
|
||||
state
|
||||
.knowledge
|
||||
.list_related(&id, limit)
|
||||
.await
|
||||
.map_err(err_str)
|
||||
}
|
||||
|
||||
/// 存量蒸馏合并(治理 P0 深化,2026-10-24):对指定 kind 的已归档分组跑一次 LLM 蒸馏,
|
||||
/// 产出单条合订本(candidate)并建 merges 边连组内条目。返回合订本 id(组内不足 2 条
|
||||
/// 或模型判 skip 返回 None)。
|
||||
#[tauri::command]
|
||||
pub async fn knowledge_distill_group(
|
||||
state: State<'_, AppState>,
|
||||
kind: String,
|
||||
limit: Option<i64>,
|
||||
) -> Result<Option<String>, String> {
|
||||
let provider_config = crate::commands::ai::prompt::get_active_provider(&state)
|
||||
.await
|
||||
.map_err(err_str)?;
|
||||
crate::commands::ai::knowledge_distill::distill_archived_group(
|
||||
&state.db,
|
||||
&provider_config,
|
||||
&state.llm_concurrency,
|
||||
&kind,
|
||||
limit.map(|n| n as usize),
|
||||
)
|
||||
.await
|
||||
.map_err(err_str)
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 配置 + 手动提炼
|
||||
// ============================================================
|
||||
@@ -367,14 +441,17 @@ pub struct UpdateKnowledgeInput {
|
||||
pub reasoning: Option<String>,
|
||||
}
|
||||
|
||||
/// 知识详情聚合负载(基本信息 + 全部生命线事件)
|
||||
/// 知识详情聚合负载(基本信息 + 全部生命线事件 + 关联知识)
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct KnowledgeDetailPayload {
|
||||
pub knowledge: KnowledgeRecord,
|
||||
pub events: Vec<KnowledgeEventRecord>,
|
||||
/// 关联知识(阶段1 连边,双向读+对端展开);老前端不消费此字段无影响
|
||||
#[serde(default)]
|
||||
pub related: Vec<RelatedKnowledge>,
|
||||
}
|
||||
|
||||
/// 知识详情(基本信息 + 生命线事件) — 详情页一次拉全
|
||||
/// 知识详情(基本信息 + 生命线事件 + 关联知识) — 详情页一次拉全
|
||||
#[tauri::command]
|
||||
pub async fn knowledge_get_detail(
|
||||
state: State<'_, AppState>,
|
||||
@@ -391,7 +468,9 @@ pub async fn knowledge_get_detail(
|
||||
.list_by_knowledge(&id)
|
||||
.await
|
||||
.map_err(err_str)?;
|
||||
Ok(KnowledgeDetailPayload { knowledge, events })
|
||||
// 关联边读取失败非阻断(边表为空/极老库未到 V54 时降级空列表)
|
||||
let related = state.knowledge.list_related(&id, 10).await.unwrap_or_default();
|
||||
Ok(KnowledgeDetailPayload { knowledge, events, related })
|
||||
}
|
||||
|
||||
/// 编辑知识(部分更新 title/content/tags/confidence/reasoning)
|
||||
|
||||
Reference in New Issue
Block a user