dsh-data-domain-knowledge 0.1.0-alpha.13 → 0.1.0-alpha.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/README.md +84 -52
  2. package/cordis.patch.yml +21 -17
  3. package/eval/benchmark-extraction-format.mjs +20 -0
  4. package/lib/client.js +2846 -3872
  5. package/lib/doc-page.js +1 -1
  6. package/lib/pages.js +1299 -1660
  7. package/lib/types/axis-registry.d.ts +6 -0
  8. package/lib/types/axis-registry.d.ts.map +1 -1
  9. package/lib/types/axis-registry.js +45 -0
  10. package/lib/types/axis-registry.js.map +1 -1
  11. package/lib/types/diagnosis/cards.d.ts +7 -3
  12. package/lib/types/diagnosis/cards.d.ts.map +1 -1
  13. package/lib/types/diagnosis/cards.js +13 -8
  14. package/lib/types/diagnosis/cards.js.map +1 -1
  15. package/lib/types/diagnosis/run.d.ts +4 -13
  16. package/lib/types/diagnosis/run.d.ts.map +1 -1
  17. package/lib/types/diagnosis/run.js +26 -16
  18. package/lib/types/diagnosis/run.js.map +1 -1
  19. package/lib/types/diagnosis/schema.js +2 -2
  20. package/lib/types/diagnosis/schema.js.map +1 -1
  21. package/lib/types/diagnosis/seed-source.d.ts +1 -1
  22. package/lib/types/diagnosis/seed-source.d.ts.map +1 -1
  23. package/lib/types/diagnosis/seed-source.js +5 -4
  24. package/lib/types/diagnosis/seed-source.js.map +1 -1
  25. package/lib/types/diagnosis/seed.d.ts +4 -4
  26. package/lib/types/diagnosis/seed.d.ts.map +1 -1
  27. package/lib/types/diagnosis/seed.js +6 -8
  28. package/lib/types/diagnosis/seed.js.map +1 -1
  29. package/lib/types/diagnosis/store.d.ts +8 -16
  30. package/lib/types/diagnosis/store.d.ts.map +1 -1
  31. package/lib/types/diagnosis/store.js +41 -66
  32. package/lib/types/diagnosis/store.js.map +1 -1
  33. package/lib/types/diagnosis/types.d.ts +10 -16
  34. package/lib/types/diagnosis/types.d.ts.map +1 -1
  35. package/lib/types/diagnosis/types.js.map +1 -1
  36. package/lib/types/environment/service.d.ts +4 -3
  37. package/lib/types/environment/service.d.ts.map +1 -1
  38. package/lib/types/environment/service.js +91 -23
  39. package/lib/types/environment/service.js.map +1 -1
  40. package/lib/types/environment/types.d.ts +9 -0
  41. package/lib/types/environment/types.d.ts.map +1 -1
  42. package/lib/types/events.d.ts +2 -0
  43. package/lib/types/events.d.ts.map +1 -1
  44. package/lib/types/events.js +13 -0
  45. package/lib/types/events.js.map +1 -1
  46. package/lib/types/extract-contract.d.ts +1 -1
  47. package/lib/types/extract-contract.d.ts.map +1 -1
  48. package/lib/types/extract-contract.js +34 -31
  49. package/lib/types/extract-contract.js.map +1 -1
  50. package/lib/types/extract-model.d.ts +2 -0
  51. package/lib/types/extract-model.d.ts.map +1 -1
  52. package/lib/types/extract-model.js.map +1 -1
  53. package/lib/types/extract-table-contract.d.ts +3 -0
  54. package/lib/types/extract-table-contract.d.ts.map +1 -0
  55. package/lib/types/extract-table-contract.js +30 -0
  56. package/lib/types/extract-table-contract.js.map +1 -0
  57. package/lib/types/extract-table.d.ts +8 -0
  58. package/lib/types/extract-table.d.ts.map +1 -0
  59. package/lib/types/extract-table.js +151 -0
  60. package/lib/types/extract-table.js.map +1 -0
  61. package/lib/types/extraction-runs.d.ts +3 -0
  62. package/lib/types/extraction-runs.d.ts.map +1 -1
  63. package/lib/types/extraction-runs.js +6 -0
  64. package/lib/types/extraction-runs.js.map +1 -1
  65. package/lib/types/index.d.ts.map +1 -1
  66. package/lib/types/index.js +196 -44
  67. package/lib/types/index.js.map +1 -1
  68. package/lib/types/intent/scope.d.ts.map +1 -1
  69. package/lib/types/intent/scope.js +1 -0
  70. package/lib/types/intent/scope.js.map +1 -1
  71. package/lib/types/knowledge-bases.d.ts.map +1 -1
  72. package/lib/types/knowledge-bases.js +3 -2
  73. package/lib/types/knowledge-bases.js.map +1 -1
  74. package/lib/types/knowledge.d.ts +3 -0
  75. package/lib/types/knowledge.d.ts.map +1 -1
  76. package/lib/types/knowledge.js +12 -3
  77. package/lib/types/knowledge.js.map +1 -1
  78. package/lib/types/model-text.d.ts +1 -1
  79. package/lib/types/model-text.d.ts.map +1 -1
  80. package/lib/types/model-text.js +5 -4
  81. package/lib/types/model-text.js.map +1 -1
  82. package/lib/types/pipeline/engine.d.ts +57 -0
  83. package/lib/types/pipeline/engine.d.ts.map +1 -0
  84. package/lib/types/pipeline/engine.js +268 -0
  85. package/lib/types/pipeline/engine.js.map +1 -0
  86. package/lib/types/pipeline/store.d.ts +56 -0
  87. package/lib/types/pipeline/store.d.ts.map +1 -0
  88. package/lib/types/pipeline/store.js +115 -0
  89. package/lib/types/pipeline/store.js.map +1 -0
  90. package/lib/types/pipeline/types.d.ts +82 -0
  91. package/lib/types/pipeline/types.d.ts.map +1 -0
  92. package/lib/types/pipeline/types.js +5 -0
  93. package/lib/types/pipeline/types.js.map +1 -0
  94. package/lib/types/present.d.ts +2 -0
  95. package/lib/types/present.d.ts.map +1 -1
  96. package/lib/types/present.js +9 -4
  97. package/lib/types/present.js.map +1 -1
  98. package/lib/types/runtime.d.ts +20 -1
  99. package/lib/types/runtime.d.ts.map +1 -1
  100. package/lib/types/runtime.js +389 -112
  101. package/lib/types/runtime.js.map +1 -1
  102. package/lib/types/source-evidence.d.ts.map +1 -1
  103. package/lib/types/source-evidence.js +2 -0
  104. package/lib/types/source-evidence.js.map +1 -1
  105. package/lib/types/store/axis-references.js +3 -3
  106. package/lib/types/store/axis-references.js.map +1 -1
  107. package/lib/types/store/migrate.js +1 -1
  108. package/lib/types/store/migrate.js.map +1 -1
  109. package/lib/types/types.d.ts +3 -4
  110. package/lib/types/types.d.ts.map +1 -1
  111. package/lib/types/types.js.map +1 -1
  112. package/lib/types/wiki-materialize.d.ts.map +1 -1
  113. package/lib/types/wiki-materialize.js +3 -15
  114. package/lib/types/wiki-materialize.js.map +1 -1
  115. package/lib/types/wiki-trial-types.d.ts +3 -0
  116. package/lib/types/wiki-trial-types.d.ts.map +1 -1
  117. package/lib/types/wiki-trial.d.ts +2 -0
  118. package/lib/types/wiki-trial.d.ts.map +1 -1
  119. package/lib/types/wiki-trial.js +31 -7
  120. package/lib/types/wiki-trial.js.map +1 -1
  121. package/package.json +6 -3
  122. package/preset/tita-data-agent/agent.cordis.yml +21 -17
  123. package/src/axis-registry.ts +38 -0
  124. package/src/client/AttributionEventGuide.tsx +10 -9
  125. package/src/client/EnvironmentSetup.tsx +35 -15
  126. package/src/client/ExtractionTasksPage.tsx +129 -176
  127. package/src/client/KnowledgeBaseTab.tsx +31 -76
  128. package/src/client/NodeSettings.tsx +2 -3
  129. package/src/client/PipelineNotice.tsx +26 -0
  130. package/src/client/TabGuide.tsx +4 -4
  131. package/src/client/TypeDefinitionDrawer.tsx +23 -8
  132. package/src/client/WikiCardPreview.tsx +43 -10
  133. package/src/client/WikiFlowPanel.tsx +4 -4
  134. package/src/client/architecture.tsx +1 -1
  135. package/src/client/attribution/AttributionTab.tsx +6 -6
  136. package/src/client/attribution/CaseView.tsx +3 -1
  137. package/src/client/attribution/EventView.tsx +14 -4
  138. package/src/client/attribution/RunView.tsx +2 -2
  139. package/src/client/attribution/graph-options.ts +2 -2
  140. package/src/client/pages.tsx +2 -2
  141. package/src/diagnosis/cards.ts +13 -8
  142. package/src/diagnosis/run.ts +27 -17
  143. package/src/diagnosis/schema.ts +2 -2
  144. package/src/diagnosis/seed-source.ts +5 -4
  145. package/src/diagnosis/seed.ts +6 -8
  146. package/src/diagnosis/store.ts +47 -68
  147. package/src/diagnosis/types.ts +10 -16
  148. package/src/environment/service.ts +79 -23
  149. package/src/environment/types.ts +6 -0
  150. package/src/events.ts +12 -0
  151. package/src/extract-contract.ts +6 -3
  152. package/src/extract-model.ts +2 -0
  153. package/src/extract-table-contract.ts +29 -0
  154. package/src/extract-table.ts +126 -0
  155. package/src/extraction-runs.ts +6 -0
  156. package/src/index.ts +156 -45
  157. package/src/intent/scope.ts +1 -0
  158. package/src/knowledge-bases.ts +3 -2
  159. package/src/knowledge.ts +13 -3
  160. package/src/model-text.ts +5 -3
  161. package/src/pipeline/engine.ts +238 -0
  162. package/src/pipeline/store.ts +119 -0
  163. package/src/pipeline/types.ts +74 -0
  164. package/src/present.ts +10 -4
  165. package/src/runtime.ts +350 -110
  166. package/src/source-evidence.ts +1 -0
  167. package/src/store/axis-references.ts +3 -3
  168. package/src/store/migrate.ts +1 -1
  169. package/src/types.ts +3 -4
  170. package/src/wiki-materialize.ts +3 -14
  171. package/src/wiki-trial-types.ts +3 -0
  172. package/src/wiki-trial.ts +26 -7
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # dsh-data-domain-knowledge
2
2
 
