dsh-data-domain-knowledge 0.1.0-alpha.1 → 0.1.0-alpha.3
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.
- package/README.md +96 -113
- package/cordis.patch.yml +11 -5
- package/lib/client.js +5557 -3056
- package/lib/doc-page.js +7740 -0
- package/lib/types/convert/host.d.ts.map +1 -1
- package/lib/types/convert/host.js +36 -9
- package/lib/types/convert/host.js.map +1 -1
- package/lib/types/diagnosis/cards.d.ts +8 -7
- package/lib/types/diagnosis/cards.d.ts.map +1 -1
- package/lib/types/diagnosis/cards.js +119 -49
- package/lib/types/diagnosis/cards.js.map +1 -1
- package/lib/types/diagnosis/run.d.ts +51 -0
- package/lib/types/diagnosis/run.d.ts.map +1 -0
- package/lib/types/diagnosis/run.js +239 -0
- package/lib/types/diagnosis/run.js.map +1 -0
- package/lib/types/diagnosis/schema.d.ts +25 -2
- package/lib/types/diagnosis/schema.d.ts.map +1 -1
- package/lib/types/diagnosis/schema.js +64 -25
- package/lib/types/diagnosis/schema.js.map +1 -1
- package/lib/types/diagnosis/seed-source.d.ts +17 -2
- package/lib/types/diagnosis/seed-source.d.ts.map +1 -1
- package/lib/types/diagnosis/seed-source.js +18 -1
- package/lib/types/diagnosis/seed-source.js.map +1 -1
- package/lib/types/diagnosis/seed.d.ts +32 -42
- package/lib/types/diagnosis/seed.d.ts.map +1 -1
- package/lib/types/diagnosis/seed.js +187 -51
- package/lib/types/diagnosis/seed.js.map +1 -1
- package/lib/types/diagnosis/store.d.ts +114 -26
- package/lib/types/diagnosis/store.d.ts.map +1 -1
- package/lib/types/diagnosis/store.js +336 -167
- package/lib/types/diagnosis/store.js.map +1 -1
- package/lib/types/diagnosis/types.d.ts +168 -16
- package/lib/types/diagnosis/types.d.ts.map +1 -1
- package/lib/types/diagnosis/types.js +1 -1
- package/lib/types/diagnosis/types.js.map +1 -1
- package/lib/types/document-page.d.ts +39 -0
- package/lib/types/document-page.d.ts.map +1 -0
- package/lib/types/document-page.js +43 -0
- package/lib/types/document-page.js.map +1 -0
- package/lib/types/fs-atomic.d.ts +12 -0
- package/lib/types/fs-atomic.d.ts.map +1 -0
- package/lib/types/fs-atomic.js +42 -0
- package/lib/types/fs-atomic.js.map +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +214 -24
- package/lib/types/index.js.map +1 -1
- package/lib/types/knowledge-bases.d.ts +10 -2
- package/lib/types/knowledge-bases.d.ts.map +1 -1
- package/lib/types/knowledge-bases.js +20 -18
- package/lib/types/knowledge-bases.js.map +1 -1
- package/lib/types/proposals.d.ts +166 -0
- package/lib/types/proposals.d.ts.map +1 -0
- package/lib/types/proposals.js +238 -0
- package/lib/types/proposals.js.map +1 -0
- package/lib/types/runtime.d.ts +199 -7
- package/lib/types/runtime.d.ts.map +1 -1
- package/lib/types/runtime.js +728 -145
- package/lib/types/runtime.js.map +1 -1
- package/lib/types/settings-schema.d.ts +2 -2
- package/lib/types/types.d.ts +61 -10
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/types.js +56 -8
- package/lib/types/types.js.map +1 -1
- package/lib/types/wiki-types.d.ts +8 -1
- package/lib/types/wiki-types.d.ts.map +1 -1
- package/lib/types/wiki-types.js +16 -25
- package/lib/types/wiki-types.js.map +1 -1
- package/package.json +4 -3
- package/preset/tita-data-agent/agent.cordis.yml +11 -5
- package/src/client/DirectoryPicker.tsx +12 -12
- package/src/client/InfoHint.tsx +21 -8
- package/src/client/IntentTab.tsx +20 -26
- package/src/client/KnowledgeBaseTab.tsx +190 -80
- package/src/client/KnowledgePanel.tsx +42 -9
- package/src/client/KnowledgeStepRail.tsx +3 -0
- package/src/client/NodeSettings.tsx +20 -22
- package/src/client/PreviewSections.tsx +87 -33
- package/src/client/ProposalReview.tsx +313 -0
- package/src/client/TypeDefinitionDrawer.tsx +72 -38
- package/src/client/WikiTypeEditor.tsx +193 -77
- package/src/client/arch/AgentArchitectureGraph.tsx +143 -14
- package/src/client/arch/NodeLogicPanel.tsx +6 -3
- package/src/client/arch/model.ts +164 -26
- package/src/client/architecture.css +29 -9
- package/src/client/architecture.tsx +54 -29
- package/src/client/attribution/AttributionGraph.tsx +481 -34
- package/src/client/attribution/AttributionTab.tsx +507 -106
- package/src/client/attribution/CaseView.tsx +9 -14
- package/src/client/attribution/GraphStage.tsx +25 -18
- package/src/client/attribution/RunView.tsx +27 -9
- package/src/client/attribution/StageChrome.tsx +296 -140
- package/src/client/attribution/graph-options.ts +611 -47
- package/src/client/attribution/model.ts +559 -30
- package/src/client/convert/ConvertPanel.tsx +6 -1
- package/src/client/doc-page.css +134 -0
- package/src/client/doc-page.tsx +263 -0
- package/src/client/panel-state.ts +105 -0
- package/src/client/request.ts +36 -0
- package/src/client/styles.css +317 -43
- package/src/client/useFitScale.ts +15 -2
- package/src/client/wiki-type-groups.ts +86 -0
- package/src/convert/host.ts +41 -7
- package/src/diagnosis/cards.ts +120 -50
- package/src/diagnosis/run.ts +245 -0
- package/src/diagnosis/schema.ts +67 -26
- package/src/diagnosis/seed-source.ts +28 -3
- package/src/diagnosis/seed.ts +187 -85
- package/src/diagnosis/store.ts +358 -174
- package/src/diagnosis/types.ts +181 -16
- package/src/document-page.ts +51 -0
- package/src/fs-atomic.ts +42 -0
- package/src/index.ts +209 -22
- package/src/knowledge-bases.ts +20 -18
- package/src/proposals.ts +337 -0
- package/src/runtime.ts +736 -135
- package/src/types.ts +113 -19
- package/src/wiki-types.ts +17 -27
package/README.md
CHANGED
|
@@ -8,33 +8,24 @@
|
|
|
8
8
|
模型不可用时明确降级到 FTS,不会伪造向量结果。Markdown 中的
|
|
9
9
|
本地图片会与正文一起交给 WeMM,因此图片不是独立知识类型。
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## 承载范围(五个视图)
|
|
12
12
|
|
|
13
|
-
侧边栏 `TitaAgent`
|
|
13
|
+
侧边栏 `TitaAgent` 面板的五个视图就是本插件的全部范围:
|
|
14
14
|
|
|
15
|
-
| 视图 | 面板标签 |
|
|
16
|
-
| --- | --- | --- |
|
|
17
|
-
| `overview` | Agent 概览 |
|
|
18
|
-
| `intent` | 意图 | `
|
|
19
|
-
| `knowledge` | 知识库 | `
|
|
20
|
-
| `memory` | 记忆 |
|
|
21
|
-
| `eval` | 评测 |
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
意图/知识库/记忆/评测是四个概念,但它们共享同一条流水线(记录意图 → 录入来源 → 编译知识 →
|
|
25
|
-
沉淀记忆 → 评测质量)和同一个入口(面板的五个 Tab)。0020 之前,「意图」Tab 已经长在本插件里、
|
|
26
|
-
宿主实现却在第二个挂载单元里——**声明的信息架构与代码布局不一致**,这才是要修的东西。
|
|
27
|
-
|
|
28
|
-
意图的**配置与留痕**落在 `<agentRoot>/intent/`(0033):`registry.json` 是分类 / act 词表的
|
|
15
|
+
| 视图 | 面板标签 | 冻结契约 |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| `overview` | Agent 概览 | 各设置的挂载节点 |
|
|
18
|
+
| `intent` | 意图 | `intent_*` 工具名、`/intent/*` 路由、`tita-data-agent-intent` 设置、`titaDataAgentIntent` 服务;配置与留痕落 `<agentRoot>/intent/` |
|
|
19
|
+
| `knowledge` | 知识库 | `recall_knowledge` 等工具名、`/knowledge/*` 与 `/convert` 路由、`tita-data-agent-knowledge` / `-convert` 设置 |
|
|
20
|
+
| `memory` | 记忆 | 版本快照、`feedback.ndjson`、`access-audit.ndjson`,根在 `<agentRoot>/memory/<库 id>`;磁盘目录布局 |
|
|
21
|
+
| `eval` | 评测 | 问题集格式(开发期能力,不注册运行时入口) |
|
|
22
|
+
|
|
23
|
+
意图的**配置与留痕**落在 `<agentRoot>/intent/`:`registry.json` 是分类 / act 词表的
|
|
29
24
|
真源(面板的「意图配置」直接读写这个文件,不再写宿主的 settings 文档),`records.ndjson`
|
|
30
25
|
是每轮一条记录的 append-only 留痕(按 `sessionKey#turn` 读时取最后一条,所以内存里
|
|
31
26
|
「一轮一条」的语义不变)。读接口 `/intent/store` 与 `/intent/overview` 读的是**留痕**:
|
|
32
27
|
引擎内存里那份有 600 秒 TTL,重启或隔一段时间回来不该让面板上的历史凭空消失。
|
|
33
28
|
|
|
34
|
-
`src/intent/` 的宿主半与 `src/client/IntentTab.tsx` 的浏览器半之间**必须保留 HTTP 边界**(`/intent/*`):
|
|
35
|
-
两者分处两个 bundle,无法直接互相 import。这与 0018 删掉的 `POST /knowledge/sources` 不同——
|
|
36
|
-
那次是宿主→宿主的回环,可以改成进程内调用。
|
|
37
|
-
|
|
38
29
|
## 五段链路
|
|
39
30
|
|
|
40
31
|
| 段 | 名称 | 产物 | 关键配置 |
|
|
@@ -45,14 +36,14 @@
|
|
|
45
36
|
| 4 | 召回 Recall | 多路(关键词 + 向量 + 知识图谱)召回 wikiNotes,取 `recallTopK`(默认 10),再解析父级 wiki 与该 wiki 的 1 跳知识图谱 | `recallTopK` / `recallMode` |
|
|
46
37
|
| 5 | 重排 Rerank | BERT cross-encoder 对候选 wikiNotes 精排,取 `contextTopN`(默认 5)组成 `context` | `contextTopN` / `rerankProvider` / `rerankModel` |
|
|
47
38
|
|
|
48
|
-
>
|
|
49
|
-
>
|
|
50
|
-
>
|
|
39
|
+
> 第 4、5 段在**界面上是同一栏**(知识库 → 召回重排)。它们在流水线上仍是两步,
|
|
40
|
+
> 但「跑一次真实召回长什么样」是一个问题,分两栏会让用户先跑召回、再切到重排才能
|
|
41
|
+
> 看到同一次运行的全貌。
|
|
51
42
|
|
|
52
43
|
> 术语迁移:SourceRaw 曾叫 SourceRow / SourceTruth。磁盘目录 `01_source_truth`、工具名
|
|
53
44
|
> `add_source` / `query_source_truth`、HTTP `/knowledge/sources`、设置键 `allowSourceTruth`
|
|
54
45
|
> 与错误码 `SOURCE_TRUTH_DISABLED` 作为兼容名保留,语义等同 SourceRaw。
|
|
55
|
-
>
|
|
46
|
+
> 「编译 / 构建」是同一次 `rebuild()`:编译的**按主题聚合**由 Agent 完成,
|
|
56
47
|
> **wiki↔wiki 双向链接**与**分阶段重建**是设计目标,图谱当前只有 `supported_by` 溯源边。
|
|
57
48
|
|
|
58
49
|
- 设置项**不再有独立入口**:它们挂在 Agent 概览架构图的对应节点上(SourceRaw → 收录开关与
|
|
@@ -72,15 +63,15 @@
|
|
|
72
63
|
|
|
73
64
|
## 本地启用 WeMM
|
|
74
65
|
|
|
75
|
-
在 Apple Silicon
|
|
66
|
+
在 Apple Silicon 上执行一次(在插件包目录内):
|
|
76
67
|
|
|
77
68
|
```bash
|
|
78
|
-
|
|
69
|
+
bash scripts/setup-embedding.sh
|
|
79
70
|
```
|
|
80
71
|
|
|
81
72
|
脚本会把 Python 环境放到 `~/.tita-data-agent/embedding-venv`,把量化模型放到
|
|
82
|
-
`~/.tita-data-agent/models/WeMM-Embedding-2B-Quantized
|
|
83
|
-
|
|
73
|
+
`~/.tita-data-agent/models/WeMM-Embedding-2B-Quantized`。新配置会自动发现这两个路径;
|
|
74
|
+
如果 DSH 中已经保存过旧配置,则在
|
|
84
75
|
Tita Data Agent → Agent 概览 →「构建」节点的设置中确认:
|
|
85
76
|
|
|
86
77
|
- Provider:`WeMM Python(本地)`
|
|
@@ -90,7 +81,7 @@ Tita Data Agent → Agent 概览 →「构建」节点的设置中确认:
|
|
|
90
81
|
- 设备:`自动(优先 MPS)`
|
|
91
82
|
|
|
92
83
|
知识库默认保存在 `~/.tita-data-agent/knowledge`;设置了 `DSH_KNOWLEDGE_ROOT`
|
|
93
|
-
|
|
84
|
+
或已有旧的 `domain_knowledge` 目录时会优先沿用。点击「编译」后,
|
|
94
85
|
`03_compiled` 会生成 `wiki_notes.json`、`knowledge_graph.json`、
|
|
95
86
|
`vector-manifest.json`、`vectors.binary` 和 `vectors.int8`。未修改的 wikiNote
|
|
96
87
|
会复用已有向量,只有新增或变更的 note 重新编码;编码与重排各自使用常驻 Python
|
|
@@ -100,8 +91,7 @@ BERT 重排默认使用 `BAAI/bge-reranker-base`;如需完全离线,可把
|
|
|
100
91
|
`~/.tita-data-agent/models/bge-reranker-base`(会被自动发现),或设置
|
|
101
92
|
`DSH_RERANK_MODEL` / 在设置里填写本地路径。未安装时召回会降级到融合分数并给出警告。
|
|
102
93
|
**目录必须含分词器**(`tokenizer.json` 或 `sentencepiece.bpe.model`)——只有权重时模型会
|
|
103
|
-
加载成功但给所有输入同一个分(`RERANK_TOKENIZER_DEGENERATE
|
|
104
|
-
`docs/0024-本地模型运行时.md`。
|
|
94
|
+
加载成功但给所有输入同一个分(`RERANK_TOKENIZER_DEGENERATE`)。
|
|
105
95
|
|
|
106
96
|
知识写入、编译、SourceRaw 读取和召回支持统一的
|
|
107
97
|
`sessionId/turnId/intentId/taskId/subtaskId/runId/traceId/domain` lineage。卡片把
|
|
@@ -112,20 +102,12 @@ BERT 重排默认使用 `BAAI/bge-reranker-base`;如需完全离线,可把
|
|
|
112
102
|
可以通过工具 `check_knowledge_embeddings` 或 `GET /knowledge/embedding/health`
|
|
113
103
|
查看 provider、模型、设备、索引条数和最后一次错误。
|
|
114
104
|
|
|
115
|
-
## 格式转换(convert
|
|
105
|
+
## 格式转换(convert)
|
|
116
106
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
plugins/dsh-data-domain-knowledge/src/convert/
|
|
122
|
-
├─ host.ts 工具 /convert_*、路由 /convert/**、设置、面板
|
|
123
|
-
├─ ingest.ts 唯一写入口:ingestDelivery() → runtime.addSource()
|
|
124
|
-
├─ core-loader.ts 可选内核的懒加载与降级
|
|
125
|
-
└─ types.ts
|
|
126
|
-
packages/dsh-convert-core 内核(不挂载,可独立运行:node bin/tita-convert.mjs)
|
|
127
|
-
└─ @firecrawl/anydoc MIT / Rust / 预编译绑定:doc docx ppt pptx xls xlsx odt ods odp rtf epub csv 文本层 PDF
|
|
128
|
-
```
|
|
107
|
+
多格式转换是本插件的一个子模块(`src/convert/`),与知识库共用同一次挂载、同一个
|
|
108
|
+
侧边栏 Tab、同一套 runtime。解析由可选内核 `dsh-convert-core` 完成(内核不挂载,可独立
|
|
109
|
+
运行),底层是 `@firecrawl/anydoc`(MIT / Rust / 预编译绑定),支持 doc、docx、ppt、
|
|
110
|
+
pptx、xls、xlsx、odt、ods、odp、rtf、epub、csv 与文本层 PDF。
|
|
129
111
|
|
|
130
112
|
| 项 | 值 |
|
|
131
113
|
| --- | --- |
|
|
@@ -134,40 +116,30 @@ packages/dsh-convert-core 内核(不挂载,可独立运行:node bin/tita
|
|
|
134
116
|
| 设置命名空间 | `tita-data-agent-convert`(冻结契约,由本插件安装) |
|
|
135
117
|
| 交付目录 | `~/.tita-data-agent/convert-out/<taskId>/`(`index.md` / `assets/` / `manifest.json`) |
|
|
136
118
|
|
|
137
|
-
**依赖是可选的。** `dsh-convert-core` 声明在 `optionalDependencies
|
|
138
|
-
|
|
119
|
+
**依赖是可选的。** `dsh-convert-core` 声明在 `optionalDependencies`,首次调用时才加载。
|
|
120
|
+
平台没有 anydoc 预编译绑定、或用户显式不装时,
|
|
139
121
|
`convert_*` 与 `/convert` 面板返回 `DEPENDENCY_MISSING` 并给出安装建议,**knowledge 本体
|
|
140
|
-
(`add_source` / 编译 /
|
|
122
|
+
(`add_source` / 编译 / 召回)照常可用**。
|
|
141
123
|
|
|
142
|
-
|
|
143
|
-
`POST /knowledge/sources` 回环。少了一次 JSON 序列化,也因此没有旧的 ~1.2 MB body 上限。
|
|
144
|
-
单条 SourceRaw **没有字符数上限**:`maxSourceBytes` 在 0029 撤掉了(先撤面板上的字段,
|
|
145
|
-
后来连运行层那道闸门一起撤 —— 只撤面板等于留一个用户改不了、也找不到的硬上限)。
|
|
124
|
+
**单条 SourceRaw 没有字符数上限**:`maxSourceBytes` 已撤除。
|
|
146
125
|
真正的边界是转换内核的 `maxInputBytes`(管入口大小)与嵌入分批(管模型输入)。
|
|
147
126
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
1. 内核不 import knowledge,产物只写 `convert-out/`;
|
|
151
|
-
2. 转换代码写知识库只能经 `ingest.ts` 的 `IngestTarget.addSource`,别处不许直接落 `01_source_truth`;
|
|
152
|
-
3. 0017 的网页 / 视频 / OCR 应做成**可选适配器包**注册进内核,不要继续往本插件里塞 ffmpeg / whisper。
|
|
153
|
-
|
|
154
|
-
## 多知识库与文档(0021)
|
|
127
|
+
## 多知识库与文档
|
|
155
128
|
|
|
156
129
|
一个**知识库 = 独立配置 + 独立内容**(产品参照 WeKnora)。注册表持久化在
|
|
157
130
|
`<dataHome>/knowledge-bases.json`,`dataHome = process.env.TITA_DATA_AGENT_HOME || ~/.tita-data-agent`。
|
|
158
|
-
默认库 id 固定为 `default`,其 `rootDir` 始终来自插件设置 `rootDir
|
|
159
|
-
|
|
131
|
+
默认库 id 固定为 `default`,其 `rootDir` 始终来自插件设置 `rootDir`;
|
|
132
|
+
**不传 `kb` 的旧接口与旧工具一律作用于默认库,行为不变**。
|
|
160
133
|
|
|
161
134
|
```ts
|
|
162
135
|
interface KnowledgeBase { id; name; description; rootDir; isDefault; sourceTypes; wikiTypes; wikiSchemaMode; createdAt; updatedAt; sourceCount; cardCount; noteCount; buildVersion }
|
|
163
136
|
```
|
|
164
137
|
|
|
165
138
|
`sourceCount` / `cardCount` / `noteCount` / `buildVersion` 和每条分类/类型的计数都是
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
`await refresh()`。
|
|
139
|
+
**计算字段**,由真实 runtime 重新统计并缓存进同一个 JSON,
|
|
140
|
+
HTTP `GET /knowledge/bases` 在返回前先刷新。
|
|
169
141
|
|
|
170
|
-
|
|
142
|
+
**根路径下是六段**:
|
|
171
143
|
|
|
172
144
|
| 段 | 装什么 | 删掉的后果 |
|
|
173
145
|
| --- | --- | --- |
|
|
@@ -178,40 +150,43 @@ interface KnowledgeBase { id; name; description; rootDir; isDefault; sourceTypes
|
|
|
178
150
|
| `tmp/` | 运行期临时文件,二级按日期分桶 | 只影响未完成的任务 |
|
|
179
151
|
| `resource/` | 模型、Python 环境、`knowledge-bases.json` | 失去语义检索(嵌入/重排不可用) |
|
|
180
152
|
|
|
181
|
-
|
|
153
|
+
**记忆与意图为什么与知识树平级**:记忆装的是版本快照与审计流水 ——
|
|
182
154
|
那是**关于这个 Agent 的动作留痕**,不是关于知识的断言;留在知识树里会让「备份知识树」
|
|
183
155
|
被迫连审计一起备份,也让「知识树有哪几段」这个问题混进一个横切层。意图则是**会话级**的
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
知识、记忆、意图三段都是可以直接备份、直接 diff 的用户文件。
|
|
156
|
+
(同一句话在哪个知识库下说,理解方式不该变),所以它不分库。这样知识、记忆、意图三段
|
|
157
|
+
都是可以直接备份、直接 diff 的用户文件。
|
|
187
158
|
|
|
188
|
-
知识树内部(`domain_knowledge/<知识库 id
|
|
189
|
-
|
|
159
|
+
知识树内部(`domain_knowledge/<知识库 id>/`)现在是**三段**:schema 段与记忆段都已不在
|
|
160
|
+
(后者搬去了 `memory/`)。
|
|
190
161
|
|
|
191
162
|
| 段 | 装什么 | 删掉的后果 |
|
|
192
163
|
| --- | --- | --- |
|
|
193
164
|
| `01_source_truth/<source_type>/` | SourceRaw,一级是**来源分类**,二级是文档 | 丢数据 |
|
|
194
165
|
| `02_wiki/<entity_type>/` | Wiki 卡片,一级是卡片类型 | 丢结论 |
|
|
195
|
-
| `03_compiled/` | wikiNotes / 向量 / 知识图谱 | 可重建 |
|
|
196
|
-
|
|
166
|
+
| `03_compiled/` | wikiNotes / 向量 / 知识图谱 / 归因图谱 | 可重建 |
|
|
167
|
+
|
|
168
|
+
**归因图谱也在这三段里**(v1.1):一次排查的产物是一条来源分类为 `agent_diagnosis_case`
|
|
169
|
+
的 SourceRaw(落 `01_source_truth/`),模板卡由类型定义派生、不落盘,字段级的归因图
|
|
170
|
+
落 `03_compiled/diagnosis_graph.json`。旧的 `05_diagnosis/` 撤销了;它里面的 `*.jsonl`
|
|
171
|
+
如果还在,角色是**只读的迁移输入与历史快照** —— 不再被写,但仍然读得出来(证据与根因
|
|
172
|
+
就从那里来),所以旧知识根不会因为这次改动而读不出内容。
|
|
197
173
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
「没用的空文件夹」了,删掉别人的文件比留一个空目录危险得多。
|
|
174
|
+
schema 段已撤掉:它从建出来那天起就是一个**空目录**,分类注册表与 Wiki 类型注册表
|
|
175
|
+
一直住在 `<agentRoot>/resource/knowledge-bases.json`(那是配置,跟着根路径走)。
|
|
176
|
+
启动时会把空的那个目录删掉 —— **非空则保留**:那就不属于「没用的空文件夹」了,
|
|
177
|
+
删掉别人的文件比留一个空目录危险得多。
|
|
203
178
|
|
|
204
179
|
`01_source_truth` 按分类分目录(而不是平铺)的理由与 `02_wiki` 一致:分类是每份来源的
|
|
205
180
|
必备元数据(frontmatter 的 `source_type`),提到目录名上之后「按分类找东西」在文件系统
|
|
206
181
|
层面直接成立,不依赖界面。平铺在真实使用里会先变成垃圾场 —— 几十份来源混在一层,`ls`
|
|
207
182
|
读不出「我的指标口径在哪」。启动时一次性把平铺的文档搬进分类目录;读路径不依赖这个层级
|
|
208
|
-
|
|
183
|
+
(启动时会递归扫全段建 slug → path 索引),所以旧布局、新布局与两者并存的中间态
|
|
209
184
|
都能读。**改分类 = 换目录**:`add_source` 用同一 `sourceId` 配新 `sourceType` 时,旧目录
|
|
210
185
|
里那份会被删掉,不会留下孤儿。
|
|
211
186
|
|
|
212
|
-
`resource/`
|
|
213
|
-
|
|
214
|
-
|
|
187
|
+
`resource/` 装模型、虚拟环境与 `knowledge-bases.json` —— 「这个 Agent 的全部磁盘足迹」
|
|
188
|
+
因此是一个目录,备份 / 迁移 / 整个删掉都只需要认一个路径。模型与虚拟环境原先住在
|
|
189
|
+
`~/.tita-data-agent`,启动时一次性搬迁(先 `rename`,跨卷**不自动复制**,因为可能有几个
|
|
215
190
|
GB);旧的 `TITA_DATA_AGENT_HOME` 留在解析链上作为兜底,所以搬与没搬都能跑。
|
|
216
191
|
搬迁**按条目合并**:`resource/models/` 里已经有用户自己放的模型时,仍会把旧的嵌入模型
|
|
217
192
|
搬进来,只跳过同名的那个 —— 否则「目标目录存在」会让另一样东西永远搬不过来。
|
|
@@ -221,31 +196,24 @@ GB);旧的 `TITA_DATA_AGENT_HOME` 留在解析链上作为兜底,所以搬
|
|
|
221
196
|
的顺序解析。设置面板用占位符显示解析后的真实路径,并在**家当不在 `resource/` 下时
|
|
222
197
|
逐条告警**(「还在旧位置、重启会搬」和「根本不是路径、迁移搬不了」要做的事不同)。
|
|
223
198
|
|
|
224
|
-
|
|
225
|
-
> 本身**,`z.string().min(1).default('')` 会让 `settings.installSection()` 在登记命名空间
|
|
226
|
-
> 时直接抛 —— 后果是整个设置分区注册不上(面板「设置服务不可用」)、家当迁移不执行、
|
|
227
|
-
> `settings.yaml` 里的值一个都不生效,而界面上没有任何原因。见
|
|
228
|
-
> `src/settings-schema.ts` 的模块注释与 `tests/settings-schema.test.mjs`。
|
|
229
|
-
|
|
230
|
-
向量清单里记的模型名也从绝对路径改成了 `local:<模型目录名>` —— **身份与位置解耦**,
|
|
199
|
+
向量清单里记的模型名是 `local:<模型目录名>` —— **身份与位置解耦**,
|
|
231
200
|
否则把模型搬一次就让整个索引判成「配置不匹配」而作废。
|
|
232
201
|
|
|
233
|
-
|
|
202
|
+
**「文件类型 → 解析引擎」那张规则表已撤。** 它唯一被读的地方是浏览器决定
|
|
234
203
|
「这份文件直读还是送转换内核」,而那个判断现在只看扩展名本身(`DIRECT_READ_EXT`);
|
|
235
204
|
真正决定用哪个适配器的是**转换内核自己的格式表**(`ANYDOC/SCANNED/IDDOC/TEXT_EXTENSIONS`),
|
|
236
205
|
它从来不读这张表 —— 也就是说「把 .docx 设成直读文本」这类配置**改了不生效**。撤掉
|
|
237
206
|
之后:上传选择框的 `accept` 问内核要(`/convert/api/capabilities`),文件类型筛选项
|
|
238
207
|
和计数从**这一库真实的文档**推导。两边都不可能再与内核漂移。
|
|
239
208
|
|
|
240
|
-
**文档扩展名 `ext`
|
|
209
|
+
**文档扩展名 `ext` 的推导是有损的**:优先取
|
|
241
210
|
`metadata.source_path` 的 basename 扩展名;否则 `source_format === 'markdown'` → `.md`,
|
|
242
|
-
`'office'` → `.docx`,其余 → `.` + `source_format`;都没有 → `.md
|
|
243
|
-
`
|
|
211
|
+
`'office'` → `.docx`,其余 → `.` + `source_format`;都没有 → `.md`。只有来源写了
|
|
212
|
+
`source_path` 时才精确。
|
|
244
213
|
|
|
245
|
-
文档的 `parser`
|
|
246
|
-
`
|
|
247
|
-
(`add_source`、浏览器直读文本)是 `direct` —— 没有解析器。
|
|
248
|
-
猜一个引擎名(`.pdf` → `anydoc`),那是在陈述一件没有发生过的事。
|
|
214
|
+
文档的 `parser` 字段说的是**谁解析了这份文档**:经转换内核进来的会写
|
|
215
|
+
`metadata.parser`(如 `anydoc@1/pdf`),直接写进来的
|
|
216
|
+
(`add_source`、浏览器直读文本)是 `direct` —— 没有解析器。
|
|
249
217
|
|
|
250
218
|
### HTTP API
|
|
251
219
|
|
|
@@ -255,13 +223,32 @@ POST /knowledge/bases { name, description?, rootDir? } → { base }
|
|
|
255
223
|
PATCH /knowledge/bases/:id { name?, description?, sourceTypes?, wikiTypes?, wikiSchemaMode? } → { base }
|
|
256
224
|
DELETE /knowledge/bases/:id → { deleted: true }
|
|
257
225
|
GET /knowledge/documents?kb=&query=&source_type=&limit=&offset= → { documents, total }
|
|
258
|
-
GET /knowledge/documents/:docId?kb= → { document }
|
|
226
|
+
GET /knowledge/documents/:docId?kb= → { document }(正文截前 4000 字符)
|
|
227
|
+
GET /knowledge/documents/:docId/content?kb=&offset=&limit= → { text, offset, nextOffset, totalChars, eof }
|
|
228
|
+
GET /knowledge/documents/:docId/view?kb= → 独立整页(HTML,读全文)
|
|
259
229
|
GET /knowledge/documents/:docId/versions?kb= → { versions }
|
|
260
230
|
POST /knowledge/documents/:docId/revert?kb= { versionId } → { document }
|
|
261
231
|
DELETE /knowledge/documents/:docId?kb= → { deleted: true }
|
|
262
232
|
GET /knowledge/assets/:kb/* → 知识库根目录下的文件流
|
|
233
|
+
GET /knowledge/doc-page.js → 独立整页的脚本(构建产物)
|
|
234
|
+
GET /knowledge/card-proposals?kb=&status= → { total, proposals }(默认只看待审)
|
|
235
|
+
POST /knowledge/card-proposals/review { kb, proposal_id, action, reason? } → { proposalId, status, written }
|
|
236
|
+
POST /diagnosis/run { kb, record } → { sourceId, proposalId }
|
|
263
237
|
```
|
|
264
238
|
|
|
239
|
+
**`/knowledge/card-proposals/review` 是「人的确认动作」,刻意不做成 Agent 工具。**
|
|
240
|
+
类型层的写入现在有两段:Agent 与编译只**提议**(`propose_wiki_cards`、Pass 0),
|
|
241
|
+
未确认的提议不落 `02_wiki/`、不进编译、不参与召回、不在归因图上出现;人在面板上
|
|
242
|
+
逐条 review(通过并写入 / 仅确认 / 拒绝),确认之后才走 `write_knowledge_card` ——
|
|
243
|
+
而那个工具现在要求一条**已确认且尚未落卡**的 `proposal_id`,确认凭证是一次性的。
|
|
244
|
+
提议落在记忆段 `<agentRoot>/memory/<库 id>/card-proposals/`,不在知识树里。
|
|
245
|
+
|
|
246
|
+
**原文预览只发前 4000 个字符。** `GET /knowledge/documents/:docId` 返回的 `content` 是
|
|
247
|
+
截断过的,全文长度在 `contentChars`、是否截断在 `contentTruncated`。理由是抽屉只有
|
|
248
|
+
380px 宽,读不完一份几十万字的文档 —— 而把整份正文发过去正是「打开弹层要等半天」的
|
|
249
|
+
成因。要读全文走 `.../view` 那个独立整页:它按 `offset`/`limit` **一页一段**地取
|
|
250
|
+
(默认 20000 字符一页,切点对齐空行),所以任何一次响应都不与文档大小成正比。
|
|
251
|
+
|
|
265
252
|
`/knowledge/stats`、`/knowledge/search`、`/knowledge/rebuild`、`/knowledge/cards`、
|
|
266
253
|
`/knowledge/sources`、`/knowledge/graph`、`/knowledge/embedding/health` 与全部
|
|
267
254
|
`*_knowledge*` 工具都接受**可选** `kb`(query 或 body 字段)。`docId` 含 `:`
|
|
@@ -293,7 +280,7 @@ GET /knowledge/assets/:kb/* → 知识库
|
|
|
293
280
|
**回滚 = 用快照内容重新调用 `addSource`**:因此回滚前会把当时的 head 再快照一次,
|
|
294
281
|
历史只增不减,**回滚本身也可回滚**。回滚 `current-*` 是 no-op。
|
|
295
282
|
|
|
296
|
-
###
|
|
283
|
+
### 召回链路(两路 + 图谱 boost)
|
|
297
284
|
|
|
298
285
|
```text
|
|
299
286
|
query → R0 分词 → R1 两路各自超采并过阈值(候选池 50)
|
|
@@ -303,22 +290,21 @@ query → R0 分词 → R1 两路各自超采并过阈值(候选池 50)
|
|
|
303
290
|
→ R5 弃答(insufficientEvidence)
|
|
304
291
|
```
|
|
305
292
|
|
|
306
|
-
- **R0
|
|
307
|
-
的口径切开。
|
|
308
|
-
实测 `排查`→6 命中、`怎么排查指标异常`→**0**。
|
|
293
|
+
- **R0 分词**:中文按**单字 + 相邻双字**切分(不用词典),ASCII 按 `unicode61`
|
|
294
|
+
的口径切开。
|
|
309
295
|
- **R1 关键词路**:SQLite FTS5 + **BM25**(`node:sqlite`,零新依赖;不可用时如实降级)。
|
|
310
296
|
中文之所以不用内置 tokenizer:`unicode61` 不切中文,`trigram` 要求查询 ≥3 字符且会把
|
|
311
297
|
整句变成互相 AND 的三字窗口。分数按本次最高分归一到 0..1,再过 `keywordThreshold`;
|
|
312
298
|
另有**多字词覆盖率**门槛(只数双字词与 ASCII 词,单字在中文里不是证据)。
|
|
313
299
|
- **R1 向量路**:**编码器健康门**(两段无关文本必须余弦 < 0.99,否则整路停用)→
|
|
314
|
-
查询编码一次 → binary/Hamming 预筛 → int8 精算**原始余弦**(`dot / 127
|
|
315
|
-
|
|
316
|
-
- **R2 融合**:**RRF**(`k=60`,关键词 0.3 / 向量 0.7
|
|
317
|
-
|
|
300
|
+
查询编码一次 → binary/Hamming 预筛 → int8 精算**原始余弦**(`dot / 127²`)→
|
|
301
|
+
`vectorThreshold`。
|
|
302
|
+
- **R2 融合**:**RRF**(`k=60`,关键词 0.3 / 向量 0.7)——只吃**名次**,所以各路分数
|
|
303
|
+
量纲不同这件事不再影响排序。
|
|
318
304
|
- **R2 图谱**:**boost,不是第三路**。它给已经在候选池里的条目加一个 RRF 项,**不能自己
|
|
319
305
|
制造候选**。代价是「只提到某份来源、没提到任何卡片正文」的查询没有第二条路 ——
|
|
320
306
|
由关键词索引收录 **note 的溯源身份**(sourceRefs + 来源标题)来补偿。
|
|
321
|
-
- **R3
|
|
307
|
+
- **R3 重排**:作用在**候选池**上(不是已截断的 topK),
|
|
322
308
|
低于 `rerankThreshold` 的一律丢弃并报出丢了几条。阈值与 WeKnora 同刻度(**原始 logit**)。
|
|
323
309
|
worker 用 `predict_raw()`(`activation_fn=Identity`)返回 logit —— `CrossEncoder.predict`
|
|
324
310
|
对 `num_labels == 1` 默认套 sigmoid,直接拿返回值比 0.2 会让阈值永远不生效;展示用的
|
|
@@ -331,8 +317,7 @@ query → R0 分词 → R1 两路各自超采并过阈值(候选池 50)
|
|
|
331
317
|
并标注判据强度(`rerank-threshold` / `vector-threshold` / `relative-only` / `not-needed`)。
|
|
332
318
|
宁可说「没有」,也不凑满 topN 让模型编。
|
|
333
319
|
- **降级不谎报**:`routes` 只列**通过健康门且真的跑起来**的路;每一路的状态、候选数、
|
|
334
|
-
最高分、阈值与降级原因都在 `diagnostics.routes` 里。
|
|
335
|
-
`routes: ["fts","vector","graph"]`,是这次要修的核心问题之一。
|
|
320
|
+
最高分、阈值与降级原因都在 `diagnostics.routes` 里。
|
|
336
321
|
- `mode: 'graph'` 与 `hybrid` **同义**(图谱不能制造候选,「只靠图谱」不成立)。
|
|
337
322
|
- 阈值初值:`keywordThreshold 0.3` / `rerankThreshold 0.2` 沿用 WeKnora 的出厂值;
|
|
338
323
|
**`vectorThreshold` 是 0.5,不是它的 0.15** —— 那个数是它自己 embedding 模型的刻度,
|
|
@@ -344,14 +329,12 @@ query → R0 分词 → R1 两路各自超采并过阈值(候选池 50)
|
|
|
344
329
|
余弦 < 0.99),重排器查分词器词表(`vocab_size ≥ 1000` 且探针句有非 `<unk>` 条目,否则
|
|
345
330
|
`RERANK_TOKENIZER_DEGENERATE`)。原因是「能加载」不等于「可用」:本地快照缺分词器文件时,
|
|
346
331
|
重排器照样加载、照样出分(实测三条无关文本 `0.999 / 0.998 / 0.9994`),只有探针能发现。
|
|
347
|
-
修法与运维见 `docs/0024-本地模型运行时.md`。
|
|
348
332
|
- **编码器指纹** `ENCODER_FINGERPRINT` 写在向量清单里:同一个模型换了「怎么调它」也必须让
|
|
349
|
-
已有向量作废,否则 `rebuild all` 会按 contentHash
|
|
350
|
-
修好编码器后构建仍报 `reused: 44`,修复等于没发生)。
|
|
333
|
+
已有向量作废,否则 `rebuild all` 会按 contentHash 把旧向量原样复用。
|
|
351
334
|
|
|
352
335
|
`listDocuments()` / `readDocument(docId)` / `listVersions(docId)` /
|
|
353
|
-
`revertDocument(docId, versionId)` / `deleteDocument(docId)`
|
|
354
|
-
|
|
336
|
+
`revertDocument(docId, versionId)` / `deleteDocument(docId)` 是文档接口;
|
|
337
|
+
详情页的 `assets[].url` 即 `/knowledge/assets/<kbId>/<rel>`。
|
|
355
338
|
|
|
356
339
|
## 评测
|
|
357
340
|
|
package/cordis.patch.yml
CHANGED
|
@@ -112,11 +112,17 @@
|
|
|
112
112
|
3. **Never invent a number.** Every figure you report must come from a tool
|
|
113
113
|
result in this turn, and you must say which one. "I don't have that data" is
|
|
114
114
|
a correct answer; a made-up number is not.
|
|
115
|
-
4. **Put it in writing while you still have the evidence
|
|
116
|
-
metric's exact calculation, a process, a diagnosed
|
|
117
|
-
|
|
118
|
-
`
|
|
119
|
-
nowhere is rejected, and rightly so.
|
|
115
|
+
4. **Put it in writing while you still have the evidence — as a proposal, not
|
|
116
|
+
a card.** A definition, a metric's exact calculation, a process, a diagnosed
|
|
117
|
+
cause — if it will be asked again, call `propose_wiki_cards` with the
|
|
118
|
+
`source_id` you just wrote and drafts whose `source_refs` already exist in
|
|
119
|
+
the store. A draft whose refs point nowhere is rejected, and rightly so.
|
|
120
|
+
**You cannot write a card yourself**: `write_knowledge_card` only accepts a
|
|
121
|
+
proposal a human has already confirmed, and unconfirmed proposals never
|
|
122
|
+
reach the wiki — they are not compiled, not recalled and not on the graph.
|
|
123
|
+
So say what you proposed and that it is waiting for review; do not claim the
|
|
124
|
+
card exists. Call `list_card_proposals` first so you do not re-propose
|
|
125
|
+
something a human already turned down.
|
|
120
126
|
5. **Correct a card, do not quietly overwrite it.** When something in the store
|
|
121
127
|
is wrong, set its status to `problem` and say what is wrong with it. Cards
|
|
122
128
|
marked `problem` drop out of recall by default — that is how a wrong
|