use serde::{Deserialize, Serialize}; // ============================================================ // 知识库配置(提取 + 注入) // ============================================================ /// AI 提炼触发方式 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] pub enum ExtractTrigger { /// 对话正常完成时(默认) OnComplete, /// 仅手动按钮触发 ManualOnly, } /// 知识库配置持久化 KV key(P0 设置走查-2026-06-21:原纯内存 Arc 启动 default 覆盖 /// 致 8 项配置重启全丢;save_config 落此 KV,init reload_knowledge_config 恢复)。 /// 知识库配置持久化 KV key(P0 设置走查-2026-06-21:原纯内存 Arc 启动 default 覆盖 /// 致 8 项配置重启全丢;save_config 落此 KV,init reload_knowledge_config 恢复)。 pub const KNOWLEDGE_CONFIG_KEY: &str = "df-knowledge-config"; /// 审批超时配置持久化 KV key(前端 AdvancedSection.vue 也在用同一个 key,保持单一真相源)。 /// 前端值单位为毫秒(0/300000/900000/1800000/3600000),后端同步使用此 key 读取并转换。 /// 前端在运行期负责会话内的审批超时(定时器+ai_approve(false)),后端在启动恢复阶段 /// 清理重启前遗留的 pending(避免重启后无人调用 try_continue 致审批永不超时)。 pub const APPROVAL_TIMEOUT_KEY: &str = "df-approval-timeout"; /// 知识库行为配置(内存真相源 + Settings KV 持久化,前后端通过 IPC 读写) #[derive(Debug, Clone, Serialize, Deserialize)] pub struct KnowledgeConfig { /// 提炼总开关,默认 true pub auto_extract: bool, /// 提炼触发方式,默认 OnComplete pub trigger_mode: ExtractTrigger, /// 最少消息数守卫(防闲聊噪音),默认 4 pub min_messages: u32, /// 聊天时自动注入相关知识开关,默认 true pub auto_inject: bool, /// 语义检索(向量)总开关,默认 false——关闭时纯 LIKE 零外部依赖 #[serde(default)] pub vector_enabled: bool, /// embedding 用的 provider id(仅 openai_compat 类型,Anthropic 无 embed API) #[serde(default)] pub embedding_provider_id: Option, /// embedding 模型名(如 embedding-3 / text-embedding-3-small) #[serde(default)] pub embedding_model: Option, /// 检索纳入 candidate(AI 自动提炼产物)开关,默认 true /// /// 背景(知识库走查 2026-09-29):自动提炼产物全部滞留 candidate 而检索只认 published, /// 存量知识近乎零生效。纳入后配合「复用即信任」(reuse_count 达标自动晋升 published), /// 人工审核降级为可选修正路径。关=回到仅 published(兼容旧行为)。 /// serde default=true:已持久化的旧配置 JSON 缺该字段时按新默认生效,不破坏启动恢复。 #[serde(default = "default_include_candidates")] pub include_candidates: bool, /// 复用即信任自动晋升开关,默认 false /// /// 背景(决策单未拍板前默认保守):candidate 命中达标自动转正 published 是单向固化 /// (无回退路径),且 2-gram 分词的误命中同样计入 reuse_count,未审核的 LLM 提炼产物 /// 可能经误命中固化污染知识库。晋升固化路径默认关,待决策卡 C3 拍板后由用户显式开启。 /// serde default=false:已持久化的旧配置 JSON 缺该字段时按保守默认生效,不破坏启动恢复。 #[serde(default)] pub auto_publish_enabled: bool, /// 自动晋升的复用命中阈值,默认 5 /// /// 原硬编码 2 过激进:2-gram 分词的误命中两次即可凑满转正;5 次真实复用才够格晋升。 /// serde default=5:旧配置 JSON 缺该字段时按新默认生效。 #[serde(default = "default_auto_publish_reuse_threshold")] pub auto_publish_reuse_threshold: i64, } /// include_candidates 的 serde 默认值(true 语义名收口,与 Default impl 保持一处语义) fn default_include_candidates() -> bool { true } /// auto_publish_reuse_threshold 的 serde 默认值(5 语义名收口,与 Default impl 保持一处语义) fn default_auto_publish_reuse_threshold() -> i64 { 5 } impl Default for KnowledgeConfig { fn default() -> Self { Self { auto_extract: true, trigger_mode: ExtractTrigger::OnComplete, min_messages: 4, auto_inject: true, vector_enabled: false, embedding_provider_id: None, embedding_model: None, include_candidates: true, auto_publish_enabled: false, auto_publish_reuse_threshold: 5, } } }