3
- 本地知识库插件:一个知识库是一个目录,里面四样东西。`knowledge.db` 保存 **SourceRaw**
4
- (原始可追溯文档)、按主题聚合可双向链接的 wiki 卡片,以及**两者的每一个版本**;
5
- `derived.db` 输出可检索的 **wikiNotes**、wiki
6
- 知识图谱和向量索引,`<agentRoot>/memory/<库 id>` 保存操作日志、抽取轨迹、访问审计与反馈。
3
+ 本地知识库插件:一个知识库对应一个目录。`knowledge.db` 保存 **SourceRaw**
4
+ (原始可追溯文档)、轴、Knowledge、Event、wiki 卡片、版本与阶段检查点;
5
+ `derived.db` 保存可重建的 **wikiNotes**、知识图谱和向量索引,`assets/` 保存图片与附件。
6
+ 知识库目录外的 `<agentRoot>/memory/<库 id>` 保存任务与正式输出、抽取轨迹、操作日志、访问审计与反馈。
7
7
  默认使用本地 Python 推理:`BAAI/bge-small-zh-v1.5` 生成 512 维文本向量,
8
8
  `BAAI/bge-reranker-base` 对召回候选做交叉编码重排。部署入口必须完成环境自检,
9
- 索引必须匹配当前模型;不满足时提示准备环境或重新编译。
9
+ 索引必须匹配当前模型;不满足时提示准备环境或构建检索索引。
10
10
  需要图片语义检索时,可配置 WeMM 多模态模型与匹配维度,Markdown 中的本地图片
