dsh-data-domain-knowledge 0.1.0-alpha.1 → 0.1.0-alpha.2
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 +69 -110
- package/package.json +3 -3
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
|
|
116
|
-
|
|
117
|
-
多格式转换的 **DSH 宿主层**自 0018 起就在本插件里:不再是第二个挂载插件,而是本插件的一个
|
|
118
|
-
子模块(`src/convert/`),共用同一次挂载、同一个侧边栏 Tab、同一套 runtime。
|
|
105
|
+
## 格式转换(convert)
|
|
119
106
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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,15 +150,14 @@ 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>/`)现在是**四段**:`00_schema` 与 `04_memory`
|
|
160
|
+
都已不在(后者搬去了 `memory/`)。
|
|
190
161
|
|
|
191
162
|
| 段 | 装什么 | 删掉的后果 |
|
|
192
163
|
| --- | --- | --- |
|
|
@@ -195,23 +166,22 @@ interface KnowledgeBase { id; name; description; rootDir; isDefault; sourceTypes
|
|
|
195
166
|
| `03_compiled/` | wikiNotes / 向量 / 知识图谱 | 可重建 |
|
|
196
167
|
| `05_diagnosis/` | 智能归因图谱 | 可重建 |
|
|
197
168
|
|
|
198
|
-
`00_schema`
|
|
199
|
-
|
|
200
|
-
`00_schema`
|
|
201
|
-
|
|
202
|
-
「没用的空文件夹」了,删掉别人的文件比留一个空目录危险得多。
|
|
169
|
+
`00_schema` 已撤掉:它从建出来那天起就是一个**空目录**,分类注册表与 Wiki 类型注册表
|
|
170
|
+
一直住在 `<agentRoot>/resource/knowledge-bases.json`(那是配置,跟着根路径走)。
|
|
171
|
+
启动时会把空的 `00_schema` 删掉 —— **非空则保留**:那就不属于「没用的空文件夹」了,
|
|
172
|
+
删掉别人的文件比留一个空目录危险得多。
|
|
203
173
|
|
|
204
174
|
`01_source_truth` 按分类分目录(而不是平铺)的理由与 `02_wiki` 一致:分类是每份来源的
|
|
205
175
|
必备元数据(frontmatter 的 `source_type`),提到目录名上之后「按分类找东西」在文件系统
|
|
206
176
|
层面直接成立,不依赖界面。平铺在真实使用里会先变成垃圾场 —— 几十份来源混在一层,`ls`
|
|
207
177
|
读不出「我的指标口径在哪」。启动时一次性把平铺的文档搬进分类目录;读路径不依赖这个层级
|
|
208
|
-
|
|
178
|
+
(启动时会递归扫全段建 slug → path 索引),所以旧布局、新布局与两者并存的中间态
|
|
209
179
|
都能读。**改分类 = 换目录**:`add_source` 用同一 `sourceId` 配新 `sourceType` 时,旧目录
|
|
210
180
|
里那份会被删掉,不会留下孤儿。
|
|
211
181
|
|
|
212
|
-
`resource/`
|
|
213
|
-
|
|
214
|
-
|
|
182
|
+
`resource/` 装模型、虚拟环境与 `knowledge-bases.json` —— 「这个 Agent 的全部磁盘足迹」
|
|
183
|
+
因此是一个目录,备份 / 迁移 / 整个删掉都只需要认一个路径。模型与虚拟环境原先住在
|
|
184
|
+
`~/.tita-data-agent`,启动时一次性搬迁(先 `rename`,跨卷**不自动复制**,因为可能有几个
|
|
215
185
|
GB);旧的 `TITA_DATA_AGENT_HOME` 留在解析链上作为兜底,所以搬与没搬都能跑。
|
|
216
186
|
搬迁**按条目合并**:`resource/models/` 里已经有用户自己放的模型时,仍会把旧的嵌入模型
|
|
217
187
|
搬进来,只跳过同名的那个 —— 否则「目标目录存在」会让另一样东西永远搬不过来。
|
|
@@ -221,31 +191,24 @@ GB);旧的 `TITA_DATA_AGENT_HOME` 留在解析链上作为兜底,所以搬
|
|
|
221
191
|
的顺序解析。设置面板用占位符显示解析后的真实路径,并在**家当不在 `resource/` 下时
|
|
222
192
|
逐条告警**(「还在旧位置、重启会搬」和「根本不是路径、迁移搬不了」要做的事不同)。
|
|
223
193
|
|
|
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:<模型目录名>` —— **身份与位置解耦**,
|
|
194
|
+
向量清单里记的模型名是 `local:<模型目录名>` —— **身份与位置解耦**,
|
|
231
195
|
否则把模型搬一次就让整个索引判成「配置不匹配」而作废。
|
|
232
196
|
|
|
233
|
-
|
|
197
|
+
**「文件类型 → 解析引擎」那张规则表已撤。** 它唯一被读的地方是浏览器决定
|
|
234
198
|
「这份文件直读还是送转换内核」,而那个判断现在只看扩展名本身(`DIRECT_READ_EXT`);
|
|
235
199
|
真正决定用哪个适配器的是**转换内核自己的格式表**(`ANYDOC/SCANNED/IDDOC/TEXT_EXTENSIONS`),
|
|
236
200
|
它从来不读这张表 —— 也就是说「把 .docx 设成直读文本」这类配置**改了不生效**。撤掉
|
|
237
201
|
之后:上传选择框的 `accept` 问内核要(`/convert/api/capabilities`),文件类型筛选项
|
|
238
202
|
和计数从**这一库真实的文档**推导。两边都不可能再与内核漂移。
|
|
239
203
|
|
|
240
|
-
**文档扩展名 `ext`
|
|
204
|
+
**文档扩展名 `ext` 的推导是有损的**:优先取
|
|
241
205
|
`metadata.source_path` 的 basename 扩展名;否则 `source_format === 'markdown'` → `.md`,
|
|
242
|
-
`'office'` → `.docx`,其余 → `.` + `source_format`;都没有 → `.md
|
|
243
|
-
`
|
|
206
|
+
`'office'` → `.docx`,其余 → `.` + `source_format`;都没有 → `.md`。只有来源写了
|
|
207
|
+
`source_path` 时才精确。
|
|
244
208
|
|
|
245
|
-
文档的 `parser`
|
|
246
|
-
`
|
|
247
|
-
(`add_source`、浏览器直读文本)是 `direct` —— 没有解析器。
|
|
248
|
-
猜一个引擎名(`.pdf` → `anydoc`),那是在陈述一件没有发生过的事。
|
|
209
|
+
文档的 `parser` 字段说的是**谁解析了这份文档**:经转换内核进来的会写
|
|
210
|
+
`metadata.parser`(如 `anydoc@1/pdf`),直接写进来的
|
|
211
|
+
(`add_source`、浏览器直读文本)是 `direct` —— 没有解析器。
|
|
249
212
|
|
|
250
213
|
### HTTP API
|
|
251
214
|
|
|
@@ -293,7 +256,7 @@ GET /knowledge/assets/:kb/* → 知识库
|
|
|
293
256
|
**回滚 = 用快照内容重新调用 `addSource`**:因此回滚前会把当时的 head 再快照一次,
|
|
294
257
|
历史只增不减,**回滚本身也可回滚**。回滚 `current-*` 是 no-op。
|
|
295
258
|
|
|
296
|
-
###
|
|
259
|
+
### 召回链路(两路 + 图谱 boost)
|
|
297
260
|
|
|
298
261
|
```text
|
|
299
262
|
query → R0 分词 → R1 两路各自超采并过阈值(候选池 50)
|
|
@@ -303,22 +266,21 @@ query → R0 分词 → R1 两路各自超采并过阈值(候选池 50)
|
|
|
303
266
|
→ R5 弃答(insufficientEvidence)
|
|
304
267
|
```
|
|
305
268
|
|
|
306
|
-
- **R0
|
|
307
|
-
的口径切开。
|
|
308
|
-
实测 `排查`→6 命中、`怎么排查指标异常`→**0**。
|
|
269
|
+
- **R0 分词**:中文按**单字 + 相邻双字**切分(不用词典),ASCII 按 `unicode61`
|
|
270
|
+
的口径切开。
|
|
309
271
|
- **R1 关键词路**:SQLite FTS5 + **BM25**(`node:sqlite`,零新依赖;不可用时如实降级)。
|
|
310
272
|
中文之所以不用内置 tokenizer:`unicode61` 不切中文,`trigram` 要求查询 ≥3 字符且会把
|
|
311
273
|
整句变成互相 AND 的三字窗口。分数按本次最高分归一到 0..1,再过 `keywordThreshold`;
|
|
312
274
|
另有**多字词覆盖率**门槛(只数双字词与 ASCII 词,单字在中文里不是证据)。
|
|
313
275
|
- **R1 向量路**:**编码器健康门**(两段无关文本必须余弦 < 0.99,否则整路停用)→
|
|
314
|
-
查询编码一次 → binary/Hamming 预筛 → int8 精算**原始余弦**(`dot / 127
|
|
315
|
-
|
|
316
|
-
- **R2 融合**:**RRF**(`k=60`,关键词 0.3 / 向量 0.7
|
|
317
|
-
|
|
276
|
+
查询编码一次 → binary/Hamming 预筛 → int8 精算**原始余弦**(`dot / 127²`)→
|
|
277
|
+
`vectorThreshold`。
|
|
278
|
+
- **R2 融合**:**RRF**(`k=60`,关键词 0.3 / 向量 0.7)——只吃**名次**,所以各路分数
|
|
279
|
+
量纲不同这件事不再影响排序。
|
|
318
280
|
- **R2 图谱**:**boost,不是第三路**。它给已经在候选池里的条目加一个 RRF 项,**不能自己
|
|
319
281
|
制造候选**。代价是「只提到某份来源、没提到任何卡片正文」的查询没有第二条路 ——
|
|
320
282
|
由关键词索引收录 **note 的溯源身份**(sourceRefs + 来源标题)来补偿。
|
|
321
|
-
- **R3
|
|
283
|
+
- **R3 重排**:作用在**候选池**上(不是已截断的 topK),
|
|
322
284
|
低于 `rerankThreshold` 的一律丢弃并报出丢了几条。阈值与 WeKnora 同刻度(**原始 logit**)。
|
|
323
285
|
worker 用 `predict_raw()`(`activation_fn=Identity`)返回 logit —— `CrossEncoder.predict`
|
|
324
286
|
对 `num_labels == 1` 默认套 sigmoid,直接拿返回值比 0.2 会让阈值永远不生效;展示用的
|
|
@@ -331,8 +293,7 @@ query → R0 分词 → R1 两路各自超采并过阈值(候选池 50)
|
|
|
331
293
|
并标注判据强度(`rerank-threshold` / `vector-threshold` / `relative-only` / `not-needed`)。
|
|
332
294
|
宁可说「没有」,也不凑满 topN 让模型编。
|
|
333
295
|
- **降级不谎报**:`routes` 只列**通过健康门且真的跑起来**的路;每一路的状态、候选数、
|
|
334
|
-
最高分、阈值与降级原因都在 `diagnostics.routes` 里。
|
|
335
|
-
`routes: ["fts","vector","graph"]`,是这次要修的核心问题之一。
|
|
296
|
+
最高分、阈值与降级原因都在 `diagnostics.routes` 里。
|
|
336
297
|
- `mode: 'graph'` 与 `hybrid` **同义**(图谱不能制造候选,「只靠图谱」不成立)。
|
|
337
298
|
- 阈值初值:`keywordThreshold 0.3` / `rerankThreshold 0.2` 沿用 WeKnora 的出厂值;
|
|
338
299
|
**`vectorThreshold` 是 0.5,不是它的 0.15** —— 那个数是它自己 embedding 模型的刻度,
|
|
@@ -344,14 +305,12 @@ query → R0 分词 → R1 两路各自超采并过阈值(候选池 50)
|
|
|
344
305
|
余弦 < 0.99),重排器查分词器词表(`vocab_size ≥ 1000` 且探针句有非 `<unk>` 条目,否则
|
|
345
306
|
`RERANK_TOKENIZER_DEGENERATE`)。原因是「能加载」不等于「可用」:本地快照缺分词器文件时,
|
|
346
307
|
重排器照样加载、照样出分(实测三条无关文本 `0.999 / 0.998 / 0.9994`),只有探针能发现。
|
|
347
|
-
修法与运维见 `docs/0024-本地模型运行时.md`。
|
|
348
308
|
- **编码器指纹** `ENCODER_FINGERPRINT` 写在向量清单里:同一个模型换了「怎么调它」也必须让
|
|
349
|
-
已有向量作废,否则 `rebuild all` 会按 contentHash
|
|
350
|
-
修好编码器后构建仍报 `reused: 44`,修复等于没发生)。
|
|
309
|
+
已有向量作废,否则 `rebuild all` 会按 contentHash 把旧向量原样复用。
|
|
351
310
|
|
|
352
311
|
`listDocuments()` / `readDocument(docId)` / `listVersions(docId)` /
|
|
353
|
-
`revertDocument(docId, versionId)` / `deleteDocument(docId)`
|
|
354
|
-
|
|
312
|
+
`revertDocument(docId, versionId)` / `deleteDocument(docId)` 是文档接口;
|
|
313
|
+
详情页的 `assets[].url` 即 `/knowledge/assets/<kbId>/<rel>`。
|
|
355
314
|
|
|
356
315
|
## 评测
|
|
357
316
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-data-domain-knowledge",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.2",
|
|
4
4
|
"description": "Tita Data Agent knowledge lifecycle console: intent recording, source truth, wiki compiler, memory, retrieval evaluation, and the multi-format conversion host",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/types/index.js",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@deepseek-ai/schemastery": "~3.18.4"
|
|
56
56
|
},
|
|
57
57
|
"optionalDependencies": {
|
|
58
|
-
"dsh-convert-core": "0.1.0-alpha.
|
|
58
|
+
"dsh-convert-core": "0.1.0-alpha.2"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@deepseek-ai/cordis": "~4.0.4",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
89
|
"@antv/g6": "^5.1.1",
|
|
90
|
-
"dsh-data-contracts": "0.1.0-alpha.
|
|
90
|
+
"dsh-data-contracts": "0.1.0-alpha.2"
|
|
91
91
|
},
|
|
92
92
|
"scripts": {
|
|
93
93
|
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json",
|