89 KiB
技能归纳、WeKnora 普通知识库与助手知识库:实现设计
本文档用于指导大模型或开发者实现知识库体系改造。整体包含两条线:一条是“将一个或多个技能归纳到一个 WeKnora Wiki 普通知识库”;另一条是新增自研助手知识库体系。助手知识库像普通知识库一样可以创建多个库,同时系统内置一个全局大库,用于统计全库数据、承接所有 WeKnora 导入沉淀、做全局实体对齐、Wiki 展示和导入审计。
本文档中,技能归纳目标只能是 WeKnora Wiki 普通知识库;助手知识库不接收技能直接归纳,也不接收任意本地文件。普通知识库负责向量化、检索、Wiki 和图谱;助手知识库负责自研存储、WeKnora 导入、实体对齐、Wiki 展示、搜索和导入审计。无论 WeKnora 数据导入到哪个助手知识库,最终都必须沉淀一份到系统全局大库。
最终约束:如果本文历史章节与本节冲突,以本节和“2. 当前边界”中的约束为准。
1. 背景与目标
当前系统已有:
- 技能管理:后台可管理运行中的技能,技能文件位于
skills/public、skills/custom。 - 技能地址管理:已经在管理员技能管理页中以标签页形式接入,支持扫描技能内
.md、.py中的地址并批量替换。 - WeKnora / LLM Wiki 接入:前后端已有知识库、文档、Wiki 页面、Wiki 图谱等 API。
本次要新增一条管理员工作流:
管理员在“技能管理”页面选择多个技能,再选择一个目标 WeKnora Wiki 普通知识库,点击归纳。系统将每个技能作为独立来源读取、解析、抽取和归纳,把结果写入对应 WeKnora 知识库,并在技能列表和技能详情中展示“该技能已被哪些知识库归纳”。如果需要归纳到多个普通知识库,通过多次操作完成。
用户已确认的业务约束:
- 一次操作可以选择多个技能,但只能选择一个目标 WeKnora Wiki 普通知识库。
- 同一个技能可以在不同时间归纳到多个知识库,所以最终关系是技能与知识库多对多。
- 多知识库归纳通过多次操作完成;每次操作形成一批
技能 x 单目标知识库任务。 - V1 只支持归纳到可写 WeKnora Wiki 普通知识库;不支持非 Wiki、FAQ、系统会话存档、只读知识库作为技能归纳目标。
- 技能归纳时只抽取数据、业务说明、实体、概念、对象、事件、关系等知识;Python、TypeScript、Shell 等代码和脚本类文件完全排除,不读取注释、不抽取函数、不上传、不进入 prompt。
- 技能里的 Markdown、业务数据文件、表格、PDF、Office、图片等要纳入处理范围。
- 需要同步三类内容:原始资料、归纳后的 Wiki、实体与关系。
- 关系来源包括 Markdown 自然语言描述、目录和文件引用、模型自动推断。
- 允许模型推断关系,但前端不提供逐条实体/关系预览审核。
- 支持管理员手动点击“重新归纳”;不新增自动文件监听、定时后台同步或技能变更自动远程写入。
- 解除关联时弹窗让用户选择:保留知识库内容,或删除该技能贡献的内容。
- 权限仅管理员。
- 总技能数约 200 个,需要支持批量进度、后台执行、失败重试。
- 同一目标知识库内,不同技能抽取出的同一实体需要合并。
- 重归纳时先生成新版本,成功后再替换旧版本;失败时旧版本继续可用。
- 新增知识库类型区分:普通知识库是 WeKnora,助手知识库是自研存储。
- 助手知识库支持创建多个库;其中有且只有一个系统全局大库,建议命名为“知识梳理总库”,所有用户可见。
- 助手知识库只提供 Wiki 页面展示、搜索和数据导入;不落到 WeKnora。
- 助手知识库数据来源只能是 WeKnora 导出包或从某个 WeKnora 知识库触发导入。
- WeKnora 已向量化和处理完成的 Wiki、文档、实体、关系、图谱数据默认沉淀到助手知识库;如果导入的是某个自建助手库,也必须同步沉淀到全局大库。
- 普通知识库需要提供导出或“导入到助手知识库”的功能,把 WeKnora 里已经处理好的数据导入指定助手知识库;导出数据需要包含 Wiki、文档、chunk、实体、关系、图谱。
- 即使没有配置 WeKnora 地址,也要默认展示助手知识库列表和创建入口,而不是展示空的普通知识库页面。
- 管理员可切换知识库产品版本:
v1/v2,默认v1。 - 助手知识库普通用户只读,管理员可导入、编辑、删除、查看版本和回滚 Wiki 页面。
2. 当前边界
以下能力明确不做,开发实现和验收必须按这些边界收敛:
- 不支持一次选择多个目标知识库。多知识库归纳通过多次操作完成。
- 不支持非 Wiki 知识库、FAQ 知识库、系统会话存档知识库、只读知识库作为技能归纳目标。
- 不直接写 WeKnora 的 Neo4j 或底层图数据库。
- 不新增自动文件监听、定时后台同步或技能变更自动远程写入。
- 不在前端提供逐条实体/关系预览审核。
- 不把远端 WeKnora 内部 ID 暴露为前端业务主键。
- 不支持技能直接归纳到助手知识库。技能先进入 WeKnora 普通知识库,再由 WeKnora 导出沉淀到助手知识库。
- 不支持管理员向助手知识库导入任意本地文件;手动导入也必须是 WeKnora 导出包或从某个 WeKnora 知识库触发。
- 助手知识库 V1 不做页面版本管理,只保留当前合并后的 Wiki 状态和导入审计记录。
3. 术语
| 术语 | 含义 |
|---|---|
| 技能 | DeerFlow 技能目录,通常包含 SKILL.md、代码、配置、示例、文档、数据文件等。 |
| 目标知识库 | 管理员选择的一个 WeKnora Wiki 普通知识库。助手知识库不是技能归纳目标。 |
| 普通知识库 | WeKnora 知识库,负责向量化、Wiki、文档检索和图谱能力。 |
| 助手知识库 | DeerFlow 自研知识库类型,支持创建多个库,用于 Wiki 展示、搜索、WeKnora 导入和实体对齐。 |
| 知识梳理总库 | 助手知识库体系中的系统全局大库,有且只有一个,自动统计和沉淀所有助手库与普通知识库导入数据,做全局实体对齐。 |
| 自建助手库 | 管理员创建的普通助手知识库,类似普通知识库列表中的一个库,可导入 WeKnora 普通知识库导出数据。 |
| 产品版本 | 知识库产品形态开关。v1 默认为普通知识库体验,v2 默认为助手知识库体验。 |
| WeKnora 导出包 | 从普通知识库导出的已处理知识集合,包含 Wiki 页面、文档、chunk、实体、关系、图谱等。 |
| 绑定 | 一个技能与一个目标知识库之间的持久关联。skill_name + target_type + target_id 唯一。 |
| 快照 | 某次扫描技能目录得到的内容版本,包含文件清单、摘要、抽取结果和源 digest。 |
| 贡献 | 某个技能快照对目标知识库内实体、关系、Wiki 页面、原始资料的增量内容。 |
| 规范实体 | 在同一个目标知识库内合并后的实体。多个技能可以贡献到同一个实体。 |
| 规范关系 | 在同一个目标知识库内合并后的关系。多个技能可以给同一关系提供证据。 |
| 归纳任务 | 一次管理员发起的批量操作,可包含多个目标知识库和多个技能 item。 |
| item | 归纳任务中的单个技能处理单元。 |
4. 总体方案
整体采用“双知识库形态 + 本地持久绑定 + 后台任务 + WeKnora 投影 + 助手底库实体对齐”的架构。
flowchart LR
A[管理员选择多个技能] --> B[选择一个 WeKnora Wiki 目标知识库]
B --> C[创建归纳任务]
C --> D[逐技能扫描与解析]
D --> E[生成技能快照]
E --> F[LLM 归纳 Wiki 与关系抽取]
F --> G[按目标 WeKnora Wiki 合并实体/关系]
G --> H[写入 WeKnora 原始资料与 Wiki]
G --> I[写入关系投影文档]
H --> K[校验远端写入]
I --> K
K --> L[本地原子激活新版本]
L --> M[技能页展示已归纳知识库]
K --> N[WeKnora 导出已处理数据]
N --> O[导入指定助手知识库]
O --> P[同步沉淀到知识梳理总库]
P --> Q[全局实体对齐]
Q --> S[总库 Wiki 展示与搜索]
关键原则:
- DeerFlow 本地数据库保存权威绑定关系、版本状态、来源贡献和远端 artifact 映射。
- WeKnora 保存可检索知识内容,包括原文、Wiki 页面、FAQ、会话存档、关系投影文档和图谱。
- 不直接写 WeKnora 底层图数据库;关系以 WeKnora API 能力和关系投影文档承接。
- 重归纳使用 staged artifact,远端写入和校验成功后,本地才激活新版本。
- 删除或解除关联只影响该技能在目标知识库中的贡献,不误删其他技能共享的实体和关系。
- 助手知识库可以创建多个库;系统全局大库只有一个,负责汇总全库数据和做跨库实体对齐。
- WeKnora 的已处理结果可以导入指定助手知识库;无论是否指定自建助手库,都必须同步沉淀到知识梳理总库。
- 未配置 WeKnora 地址时,默认进入助手知识库页面,展示助手知识库列表、创建入口和知识梳理总库;与 WeKnora 相关的导出导入动作置灰或隐藏。
5. 现有代码落点
实现前必须先读仓库说明:
D:/cmzs-clean/deerflow-code/AGENTS.mdD:/cmzs-clean/deerflow-code/offline-backend-20260512/backend/AGENTS.mdD:/cmzs-clean/deerflow-code/offline-backend-20260512/backend/CLAUDE.md
建议改动位置:
| 模块 | 建议文件 |
|---|---|
| 后端 router | offline-backend-20260512/backend/app/gateway/routers/skill_knowledge.py |
| 后台任务调度 | offline-backend-20260512/backend/app/gateway/skill_knowledge_job_dispatcher.py |
| 后台任务执行 | offline-backend-20260512/backend/app/gateway/skill_knowledge_job_executor.py |
| 技能归纳核心逻辑 | offline-backend-20260512/backend/packages/harness/deerflow/skill_knowledge/ |
| 持久化模型 | offline-backend-20260512/backend/packages/harness/deerflow/persistence/skill_knowledge/ |
| WeKnora 客户端扩展 | offline-backend-20260512/backend/packages/harness/deerflow/integrations/weknora/client.py |
| 助手知识库核心逻辑 | offline-backend-20260512/backend/packages/harness/deerflow/assistant_knowledge/ |
| 助手知识库持久化 | offline-backend-20260512/backend/packages/harness/deerflow/persistence/assistant_knowledge/ |
| 助手知识库 Gateway | offline-backend-20260512/backend/app/gateway/routers/assistant_knowledge.py |
| WeKnora 导出到助手库任务 | offline-backend-20260512/backend/app/gateway/assistant_knowledge_import_executor.py |
| 前端 API | frontend-web/src/strategy-components/api/skill-knowledge.ts |
| 助手知识库前端 API | frontend-web/src/strategy-components/api/assistant-knowledge.ts |
| 管理员技能页 | frontend-web/src/pages/AdminSkillsPage.tsx |
| 技能行组件 | frontend-web/src/components/workspace/settings/skill-settings-page.tsx |
| WeKnora API hooks | frontend-web/src/strategy-components/api/llmwiki.ts |
| 知识库产品版本设置 | frontend-web/src/core/system-settings/api.ts |
注意边界:
packages/harness/deerflow/*不能 importapp.*。- 路由、鉴权、FastAPI app state 等放在
app/gateway/*。 - 纯扫描、解析、抽取、合并、投影计划生成放在
deerflow.*。 - 文件 IO、Office/PDF 转换、CPU 密集处理必须通过
asyncio.to_thread,避免阻塞事件循环。
6. WeKnora 能力使用策略
现有 WeKnora 客户端已支持:
- 创建知识库。
- 上传文件。
- 导入 URL。
- 创建手动文档。
- 创建、更新、删除、查询 Wiki 页面。
- 获取 Wiki 图谱。
V1 需要新增或补齐:
- 目标知识库能力探测:是否启用 Wiki,是否可写,是否支持 GraphRAG / extract_config。
- 目标知识库分类和能力标识:Wiki、非 Wiki、FAQ、会话存档、只读、图谱可写。
- 导出已处理数据的能力:Wiki 页面、文档、chunk、实体、关系、图谱。
- WeKnora 处理完成后的自动沉淀触发点:在文件向量化、Wiki 生成和图谱抽取完成后,创建“导入助手知识库”的后台任务。
- 如果 WeKnora 当前实例 Swagger 暴露了图谱相关配置更新接口,则在目标知识库启用
graph_enabled与extract_config。 - 如果未暴露稳定的实体/关系写入 API,优先使用“关系投影文档 + Wiki 关系页 + Wiki 链接”让 WeKnora 自己抽取图谱;在配置显式开启时,可通过受控 Neo4j direct writer 写入底层图数据库。
参考官方资料:
实现要求:
- 以部署实例的 Swagger 为准,不要硬编码未确认的远端 API。
- 可以封装
probe_capabilities(),返回wiki_enabled、graph_enabled_supported、extract_config_supported、wiki_page_upsert_supported、file_upload_supported等能力。 - GraphRAG 失败不能导致 Wiki 归纳整体回滚。Wiki 与原始资料成功、GraphRAG 写入失败时,绑定状态为
partial_failed,错误信息明确写“图谱投影失败,可重新归纳重试”。 - 如果 WeKnora 不支持直接导出向量、chunk 或图谱原始结构,导出层应退化为读取 Wiki 页面、文档状态、Wiki graph 和可查询的图谱摘要;助手知识库不强依赖复用 WeKnora embedding 向量。
6.1 目标知识库适配策略
一次归纳任务允许选择多个技能和多个目标知识库。后端不要把它当成一个大事务,而是展开为矩阵:
items = selected_skills x selected_targets
每个 item 对应一个 binding,一个技能归纳到三个目标知识库,就生成三个 binding。父 job 负责展示整体进度,item 独立成功、失败、取消和重试。
当目标是自建助手库时,item 写入顺序是:
写入目标助手库 -> 生成目标库 Wiki/实体/关系 -> 创建总库沉淀任务 -> 总库实体对齐和统计
总库沉淀失败不能让目标助手库写入结果消失,但 item 必须标记为 partial_failed,并允许单独重试“沉淀到总库”。
目标知识库需要通过 adapter 写入:
| 目标类型 | 写入策略 | Wiki | 关系/图谱 |
|---|---|---|---|
| WeKnora Wiki 知识库 | 上传原始资料、upsert Wiki 页面、写 graph projection | 写 WeKnora Wiki | WeKnora GraphRAG + 可选 Neo4j direct writer |
| WeKnora 非 Wiki 知识库 | 上传原始资料和归纳文档,不强制生成 Wiki | 不写 WeKnora Wiki,可写本地 sidecar Wiki | graph projection 文档 + 可选 Neo4j direct writer |
| WeKnora FAQ 知识库 | 把归纳结果转换为 FAQ 条目、来源文档和关系摘要 | 不写或只写 sidecar Wiki | 关系作为 FAQ metadata、projection 文档和图谱边 |
| 系统会话存档知识库 | 把技能归纳结果作为系统会话归档条目写入 | sidecar Wiki 展示 | 关系作为归档 metadata 和图谱边 |
| 只读 WeKnora 知识库 | 不修改远端原库;写本地 sidecar artifact,并生成待推送状态 | sidecar Wiki 展示 | sidecar graph + 待推送 Neo4j plan |
| 助手知识库 | 写入指定助手库、实体对齐、生成 Wiki 页面版本;同时异步沉淀到知识梳理总库 | 写自研 Wiki | 写自研实体/关系表;总库做跨库实体对齐 |
只读目标说明:
- “支持只读知识库作为目标”不代表绕过远端权限强行写入。
- 对只读 WeKnora,系统创建本地 sidecar 投影:归纳结果与该远端知识库绑定展示,但远端写入状态为
pending_remote_write。 - 当管理员后续授予可写权限时,可执行“推送到远端”,把 sidecar staged artifact 写入 WeKnora。
- 前端必须清楚展示“只读目标:已本地归纳,未写入远端”。
6.2 Neo4j 直接写入设计
需求确认需要支持直接写 WeKnora 的 Neo4j 或底层图数据库。该能力风险较高,必须作为受控能力实现。
必须满足:
- 通过配置显式开启,例如
weknora.graph.direct_write_enabled = true。 - 只允许管理员触发。
- Neo4j 连接串、账号、库名只允许后端配置,不允许前端传入。
- LLM 不得生成任意 Cypher 并直接执行。
- graph writer 只能执行代码中预定义的参数化模板。
- 所有写入使用事务。
- 每个节点和边都带稳定业务 key、来源 binding、snapshot、job、confidence 和 evidence。
- 支持 dry-run plan、写入审计、失败重试、回滚计划。
节点 key 建议:
provider = deerflow
scope = target_type + target_id
entity_key = entity_type + normalized_name 或 external_id
边 key 建议:
source_entity_key + predicate + target_entity_key + contribution_scope
Neo4j 写入只作为图谱层加速和展示,不替代本地 contribution 表。本地 contribution 表仍是删除、回滚、重建、审计的权威来源。
6.3 实体/关系预览审核
前端必须提供逐条实体/关系预览审核能力。审核发生在“抽取完成、写入目标前”。
审核对象:
- 实体。
- 关系。
- 实体对齐候选。
- 关系合并候选。
- Wiki 页面草稿。
管理员操作:
- 批准。
- 拒绝。
- 编辑名称、类型、谓词、别名、摘要、confidence。
- 批量批准高置信结果。
- 批量拒绝低置信结果。
审核模式建议:
| 模式 | 说明 |
|---|---|
required |
所有实体/关系必须审核后才能写入。 |
auto_high_confidence |
高置信自动通过,低置信进入审核队列。 |
off |
不阻塞写入,但仍保留预览页面和事后审计。 |
默认建议 auto_high_confidence。如果用户希望“必须逐条审核”,可在系统设置中改为 required。
审核记录必须入库:
- 操作人。
- 操作时间。
- 原始抽取值。
- 修改后值。
- 通过或拒绝原因。
- 对应 job/item/binding/snapshot。
6.4 自动同步设计
需要支持三类自动同步:
- 文件监听:技能知识文件变化后自动创建归纳任务。
- 定时同步:按管理员配置的周期重新扫描并归纳。
- 技能变更自动远程写入:技能保存、启停、导入后触发相关 binding 同步。
自动同步仍需遵守:
- 只处理非代码知识文件。
- 代码文件变化不触发归纳。
- 自动任务必须 debounced,避免保存过程中连续触发。
- 自动任务必须走 staged 版本,成功后激活,失败保留旧版本。
- 同一 binding 同一时间只能有一个 active item。
- 审核模式为
required时,自动任务停在awaiting_review,不写远端。
建议新增配置:
{
"skill_knowledge_auto_sync": {
"watch_enabled": true,
"schedule_enabled": true,
"schedule_cron": "0 */6 * * *",
"debounce_seconds": 120,
"write_remote_enabled": true
}
}
6.5 远端 ID 暴露与业务 key
需求确认前端需要暴露 WeKnora 远端 ID,并可作为跨系统业务 key 使用。
实现要求:
- API 返回
remote_refs,包含 provider、remote kind、remote id、slug、url。 - 前端可以展示、复制、筛选远端 ID。
- 与外部系统交互时,可使用
provider + remote_id作为业务 key。 - 本地数据库仍保留
id作为 surrogate primary key,避免远端 ID 变更导致本地关系断裂。
建议响应结构:
{
"id": "local-artifact-id",
"business_key": "weknora:wiki_page:remote-page-id",
"remote_refs": [
{
"provider": "weknora",
"remote_kind": "wiki_page",
"remote_id": "remote-page-id",
"slug": "skills/example/overview",
"url": "/llmwiki/kb/xxx/wiki/skills/example/overview"
}
]
}
不要把远端 ID 当作唯一存储来源;本地仍需要维护 mapping、审计和状态。
7. 数据处理范围
归纳一个技能时,扫描技能根目录下所有有效的非代码知识文件。代码类文件不作为知识源,也不影响知识 digest。
必须处理:
| 类型 | 策略 |
|---|---|
.md / .mdx / .txt |
直接读取,保留标题、段落、链接、表格和自然语言说明;代码块内容默认跳过,只保留“此处存在示例代码”的弱提示。 |
.json / .yaml / .yml / .toml / .ini |
仅当它们承载业务数据、数据字典、枚举、模板或知识配置时处理;运行配置、依赖配置、工具入口、工程配置不入库。 |
.csv / .tsv |
结构化读取,抽样概要 + 全量原始资料上传。 |
.xlsx / .xls |
使用已有文件转换或表格解析能力,保留 sheet、列名、样例和统计。 |
.pdf / .docx / .pptx |
复用现有 deerflow.utils.file_conversion 或 MarkItDown 路径转文本,同时上传原始文件。 |
| 图片 | 上传原始文件;如果已有 VLM/OCR 能力则抽取图片描述,否则记录为二进制附件。 |
| 压缩包 | 安全解压到临时目录后递归处理,必须限制大小、文件数、路径穿越、符号链接。 |
| 其他二进制 | 记录 manifest 并尝试作为原始附件上传;无法解析时不生成文本摘要。 |
必须排除:
.py.ts.tsx.js.jsx.sh.bat.ps1- 其他脚本、源码、构建脚本、依赖锁文件
.gitnode_modules__pycache__.pytest_cachedistbuild- 临时缓存目录
- 明确生成物和大体积模型文件
必须阻断:
.env- 私钥、公钥私钥对、证书私钥
- token、password、secret、access key 等高置信密钥文件
阻断规则是安全底线:发现疑似密钥时,该文件不能上传到 WeKnora,也不能进入 LLM prompt。任务 item 标记为 partial_failed 或 failed,前端展示“因安全策略跳过敏感文件”,并给出文件路径,不输出密钥内容。
代码排除规则:
- 不读取源码内容。
- 不抽取源码注释。
- 不抽取函数、类、import、依赖、入口、调用链。
- 不上传源码文件。
- 不把源码路径作为 Wiki 知识展示;最多在管理员任务详情中显示“已跳过代码类文件数量”。
- 计算
source_digest时只包含知识文件;纯代码变更不应导致技能归纳状态变为 stale。
8. 中间表示 IR
扫描和抽取后生成统一 IR,后续 Wiki 生成、实体合并、远端投影都基于 IR,而不是直接从文件内容临时拼装。
建议结构:
{
"skill": {
"name": "example-skill",
"display_name": "示例技能",
"description": "从 SKILL.md 和元数据提取",
"source_root": "skills/public/example-skill",
"source_digest": "sha256:..."
},
"files": [
{
"path": "SKILL.md",
"kind": "markdown",
"sha256": "...",
"size": 12345,
"text_digest": "sha256:...",
"title": "Example Skill",
"summary": "文件摘要",
"anchors": [
{
"id": "heading-install",
"line_start": 12,
"line_end": 36,
"text_digest": "sha256:..."
}
],
"references": [
{
"target_path": "data/schema.yaml",
"evidence": "Markdown link or import",
"confidence": 1.0
}
],
"safety": {
"status": "allowed",
"warnings": []
}
}
],
"entities": [
{
"local_id": "ent_001",
"type": "tool",
"name": "web_search",
"aliases": ["网络搜索"],
"description": "用于检索外部信息的工具",
"attributes": {
"entrypoint": "config.yaml tools.web_search"
},
"evidence": [
{
"file_path": "config.yaml",
"line_start": 10,
"line_end": 20,
"quote": "短证据,不包含敏感信息"
}
],
"confidence": 0.94
}
],
"relations": [
{
"local_id": "rel_001",
"source_local_id": "ent_001",
"predicate": "used_by",
"target_local_id": "ent_002",
"description": "web_search 被示例技能用于首步检索",
"relation_source": "llm_inferred",
"evidence": [
{
"file_path": "SKILL.md",
"line_start": 22,
"line_end": 28,
"quote": "短证据"
}
],
"confidence": 0.88
}
],
"wiki": {
"skill_page": {
"slug": "skills/example-skill/overview",
"title": "示例技能",
"content": "Markdown Wiki 内容"
},
"pages": []
}
}
IR 需要版本化:
extractor_version:扫描、解析、提示词和抽取 schema 的整体版本。prompt_hash:LLM 抽取提示词 hash。model_name:抽取模型名。source_digest:技能目录内容 digest。
只要 source_digest + extractor_version + prompt_hash + model_name 相同,就可以复用已有 snapshot,避免 200 个技能批量时反复抽取。
9. 关系抽取规则
关系来源分三类:
| 来源 | 示例 | 置信度策略 |
|---|---|---|
| 确定性结构关系 | 目录包含文件、Markdown 链接、数据文件引用、业务配置引用 | confidence = 1.0 |
| 显式文本关系 | Markdown 中写明“本技能依赖 A”、“输出 B”、“调用接口 C” | LLM 抽取,但要求证据;通常 0.75 以上 |
| 模型推断关系 | 从上下文推断某工具服务于某步骤、某配置控制某行为 | 必须有证据片段和解释;无证据不得入库 |
无人工审核的前提下,必须设置阈值:
confidence >= 0.75:写入 Wiki 关系页和图谱投影文档。0.50 <= confidence < 0.75:只写入技能 Wiki 的“可能关系”小节,不进入规范关系。confidence < 0.50:丢弃。
每条关系都必须包含:
sourcepredicatetargetconfidencerelation_sourceevidence
如果没有证据路径和证据文本,不允许写入规范关系。
建议谓词归一化:
| 原始表达 | 规范 predicate |
|---|---|
| 依赖、需要、requires | depends_on |
| 调用、使用、uses | uses |
| 生成、输出、produces | produces |
| 读取、输入、consumes | consumes |
| 配置、控制 | configures |
| 包含、目录下有 | contains |
| 引用、链接到 | references |
| 替换、迁移到 | replaces |
| 属于 | belongs_to |
实现可以先内置有限谓词表,再允许保留 custom_predicate,但 UI 与关系页要展示规范谓词。
10. 同一知识库内的实体合并
实体合并范围只在一个目标知识库内生效,不跨知识库合并。
规范实体 key:
kb_mapping_id + entity_type + normalized_name
normalized_name 规则:
- Unicode NFKC 归一化。
- trim。
- 多空白折叠成单空格。
- ASCII 字母转小写。
- 中英文标点归一化。
- 去除无意义包裹符号,例如反引号、引号。
如果实体带有明确外部 ID,可优先使用:
kb_mapping_id + entity_type + external_id_type + external_id
合并规则:
normalized_name相同且entity_type兼容:合并。- 名称相同但类型不兼容:不合并,例如
config:web_search和tool:web_search可保持两个实体,必要时用configures关系连接。 - LLM 判断别名合并:只有
confidence >= 0.90且有明确证据时允许。 - 属性冲突不做最后写入覆盖,必须按来源保留 provenance。
实体贡献示例:
{
"canonical_entity_id": "ce_123",
"binding_id": "bind_001",
"snapshot_id": "snap_001",
"local_entity_id": "ent_001",
"attributes": {
"entrypoint": {
"value": "config.yaml tools.web_search",
"evidence": "config.yaml:10"
}
},
"confidence": 0.94
}
删除贡献时:
- 只删除该 binding 的贡献。
- 如果规范实体仍有其他贡献,保留实体页并重新生成聚合内容。
- 如果规范实体贡献数为 0,删除或标记归档该规范实体及其 Wiki 页面。
11. 关系合并
规范关系 key:
kb_mapping_id + source_canonical_entity_id + normalized_predicate + target_canonical_entity_id
合并规则:
- 同一 key 的关系合并为一条规范关系。
- 每个技能的证据作为 relation contribution 追加。
confidence可存储最大值、平均值和证据数,但展示优先显示最高置信证据。- 如果来源实体或目标实体被删除到无贡献,相关关系也需要重新计算。
关系 Wiki 页面内容必须保留:
- 关系三元组。
- 关系说明。
- 贡献技能列表。
- 证据路径。
- 置信度。
- 最近更新时间。
12. WeKnora 内容投影
每个技能归纳到一个目标知识库后,按目标 adapter 写入三类内容。目标是 WeKnora 时写入 WeKnora;目标是助手知识库或只读 sidecar 时写入 DeerFlow 自研存储。
12.1 原始资料
原始资料分两种:
- 可直接上传的文件:走 WeKnora 文件上传。
- 纯文本或需要展开的内容:创建手动文档,保留路径和 fenced code。
原始资料命名建议:
skills/{skill_name}/source/{relative_path}
文档 metadata 建议:
{
"source_type": "deerflow_skill",
"skill_name": "example-skill",
"binding_id": "bind_001",
"snapshot_id": "snap_001",
"source_digest": "sha256:...",
"relative_path": "SKILL.md",
"artifact_kind": "raw_source"
}
如果 WeKnora 不支持自定义 metadata,则本地 artifact 表必须保存远端 ID、slug、digest、kind 和来源关系。
12.2 技能 Wiki 页面
每个技能至少生成:
skills/{skill_name}/overview
skills/{skill_name}/files
skills/{skill_name}/entities
skills/{skill_name}/relations
skills/{skill_name}/evidence
内容要求:
overview:技能用途、输入、输出、依赖、使用方式、风险提示。files:重要文件清单、每个文件摘要、关键入口。entities:该技能贡献的实体,使用 Wiki 链接指向规范实体页。relations:确定关系和高置信推断关系,使用 Wiki 链接指向规范关系页。evidence:证据目录,只包含短摘录和位置,不包含敏感内容。
12.3 规范实体 Wiki 页面
规范实体页 slug:
entities/{entity_type}/{stable_entity_id}-{slugified_name}
页面内容:
- 实体名称和类型。
- 别名。
- 归并来源技能。
- 聚合描述。
- 属性表,冲突属性按来源列出。
- 相关关系列表。
- 证据索引。
12.4 规范关系 Wiki 页面
规范关系页 slug:
relations/{predicate}/{stable_relation_id}
页面内容:
[[source_entity]] --predicate--> [[target_entity]]- 中文说明。
- 贡献技能。
- 证据。
- 置信度。
- 更新时间。
说明:即便 WeKnora Wiki graph 只能展示无类型链接,关系类型也不能丢。类型和证据由关系页保存,Wiki 链接负责把实体页和关系页连接起来。
12.5 图谱投影文档
为提高 WeKnora GraphRAG 抽取成功率,每个 binding 生成一份机器可读关系文档:
skills/{skill_name}/graph-projection.jsonl
每行一个关系:
{
"source": "web_search",
"source_type": "tool",
"predicate": "used_by",
"target": "example-skill",
"target_type": "skill",
"description": "web_search 被 example-skill 用于首步检索",
"confidence": 0.88,
"evidence": "SKILL.md:22-28"
}
同时生成一份人类可读 Markdown:
skills/{skill_name}/graph-projection.md
该文档使用短句和固定模板,降低 WeKnora 抽取歧义:
# 技能关系投影:example-skill
- 实体 `web_search`(tool)与实体 `example-skill`(skill)存在 `used_by` 关系。
- 说明:web_search 被 example-skill 用于首步检索。
- 证据:SKILL.md:22-28
- 置信度:0.88
GraphRAG 可用时上传这些投影文档;Neo4j direct writer 开启时,同时把通过审核的规范实体和关系写入底层图数据库;两者都不可用时仍保留 Wiki 关系页和本地关系表。
13. 重归纳一致性
重归纳必须满足“成功后替换,失败不影响旧版本”。
流程:
- 读取当前 binding 和 active snapshot。
- 重新扫描技能目录,生成新 snapshot。
- 如果 digest 未变化且未强制重归纳,可以直接返回
synced。 - 在本地创建 staged artifact 记录。
- 写入 WeKnora 新版本原始资料、Wiki 页面、关系投影文档。
- 校验远端可读取或状态完成。
- 在一个数据库事务中:
- 将旧 artifact 标记为
retired。 - 将 staged artifact 标记为
active。 - 将 binding 的
current_snapshot_id指向新 snapshot。 - 更新实体和关系贡献。
- 设置 binding 状态为
synced或partial_failed。
- 将旧 artifact 标记为
- 对旧远端文件执行 best-effort 清理。
- 清理失败只记录 warning,不回滚已经激活的新版本。
如果第 5 或第 6 步失败:
- binding 仍指向旧 snapshot。
- 旧 WeKnora 内容继续有效。
- staged artifact 标记为
failed。 - item 状态为
failed或partial_failed。 - 前端显示错误,允许 retry / 重新归纳。
Wiki 页面建议采用稳定 slug upsert。原始资料如果 WeKnora 没有 update API,则创建新远端文档,确认成功后再删除旧远端文档。
14. 解除关联
解除一个技能与一个知识库的绑定时,前端必须弹窗让管理员选择:
| 选项 | 行为 |
|---|---|
| 保留知识库内容 | 绑定标记为 detached_keep。WeKnora 远端内容、助手库 Wiki revision 或 sidecar 内容保留为冻结知识,不再随技能重归纳更新。技能页不再显示为“当前归纳”,但可在历史中显示“已解除,内容保留”。 |
| 删除该技能贡献的内容 | 删除该 binding 的原始资料、技能 Wiki 页、关系投影文档、助手库 Wiki revision contribution、sidecar artifact 和实体/关系贡献;共享实体/关系只减少该技能贡献,仍有其他贡献则重建聚合页,没有贡献才删除。 |
如果删除远端内容部分失败:
- 本地记录 artifact
delete_failed。 - binding 状态为
detached_delete_pending_cleanup。 - 提供“重试清理”动作。
不要因为某个共享实体由该技能参与过,就删除其他技能还在使用的实体页。
15. 状态机
绑定状态建议:
| 状态 | 含义 |
|---|---|
pending |
已创建绑定,但尚未开始处理。 |
queued |
已进入任务队列。 |
running |
正在处理。 |
awaiting_review |
抽取完成,等待管理员审核实体、关系或 Wiki 草稿。 |
synced |
当前版本已成功归纳到目标知识库。 |
pending_remote_write |
只读目标已完成本地 sidecar 归纳,等待远端具备写权限后推送。 |
stale |
技能源文件已变化,但尚未手动重新归纳。 |
partial_failed |
核心 Wiki/原始资料成功,但部分文件、图谱或清理失败。 |
failed |
当前归纳失败,旧版本若存在则继续有效。 |
detached_keep |
已解除关联,远端内容保留。 |
detached_delete_pending_cleanup |
已解除关联,但删除远端内容未完全成功。 |
detached_deleted |
已解除关联,远端贡献已清理。 |
item 阶段建议:
scanning
parsing
summarizing
extracting
awaiting_review
merging
uploading_sources
writing_wiki
writing_graph_projection
verifying
activating
cleanup
completed
前端展示时,父任务进度由 item 数量和阶段加权计算,不要只显示一个不可解释的 spinner。
16. 持久化设计
下面是建议表结构,字段命名可按项目现有风格调整。
16.1 skill_knowledge_bindings
保存技能与知识库的多对多关系。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
skill_name |
技能名。 |
target_type |
weknora / assistant。 |
target_mode |
wiki / document / faq / conversation_archive / readonly_sidecar。 |
target_id |
目标知识库 ID。WeKnora 使用本地 mapping ID,助手库使用全局 base ID。 |
remote_business_key |
暴露给前端和外部系统的远端业务 key,例如 weknora:kb:xxx,可为空。 |
status |
绑定状态。 |
active |
是否当前有效绑定。 |
current_snapshot_id |
当前激活的技能快照。 |
source_digest |
最近扫描到的技能源 digest。 |
synced_digest |
最近成功归纳的 digest。 |
last_job_id |
最近一次父任务。 |
last_item_id |
最近一次 item。 |
last_synced_at |
最近成功归纳时间。 |
last_error_code |
最近错误码。 |
last_error_message |
最近错误摘要。 |
created_by |
管理员用户。 |
created_at / updated_at |
时间戳。 |
约束:
unique(skill_name, target_type, target_id)
16.2 skill_knowledge_snapshots
保存技能扫描和抽取结果。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
skill_name |
技能名。 |
source_digest |
技能目录 digest。 |
extractor_version |
抽取器版本。 |
prompt_hash |
提示词 hash。 |
model_name |
模型名。 |
manifest_json |
文件清单、hash、安全状态。 |
ir_json |
抽取后的 IR;较大时可存 blob 引用。 |
status |
ready / failed。 |
counts_json |
文件数、实体数、关系数、跳过数。 |
created_at |
创建时间。 |
约束:
unique(skill_name, source_digest, extractor_version, prompt_hash, model_name)
16.3 skill_knowledge_sync_jobs
保存一次批量归纳任务。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
target_count |
本次目标知识库数量。 |
targets_json |
目标知识库列表,每项包含 target_type、target_mode、target_id、展示名和远端业务 key。 |
status |
queued / running / completed / partial_failed / failed / canceled。 |
total_count |
技能数。 |
success_count |
成功数。 |
partial_failed_count |
部分失败数。 |
failed_count |
失败数。 |
cancel_requested |
是否请求取消。 |
created_by |
管理员用户。 |
created_at / started_at / completed_at |
时间戳。 |
16.4 skill_knowledge_sync_items
保存每个技能的任务项。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
job_id |
父任务。 |
binding_id |
绑定。 |
target_type |
目标类型。 |
target_mode |
目标模式。 |
target_id |
目标 ID。 |
skill_name |
技能名。 |
snapshot_id |
本次输入快照。 |
status |
item 状态。 |
phase |
当前阶段。 |
progress |
0-100。 |
active_dedupe_key |
活跃任务去重 key。 |
lease_owner |
执行器标识。 |
lease_until |
租约过期时间。 |
attempts |
尝试次数。 |
last_error_code |
错误码。 |
last_error_message |
错误摘要。 |
created_at / updated_at / started_at / completed_at |
时间戳。 |
活跃去重 key:
skill_name + target_type + target_id
同一绑定同一时间只能有一个 active item。
16.5 skill_knowledge_artifacts
保存本地到 WeKnora 的远端 artifact 映射。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
target_type |
目标类型。 |
target_mode |
目标模式。 |
target_id |
目标 ID。 |
binding_id |
绑定,可为空;规范实体/关系聚合页可只属于知识库。 |
snapshot_id |
来源快照。 |
scope |
binding / kb_aggregate。 |
kind |
raw_source / skill_wiki / entity_wiki / relation_wiki / graph_projection。 |
stable_key |
本地稳定 key。 |
remote_kind |
file / manual_document / wiki_page。 |
remote_id |
远端 ID。后端保存完整映射,前端可按权限展示和复制。 |
wiki_slug |
Wiki 页面 slug。 |
content_hash |
写入内容 hash。 |
version |
版本号。 |
status |
staged / active / retired / failed / delete_failed。 |
created_at / updated_at |
时间戳。 |
16.6 skill_knowledge_entities
规范实体表。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
target_type |
目标类型。 |
target_mode |
目标模式。 |
target_id |
目标 ID。 |
entity_type |
实体类型。 |
normalized_name |
归一化名称。 |
display_name |
展示名称。 |
aliases_json |
别名。 |
description |
聚合描述。 |
stable_slug |
Wiki slug。 |
status |
active / retired。 |
created_at / updated_at |
时间戳。 |
约束:
unique(target_type, target_id, entity_type, normalized_name)
16.7 skill_knowledge_entity_contributions
规范实体的技能贡献。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
canonical_entity_id |
规范实体 ID。 |
binding_id |
绑定。 |
snapshot_id |
快照。 |
local_entity_id |
IR 中的实体 ID。 |
attributes_json |
该技能贡献的属性。 |
evidence_json |
证据。 |
confidence |
置信度。 |
status |
active / retired。 |
created_at / updated_at |
时间戳。 |
16.8 skill_knowledge_relations
规范关系表。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
target_type |
目标类型。 |
target_mode |
目标模式。 |
target_id |
目标 ID。 |
source_entity_id |
源规范实体。 |
predicate |
规范谓词。 |
target_entity_id |
目标规范实体。 |
description |
聚合说明。 |
stable_slug |
Wiki slug。 |
status |
active / retired。 |
created_at / updated_at |
时间戳。 |
约束:
unique(target_type, target_id, source_entity_id, predicate, target_entity_id)
16.9 skill_knowledge_relation_contributions
规范关系的技能贡献。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
canonical_relation_id |
规范关系 ID。 |
binding_id |
绑定。 |
snapshot_id |
快照。 |
local_relation_id |
IR 中的关系 ID。 |
relation_source |
deterministic / explicit_text / llm_inferred。 |
evidence_json |
证据。 |
confidence |
置信度。 |
status |
active / retired。 |
created_at / updated_at |
时间戳。 |
17. 后台任务设计
参考现有 deep research job 的持久化后台任务模式:
- 任务入库后返回
202 Accepted。 - 执行器通过 DB 原子条件 claim item。
- 每个 item 有
lease_owner、lease_until。 - 执行中定期 heartbeat。
- 服务重启后可恢复过期 lease。
- cancel 使用
cancel_requested,任务在阶段边界检查并安全停止。
并发建议:
- 同时处理技能数:2 到 4。
- 同时调用 WeKnora 写入:2 到 3。
- 同时 LLM 抽取:按系统现有限流,建议默认 2。
200 个技能批量时:
- 父 job 只保存聚合进度,不串行阻塞 HTTP 请求。
- 每个技能 item 独立失败、独立重试。
- 前端按 job polling,不为每个技能单独发 N 个请求。
- 获取技能列表时批量查 binding summary,避免 N+1。
- 快照缓存可复用,跨知识库只重新投影,不重复解析同一技能内容。
18. 后端 API 设计
新增 router:
/api/skill-knowledge
所有写接口仅管理员可用。
18.1 获取技能绑定摘要
GET /api/skill-knowledge/bindings?skill_names=a,b,c
返回:
{
"items": [
{
"skill_name": "example-skill",
"knowledge_bases": [
{
"binding_id": "bind_001",
"target_type": "weknora",
"target_mode": "wiki",
"target_id": "local-kb-id",
"knowledge_base_name": "作战知识库",
"remote_business_key": "weknora:kb:remote-kb-id",
"status": "synced",
"last_synced_at": "2026-08-31T10:00:00Z",
"source_digest": "sha256:...",
"synced_digest": "sha256:...",
"stale": false
}
]
}
]
}
18.2 创建归纳任务
POST /api/skill-knowledge/sync-jobs
请求:
{
"skill_names": ["skill-a", "skill-b"],
"targets": [
{
"target_type": "weknora",
"target_mode": "wiki",
"target_id": "local-kb-id"
},
{
"target_type": "assistant",
"target_mode": "wiki",
"target_id": "assistant-global-base"
}
],
"force": false
}
行为:
- 校验管理员。
- 校验技能存在。
- 校验目标知识库存在,并解析目标 adapter。
- 对只读目标创建 sidecar binding,不强行写远端。
- 对每个
skill x targetupsert binding。 - 创建父 job 和 item。
- 如果同一 binding 已有 active item,返回当前 item,不重复创建。
- 返回
202。
返回:
{
"job_id": "job_001",
"status": "queued",
"skill_count": 2,
"target_count": 2,
"total_count": 4,
"items": [
{
"item_id": "item_001",
"skill_name": "skill-a",
"target_type": "weknora",
"target_mode": "wiki",
"target_id": "local-kb-id",
"binding_id": "bind_001",
"status": "queued"
}
]
}
18.3 查询任务
GET /api/skill-knowledge/sync-jobs/{job_id}
返回父 job、item 列表、每个 item 当前阶段、错误摘要、绑定结果。
18.4 取消任务
POST /api/skill-knowledge/sync-jobs/{job_id}/cancel
设置 cancel_requested = true。已激活成功的 item 不回滚;未完成 item 在阶段边界停止。
18.5 重试 item
POST /api/skill-knowledge/sync-items/{item_id}/retry
只允许失败或部分失败 item。重试复用原 binding。
18.6 对单个绑定重新归纳
POST /api/skill-knowledge/bindings/{binding_id}/resync
请求:
{
"force": true
}
行为:创建一个只包含该 binding 的新 job。
18.7 解除关联
建议使用显式 POST,避免 DELETE body 兼容性问题:
POST /api/skill-knowledge/bindings/{binding_id}/detach
请求:
{
"remote_content_action": "keep"
}
或:
{
"remote_content_action": "delete"
}
返回解除结果、清理状态和仍被共享的实体/关系数量。
18.8 知识库反查技能
GET /api/skill-knowledge/knowledge-bases/{knowledge_base_id}/skills
用于知识库详情页展示“该知识库由哪些技能归纳而来”。
18.9 可选:源状态扫描
POST /api/skill-knowledge/source-status
请求:
{
"skill_names": ["skill-a", "skill-b"],
"knowledge_base_id": "local-kb-id"
}
只做本地快速 fingerprint 比对,标记是否可能 stale,不写 WeKnora。
18.10 审核队列
GET /api/skill-knowledge/reviews?job_id=xxx
POST /api/skill-knowledge/reviews/{review_id}/approve
POST /api/skill-knowledge/reviews/{review_id}/reject
PUT /api/skill-knowledge/reviews/{review_id}
POST /api/skill-knowledge/reviews/bulk-approve
POST /api/skill-knowledge/reviews/bulk-reject
审核通过后 item 才能进入写入阶段。审核模式为 off 时,接口仍保留预览和审计能力。
18.11 自动同步配置
GET /api/skill-knowledge/auto-sync-settings
PUT /api/skill-knowledge/auto-sync-settings
POST /api/skill-knowledge/bindings/{binding_id}/enable-auto-sync
POST /api/skill-knowledge/bindings/{binding_id}/disable-auto-sync
自动同步设置只允许管理员修改。
19. 前端交互设计
19.1 技能管理页
在 AdminSkillsPage.tsx 的“技能列表”页签增加:
- 技能行 checkbox。
- 顶部批量操作按钮:“归纳到知识库”。
- 支持全选当前页、清空选择。
- 选择状态跨前端分页保留。
- 技能较多时保持现有搜索/过滤能力。
点击“归纳到知识库”打开弹窗:
- 显示已选技能数量。
- 多选目标知识库。
- 按类型分组展示:WeKnora Wiki、WeKnora 非 Wiki、FAQ、系统会话存档、只读 sidecar、助手知识库。
- 只读目标要展示“本地归纳,暂不写远端”的状态说明。
- 助手知识库作为目标时,提示“直接写入知识梳理底库,不经过 WeKnora”。
- 二次确认文案说明:“将生成原始资料、Wiki 页面和关系内容;抽取完成后进入实体/关系预览审核。”
提交后:
- 创建后台 job。
- 跳转或打开“归纳任务”抽屉/页签。
- 展示总进度、成功、失败、部分失败。
- 任务运行中每 2-3 秒 polling。
- item 到达
awaiting_review时,显示“待审核”并提供审核入口。
19.1.1 实体/关系审核页
审核页按 job 聚合展示:
- 左侧筛选:技能、目标知识库、类型、置信度、来源。
- 中间列表:实体、关系、实体对齐候选、关系合并候选、Wiki 草稿。
- 右侧详情:原始值、模型解释、证据、目标写入位置。
管理员可以:
- 单条批准、拒绝、编辑。
- 批量批准高置信结果。
- 批量拒绝低置信结果。
- 修改实体类型、名称、别名。
- 修改关系 predicate、说明、confidence。
- 查看远端 ID 或 sidecar ID。
审核完成后,任务继续写入目标知识库。
19.2 技能行提示
SkillRow 增加归纳状态区域:
- 未归纳:不显示或显示弱提示“未归纳”。
- 已归纳:显示
已归纳至 N 个知识库。 - 展开或悬浮可看到知识库 chips:
- 知识库名称
- 状态
- 最近归纳时间
- stale 标识
每个绑定提供动作:
- 查看知识库。
- 重新归纳。
- 解除关联。
- 失败时重试。
状态建议:
| 状态 | UI 文案 |
|---|---|
synced |
已归纳 |
stale |
待重新归纳 |
running |
归纳中 |
partial_failed |
部分完成 |
failed |
失败 |
detached_keep |
已解除,内容保留 |
19.3 解除关联弹窗
弹窗必须让管理员明确选择:
- 保留知识库内容。
- 删除该技能贡献的内容。
弹窗文案应提醒:
- 删除只删除该技能贡献,不删除其他技能共享的实体与关系。
- 若删除远端内容失败,可稍后重试清理。
19.4 归纳任务页签
建议在管理员技能管理页新增第三个页签:
技能列表 | 技能地址管理 | 归纳任务
任务列表显示:
- 创建时间。
- 目标知识库。
- 操作人。
- 总技能数。
- 成功 / 部分失败 / 失败。
- 状态。
- 操作:查看详情、取消、重试失败项。
详情显示 item:
- 技能名。
- 目标知识库。
- 目标类型。
- 当前阶段。
- 进度。
- 错误摘要。
- 绑定状态。
19.6 自动同步设置
管理员可在技能归纳设置中配置:
- 是否开启文件监听。
- 是否开启定时同步。
- 同步周期。
- 自动写远端开关。
- 审核模式。
- 单个 binding 是否参与自动同步。
19.5 知识库详情反向展示
如果现有 WeKnora / LLM Wiki 页面有知识库详情入口,增加“来源技能”区域:
- 技能名。
- 归纳状态。
- 最近归纳时间。
- 查看技能。
- 重新归纳。
20. stale 检测与自动同步
系统既要支持手动重新归纳,也要支持自动同步。stale 检测负责判断“源知识文件是否变化”;自动同步负责在配置允许时创建后台任务并远程写入。
本地标识 stale:
- 技能编辑、启停、删除等已知写操作完成后,查找相关 binding 并标记
stale。 - 技能列表加载时可做轻量 fingerprint:路径、大小、mtime。
- 真正归纳时计算完整 SHA digest。
- 如果归纳过程中源文件变化,最终激活前再次校验 expected digest;不一致则失败并标记 stale,避免一个版本混入两次源内容。
- 代码文件和脚本文件不参与 fingerprint,也不触发 stale。
自动同步:
- 当
watch_enabled开启时,知识文件变化后自动创建相关 binding 的归纳任务。 - 当
schedule_enabled开启时,scheduler 按周期扫描并归纳 stale binding。 - 当技能保存、导入、删除或启停时,可触发相关 binding 的自动任务。
- 自动任务必须遵循审核模式;如果需要审核,任务停在
awaiting_review。 - 自动任务必须遵循 staged 激活;失败不覆盖旧版本。
21. 权限与安全
权限:
- 所有归纳、重归纳、解除关联、取消、重试接口仅管理员。
- 读接口如果包含后台任务错误或源文件路径,也建议仅管理员。
文件安全:
- 技能根必须限制在
skills/public或skills/custom。 - 禁止路径穿越。
- 默认不跟随 symlink;如果要支持 symlink,必须确认 resolved path 仍在技能根内。
- 压缩包解压必须限制总大小、文件数量、单文件大小、目录层级。
- 不执行技能代码。
- 不读取或上传密钥文件。
- 日志和错误信息不得包含文件全文、token、secret。
远端安全:
- 不新增外部 URL 抓取能力。
- 如果技能内容中包含 URL,只作为文本关系或知识内容处理,不主动访问。
- WeKnora 调用失败时,记录错误摘要和 request id,不记录认证头。
22. LLM 抽取设计
抽取可分两级:
- 小技能:一次性把文本摘要和结构信息送入模型。
- 大技能:先按文件或章节生成局部摘要与候选实体关系,再合并。
提示词需要明确:
- 只基于提供的内容抽取,不凭空编造。
- 允许推断,但推断必须有 evidence。
- 输出必须符合 JSON schema。
- 不输出敏感信息。
- 关系必须有 confidence。
- 低置信关系要标记,不进入规范关系。
建议 schema:
{
"summary": {
"purpose": "技能用途",
"inputs": ["输入"],
"outputs": ["输出"],
"usage": "使用方式",
"risks": ["风险"]
},
"entities": [
{
"id": "ent_001",
"type": "skill|tool|api|file|config|dataset|concept|workflow|external_system|output",
"name": "实体名",
"aliases": [],
"description": "描述",
"attributes": {},
"evidence": [
{
"file_path": "SKILL.md",
"line_start": 1,
"line_end": 3,
"quote": "短证据"
}
],
"confidence": 0.9
}
],
"relations": [
{
"id": "rel_001",
"source_entity_id": "ent_001",
"predicate": "uses",
"target_entity_id": "ent_002",
"description": "关系描述",
"relation_source": "explicit_text|llm_inferred",
"evidence": [],
"confidence": 0.86
}
]
}
模型输出后必须做程序校验:
- JSON schema 校验。
- entity id 存在性校验。
- relation source/target 必须存在。
- evidence path 必须来自本次 manifest。
- confidence 必须在 0 到 1。
- 敏感内容二次扫描。
23. 后端实现步骤
建议按以下顺序实现。
23.1 持久化层
新增 deerflow.persistence.skill_knowledge:
- SQL model。
- memory store,用于测试或无 DB 环境。
- repository API。
- migration 或
create_all接入。
Repository API 建议:
class SkillKnowledgeStore:
async def upsert_binding(...)
async def list_bindings(...)
async def create_job(...)
async def create_items(...)
async def claim_next_item(...)
async def heartbeat_item(...)
async def complete_item(...)
async def fail_item(...)
async def create_or_get_snapshot(...)
async def stage_artifacts(...)
async def activate_snapshot(...)
async def detach_binding(...)
23.2 扫描与解析
新增:
deerflow/skill_knowledge/scanner.py
deerflow/skill_knowledge/parsers.py
deerflow/skill_knowledge/safety.py
deerflow/skill_knowledge/digest.py
输出 manifest 和初始文本块。
23.3 抽取与归纳
新增:
deerflow/skill_knowledge/extractor.py
deerflow/skill_knowledge/wiki_builder.py
职责:
- 构造 prompt。
- 调用项目已有模型封装。
- 解析 JSON。
- 校验 schema。
- 构建技能 Wiki 页面内容。
23.4 实体关系合并
新增:
deerflow/skill_knowledge/merge.py
职责:
- 名称归一化。
- 实体 upsert。
- 关系 upsert。
- 贡献增删。
- 共享实体/关系重建计划。
23.5 WeKnora 投影
新增:
deerflow/skill_knowledge/projector.py
deerflow/skill_knowledge/target_adapters.py
deerflow/skill_knowledge/graph_writer.py
职责:
- 根据 IR 和聚合结果生成 artifact plan。
- 按目标知识库类型选择 adapter。
- 调用 WeKnora client 上传原文、FAQ、会话归档或 Wiki 页面。
- 为只读目标写本地 sidecar artifact。
- 上传 graph projection docs。
- 在配置允许时通过受控 graph writer 写 Neo4j。
- 校验远端状态。
23.6 Gateway
新增:
app/gateway/routers/skill_knowledge.py
app/gateway/skill_knowledge_job_dispatcher.py
app/gateway/skill_knowledge_job_executor.py
app/gateway/skill_knowledge_watcher.py
app/gateway/skill_knowledge_scheduler.py
在 app 初始化中注册:
- store。
- dispatcher。
- watcher。
- scheduler。
- router。
23.7 前端
新增:
frontend-web/src/strategy-components/api/skill-knowledge.ts
frontend-web/src/components/workspace/skills/skill-knowledge-sync-dialog.tsx
frontend-web/src/components/workspace/skills/skill-knowledge-bindings.tsx
frontend-web/src/components/workspace/skills/skill-knowledge-jobs-panel.tsx
修改:
AdminSkillsPage.tsx:技能列表批量选择、归纳弹窗、归纳任务页签。skill-settings-page.tsx:SkillRow展示归纳知识库 chips 和操作。- 知识库详情页:展示来源技能。
23.8 助手知识库
新增:
offline-backend-20260512/backend/packages/harness/deerflow/assistant_knowledge/
offline-backend-20260512/backend/packages/harness/deerflow/persistence/assistant_knowledge/
offline-backend-20260512/backend/app/gateway/routers/assistant_knowledge.py
offline-backend-20260512/backend/app/gateway/assistant_knowledge_import_executor.py
frontend-web/src/strategy-components/api/assistant-knowledge.ts
frontend-web/src/pages/AssistantKnowledgePage.tsx
职责:
- 初始化唯一全局助手知识库“知识梳理”。
- 从 WeKnora 导出包导入 Wiki、文档、chunk、实体、关系、图谱。
- 做全局实体对齐和关系合并。
- 生成助手库 Wiki 页面。
- 建立搜索索引。
- 支持普通用户只读、管理员导入和维护。
- 支持知识库产品版本
v1/v2切换。
23.9 审核队列
新增:
offline-backend-20260512/backend/packages/harness/deerflow/persistence/skill_knowledge/review_model.py
frontend-web/src/components/workspace/skills/skill-knowledge-review-panel.tsx
职责:
- 保存实体、关系、对齐候选、Wiki 草稿的审核项。
- 支持批准、拒绝、编辑、批量处理。
- 审核完成后唤醒对应 item 继续写入。
- 保留完整审计。
24. 测试计划
后端测试:
| 测试 | 覆盖点 |
|---|---|
test_skill_knowledge_scanner.py |
文件扫描、排除目录、敏感文件阻断、压缩包安全。 |
test_skill_knowledge_extractor.py |
LLM 输出 schema 校验、低置信关系过滤、证据路径校验。 |
test_skill_knowledge_entity_merge.py |
同知识库实体合并、跨知识库不合并、属性冲突 provenance。 |
test_skill_knowledge_repository.py |
绑定唯一、多对多、状态机、detach keep/delete。 |
test_skill_knowledge_jobs.py |
job/item claim、lease、重试、取消、崩溃恢复、200 item 聚合进度。 |
test_skill_knowledge_weknora_projection.py |
Wiki slug upsert、artifact staged/active、GraphRAG 不可用 partial_failed。 |
test_skill_knowledge_api.py |
管理员鉴权、目标知识库校验、创建任务、查询任务、解除关联。 |
test_skill_knowledge_target_adapters.py |
Wiki、非 Wiki、FAQ、会话存档、只读 sidecar、助手库目标写入。 |
test_skill_knowledge_review.py |
实体/关系逐条审核、编辑、批量批准、审核阻塞写入。 |
test_skill_knowledge_auto_sync.py |
文件监听、定时同步、代码文件变化不触发、staged 自动写入。 |
test_skill_knowledge_graph_writer.py |
Neo4j 参数化写入、事务、审计、回滚计划、禁用任意 Cypher。 |
test_assistant_knowledge_repository.py |
唯一全局底库、来源、导入任务、实体关系贡献。 |
test_assistant_knowledge_import.py |
WeKnora 导出包导入、实体对齐、关系合并、搜索索引。 |
test_assistant_knowledge_api.py |
普通用户只读、管理员写入、未配置 WeKnora 场景。 |
前端测试:
- 管理员技能页可以多选技能并打开知识库选择弹窗。
- 知识库选择弹窗支持多选目标,包含 Wiki、非 Wiki、FAQ、会话存档、只读 sidecar 和助手知识库。
- 创建 job 后显示进度并 polling。
- 抽取后进入实体/关系审核页,审核通过后继续写入。
- 技能行展示已归纳知识库 chips。
- 重归纳按钮调用正确接口。
- 解除关联弹窗必须选择 keep/delete。
- 200 个技能绑定摘要使用批量接口,不触发 N+1。
- 未配置 WeKnora 时仍能展示助手知识库初始化入口。
- 普通知识库详情页可触发导入到助手知识库。
- 助手知识库搜索、Wiki 页面、来源列表按权限展示。
建议命令:
cd offline-backend-20260512/backend
PYTHONPATH=. uv run pytest tests/test_skill_knowledge_*.py -v
PYTHONPATH=. uv run pytest tests/test_harness_boundary.py -v
cd frontend-web
pnpm typecheck
pnpm test -- skill-knowledge
25. 验收场景
必须通过:
- 管理员选择 3 个技能归纳到 2 个目标知识库,生成 1 个 job、6 个 item、6 个 binding。
- 同一个技能随后归纳到另一个知识库,新增第二个 binding,技能行显示已归纳至 2 个知识库。
- 技能可以直接归纳到助手知识库,并生成实体对齐、Wiki 页面版本和搜索索引。
- 同一个技能同一个 digest 重复归纳,不产生重复 Wiki 页面或重复实体关系。
- 两个技能在同一知识库中抽取出同名同类型实体,只生成一个规范实体页,并列出两个贡献技能。
- 解除其中一个技能并选择删除内容后,共享实体仍保留另一个技能贡献。
- 关系必须带 evidence 和 confidence;低于 0.75 的推断关系不进入规范关系。
- 重归纳成功后,新版本替换旧版本;旧 artifact 进入 retired。
- 重归纳失败时,旧版本继续显示为当前版本。
- 解除关联选择保留内容后,远端 Wiki 和文档保留,但 binding 不再参与后续重归纳。
- 非管理员访问写接口返回 403。
- 非 Wiki、FAQ、系统会话存档知识库可作为目标,并通过对应 adapter 写入。
- 只读知识库可作为目标,结果写入本地 sidecar,远端状态显示
pending_remote_write。 - 直接 Neo4j 写入只在配置开启时执行,且只使用参数化 graph writer。
- 自动文件监听和定时同步可以创建后台任务,代码文件变化不会触发同步。
- 前端可逐条审核实体/关系,也可按策略批量处理。
- 前端展示 WeKnora 远端 ID,并可复制业务 key。
- WeKnora GraphRAG 不可用时,原始资料和 Wiki 成功,状态为
partial_failed,可重试图谱投影。 - 200 个技能批量归纳时,页面显示整体进度,失败技能可单独重试,后端没有 N+1 查询。
- 技能中出现
.env或私钥时,该文件不上传、不进 prompt,页面显示安全跳过。 - 技能中的
.py、.ts、.sh等代码文件不读取、不上传、不摘要,代码文件变化不触发知识 stale。 - 未配置 WeKnora 时,助手知识库仍可初始化和查看。
- 管理员可从普通知识库触发导入到助手知识库。
- 管理员可向助手知识库导入本地文件,安全扫描通过后生成 Wiki 页面版本。
- WeKnora 导出包中的 Wiki、文档、chunk、实体、关系、图谱都能进入助手底库。
- 助手底库把多个来源中的同一人或同一对象合并为一个实体 Wiki 页。
- 助手 Wiki 支持历史版本、对比和回滚。
- 助手知识库普通用户只读,管理员可导入、重导、删除来源。
26. 分阶段交付
第一阶段:数据模型与 API 骨架
- 建表和 store。
- 绑定列表、创建 job、查询 job、detach API。
- 管理员鉴权。
- 前端技能行能展示空绑定状态。
第二阶段:扫描、快照与后台任务
- 技能目录扫描。
- 文件 digest 和 manifest。
- job/item 执行器、lease、heartbeat、失败重试。
- 200 技能批量进度。
第三阶段:Wiki 归纳与原始资料上传
- LLM 摘要和 Wiki 页面生成。
- WeKnora 原文上传。
- Wiki page upsert。
- staged/active 替换。
第四阶段:实体关系合并与关系投影
- 规范实体和关系表。
- contribution 机制。
- 关系 Wiki 页面。
- graph projection docs。
- GraphRAG 能力探测和 partial_failed。
第五阶段:完整前端体验
- 多选技能归纳弹窗。
- 归纳任务页签。
- 技能行 chips、详情、重归纳、解除关联。
- 知识库详情来源技能反查。
第六阶段:安全、测试、文档收口
- 敏感文件阻断。
- 压缩包安全。
- 崩溃恢复。
- README / CLAUDE 更新。
- 后端和前端测试。
第七阶段:助手知识库与产品版本
- 新增唯一全局助手知识库“知识梳理”。
- 新增 WeKnora 导出到助手库导入任务。
- 新增技能直接导入助手知识库。
- 新增管理员本地文件导入助手知识库。
- 新增助手库实体对齐、关系合并和 Wiki 展示。
- 新增助手库搜索。
- 新增助手库 Wiki 页面版本管理、对比和回滚。
- 新增知识库产品版本
v1/v2切换。 - 处理未配置 WeKnora 时的助手库默认展示。
第八阶段:多目标、审核、自动同步和底层图写入
- 支持一次选择多个目标知识库。
- 支持非 Wiki、FAQ、系统会话存档和只读目标 adapter。
- 支持实体/关系逐条审核。
- 支持文件监听、定时同步、技能变更自动远程写入。
- 支持受控 Neo4j direct writer。
- 支持远端 WeKnora ID 作为业务 key 暴露给前端。
27. 给实现大模型的硬性指令
实现时必须遵守:
- 先完整阅读根目录
AGENTS.md、后端AGENTS.md、后端CLAUDE.md。 - 不要回滚用户已有改动。
- 支持直接写 WeKnora 的 Neo4j,但必须通过受控 graph writer、显式配置、参数化模板、事务和审计。
- 支持把远端 WeKnora ID 作为前端业务 key 暴露,但本地仍保留 surrogate id。
- 不要让
deerflow.*importapp.*。 - 不要执行技能里的代码。
- 不要读取、上传、摘要或展示技能里的代码文件、脚本文件和代码块内容。
- 不要上传或提示词输入密钥文件。
- 技能可以直接归纳到助手知识库,必须走同样的安全扫描、审核和实体对齐。
- 不要创建多个助手知识库;助手知识库只有一个全局“知识梳理”底库。
- 自动 watcher、定时同步和技能变更远程写入必须使用 staged 激活、去重、审核和失败保留旧版本。
- 重归纳必须 staged 写入,成功后再激活。
- 删除绑定贡献时必须按 contribution refcount 处理共享实体和关系。
- 助手知识库需要 Wiki 页面版本管理、版本对比、回滚和导入任务审计。
- 直接写 Neo4j 必须通过受控 graph writer 和参数化模板,不允许执行 LLM 生成的任意 Cypher。
- 远端 WeKnora ID 可以作为前端业务 key 暴露,但本地仍要保留 surrogate id 和 mapping。
- 后端代码变更后按仓库要求更新相关 README / CLAUDE。
- 涉及文件编辑使用
apply_patch或项目正常格式化工具,不做无关重构。
28. 实现任务清单
- 新增
skill_knowledge持久化模型和 store。 - 新增绑定、job、item、artifact、entity、relation、contribution 表。
- 新增管理员 router
/api/skill-knowledge。 - 接入知识库能力校验,支持 Wiki、非 Wiki、FAQ、会话存档、只读 sidecar 和助手知识库。
- 支持一次选择多个目标知识库,并按
技能 x 目标生成 item。 - 新增技能扫描器,支持全部非代码知识文件、安全排除和 digest。
- 技能扫描器完全排除代码文件、脚本文件和 Markdown 代码块内容。
- 新增 snapshot 缓存。
- 新增 LLM 抽取器,输出 schema 校验。
- 新增 Wiki 页面生成器。
- 新增实体归一化与合并逻辑。
- 新增关系归一化与合并逻辑。
- 新增 WeKnora artifact projector。
- 新增 target adapters。
- 新增 graph projection 文档生成和上传。
- 新增受控 Neo4j direct graph writer。
- 新增实体/关系审核队列。
- 新增后台 job dispatcher / executor。
- 新增文件 watcher、定时同步 scheduler、技能变更自动写入触发。
- 实现 resync 成功替换、失败保留旧版本。
- 实现 detach keep/delete。
- 技能变更后标记 binding stale。
- 前端新增
skill-knowledge.tsAPI。 - 技能管理页新增多选归纳入口。
- 新增选择知识库弹窗。
- 新增归纳任务页签。
- 技能行展示已归纳知识库状态。
- 实现重归纳、重试、取消、解除关联 UI。
- 知识库详情展示来源技能。
- 新增唯一全局助手知识库“知识梳理”。
- 新增助手知识库持久化模型、来源、导入任务、Wiki、实体、关系、贡献表。
- 新增 WeKnora 导出到助手知识库任务。
- 支持技能直接导入助手知识库。
- 支持管理员本地文件导入助手知识库。
- 导出范围覆盖 Wiki、文档、chunk、实体、关系、图谱。
- 助手知识库实现全局实体对齐和关系合并。
- 助手知识库生成 Wiki 页面并支持搜索。
- 助手知识库支持 Wiki 页面版本管理、对比、发布和回滚。
- 新增知识库产品版本
v1/v2设置,默认v1。 - 未配置 WeKnora 时仍展示助手知识库创建或初始化入口。
- 助手知识库普通用户只读,管理员可导入、重导、删除。
- 后端测试覆盖核心状态机和安全边界。
- 前端测试覆盖主要交互。
- 更新后端 README / CLAUDE 与必要前端文档。
29. 风险与处理
| 风险 | 处理 |
|---|---|
| WeKnora 图谱 API 在部署版本不稳定 | 以 Swagger 能力探测为准;Wiki 关系页和 graph projection 文档作为稳定方案。 |
| LLM 推断关系误判 | 强制 evidence、confidence 阈值、低置信不进入规范关系。 |
| 200 技能批量耗时长 | 后台 job、item 并发、snapshot 缓存、前端批量查询。 |
| 重归纳中断导致新旧混杂 | staged artifact + 本地事务激活 + 失败保留旧版本。 |
| 删除共享实体误删其他技能知识 | contribution refcount,删除只移除该 binding 贡献。 |
| 敏感信息进入知识库 | 文件级安全阻断、prompt 前二次扫描、日志脱敏。 |
| 技能目录处理阻塞 Gateway | 文件 IO 和转换统一 asyncio.to_thread。 |
| 技能源文件归纳中变化 | expected digest 校验,不一致则失败并标记 stale。 |
30. 新增:普通知识库与助手知识库双体系
本节是基于新需求的补充设计。后续实现以本节为准;如果本节与前文旧的 WeKnora-only 表述冲突,优先采用本节。
30.1 产品形态
系统需要区分两类知识库:
| 类型 | 存储 | 用途 | 可见性 | 写入来源 |
|---|---|---|---|---|
| 普通知识库 | WeKnora | 文档向量化、Wiki、检索、图谱、技能归纳目标 | 按现有 WeKnora 逻辑 | 技能归纳、现有 WeKnora 导入 |
| 助手知识库 | DeerFlow 自研库 | 全局知识梳理、实体对齐、Wiki 展示、搜索、版本管理 | 所有人可见,普通用户只读 | WeKnora 导出、WeKnora 自动沉淀、技能直接归纳、管理员本地文件导入 |
产品版本开关:
v1:默认值,优先展示现有普通知识库体验。v2:优先展示助手知识库体验。- 管理员可在系统设置中切换版本。
- 如果未配置 WeKnora,即使当前版本默认是
v1,页面也应展示助手知识库创建/初始化入口;WeKnora 相关能力隐藏或置灰,并提示“未配置普通知识库服务”。
建议新增系统设置项:
{
"knowledge_base_product_version": "v1"
}
30.2 助手知识库定位
助手知识库只有一个全局底库,建议默认名:
知识梳理
它不是 WeKnora 的另一个知识库,也不向 WeKnora 写数据。它是 DeerFlow 自己维护的结构化知识底库。
助手知识库对用户展示:
- Wiki 页面列表。
- Wiki 页面详情。
- Wiki 页面版本、对比和回滚。
- 实体页。
- 关系页。
- 搜索。
- 数据导入记录。
助手知识库内部可以存实体、关系、贡献、来源、搜索索引,但前端主体验以 Wiki 为中心,不做复杂图数据库管理页。
权限:
- 普通用户:可查看、搜索。
- 管理员:可初始化助手知识库、从 WeKnora 导入、重新导入、删除导入来源、编辑或删除 Wiki 页面。
30.3 数据来源
助手知识库的数据来源包括 WeKnora、技能归纳和管理员本地文件。
支持四种触发方式:
| 方式 | 说明 |
|---|---|
| 自动沉淀 | WeKnora 普通知识库完成文档向量化、Wiki 生成和图谱抽取后,默认创建一个导入任务,把处理结果沉淀到助手知识库。 |
| 手动导入 | 管理员在普通知识库页面点击“导入到助手知识库”或“导出到知识梳理”,本质仍是导出 WeKnora 数据后导入助手库。 |
| 技能直接归纳 | 管理员在技能管理页选择助手知识库作为目标,系统直接写入自研助手底库。 |
| 本地文件导入 | 管理员在助手知识库页面上传本地文件,系统安全扫描后抽取实体、关系和 Wiki 页面。 |
限制:
- 普通用户不能写入助手知识库。
- 本地文件导入必须走敏感信息扫描、文件类型白名单、大小限制和导入审计。
- 技能直接归纳仍然完全排除代码文件、脚本文件和 Markdown 代码块内容。
30.4 WeKnora 导出范围
从 WeKnora 导入助手知识库时,需要尽可能导出全部已处理数据:
- 知识库元数据。
- Wiki 页面。
- Wiki 页面之间的链接。
- 已上传文档信息。
- 已向量化完成的 chunk 文本、chunk metadata、来源文档映射。
- WeKnora 可读取的实体。
- WeKnora 可读取的关系。
- WeKnora 可读取的图谱节点和边。
- 技能归纳产生的 source metadata,例如
skill_name、binding_id、snapshot_id。
说明:
- 助手知识库不强依赖复用 WeKnora embedding 向量。若 WeKnora 不暴露 embedding 原始向量,导入 chunk 文本和 metadata 即可。
- 如果 WeKnora 不暴露稳定的图谱导出 API,则使用现有 Wiki graph、关系投影文档、Wiki 关系页和可查询接口重建实体关系。
- 导入过程要记录能力缺失:例如“已导入 Wiki 与文档,图谱 API 不可用,关系由 Wiki 关系页重建”。
导出包建议:
{
"export_id": "wk_export_001",
"source": {
"type": "weknora",
"knowledge_base_id": "local-kb-id",
"knowledge_base_name": "作战知识库",
"exported_at": "2026-09-01T10:00:00Z"
},
"wiki_pages": [],
"documents": [],
"chunks": [],
"entities": [],
"relations": [],
"graph": {
"nodes": [],
"edges": []
}
}
30.5 助手库实体对齐
助手知识库的核心价值是把来自不同 WeKnora 普通知识库、不同技能来源、不同 Wiki 页中的同一实体合并。
实体对齐范围是全局助手库:
assistant_base_id + entity_type + normalized_name
如果存在更强 ID,则优先:
assistant_base_id + entity_type + external_id_type + external_id
对齐规则:
- 确定性同一:证件号、统一社会信用代码、装备编号、系统唯一 ID 等完全一致,直接合并。
- 高置信名称同一:同类型实体 normalized name 一致,合并。
- 模型推断同一:允许模型判断“张三”“张三同志”“Zhang San”是否同一人,但必须给出 evidence 和 confidence。
confidence >= 0.90的模型对齐可以自动合并。0.70 <= confidence < 0.90的模型对齐不自动合并,可记录为候选别名或候选关联。confidence < 0.70丢弃。
合并后必须保留来源贡献:
- 来自哪个 WeKnora 知识库。
- 来自哪个 Wiki 页面或 chunk。
- 来自哪个技能 binding。
- 证据文本。
- 导入任务 ID。
属性冲突不覆盖:
- 不同来源给出不同姓名、职务、时间、地点、数值时,按来源分组展示。
- Wiki 页面中展示“多来源信息”而不是最后写入覆盖。
30.6 助手库关系对齐
关系 key:
assistant_base_id + source_assistant_entity_id + normalized_predicate + target_assistant_entity_id
关系来源:
- WeKnora 图谱边。
- WeKnora Wiki graph 链接。
- 技能归纳时写入 WeKnora 的关系页。
- graph projection 文档。
- 模型从 WeKnora 导出包中推断的高置信关系。
关系合并后保留多个证据贡献。
关系 Wiki 页面建议:
assistant/relations/{predicate}/{stable_relation_id}
关系页内容:
- 源实体。
- 关系类型。
- 目标实体。
- 关系描述。
- 来源知识库。
- 来源 Wiki 页。
- 证据和置信度。
30.7 助手库 Wiki 生成
助手库最终以 Wiki 页面展示。
页面类型:
| 页面 | slug 示例 | 说明 |
|---|---|---|
| 首页 | assistant/home |
知识梳理总览、实体数量、来源数量、最近导入。 |
| 来源页 | assistant/sources/{source_id} |
某个 WeKnora 知识库导入结果。 |
| 实体页 | assistant/entities/{type}/{entity_id}-{name} |
对齐后的全局实体页面。 |
| 关系页 | assistant/relations/{predicate}/{relation_id} |
对齐后的全局关系页面。 |
| 主题页 | assistant/topics/{topic} |
从 WeKnora Wiki 分类或目录生成。 |
实体页结构:
- 标题:实体名。
- 类型:人物、组织、地点、装备、事件、概念、数据对象等。
- 摘要:模型基于多来源融合生成。
- 别名。
- 多来源属性。
- 相关实体。
- 相关关系。
- 来源 Wiki 页面。
- 证据。
助手库 Wiki 页面需要版本管理。每次 WeKnora 导入、技能直接归纳、管理员本地文件导入、实体对齐重建或人工编辑,都生成新 revision。新 revision 先处于 draft 或 staged 状态,发布成功后成为 current。
版本能力:
- 查看历史版本。
- 对比两个版本。
- 回滚到历史版本。
- 查看版本来源:导入任务、技能归纳任务、人工编辑。
- 查看版本发布人和发布时间。
30.8 助手库搜索
助手知识库需要支持搜索。
V1 建议实现:
- Wiki 标题搜索。
- 实体名称和别名搜索。
- Wiki 正文全文搜索。
- 来源知识库过滤。
- 实体类型过滤。
实现选择:
- SQLite 可使用 FTS5。
- PostgreSQL 可使用 tsvector 或 trigram。
- 如果现有持久化层不方便,先实现数据库 LIKE + normalized name 索引,后续再升级全文索引。
搜索结果只展示 Wiki 页面,不直接展示底层 chunk。
30.9 助手库持久化表
建议新增:
deerflow.persistence.assistant_knowledge
核心表:
assistant_knowledge_base
只允许一条 active 记录。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
name |
默认“知识梳理”。 |
status |
active / disabled。 |
created_by |
初始化管理员。 |
created_at / updated_at |
时间戳。 |
assistant_knowledge_sources
记录每个来源。来源可以是 WeKnora 知识库、技能归纳或管理员本地导入。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
base_id |
助手库 ID。 |
source_type |
weknora / skill / local_file。 |
knowledge_base_mapping_id |
DeerFlow 本地 WeKnora 映射 ID,可为空。 |
skill_name |
技能名,可为空。 |
upload_batch_id |
本地文件导入批次,可为空。 |
source_name |
来源名称。 |
last_import_job_id |
最近导入任务。 |
status |
active / import_failed / deleted。 |
created_at / updated_at |
时间戳。 |
assistant_knowledge_import_jobs
| 字段 | 说明 |
|---|---|
id |
UUID。 |
base_id |
助手库 ID。 |
source_id |
来源 ID。 |
trigger |
auto_after_weknora_indexed / manual_from_weknora / skill_direct / manual_file_upload / scheduled / watcher。 |
status |
queued / running / completed / partial_failed / failed。 |
phase |
exporting / scanning / parsing / awaiting_review / aligning_entities / aligning_relations / writing_wiki / indexing_search / completed。 |
counts_json |
导入页面、实体、关系、chunk 数。 |
last_error_message |
错误摘要。 |
created_by |
操作人;自动任务可为空或 system。 |
created_at / completed_at |
时间戳。 |
assistant_knowledge_wiki_pages
| 字段 | 说明 |
|---|---|
id |
UUID。 |
base_id |
助手库 ID。 |
slug |
全局唯一 slug。 |
title |
标题。 |
page_type |
home / source / entity / relation / topic。 |
current_revision_id |
当前发布版本。 |
content_markdown |
当前版本冗余内容,便于列表和搜索。 |
summary |
摘要。 |
status |
active / deleted。 |
search_text |
搜索文本。 |
updated_at |
更新时间。 |
assistant_knowledge_wiki_revisions
保存 Wiki 页面版本。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
page_id |
Wiki 页面。 |
revision_no |
递增版本号。 |
content_markdown |
版本内容。 |
summary |
版本摘要。 |
source_id |
来源,可为空。 |
import_job_id |
导入任务,可为空。 |
change_type |
import / skill_sync / manual_edit / entity_rebuild / rollback。 |
status |
draft / staged / published / superseded。 |
created_by |
创建人。 |
created_at / published_at |
时间戳。 |
assistant_knowledge_entities
保存全局对齐后的实体。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
base_id |
助手库 ID。 |
entity_type |
实体类型。 |
normalized_name |
归一化名称。 |
display_name |
展示名称。 |
aliases_json |
别名。 |
attributes_json |
聚合属性。 |
wiki_page_id |
实体 Wiki 页。 |
status |
active / deleted。 |
assistant_knowledge_entity_contributions
| 字段 | 说明 |
|---|---|
id |
UUID。 |
entity_id |
全局实体。 |
source_id |
WeKnora 来源。 |
import_job_id |
导入任务。 |
source_wiki_slug |
来源 Wiki 页。 |
source_chunk_id |
来源 chunk,可为空。 |
source_skill_name |
来源技能,可为空。 |
evidence_json |
证据。 |
confidence |
置信度。 |
assistant_knowledge_relations
保存全局对齐后的关系。
| 字段 | 说明 |
|---|---|
id |
UUID。 |
base_id |
助手库 ID。 |
source_entity_id |
源实体。 |
predicate |
关系类型。 |
target_entity_id |
目标实体。 |
description |
聚合描述。 |
wiki_page_id |
关系 Wiki 页。 |
status |
active / deleted。 |
assistant_knowledge_relation_contributions
| 字段 | 说明 |
|---|---|
id |
UUID。 |
relation_id |
全局关系。 |
source_id |
WeKnora 来源。 |
import_job_id |
导入任务。 |
source_wiki_slug |
来源 Wiki 页。 |
graph_edge_id |
WeKnora 图谱边 ID,可为空。 |
evidence_json |
证据。 |
confidence |
置信度。 |
30.10 助手库 API
新增 router:
/api/assistant-knowledge
建议接口:
GET /api/assistant-knowledge/base
POST /api/assistant-knowledge/base/initialize
GET /api/assistant-knowledge/wiki-pages
GET /api/assistant-knowledge/wiki-pages/{slug}
GET /api/assistant-knowledge/wiki-pages/{slug}/revisions
GET /api/assistant-knowledge/wiki-pages/{slug}/revisions/{revision_id}
POST /api/assistant-knowledge/wiki-pages/{slug}/revisions/{revision_id}/rollback
GET /api/assistant-knowledge/search?q=xxx&type=entity&source_id=xxx
GET /api/assistant-knowledge/entities/{id}
GET /api/assistant-knowledge/relations/{id}
GET /api/assistant-knowledge/sources
GET /api/assistant-knowledge/import-jobs
GET /api/assistant-knowledge/import-jobs/{id}
POST /api/assistant-knowledge/sources/{source_id}/reimport
POST /api/assistant-knowledge/imports/files
POST /api/assistant-knowledge/imports/skills
DELETE /api/assistant-knowledge/sources/{source_id}
新增 WeKnora 普通知识库导出或导入触发接口:
POST /api/llmwiki/knowledge-bases/{knowledge_base_id}/export-to-assistant
行为:
- 校验管理员。
- 校验助手知识库已初始化;未初始化则自动创建“知识梳理”或提示管理员确认创建。
- 校验 WeKnora 知识库已完成处理。
- 创建
assistant_knowledge_import_jobs。 - 后台导出 WeKnora 数据并导入助手库。
本地文件导入接口:
POST /api/assistant-knowledge/imports/files
使用 multipart 上传文件。后端必须先完成安全扫描和敏感信息阻断,再进入解析、抽取、审核、实体对齐和 Wiki 版本生成。
技能直接导入接口:
POST /api/assistant-knowledge/imports/skills
请求:
{
"skill_names": ["skill-a", "skill-b"],
"force": false
}
该接口也可以由 /api/skill-knowledge/sync-jobs 在目标类型为 assistant 时内部复用。
系统设置接口需要支持:
GET /api/system-settings/knowledge-base-product-version
PUT /api/system-settings/knowledge-base-product-version
30.11 前端页面
知识库入口需要支持产品版本切换。
建议:
- 管理员设置页提供“知识库版本”切换:
v1 普通知识库/v2 助手知识库,默认v1。 - 知识库页面顶部用 Tabs 或 Segmented Control 区分“普通知识库”和“助手知识库”。
- 未配置 WeKnora 时,普通知识库 tab 隐藏或禁用;助手知识库 tab 正常显示。
- 助手知识库未初始化时,展示“创建知识梳理库”按钮。
- 创建后展示 Wiki 首页、搜索框、来源列表、最近导入和页面版本入口。
- 普通知识库详情页增加按钮:“导入到助手知识库”。
- 普通知识库列表中可显示“已沉淀到知识梳理 / 待导入 / 导入失败”状态。
- 助手知识库页面为管理员提供“导入本地文件”和“导入技能”入口。
助手知识库页面建议:
知识梳理
├── 搜索
├── Wiki 首页
├── 实体
├── 关系
├── 来源知识库
├── 导入记录
└── 页面版本
普通用户只看到搜索、Wiki、实体、关系、来源和只读版本历史。管理员额外看到导入、重新导入、删除来源、版本对比和回滚。
30.12 自动沉淀时机
WeKnora 普通知识库完成以下任意流程后,应触发或排队助手库导入:
- 管理员从技能归纳到 WeKnora 成功。
- WeKnora 文档上传并完成向量化。
- WeKnora Wiki 页面生成或更新完成。
- WeKnora 图谱抽取完成。
- 管理员手动点击“导入到助手知识库”。
为了避免频繁重复导入:
- 对每个 WeKnora 知识库维护
last_export_digest。 - 导出前计算 Wiki 页面、文档 chunk、图谱摘要的 digest。
- digest 未变化时跳过导入。
- 同一 WeKnora 知识库同一时间只允许一个 active 导入任务。
30.13 与技能归纳的关系
技能归纳支持两条链路。
链路 A:先进入 WeKnora,再沉淀助手库。
技能知识文件
-> WeKnora 普通知识库
-> WeKnora 向量化 / Wiki / 图谱
-> 导出已处理数据
-> 助手知识库“知识梳理”
-> 全局实体对齐
-> Wiki 展示与搜索
链路 B:直接进入助手知识库。
技能知识文件
-> 助手知识库“知识梳理”
-> 实体/关系预览审核
-> 全局实体对齐
-> Wiki 页面版本发布
-> 搜索索引
代码文件在第一步就被排除,不进入后续任何知识库。
30.14 新增测试与验收
新增后端测试:
- 未配置 WeKnora 时,助手知识库 base 接口可用,普通知识库导入接口返回明确不可用。
- 初始化助手知识库后,只存在一个 active base。
- 普通用户可读助手 Wiki,写接口返回 403。
- 管理员可从 WeKnora 知识库触发导入任务。
- 管理员可把技能直接导入助手知识库。
- 管理员可上传本地文件导入助手知识库。
- WeKnora 导出包包含 Wiki、文档、chunk、实体、关系、图谱时,助手库全部导入。
- 同一个人或同一对象来自多个 WeKnora 来源时,在助手库合并为一个实体。
- 模型推断实体对齐
confidence >= 0.90自动合并,低于阈值不合并。 - 删除某个来源时,只删除该来源贡献;其他来源贡献仍保留。
- 助手库搜索能命中 Wiki 标题、实体别名和正文。
- 助手 Wiki 页面支持 revision、对比和回滚。
- 技能归纳扫描不读取、不上传、不摘要代码文件,代码文件变化不触发 stale。
新增前端测试:
- 知识库产品版本默认
v1。 - 管理员可切换
v1/v2。 - 未配置 WeKnora 时仍可看到“创建知识梳理库”。
- 普通知识库详情页有“导入到助手知识库”按钮。
- 助手知识库页面展示 Wiki、搜索、来源、导入记录。
- 助手知识库页面展示页面版本、对比和回滚入口。
- 普通用户看不到导入、删除、重新导入和回滚动作。