11
11
  会与正文一起交给模型。图片不作为独立知识类型。
12
12
 
@@ -16,10 +16,10 @@ Tita Agent 的固定数据根目录是 `$DSH_HOME/tita-agent`(默认 `~/.dsh/t
16
16
 
17
17
  ## 首次运行环境准备
18
18
 
19
- 向量模型和重排模型是部署必需项。打开 Tita 设置 → 环境准备 → 一键安装 / 修复。
20
- 系统用 DSH 自带的 Python 3.12 创建专属依赖环境,不另行下载 Python;再下载固定 revision 的 `BAAI/bge-small-zh-v1.5`
21
- (512 维)和 `BAAI/bge-reranker-base`,然后运行真实推理自检。阶段、错误和下载日志
22
- 可查看;下载失败可以重试。未就绪时阻止编译和知识召回,来源与历史内容仍可保存、读取。
19
+ 向量模型和重排模型在 Tita 设置 → 环境准备中选择,再安装 / 修复。
20
+ 系统用 DSH 自带的 Python 3.12 创建专属依赖环境,不另行下载 Python;再下载所选模型,
21
+ 默认是 `BAAI/bge-small-zh-v1.5`(512 维)和 `BAAI/bge-reranker-base`,然后运行真实推理自检。阶段、错误和下载日志
22
+ 可查看;下载失败可以重试。就绪检查按所用能力执行:抽取、归一和物化只需要 LLM;构建向量索引需要向量模型;召回按启用的向量和重排能力检查。来源与历史内容仍可保存、读取。
23
23
  自检不单独检查 `sentencepiece`;依赖安装失败会显示安装错误,模型真实推理失败会显示对应模型的错误。
24
24
 
25
25
  命令行入口:
@@ -31,7 +31,7 @@ pnpm --filter dsh-data-domain-knowledge doctor
31
31
  ```
32
32
 
33
33
  自检失败时命令返回非零退出码。依赖装在 Tita 专属虚拟环境中,不修改系统 Python,也不隐式运行 npm postinstall
34
- 模型下载。已有知识在准备完成后需重新编译;宿主无需重启。自定义路径保留,使用默认
34
+ 模型下载。已有卡片在准备完成后需构建检索索引,文档无需重新抽取;宿主无需重启。自定义路径保留,使用默认
35
35
  资源时把高级设置中的路径恢复为空,并使用匹配的向量维度。
36
36
  细节见 [运行环境准备与自检](../../docs/current/16-知识运行环境准备与自检.md)。
37
37
 
@@ -52,19 +52,49 @@ pnpm --filter dsh-data-domain-knowledge doctor
52
52
  分类与 act 是代码内置的固定契约,不提供编辑入口。读接口 `/intent/store` 与 `/intent/overview` 读的是**留痕**:
53
53
  引擎内存里那份有 600 秒 TTL,重启或隔一段时间回来不该让面板上的历史凭空消失。
54
54
 
55
- ## 五段链路
55
+ ## 独立运行知识链路
56
56
 
57
- | 段 | 名称 | 产物 | 关键配置 |
58
- | --- | --- | --- | --- |
59
- | 1 | SourceRaw | 原始可追溯文档:`knowledge.db` 的 `source` + `blob` | `allowSourceTruth` / `rootDir` |
60
- | 2 | 编译 Compile | wiki:`knowledge.db` 的 `card`(**按 wiki 类型 schema 抽实体,直接入库**);wikiNotes:`derived.db` 的 `wiki_notes.json` | `extractCandidates` / `extractWithModel` / `wikiTypes` |
61
- | 3 | 构建 Build | wikiNotes → 向量索引;wiki → `derived.db` 的 `knowledge_graph.json` | `embeddingProvider` / `embeddingModel` / `python` |
62
- | 4 | 召回 Recall | 多路(坐标 + 关键词 + 向量)召回 wikiNotes,取 `recallTopK`(默认 10),再解析父级 wiki 与该 wiki 的 1 跳知识图谱 | `recallTopK` |
63
- | 5 | 重排 Rerank | BERT cross-encoder 对候选 wikiNotes 精排,取 `contextTopN`(默认 5)组成 `context` | `contextTopN` / `rerankProvider` / `rerankModel` |
57
+ 导入默认只保存来源。打开「知识处理」页面,按需运行以下阶段。也可以选择「全链路运行」。
58
+
59
+ | 阶段 | 输入 → 产物 | 模型与复用 |
60
+ | --- | --- | --- |
61
+ | 入库 | 文档 → SourceRaw 与版本 | 不调用模型;`import_sources` 默认 `compile: false` |
62
+ | 抽取 Knowledge / Event | 指定来源版本 → 原始 mention、引文与抽取检查点 | 本库所选 LLM;默认表格输出,兼容历史 JSON;未变化来源复用 |
63
+ | 归一合并 | 保存的抽取返回 → canonical 轴、Knowledge、Event | 精确查注册表;必要时模型补判;不重新抽取文档 |
64
+ | 物化 WikiCard | Knowledge 完整坐标分组 → 卡片与章节;Event 只建立同坐标引用 | 可选模型组织;Event 不进入卡片正文,也不单独生成 WikiCard |
65
+ | 构建检索索引 | 已保存卡片 → Wiki Note、FTS、向量与图谱 | 使用所选向量模型;事务发布一份检索快照 |
66
+ | 召回与重排 | Query → 多路候选 → RRF / 图谱加权 → 重排 → Context | 候选池先于最终截断;单个候选也经过重排阈值;停用卡片不召回 |
67
+
68
+ 向量、重排模型在环境准备中按列表选择;安装并通过实际推理后启用。选择托管模型会替换高级设置中的自定义模型路径,自检失败会恢复。更换向量模型只需重建索引,不需要重新抽取。
69
+
70
+ 本库「编译设置」支持选择 LLM 与模型声明的思考强度。任务入队时保存实际路由、强度、抽取备注与卡片组织设置;修改设置作用于后续任务。
71
+
72
+ ### 运行接口
73
+
74
+ - `run_knowledge_pipeline`:`stage` 为 `extract`、`normalize`、`materialize`、`build` 或 `all`。`source_ids` 限定文档,`group_keys` 限定完整卡片分组。`force` 显式强制当前阶段。
75
+ - `get_knowledge_pipeline`:不传 `task_id` 返回阶段待办与任务历史;传任务 ID 与 `after` 游标读取状态和正式输出。刷新后可补读。
76
+ - `get_knowledge_events`:按召回 WikiCard 的 `metadata.event_refs` 读取对应 Event,不把整库事件加入每次召回。
77
+ - `GET/POST /knowledge/pipeline`:阶段状态 / 创建后台任务。`GET /knowledge/pipeline-tasks` 分页读历史,`GET/POST /knowledge/pipeline-task` 读输出 / 暂停、继续、停止、重新运行。
78
+ - `import_sources` 显式 `compile: true` 对本批写入的来源运行完整链路。`rebuild_knowledge` 仅重建已保存卡片的检索产物;正式抽取使用独立阶段接口。
79
+ - 抽取试跑仅保存审计报告;预览实体解析使用隔离副本,不写正式 Knowledge 或实体注册表。
80
+
81
+ 旧 `runtime.rebuild` 保留兼容的规则抽取兜底。当前 HTTP / 工具重建默认只构建已保存卡片的检索产物;独立阶段的模型失败会明确失败,不自动切换到规则抽取。
82
+
83
+ ### 增量、失败与证据
84
+
85
+ 抽取指纹包括文档正文、标题、抽取契约、备注、LLM 路由与强度;卡片模板与无关实体更新不会强制重抽。归一、物化分别维护自己的依赖指纹。
86
+
87
+ 归一时先在内存副本解析实体。提交前核验来源版本和实体注册表;在短事务中提交实体、Knowledge、Event 和归一检查点。重新归一会撤回该来源旧版本的有效贡献,并保留出处历史。其他来源支撑的同一事实继续有效。Event 根据明确身份归并,文本相似不触发跨文档合并。
88
+
89
+ 来源已变化或新抽取尚未归一时,涉及的卡片分组显示「先归一来源」。物化按唯一坐标分组计数;不按 Knowledge 条数估算卡片数。Event 与 Knowledge 同层独立保存;WikiCard 只由 Knowledge 生成,并保存同坐标 Event 的引用。物化失败保留旧卡片。归一与物化不会提前更新已发布检索索引;构建成功后统一发布。删除与停用仍立即限制召回可见性。
90
+
91
+ 任务状态与输出写入既有抽取审计库。暂停、停止在当前文档或卡片边界生效。服务重启把未结束任务标记为中断,已完成检查点保留;重新运行默认复用成功项。实时预览每份来源最多 4 MB,完整模型返回保存在报告中;页面显示最近输出。
92
+
93
+ **目录边界的原理:** `src/pipeline/` 只承接阶段契约、持久检查点和任务编排;领域归一、成卡与检索继续调用现有运行时。业务检查点仍在 `knowledge.db`,任务审计仍在原有记忆库,索引仍在 `derived.db`。不新增一套业务真源,也不把不可重建的模型返回放进可清理的派生层。
94
+
95
+ ### 表格格式基准
64
96
 
65
- > 第 4、5 段在**界面上是同一栏**(知识库 → 召回重排)。它们在流水线上仍是两步,
66
- > 但「跑一次真实召回长什么样」是一个问题,分两栏会让用户先跑召回、再切到重排才能
67
- > 看到同一次运行的全貌。
97
+ 运行 `pnpm bench:extraction-format`。脚本使用同一份中文语义载荷,以 `o200k_base` 比较 TOON 与紧凑 JSON 的输出 token;不代表具体模型账单或抽取准确率。示例中,12 条知识减少 43.8%,40 条减少 51.6%;单条增加 6.9%,因为固定表头有开销。实际效果取决于字段长度、引文重复率和模型 tokenizer。
68
98
 
69
99
  ## Knowledge / Wiki Card 的存储约束
70
100
 
@@ -73,8 +103,10 @@ pnpm --filter dsh-data-domain-knowledge doctor
73
103
  | 层 | 真源 | 说明 |
74
104
  | --- | --- | --- |
75
105
  | Knowledge | `knowledge` + `knowledge_sources` | 原子事实、坐标、来源、状态;不保存 Card 的排版 |
106
+ | Event | `event` | 一次事件、时间线、结果、证据与来源;独立于 WikiCard 保存 |
76
107
  | Wiki Card | `card` + `blob` + `revision` | 面向阅读和召回组装的正文;正文中的 Markdown 标题是 Section 真源 |
77
108
  | Knowledge 落位 | `card_knowledge` | 记录 Knowledge 在某张 Card 中的 Section 和顺序;这是关联索引,不是 Knowledge 属性 |
109
+ | Event 引用 | `card_event` | 连接同坐标的 WikiCard 与 Event;引用更新不改卡片正文或检索文本 |
78
110
  | Wiki Note / FTS / Vector / Graph | `derived.db` | 可以从 Card 和 Knowledge 重新构建;编译结果在同一事务发布 |
79
111
 
80
112
  ### 状态语义
@@ -120,14 +152,20 @@ Notes、FTS、向量、图和 manifest 在 `derived.db` 中通过一次事务发
120
152
 
121
153
  ## Knowledge、Wiki Card、Wiki Note 的生命周期
122
154
 
123
- 三者不是三个并列的知识真源,而是同一条知识链上的三个层次:
155
+ 这条链路包含原始证据、并列的 Knowledge / Event 事实、知识组织卡片和检索派生片段:
124
156
 
125
157
  ```text
126
- SourceRaw → Knowledge → Wiki Card → Wiki Note → FTS / Vector / Rerank
127
- 事实真源 阅读组织视图 检索派生片段
158
+ SourceRaw → 抽取 → { Knowledge, Event }
159
+ │ │
160
+ ↓ │ card_event
161
+ WikiCard ←────┘
162
+ │
163
+ ↓
164
+ WikiNote → FTS / Vector / Rerank
128
165
  ```
129
166
 
130
- - Knowledge 是不可由 Card 反向重建的事实记录。抽取、来源追加、合并、冲突裁决和状态变化都发生在这里。
167
+ - Knowledge 是不可由 Card 反向重建的事实记录。归一、来源追加、合并、冲突裁决和状态变化都发生在这里;抽取阶段只保存原始返回与检查点。
168
+ - Event 与 Knowledge 是并列事实,分别保留事件时间线和可复用判断。WikiCard 只组织 Knowledge;它按坐标引用 Event,不复制 Event 正文。
131
169
  - Wiki Card 是 Knowledge 的组织视图。Card 正文、摘要、Section 和阅读顺序可以重新编排;重新编排不应修改 Knowledge。
132
170
  - Wiki Note 是 Card 的检索切片。它没有独立的业务生命周期,`status` 只是父 Card 状态的快照;Card 变化后重新编译 Wiki Note,索引随之重建。
133
171
 
@@ -137,11 +175,7 @@ SourceRaw → Knowledge → Wiki Card → Wiki Note → FTS / Vector / Rerank
137
175
 
138
176
  - 知识库设置集中在侧边抽屉:数据位置、向量模型、检索与上下文。召回固定使用多路径融合;
139
177
  低频设备、阈值和模型细节收在高级设置中。Agent 系统提示词常显,并链接到 preset 真源目录。
140
- - **编译直接入库(0044)**:`rebuild_knowledge` 的 Pass 0 对指纹变了的来源做实体抽取,
141
- 按 `entityType:entityId` / `title` / `metadata.aliases` 三重索引判重 —— 命中已有卡片就把
142
- 新正文**追加**进去(不覆盖、不丢弃),没命中就新建。缺必填小节 / 字段的卡片**照常入库**,
143
- 问题写进 `metadata.schema_issues`,面板显示成「待补」。**没有任何确认门**:卡片一写盘就进
144
- wikiNotes、向量与图谱,立刻可召回。
178
+ - **知识处理分开运行**:抽取只保存检查点,归一写入事实,物化按坐标产出卡片。只有构建检索索引后,新卡片才进入正式召回。任务失败保留已完成项,可查看输出和报告后重新运行。
145
179
  - **正文只读,备注可加**:卡片正文由编译产出,人改不了(手工写正文返回
146
180
  `WIKI_CARD_IMMUTABLE`)。人的判断落在 front matter 的 `annotations` 上
147
181
  (`kind: 'anomaly'` 表示异常点),**编译不会覆盖它**。review(`review_wiki_card`)在入库
@@ -150,16 +184,11 @@ SourceRaw → Knowledge → Wiki Card → Wiki Note → FTS / Vector / Rerank
150
184
  不动 `active` / `deprecated` / `problem` —— 那些是人另外做过的决定)。
151
185
  标注异常点会把有效评分压到 `ANOMALY_SCORE`,但卡片**照样召回得到**,只是排在后面。
152
186
 
153
- **合并按小节折进去**:同一实体被第二份文档命中时,新正文并进相同标签的小节里,
154
- 每个小节只出现一次;原来还是占位(「(文档未说明)」)的小节被真内容替换。
155
- 两份正文里只要有一份没有 `##` 结构(规则路径切出来的原文),退回整段拼接。
156
- - **批量导入只编译一次**(0045):`import_sources` 收一组来源(一次最多 50 份),逐份写入、
157
- **整批只编译一次**,逐条汇报成败 —— 第 7 份坏了不会让前 6 份白写。十份文档不再是十次审批、
158
- 十次往返、十次抽取。它与 `POST /knowledge/import` 落到同一个运行时方法 `runtime.importSources`,
159
- 与单份的 `add_source` 只差「一次多少份」。
187
+ - **物化整组重算**:同一坐标的有效 Knowledge 一起组织,沿用卡片 ID、review 和备注;Event 只更新关联引用。只重试物化时不会再次抽取文档。
188
+ - **批量导入只入库**:逐份保存、逐条报告导入失败;显式 `compile: true` 才运行本批来源的全链路。
160
189
  - **对话流里有专用卡片**(0045):`import_sources` / `recall_knowledge` / `rebuild_knowledge` /
161
190
  `add_source` / `propose_wiki_cards` 各自带 `presentationMeta`,浏览器半按**工具名**注册
162
- `tool.call.toolview`,于是对话里显示的是「导入 3 份来源并编译 · 写入 3 份 · 新建 2 张卡」
191
+ `tool.call.toolview`,显式编译或回放旧记录时,对话里可显示「导入 3 份来源并编译 · 写入 3 份 · 新建 2 张卡」
163
192
  与可展开的命中列表(名次、分数、`entityType:entityId`、review 评分),而不是一坨 JSON。
164
193
  meta 随会话日志落盘,所以**回放与当时看到的一致**。
165
194
  - **来源里的图跟着文字进卡片**(0047):抽取那一段交给模型的是文字,模型不会把图带回来,
@@ -170,17 +199,18 @@ SourceRaw → Knowledge → Wiki Card → Wiki Note → FTS / Vector / Rerank
170
199
  进 `warnings`。收尾的署名图 / 二维码(图后没有正文且锚点很短)故意不挂。每张 wikiNote
171
200
  只带**自己那一节**的图,因为多模态编码只吃每条的**第一张**图。图不参与抽取指纹,所以
172
201
  0047 之前编好的库重编时,来源虽然被指纹跳过,图仍然会被补上。
173
- - **图片引用有三种写法,解析只认「真实存在的那个」**(0047):`01_source_raw/_assets/…`
174
- (规范形,知识库根相对)、`_assets/…`(转换内核早期写进 SourceRaw 的形式)、
202
+ - **旧图片引用兼容三种写法,解析只认「真实存在的那个」**(0047 历史):`01_source_raw/_assets/…`
203
+ (当时的知识库根相对规范形)、`_assets/…`(转换内核早期写进 SourceRaw 的形式)、
175
204
  `../../01_source_raw/_assets/…`(`cardHints` 给手工建卡的形式)。文档的资产清单与卡片的
176
205
  `imagePaths` 走同一个 `assetRefCandidates`(根目录 → `01_source_raw/` → 文件自己的目录),
177
206
  否则同一张图在文档里找得到、在卡片里找不到。派生字段(图片路径、溯源链)变了也算
178
- 「语料变了」,否则增量编译的空操作会把刷新结果丢掉。
207
+ 「语料变了」,否则增量编译的空操作会把刷新结果丢掉。当前新资产写入 `assets/`,
208
+ 上述旧路径不定义新的知识库目录结构。
179
209
  - **SourceRaw 的 front matter 是 OKF v0.2 形状**(0048):`title`、`description`、
180
210
  `resource`(底层资产地址)、`tags`、
181
211
  `generated: {by, at}`(`by` = 谁解析的,`at` = **采集时间** —— OKF 里没有「抓取时间」
182
212
  这个概念)、`sources: [{id, resource, title, author, last_modified}]`(对网页就是那个页面
183
- 本身:地址、标题、作者、发布时间)。`source_id` / `external_id` / `created_at` /
213
+ 本身:地址、标题、作者、发布时间)。`created_at` /
184
214
  `updated_at` / `metadata` / `lineage` 是我们的扩展键(OKF 明确允许,且要求消费者容忍
185
215
  未知键)。
186
216
  规范:<https://github.com/GoogleCloudPlatform/open-knowledge-format>(v0.2)。
@@ -247,14 +277,15 @@ bash scripts/setup-embedding.sh
247
277
  - 维度:`2048`
248
278
  - 设备:`自动(优先 MPS)`
249
279
 
250
- 知识库默认保存在 `~/.dsh/tita-agent/domain_knowledge/<库 id>`。点击「编译」后,
251
- 编译结果写入 `derived.db`。未修改的 wikiNote
280
+ 知识库默认保存在 `~/.dsh/tita-agent/domain_knowledge/<库 id>`。运行「构建检索索引」后,
281
+ 检索产物写入 `derived.db`。未修改的 wikiNote
252
282
  会复用已有向量,只有新增或变更的 note 重新编码;编码与重排各自使用常驻 Python
253
- worker(同一份 `src/python/embedding_worker.py`),避免每个请求重复加载模型。
283
+ worker(同一份 `src/python/embedding_worker.py`),避免每个请求重复加载模型。换向量模型后重建索引,不重抽文档。
254
284
 
255
285
  BERT 重排默认使用 `BAAI/bge-reranker-base`;如需完全离线,可把模型放到
256
286
  `~/.dsh/tita-agent/resource/models/bge-reranker-base`(会被自动发现),或设置
257
- `DSH_RERANK_MODEL` / 在设置里填写本地路径。未安装时召回会降级到融合分数并给出警告。
287
+ `DSH_RERANK_MODEL` / 在设置里填写本地路径。启用重排的召回按该能力的自检结果放行;
288
+ 未就绪时先准备环境,显式停用重排则使用融合分数。
258
289
  **目录必须含分词器**(`tokenizer.json` 或 `sentencepiece.bpe.model`)——只有权重时模型会
259
290
  加载成功但给所有输入同一个分(`RERANK_TOKENIZER_DEGENERATE`)。
260
291
 
@@ -311,14 +342,14 @@ HTTP `GET /knowledge/bases` 在返回前先刷新。
311
342
  | 段 | 装什么 | 删掉的后果 |
312
343
  | --- | --- | --- |
313
344
  | `domain_knowledge/` | 知识树,按知识库 id 分叉 | 丢数据 |
314
- | `memory/<知识库 id>/` | 抽取轨迹、轴 / Knowledge 真源、处理日志、反馈与访问审计(append-only) | 丢历史,不可重建 |
345
+ | `memory/<知识库 id>/` | 任务与正式输出、抽取轨迹、处理日志、反馈与访问审计 | 丢历史,不可重建 |
315
346
  | `intent/` | `intent.db`(当前记录 + 审计历史) | 丢审计流 |
316
347
  | `output/` | 交付物,二级按日期分桶 | 什么都不损失 |
317
348
  | `tmp/` | 运行期临时文件,二级按日期分桶 | 只影响未完成的任务 |
318
349
  | `resource/` | 模型、Python 环境、`knowledge-bases.json` | 失去语义检索(嵌入/重排不可用) |
319
350
 
320
- **记忆与意图为什么与知识树平级**:记忆装的是**关于这个 Agent 的动作留痕**(抽取轨迹、
321
- 轴与 Knowledge 真源、处理日志、审计流水),不是关于知识的断言;留在知识树里会让「备份知识树」
351
+ **记忆与意图为什么与知识树平级**:记忆装的是**关于这个 Agent 的动作留痕**(任务、正式输出、
352
+ 抽取轨迹、处理日志、审计流水),知识断言及其阶段检查点保存在 `knowledge.db`。把动作留痕放进知识树,会让「备份知识树」
322
353
  被迫连审计一起备份,也让「知识树有哪几段」这个问题混进一个横切层。意图则是**会话级**的
323
354
  (同一句话在哪个知识库下说,理解方式不该变),所以它不分库。这样知识、记忆、意图三段
324
355
  都是可以直接备份、直接 diff 的用户文件。
@@ -327,7 +358,7 @@ HTTP `GET /knowledge/bases` 在返回前先刷新。
327
358
 
328
359
  | 文件或目录 | 内容 | 删除影响 |
329
360
  | --- | --- | --- |
330
- | `knowledge.db` | SourceRaw、Knowledge、Wiki Card 与版本记录 | 丢失知识真源 |
361
+ | `knowledge.db` | SourceRaw、轴、Knowledge、Event、Wiki Card、版本记录与阶段检查点 | 丢失知识真源 |
331
362
  | `derived.db` | wikiNotes、知识图谱、检索索引 | 可重新编译 |
332
363
  | `assets/` | 来源图片与附件 | 丢失对应素材 |
333
364
 
@@ -390,8 +421,9 @@ POST /knowledge/card-review { kb, entity_id, action } → { entityI
390
421
  POST /diagnosis/run { kb, record } → { sourceId, entityId }
391
422
  ```
392
423
 
393
- **0044:入库之后才 review,不再是「确认之后才入库」。** 编译(Pass 0)与
394
- `propose_wiki_cards` 都**直接写 `02_wiki`**,卡片立刻进编译、进图、能被召回。
424
+ **0044:入库之后才 review,不再是「确认之后才入库」(历史演进)。** 当时编译(Pass 0)与
425
+ `propose_wiki_cards` 直接写 `02_wiki`,随后进入编译与召回。当前卡片保存在 `knowledge.db`,
426
+ 新物化的卡片在构建检索索引后进入正式召回;review 仍作用于已经入库的卡片。
395
427
  人在面板上做的是 `POST /knowledge/card-review`(review 抬分 / 撤销)与
396
428
  `POST /knowledge/card-annotate`(加备注 / 标异常点)—— 两个动作都可逆,
397
429
  而且都作用在**已经存在于库里的卡片**上。原来的提议队列
package/cordis.patch.yml CHANGED
@@ -78,10 +78,9 @@
78
78
  - **The knowledge store.** Each knowledge base is one directory holding three
79
79
  things. `knowledge.db` is the knowledge itself: SourceRaw (the original
80
80
  business documents, never rewritten, kept so a conclusion can point back at
81
- where it came from), the cards people read — one per entity, each with
82
- mandatory `source_refs`, each following a type (`concept`, `metric`, `table`,
83
- `event`, `playbook`, `case`) — and every version of both, plus who changed
84
- what and when. `derived.db` is what `recall_knowledge` actually searches:
81
+ where it came from), Knowledge facts, independent Event records, and WikiCards
82
+ that organize Knowledge and point to related Events — plus every card version
83
+ and who changed what and when. `derived.db` is what `recall_knowledge` searches:
85
84
  wikiNotes, a vector index, a knowledge graph and a keyword index; it is
86
85
  recomputed, never backed up. `assets/` holds images. There are no
87
86
  per-segment folders inside a base; use the knowledge tools, not the
@@ -113,28 +112,33 @@
113
112
  record, then continue.
114
113
  2. **Recall before you answer about this organisation.** For its own rules,
115
114
  definitions, metrics, processes or history, call `recall_knowledge` first and
116
- answer from what comes back. An empty result is a finding, not a licence to
115
+ answer from what comes back. If a relevant card has `metadata.event_refs`, read
116
+ those IDs with `get_knowledge_events` before answering about incident history.
117
+ An empty result is a finding, not a licence to
117
118
  improvise — say the store has nothing on it. The wiki layer answers "what does
118
119
  this organisation mean by X"; when you need "where exactly does it say that",
119
120
  or a card and the document behind it disagree, go read the source.
120
121
  3. **Never invent a number.** Every figure you report must come from a tool
121
122
  result in this turn, and you must say which one. "I don't have that data" is
122
123
  a correct answer; a made-up number is not.
123
- 4. **Compiling is the normal path, and it writes cards by itself.** You do not
124
- have to create wiki cards: when a source is added or changed, `rebuild_knowledge`
125
- extracts entities from it, follows each wiki type's schema (required sections and
126
- fields), checks whether the wiki already has that entity, and either appends to
127
- the existing card or creates a new one. A card with missing sections is still
128
- written — the store keeps what it knows and fills the rest in when a later
129
- document covers it. So after adding a source, rebuild; then `recall_knowledge`
130
- and answer from what comes back. **More than one document at a time: use
131
- `import_sources`** — it writes the whole batch and compiles once, in one call.
132
- Ten documents through `add_source` means ten approvals and ten compiles, and the
133
- first nine results are thrown away by the tenth.
124
+ 4. **Import and knowledge processing are separate stages.** Use `import_sources`
125
+ for a batch. By default it only stores sources; adding or changing a source
126
+ never means the user asked to extract or publish it. Report the saved sources
127
+ and pending stages. When processing is requested, use `run_knowledge_pipeline`
128
+ with `extract`, then `normalize`, then `materialize`, then `build` as needed.
129
+ Track its durable task with `get_knowledge_pipeline`; use the output cursor
130
+ to inspect model text and failures. `source_ids` limits extraction to selected
131
+ documents. Materialization selects complete coordinate groups, combines all
132
+ their current Knowledge and Events, and retains the existing card identity.
133
+ An explicit full-chain request can use stage `all` or `compile: true` during
134
+ import. Unchanged results are reused; never force extraction just to build
135
+ indexes or retry materialization. `rebuild_knowledge` rebuilds saved cards'
136
+ retrieval artifacts without extracting documents. After successful index
137
+ publication, call `recall_knowledge` and answer from returned evidence.
134
138
  5. **You can add to the wiki, but you cannot rewrite it.** Call `propose_wiki_cards`
135
139
  with the `source_id` you just wrote and cards whose `source_refs` already exist in
136
140
  the store when you already have structured cards in hand — it writes them
137
- straight into `02_wiki`, they are recalled from the next compile on. A card whose
141
+ into the card store in `knowledge.db`; they are recalled after index publication. A card whose
138
142
  refs point nowhere is rejected, and rightly so. **A card body is read-only**: it
139
143
  belongs to the compiler. When something in the store is wrong, or a card and its
140
144
  source disagree, do not rewrite it — attach an annotation with
@@ -0,0 +1,20 @@
1
+ import { encode as tokens } from 'gpt-tokenizer'
2
+ import { encodeExtractionTable, decodeExtractionTable } from '../lib/types/extract-table.js'
3
+
4
+ // Compare the same semantic payload with the same o200k_base tokenizer.
5
+ // This measures transport size, not model extraction accuracy or the provider's billing.
6
+ function payload(count) {
7
+ const quote = '经营报表核对前,需要先统一订单状态、统计周期和退款口径。'
8
+ const sources = [{ quote, heading_path: ['经营报表', '口径核验'] }]
9
+ return { subject: '经营报表', knowledge: Array.from({ length: count }, (_, index) => ({ id: `k${index+1}`, text: `第 ${index+1} 项核验:统一统计周期,并检查订单状态与退款口径。`, object: '经营报表', action: '核对', scene: '周报', section: '核验步骤', order: index+1, sources })), events: [], objects: [{ mention: '经营报表', definition: '经营指标报表', evidence: quote }], actions: [{ mention: '核对', definition: '核验报表口径', evidence: quote }], scenes: [{ mention: '周报', definition: '每周报表场景', evidence: quote }], dropped: [] }
10
+ }
11
+ const results = [1, 12, 40].map(count => {
12
+ const value = payload(count)
13
+ const table = encodeExtractionTable(value)
14
+ decodeExtractionTable(table)
15
+ const json = tokens(JSON.stringify(value)).length
16
+ const toon = tokens(table).length
17
+ return { knowledge: count, jsonTokens: json, tableTokens: toon, outputReduction: `${((1-toon/json)*100).toFixed(1)}%` }
18
+ })
19
+ console.table(results)
20
+ console.log('固定表头对小样本有额外开销;真实节省取决于行数、字段长度、引文重复率和所选模型的 tokenizer。')