dsh-data-domain-knowledge 0.1.0-alpha.10 → 0.1.0-alpha.12
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 +85 -97
- package/eval/README.md +19 -8
- package/eval/evaluate-retrieval.mjs +17 -8
- package/eval/queries.example.jsonl +1 -0
- package/lib/client.js +4731 -2909
- package/lib/doc-page.js +1 -1
- package/lib/pages.js +1985 -1035
- package/lib/types/axis-registry.d.ts +29 -4
- package/lib/types/axis-registry.d.ts.map +1 -1
- package/lib/types/axis-registry.js +175 -22
- package/lib/types/axis-registry.js.map +1 -1
- package/lib/types/card-organize.d.ts +10 -3
- package/lib/types/card-organize.d.ts.map +1 -1
- package/lib/types/card-organize.js +22 -4
- package/lib/types/card-organize.js.map +1 -1
- package/lib/types/compiler/embedding-identity.d.ts +3 -0
- package/lib/types/compiler/embedding-identity.d.ts.map +1 -0
- package/lib/types/compiler/embedding-identity.js +24 -0
- package/lib/types/compiler/embedding-identity.js.map +1 -0
- package/lib/types/compiler/snapshot.d.ts +16 -0
- package/lib/types/compiler/snapshot.d.ts.map +1 -0
- package/lib/types/compiler/snapshot.js +2 -0
- package/lib/types/compiler/snapshot.js.map +1 -0
- package/lib/types/convert/host.d.ts +6 -5
- package/lib/types/convert/host.d.ts.map +1 -1
- package/lib/types/convert/host.js +55 -18
- package/lib/types/convert/host.js.map +1 -1
- package/lib/types/diagnosis/store.d.ts +7 -2
- package/lib/types/diagnosis/store.d.ts.map +1 -1
- package/lib/types/diagnosis/store.js +39 -2
- package/lib/types/diagnosis/store.js.map +1 -1
- package/lib/types/diagnosis/types.d.ts +38 -0
- package/lib/types/diagnosis/types.d.ts.map +1 -1
- package/lib/types/environment/install.d.ts +6 -0
- package/lib/types/environment/install.d.ts.map +1 -0
- package/lib/types/environment/install.js +163 -0
- package/lib/types/environment/install.js.map +1 -0
- package/lib/types/environment/manifest.d.ts +17 -0
- package/lib/types/environment/manifest.d.ts.map +1 -0
- package/lib/types/environment/manifest.js +24 -0
- package/lib/types/environment/manifest.js.map +1 -0
- package/lib/types/environment/process.d.ts +10 -0
- package/lib/types/environment/process.d.ts.map +1 -0
- package/lib/types/environment/process.js +54 -0
- package/lib/types/environment/process.js.map +1 -0
- package/lib/types/environment/service.d.ts +47 -0
- package/lib/types/environment/service.d.ts.map +1 -0
- package/lib/types/environment/service.js +232 -0
- package/lib/types/environment/service.js.map +1 -0
- package/lib/types/environment/types.d.ts +31 -0
- package/lib/types/environment/types.d.ts.map +1 -0
- package/lib/types/environment/types.js +2 -0
- package/lib/types/environment/types.js.map +1 -0
- package/lib/types/events.d.ts +70 -0
- package/lib/types/events.d.ts.map +1 -0
- package/lib/types/events.js +39 -0
- package/lib/types/events.js.map +1 -0
- package/lib/types/extract-contract.js +21 -1
- package/lib/types/extract-contract.js.map +1 -1
- package/lib/types/extract-model.d.ts +3 -0
- package/lib/types/extract-model.d.ts.map +1 -1
- package/lib/types/extract-model.js.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +267 -53
- package/lib/types/index.js.map +1 -1
- package/lib/types/intent/engine.d.ts +2 -0
- package/lib/types/intent/engine.d.ts.map +1 -1
- package/lib/types/intent/engine.js +12 -1
- package/lib/types/intent/engine.js.map +1 -1
- package/lib/types/intent/host.d.ts.map +1 -1
- package/lib/types/intent/host.js +10 -3
- package/lib/types/intent/host.js.map +1 -1
- package/lib/types/intent/scope.d.ts.map +1 -1
- package/lib/types/intent/scope.js +4 -0
- package/lib/types/intent/scope.js.map +1 -1
- package/lib/types/intent/tools.d.ts +1 -1
- package/lib/types/intent/tools.d.ts.map +1 -1
- package/lib/types/intent/tools.js +17 -6
- package/lib/types/intent/tools.js.map +1 -1
- package/lib/types/intent/types.d.ts +2 -0
- package/lib/types/intent/types.d.ts.map +1 -1
- package/lib/types/knowledge-bases.d.ts +8 -2
- package/lib/types/knowledge-bases.d.ts.map +1 -1
- package/lib/types/knowledge-bases.js +45 -1
- package/lib/types/knowledge-bases.js.map +1 -1
- package/lib/types/knowledge.d.ts +14 -6
- package/lib/types/knowledge.d.ts.map +1 -1
- package/lib/types/knowledge.js +56 -39
- package/lib/types/knowledge.js.map +1 -1
- package/lib/types/model-text.d.ts +3 -1
- package/lib/types/model-text.d.ts.map +1 -1
- package/lib/types/model-text.js +3 -27
- package/lib/types/model-text.js.map +1 -1
- package/lib/types/organize-contract.d.ts.map +1 -1
- package/lib/types/organize-contract.js +3 -1
- package/lib/types/organize-contract.js.map +1 -1
- package/lib/types/query-analysis.d.ts +13 -1
- package/lib/types/query-analysis.d.ts.map +1 -1
- package/lib/types/query-analysis.js +62 -6
- package/lib/types/query-analysis.js.map +1 -1
- package/lib/types/recall-rank.d.ts +3 -3
- package/lib/types/recall-rank.d.ts.map +1 -1
- package/lib/types/recall-rank.js +4 -4
- package/lib/types/recall-rank.js.map +1 -1
- package/lib/types/retrieval/vector-index.d.ts +31 -0
- package/lib/types/retrieval/vector-index.d.ts.map +1 -0
- package/lib/types/retrieval/vector-index.js +15 -0
- package/lib/types/retrieval/vector-index.js.map +1 -0
- package/lib/types/retrieval/visibility.d.ts +6 -0
- package/lib/types/retrieval/visibility.d.ts.map +1 -0
- package/lib/types/retrieval/visibility.js +11 -0
- package/lib/types/retrieval/visibility.js.map +1 -0
- package/lib/types/runtime.d.ts +137 -16
- package/lib/types/runtime.d.ts.map +1 -1
- package/lib/types/runtime.js +1599 -362
- package/lib/types/runtime.js.map +1 -1
- package/lib/types/settings-schema.d.ts +4 -2
- package/lib/types/settings-schema.d.ts.map +1 -1
- package/lib/types/settings-schema.js +2 -1
- package/lib/types/settings-schema.js.map +1 -1
- package/lib/types/settings-volatile.d.ts +3 -3
- package/lib/types/settings-volatile.js +3 -3
- package/lib/types/source-evidence.d.ts +6 -0
- package/lib/types/source-evidence.d.ts.map +1 -0
- package/lib/types/source-evidence.js +28 -0
- package/lib/types/source-evidence.js.map +1 -0
- package/lib/types/store/axis-references.d.ts +5 -0
- package/lib/types/store/axis-references.d.ts.map +1 -0
- package/lib/types/store/axis-references.js +106 -0
- package/lib/types/store/axis-references.js.map +1 -0
- package/lib/types/store/derived.d.ts +11 -0
- package/lib/types/store/derived.d.ts.map +1 -1
- package/lib/types/store/derived.js +31 -6
- package/lib/types/store/derived.js.map +1 -1
- package/lib/types/store/knowledge-db.d.ts +12 -1
- package/lib/types/store/knowledge-db.d.ts.map +1 -1
- package/lib/types/store/knowledge-db.js +108 -12
- package/lib/types/store/knowledge-db.js.map +1 -1
- package/lib/types/store/migrate.d.ts.map +1 -1
- package/lib/types/store/migrate.js +11 -1
- package/lib/types/store/migrate.js.map +1 -1
- package/lib/types/types.d.ts +47 -4
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/types.js +3 -1
- package/lib/types/types.js.map +1 -1
- package/lib/types/wiki-materialize.d.ts +4 -0
- package/lib/types/wiki-materialize.d.ts.map +1 -1
- package/lib/types/wiki-materialize.js +34 -8
- package/lib/types/wiki-materialize.js.map +1 -1
- package/lib/types/wiki-trial-types.d.ts +80 -0
- package/lib/types/wiki-trial-types.d.ts.map +1 -1
- package/lib/types/wiki-trial.d.ts +28 -12
- package/lib/types/wiki-trial.d.ts.map +1 -1
- package/lib/types/wiki-trial.js +297 -76
- package/lib/types/wiki-trial.js.map +1 -1
- package/package.json +9 -1
- package/python/prepare-models.py +19 -0
- package/python/requirements.txt +8 -6
- package/scripts/doctor.mjs +14 -2
- package/scripts/environment.mjs +29 -0
- package/src/axis-registry.ts +181 -22
- package/src/card-organize.ts +23 -6
- package/src/client/AgentPresetCard.tsx +8 -17
- package/src/client/AttributionEventGuide.tsx +29 -28
- package/src/client/AxisRegistrySection.tsx +204 -164
- package/src/client/CompileDialogs.tsx +34 -27
- package/src/client/DeleteDocumentDialog.tsx +36 -5
- package/src/client/EnvironmentSetup.tsx +99 -0
- package/src/client/ExtractionTasksPage.tsx +189 -0
- package/src/client/KnowledgeBaseTab.tsx +156 -100
- package/src/client/KnowledgePanel.tsx +41 -34
- package/src/client/NodeSettings.tsx +55 -59
- package/src/client/PreviewSections.tsx +67 -30
- package/src/client/RecallPanel.tsx +34 -60
- package/src/client/TrialReportView.tsx +346 -214
- package/src/client/TypeDefinitionDrawer.tsx +126 -23
- package/src/client/WikiCardPreview.tsx +4 -6
- package/src/client/arch/model.ts +1 -1
- package/src/client/architecture.tsx +3 -4
- package/src/client/attribution/AttributionGraph.tsx +10 -6
- package/src/client/attribution/AttributionTab.tsx +99 -48
- package/src/client/attribution/EventView.tsx +98 -0
- package/src/client/attribution/StageChrome.tsx +34 -3
- package/src/client/attribution/graph-options.ts +9 -8
- package/src/client/attribution/model.ts +1 -1
- package/src/client/index.ts +41 -2
- package/src/client/pages.css +36 -6
- package/src/client/pages.tsx +7 -1
- package/src/client/styles.css +98 -0
- package/src/client/wiki-trial.ts +11 -2
- package/src/compiler/embedding-identity.ts +21 -0
- package/src/compiler/snapshot.ts +17 -0
- package/src/convert/host.ts +53 -21
- package/src/diagnosis/store.ts +43 -4
- package/src/diagnosis/types.ts +25 -0
- package/src/environment/install.ts +117 -0
- package/src/environment/manifest.ts +25 -0
- package/src/environment/process.ts +54 -0
- package/src/environment/service.ts +191 -0
- package/src/environment/types.ts +30 -0
- package/src/events.ts +91 -0
- package/src/extract-contract.ts +21 -1
- package/src/extract-model.ts +8 -1
- package/src/index.ts +256 -49
- package/src/intent/README.md +1 -1
- package/src/intent/engine.ts +11 -1
- package/src/intent/host.ts +10 -3
- package/src/intent/scope.ts +4 -0
- package/src/intent/tools.ts +18 -7
- package/src/intent/types.ts +2 -0
- package/src/knowledge-bases.ts +49 -4
- package/src/knowledge.ts +56 -40
- package/src/model-text.ts +8 -1
- package/src/organize-contract.ts +3 -1
- package/src/query-analysis.ts +68 -8
- package/src/recall-rank.ts +5 -5
- package/src/retrieval/vector-index.ts +44 -0
- package/src/retrieval/visibility.ts +14 -0
- package/src/runtime.ts +1601 -392
- package/src/settings-schema.ts +2 -1
- package/src/settings-volatile.ts +3 -3
- package/src/source-evidence.ts +30 -0
- package/src/store/axis-references.ts +96 -0
- package/src/store/derived.ts +31 -6
- package/src/store/knowledge-db.ts +113 -12
- package/src/store/migrate.ts +11 -1
- package/src/types.ts +46 -5
- package/src/wiki-materialize.ts +37 -7
- package/src/wiki-trial-types.ts +76 -1
- package/src/wiki-trial.ts +322 -83
package/README.md
CHANGED
|
@@ -3,18 +3,38 @@
|
|
|
3
3
|
本地知识库插件:一个知识库是一个目录,里面四样东西。`knowledge.db` 保存 **SourceRaw**
|
|
4
4
|
(原始可追溯文档)、按主题聚合可双向链接的 wiki 卡片,以及**两者的每一个版本**;
|
|
5
5
|
`derived.db` 输出可检索的 **wikiNotes**、wiki
|
|
6
|
-
知识图谱和向量索引,`<agentRoot>/memory/<库 id>`
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
知识图谱和向量索引,`<agentRoot>/memory/<库 id>` 保存操作日志、抽取轨迹、访问审计与反馈。
|
|
7
|
+
默认使用本地 Python 推理:`BAAI/bge-small-zh-v1.5` 生成 512 维文本向量,
|
|
8
|
+
`BAAI/bge-reranker-base` 对召回候选做交叉编码重排。部署入口必须完成环境自检,
|
|
9
|
+
索引必须匹配当前模型;不满足时提示准备环境或重新编译。
|
|
10
|
+
需要图片语义检索时,可配置 WeMM 多模态模型与匹配维度,Markdown 中的本地图片
|
|
11
|
+
会与正文一起交给模型。图片不作为独立知识类型。
|
|
11
12
|
|
|
12
13
|
Tita Agent 的固定数据根目录是 `$DSH_HOME/tita-agent`(默认 `~/.dsh/tita-agent`)。
|
|
13
14
|
设置面板只展示这个目录并提供「打开目录」,不允许切换根路径;知识库、意图记录、记忆、
|
|
14
|
-
模型和 Python
|
|
15
|
-
`~/Desktop/titaagent` 与 `~/.tita-data-agent` 数据;旧数据需要用户自行处理。
|
|
15
|
+
模型和 Python 环境都从这里派生。
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## 首次运行环境准备
|
|
18
|
+
|
|
19
|
+
Python、向量模型、重排模型是部署必需项。打开 Tita 设置 → 环境准备 → 一键安装 / 修复。
|
|
20
|
+
系统使用 uv 安装专属 Python 环境,下载固定 revision 的 `BAAI/bge-small-zh-v1.5`
|
|
21
|
+
(512 维)和 `BAAI/bge-reranker-base`,然后运行真实推理自检。阶段、错误和下载日志
|
|
22
|
+
可查看;下载失败可以重试。未就绪时阻止编译和知识召回,来源与历史内容仍可保存、读取。
|
|
23
|
+
|
|
24
|
+
命令行入口:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm --filter dsh-data-domain-knowledge environment:prepare
|
|
28
|
+
pnpm --filter dsh-data-domain-knowledge environment:check
|
|
29
|
+
pnpm --filter dsh-data-domain-knowledge doctor
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
自检失败时命令返回非零退出码。安装不修改系统 Python,也不隐式运行 npm postinstall
|
|
33
|
+
模型下载。已有知识在准备完成后需重新编译;宿主无需重启。自定义路径保留,使用默认
|
|
34
|
+
资源时把高级设置中的路径恢复为空,并使用匹配的向量维度。
|
|
35
|
+
细节见 [运行环境准备与自检](../../docs/current/16-知识运行环境准备与自检.md)。
|
|
36
|
+
|
|
37
|
+
## 承载范围
|
|
18
38
|
|
|
19
39
|
侧边栏 `TitaAgent` 面板的五个视图就是本插件的全部范围:
|
|
20
40
|
|
|
@@ -23,12 +43,11 @@ Tita Agent 的固定数据根目录是 `$DSH_HOME/tita-agent`(默认 `~/.dsh/t
|
|
|
23
43
|
| `overview` | Agent 概览 | 各设置的挂载节点 |
|
|
24
44
|
| `intent` | 意图 | `intent_record` / `intent_store_view`、`/intent/*` 路由、`titaDataAgentIntent` 服务;会话审计留痕落 `<agentRoot>/intent/` |
|
|
25
45
|
| `knowledge` | 知识库 | `recall_knowledge` 等工具名、`/knowledge/*` 与 `/convert` 路由、`tita-data-agent-knowledge` / `-convert` 设置 |
|
|
26
|
-
| `memory` | 记忆 |
|
|
46
|
+
| `memory` | 记忆 | 抽取轨迹、处理日志、`feedback.ndjson`、`access-audit.ndjson`,根在 `<agentRoot>/memory/<库 id>`;轴 / Knowledge 真源在主库 |
|
|
27
47
|
| `eval` | 评测 | 问题集格式(开发期能力,不注册运行时入口) |
|
|
28
48
|
|
|
29
49
|
意图的**会话审计留痕**落在 `<agentRoot>/intent/`:`intent.db` 保存当前记录与追加历史
|
|
30
|
-
(按 `sessionKey#turn`
|
|
31
|
-
`records.ndjson` 只做一次性迁移,不再继续写入。
|
|
50
|
+
(按 `sessionKey#turn` 读取时取当前版本,所以内存里「一轮一条」的语义不变)。
|
|
32
51
|
分类与 act 是代码内置的固定契约,不提供编辑入口。读接口 `/intent/store` 与 `/intent/overview` 读的是**留痕**:
|
|
33
52
|
引擎内存里那份有 600 秒 TTL,重启或隔一段时间回来不该让面板上的历史凭空消失。
|
|
34
53
|
|
|
@@ -39,7 +58,7 @@ Tita Agent 的固定数据根目录是 `$DSH_HOME/tita-agent`(默认 `~/.dsh/t
|
|
|
39
58
|
| 1 | SourceRaw | 原始可追溯文档:`knowledge.db` 的 `source` + `blob` | `allowSourceTruth` / `rootDir` |
|
|
40
59
|
| 2 | 编译 Compile | wiki:`knowledge.db` 的 `card`(**按 wiki 类型 schema 抽实体,直接入库**);wikiNotes:`derived.db` 的 `wiki_notes.json` | `extractCandidates` / `extractWithModel` / `wikiTypes` |
|
|
41
60
|
| 3 | 构建 Build | wikiNotes → 向量索引;wiki → `derived.db` 的 `knowledge_graph.json` | `embeddingProvider` / `embeddingModel` / `python` |
|
|
42
|
-
| 4 | 召回 Recall |
|
|
61
|
+
| 4 | 召回 Recall | 多路(坐标 + 关键词 + 向量)召回 wikiNotes,取 `recallTopK`(默认 10),再解析父级 wiki 与该 wiki 的 1 跳知识图谱 | `recallTopK` |
|
|
43
62
|
| 5 | 重排 Rerank | BERT cross-encoder 对候选 wikiNotes 精排,取 `contextTopN`(默认 5)组成 `context` | `contextTopN` / `rerankProvider` / `rerankModel` |
|
|
44
63
|
|
|
45
64
|
> 第 4、5 段在**界面上是同一栏**(知识库 → 召回重排)。它们在流水线上仍是两步,
|
|
@@ -55,7 +74,7 @@ Tita Agent 的固定数据根目录是 `$DSH_HOME/tita-agent`(默认 `~/.dsh/t
|
|
|
55
74
|
| Knowledge | `knowledge` + `knowledge_sources` | 原子事实、坐标、来源、状态;不保存 Card 的排版 |
|
|
56
75
|
| Wiki Card | `card` + `blob` + `revision` | 面向阅读和召回组装的正文;正文中的 Markdown 标题是 Section 真源 |
|
|
57
76
|
| Knowledge 落位 | `card_knowledge` | 记录 Knowledge 在某张 Card 中的 Section 和顺序;这是关联索引,不是 Knowledge 属性 |
|
|
58
|
-
| Wiki Note / FTS / Vector / Graph |
|
|
77
|
+
| Wiki Note / FTS / Vector / Graph | `derived.db` | 可以从 Card 和 Knowledge 重新构建;编译结果在同一事务发布 |
|
|
59
78
|
|
|
60
79
|
### 状态语义
|
|
61
80
|
|
|
@@ -72,7 +91,29 @@ Knowledge ID 只在一个 `knowledge.db` 内有意义。相同文本在同一个
|
|
|
72
91
|
|
|
73
92
|
这意味着当前实现适用于“一个知识库对应一个业务范围”的模型。未来如果一个库需要混合多个租户、环境或有效期,再把 Scope 纳入判重策略。
|
|
74
93
|
|
|
75
|
-
###
|
|
94
|
+
### 身份算法
|
|
95
|
+
|
|
96
|
+
新 Knowledge ID 使用归一化文本的 SHA-256。归一化保留比较条件、小数、负号和标识符
|
|
97
|
+
分隔符,判重同时比较正文。存量 ID 不重写;人工编辑正文保留 ID 并增加内容版本。
|
|
98
|
+
|
|
99
|
+
### 来源更新与复核
|
|
100
|
+
|
|
101
|
+
来源改版后保留旧 Knowledge 和原始证据版本,不自动判定失效。证据记录 `toVersion`,
|
|
102
|
+
读取时返回 `currentVersion`、`evidenceStatus`、`quoteInCurrentVersion`。召回中缺少当前
|
|
103
|
+
可定位证据的知识带 `requiresReview: true`;是否停用仍由人工裁决。
|
|
104
|
+
|
|
105
|
+
引用定位不等于语义成立。组织校验能拒绝输入中没有出现的数值或比较条件,但不能证明
|
|
106
|
+
任意自然语言陈述成立;召回如实返回 `claimVerification: 'unverified'`。
|
|
107
|
+
|
|
108
|
+
### 编译发布与一致性
|
|
109
|
+
|
|
110
|
+
Notes、FTS、向量、图和 manifest 在 `derived.db` 中通过一次事务发布。召回与图查询
|
|
111
|
+
读取已发布快照;失败或取消时保留上一版结果。删除状态立即过滤旧片段。抽取失败不
|
|
112
|
+
保存成功指纹,模型身份、位置或本地文件版本变化会阻止旧向量复用。
|
|
113
|
+
|
|
114
|
+
目录边界、事务和验证范围见 [知识一致性与编译快照](../../docs/current/15-知识一致性与编译快照.md)。
|
|
115
|
+
|
|
116
|
+
### Knowledge 类型字段
|
|
76
117
|
|
|
77
118
|
当前不把 `Fact` / `Rule` / `Procedure` / `Constraint` 加成 Knowledge 的正式列。类型暂作为抽取或 Card metadata 的扩展信息,只有当不同类型需要不同的召回、验证或执行策略时,才升级为结构化字段。
|
|
78
119
|
|
|
@@ -93,24 +134,8 @@ SourceRaw → Knowledge → Wiki Card → Wiki Note → FTS / Vector / Rerank
|
|
|
93
134
|
|
|
94
135
|
因此,删除来源、合并 Knowledge、修改 Card 或重建检索索引时,都必须沿着这条依赖方向处理,不能直接把 Wiki Note 当成可编辑知识,也不能用 Card review 代替 Knowledge 验证。
|
|
95
136
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
> **0067(2026-10-06)**:转换的**原始输入**(那份 PDF / Word / HTML)搬进 `<库根>/source_raw/`,
|
|
99
|
-
> 位置记在 `source` 表的 `original_rel` / `original_sha256` / `original_bytes` 三列上。
|
|
100
|
-
> **知识库内不再有段目录**(原先的
|
|
101
|
-
> `01_source_raw` / `02_wiki` / `03_compiled` / `05_diagnosis` 由迁移导入后删除)。
|
|
102
|
-
> 「知识树能被用户直接读」由导出通道接住:`POST /knowledge/export`。
|
|
103
|
-
>
|
|
104
|
-
> 术语迁移:SourceRaw 曾叫 SourceRow / SourceTruth。磁盘目录 `01_source_raw`、工具名
|
|
105
|
-
> `add_source` / `query_source_truth`、HTTP `/knowledge/sources`、设置键 `allowSourceTruth`
|
|
106
|
-
> 与错误码 `SOURCE_TRUTH_DISABLED` 作为兼容名保留,语义等同 SourceRaw。
|
|
107
|
-
> 「编译 / 构建」是同一次 `rebuild()`:编译**按 wiki 类型 schema 抽实体**(模型优先、
|
|
108
|
-
> 规则兜底),判重后直接写 `02_wiki`;**wiki↔wiki 双向链接**与**分阶段重建**是设计目标,
|
|
109
|
-
> 图谱当前只有 `supported_by` 溯源边加规则抽出的 `relates_to`。
|
|
110
|
-
|
|
111
|
-
- 设置项**不再有独立入口**:它们挂在 Agent 概览架构图的对应节点上(SourceRaw → 收录开关与
|
|
112
|
-
知识库根目录;编译 → Schema;构建 → Embedding / Python;召回 → topK / 默认路线;
|
|
113
|
-
重排 → topN / reranker;意图与上下文 → 意图路由),每个节点只保存本节点字段。
|
|
137
|
+
- 知识库设置集中在侧边抽屉:数据位置、向量模型、检索与上下文。召回固定使用多路径融合;
|
|
138
|
+
低频设备、阈值和模型细节收在高级设置中。Agent 系统提示词常显,并链接到 preset 真源目录。
|
|
114
139
|
- **编译直接入库(0044)**:`rebuild_knowledge` 的 Pass 0 对指纹变了的来源做实体抽取,
|
|
115
140
|
按 `entityType:entityId` / `title` / `metadata.aliases` 三重索引判重 —— 命中已有卡片就把
|
|
116
141
|
新正文**追加**进去(不覆盖、不丢弃),没命中就新建。缺必填小节 / 字段的卡片**照常入库**,
|
|
@@ -156,7 +181,7 @@ SourceRaw → Knowledge → Wiki Card → Wiki Note → FTS / Vector / Rerank
|
|
|
156
181
|
这个概念)、`sources: [{id, resource, title, author, last_modified}]`(对网页就是那个页面
|
|
157
182
|
本身:地址、标题、作者、发布时间)。`source_id` / `external_id` / `created_at` /
|
|
158
183
|
`updated_at` / `metadata` / `lineage` 是我们的扩展键(OKF 明确允许,且要求消费者容忍
|
|
159
|
-
|
|
184
|
+
未知键)。
|
|
160
185
|
规范:<https://github.com/GoogleCloudPlatform/open-knowledge-format>(v0.2)。
|
|
161
186
|
- **召回组装按「卡片」而不是按「片段」**(0050):R1–R3 不变(多路召回 + RRF + 对候选池重排,
|
|
162
187
|
召回与重排的对象都是 wikiNotes),R4 改成四步 —— ① 取 notes 对应的 wiki 去重,一张卡片的等级
|
|
@@ -191,10 +216,10 @@ SourceRaw → Knowledge → Wiki Card → Wiki Note → FTS / Vector / Rerank
|
|
|
191
216
|
`JSON.stringify`,同一个 `undefined` 在那里无声无息,所以这个错只在工具调用上现形。
|
|
192
217
|
- 编译期一条 wiki 至少产出一条 note;正文按 `##`/`###` 分节且超过 800 字符时按节切分,
|
|
193
218
|
首条 note 的 `unitId` 保持 `<entityType>:<entityId>`,后续为 `<entityType>:<entityId>#<n>`,
|
|
194
|
-
每条 note 都带 `wikiId` 指回父级 wiki
|
|
219
|
+
每条 note 都带 `wikiId` 指回父级 wiki。
|
|
195
220
|
- `recall_knowledge` 返回 `hits`(重排后的 wikiNotes)、`context`(`{ note, wiki, graph }[]`)、
|
|
196
221
|
`wiki`、`graph`、`routes`、`recallMode`、`rerank`、`recallTopK`、`contextTopN`;入参 `top_k`
|
|
197
|
-
|
|
222
|
+
控制召回条数,`top_n` 控制进入上下文的条数,`mode` 覆盖默认召回路线,
|
|
198
223
|
`rerank: false` 可单次关闭重排。
|
|
199
224
|
- `rerankProvider` 默认 `bert-python`,模型默认 `BAAI/bge-reranker-base`
|
|
200
225
|
(存在 `~/.dsh/tita-agent/resource/models/bge-reranker-base` 时优先用本地目录)。重排在独立
|
|
@@ -211,8 +236,7 @@ bash scripts/setup-embedding.sh
|
|
|
211
236
|
|
|
212
237
|
脚本会把 Python 环境放到 `~/.dsh/tita-agent/resource/python`,把量化模型放到
|
|
213
238
|
`~/.dsh/tita-agent/resource/models/WeMM-Embedding-2B-Quantized`。新配置会自动发现这两个路径;
|
|
214
|
-
|
|
215
|
-
Tita Data Agent → Agent 概览 →「构建」节点的设置中确认:
|
|
239
|
+
设置位于 Tita Data Agent → Agent 概览 →「构建」节点:
|
|
216
240
|
|
|
217
241
|
- Provider:`WeMM Python(本地)`
|
|
218
242
|
- Python:`~/.dsh/tita-agent/resource/python/bin/python`
|
|
@@ -220,10 +244,8 @@ Tita Data Agent → Agent 概览 →「构建」节点的设置中确认:
|
|
|
220
244
|
- 维度:`1024`
|
|
221
245
|
- 设备:`自动(优先 MPS)`
|
|
222
246
|
|
|
223
|
-
知识库默认保存在 `~/.dsh/tita-agent/domain_knowledge/<库 id
|
|
224
|
-
|
|
225
|
-
`03_compiled` 会生成 `wiki_notes.json`、`knowledge_graph.json`、`wiki-index.md`、
|
|
226
|
-
`vector-manifest.json`、`vectors.binary` 和 `vectors.int8`。未修改的 wikiNote
|
|
247
|
+
知识库默认保存在 `~/.dsh/tita-agent/domain_knowledge/<库 id>`。点击「编译」后,
|
|
248
|
+
编译结果写入 `derived.db`。未修改的 wikiNote
|
|
227
249
|
会复用已有向量,只有新增或变更的 note 重新编码;编码与重排各自使用常驻 Python
|
|
228
250
|
worker(同一份 `src/python/embedding_worker.py`),避免每个请求重复加载模型。
|
|
229
251
|
|
|
@@ -271,8 +293,7 @@ pptx、xls、xlsx、odt、ods、odp、rtf、epub、csv 与文本层 PDF;另有
|
|
|
271
293
|
|
|
272
294
|
一个**知识库 = 独立配置 + 独立内容**(产品参照 WeKnora)。注册表持久化在
|
|
273
295
|
`<agentRoot>/resource/knowledge-bases.json`。
|
|
274
|
-
默认库 id 固定为 `default`,其 `rootDir` 固定为 `<agentRoot>/domain_knowledge/default
|
|
275
|
-
**不传 `kb` 的旧接口与旧工具一律作用于默认库,行为不变**。
|
|
296
|
+
默认库 id 固定为 `default`,其 `rootDir` 固定为 `<agentRoot>/domain_knowledge/default`。
|
|
276
297
|
|
|
277
298
|
```ts
|
|
278
299
|
interface KnowledgeBase { id; name; description; rootDir; isDefault; wikiTypes; createdAt; updatedAt; sourceCount; cardCount; noteCount; buildVersion }
|
|
@@ -282,7 +303,7 @@ interface KnowledgeBase { id; name; description; rootDir; isDefault; wikiTypes;
|
|
|
282
303
|
**计算字段**,由真实 runtime 重新统计并缓存进同一个 JSON,
|
|
283
304
|
HTTP `GET /knowledge/bases` 在返回前先刷新。
|
|
284
305
|
|
|
285
|
-
|
|
306
|
+
**Agent 数据根目录包含以下内容**:
|
|
286
307
|
|
|
287
308
|
| 段 | 装什么 | 删掉的后果 |
|
|
288
309
|
| --- | --- | --- |
|
|
@@ -299,51 +320,23 @@ HTTP `GET /knowledge/bases` 在返回前先刷新。
|
|
|
299
320
|
(同一句话在哪个知识库下说,理解方式不该变),所以它不分库。这样知识、记忆、意图三段
|
|
300
321
|
都是可以直接备份、直接 diff 的用户文件。
|
|
301
322
|
|
|
302
|
-
|
|
303
|
-
(后者搬去了 `memory/`)。
|
|
323
|
+
每个知识库的数据根目录为 `<agentRoot>/domain_knowledge/<知识库 id>/`:
|
|
304
324
|
|
|
305
|
-
|
|
|
325
|
+
| 文件或目录 | 内容 | 删除影响 |
|
|
306
326
|
| --- | --- | --- |
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
`
|
|
313
|
-
落 `03_compiled/diagnosis_graph.json`。旧的 `05_diagnosis/` 撤销了;它里面的 `*.jsonl`
|
|
314
|
-
如果还在,角色是**只读的迁移输入与历史快照** —— 不再被写,但仍然读得出来(证据与根因
|
|
315
|
-
就从那里来),所以旧知识根不会因为这次改动而读不出内容。
|
|
316
|
-
|
|
317
|
-
schema 段已撤掉:它从建出来那天起就是一个**空目录**,分类注册表与 Wiki 类型注册表
|
|
318
|
-
一直住在 `<agentRoot>/resource/knowledge-bases.json`(那是配置,跟着根路径走)。
|
|
319
|
-
启动时会把空的那个目录删掉 —— **非空则保留**:那就不属于「没用的空文件夹」了,
|
|
320
|
-
删掉别人的文件比留一个空目录危险得多。
|
|
321
|
-
|
|
322
|
-
**文件名用标题(0051)。** `01_source_raw/阿里集团大数据建设OneData体系.md` —— `ls`
|
|
323
|
-
认得出、`grep` 文件名有用、`git diff` 看得出改的是哪份材料;`source_id`(`article:bc82…`)仍是
|
|
324
|
-
稳定身份,住在 front matter 里。三条配套规则:①标题里的路径不安全字符换成 `-`、截断到 120 字符、
|
|
325
|
-
只剩替换字符时退回 `source_id`;②**重名默认拒收**(`SOURCE_TITLE_DUPLICATED`,报错指出被谁占着,
|
|
326
|
-
改标题再来)—— 标题是来源的核心属性,两份不同的东西同名是要人处理的信号,不该由命名规则悄悄加后缀;
|
|
327
|
-
③确实要留两份同标题材料时显式传 `allow_duplicate_title: true`,落成 `<标题>-<内容哈希前 6 位>.md`
|
|
328
|
-
并回一条 warning。改名与迁移(老段名 `01_source_truth` → `01_source_raw`、文件名换成标题)在
|
|
329
|
-
`ensureLayout` 里一次性完成,**可重入**;存量正文里带老段名的图片引用不改写,解析器认两个段名。
|
|
330
|
-
|
|
331
|
-
`01_source_raw` 直接平铺来源文档:文件名就是标题,`source_id` 保留稳定身份,格式、作者、
|
|
332
|
-
外部链接等通用信息写在 front matter。目录结构不承担业务分类职责。
|
|
333
|
-
|
|
334
|
-
`resource/` 装模型、虚拟环境与 `knowledge-bases.json` —— 「这个 Agent 的全部磁盘足迹」
|
|
335
|
-
因此是一个目录,备份 / 迁移 / 整个删掉都只需要认一个路径。新版本直接使用
|
|
336
|
-
`<agentRoot>/resource/`,启动时不会读取、搬运或删除旧的用户目录。
|
|
337
|
-
旧的 `TITA_DATA_AGENT_HOME` 不再参与解析;如果当前根路径下没有本地资源,就使用
|
|
338
|
-
`python3` / HF 模型名作为兜底。
|
|
327
|
+
| `knowledge.db` | SourceRaw、Knowledge、Wiki Card 与版本记录 | 丢失知识真源 |
|
|
328
|
+
| `derived.db` | wikiNotes、知识图谱、检索索引 | 可重新编译 |
|
|
329
|
+
| `assets/` | 来源图片与附件 | 丢失对应素材 |
|
|
330
|
+
|
|
331
|
+
`resource/` 保存模型、Python 环境与 `knowledge-bases.json`。
|
|
332
|
+
如果资源目录没有本地 Python 或模型,就使用 `python3` 或 Hugging Face 模型名。
|
|
339
333
|
|
|
340
334
|
配置里 `python` / `embeddingModel` / `rerankModel` 三个字段的**默认值改成了空串 =
|
|
341
335
|
自动**:按 `<agentRoot>/resource/…` → 兜底名(`python3` / HF 模型名)的顺序解析。
|
|
342
336
|
设置面板用占位符显示解析后的真实路径,并在**资源不是当前 `resource/` 下的本地路径时
|
|
343
337
|
逐条告警**。
|
|
344
338
|
|
|
345
|
-
向量清单里记的模型名是 `local:<模型目录名>` ——
|
|
346
|
-
否则把模型搬一次就让整个索引判成「配置不匹配」而作废。
|
|
339
|
+
向量清单里记的模型名是 `local:<模型目录名>` —— **身份与位置解耦**。
|
|
347
340
|
|
|
348
341
|
**「文件类型 → 解析引擎」那张规则表已撤。** 它唯一被读的地方是浏览器决定
|
|
349
342
|
「这份文件直读还是送转换内核」,而那个判断现在只看扩展名本身(`DIRECT_READ_EXT`);
|
|
@@ -366,9 +359,11 @@ schema 段已撤掉:它从建出来那天起就是一个**空目录**,分类
|
|
|
366
359
|
```text
|
|
367
360
|
GET /knowledge/bases → { bases, defaultBaseId }
|
|
368
361
|
POST /knowledge/bases { name, description?, rootDir? } → { base }
|
|
369
|
-
|
|
362
|
+
GET /knowledge/models?kb=:id → DSH 编译模型目录与当前默认模型状态
|
|
363
|
+
PATCH /knowledge/bases/:id { name?, description?, extractionNote?, compileModel? } → { base }
|
|
370
364
|
DELETE /knowledge/bases/:id → { deleted: true }
|
|
371
365
|
GET /knowledge/documents?kb=&query=&limit=&offset= → { documents, total }
|
|
366
|
+
GET /knowledge/events?kb= → { events }
|
|
372
367
|
GET /knowledge/documents/:docId?kb= → { document }(正文截前 4000 字符)
|
|
373
368
|
GET /knowledge/documents/:docId/content?kb=&offset=&limit= → { text, offset, nextOffset, totalChars, eof }
|
|
374
369
|
GET /knowledge/documents/:docId/view?kb= → 独立整页(HTML,读全文)
|
|
@@ -454,20 +449,17 @@ Document ──▶ Knowledge × N ──▶ 坐标 (对象 × 动作 × 场景)
|
|
|
454
449
|
```
|
|
455
450
|
|
|
456
451
|
> **一个坐标最多一张卡**,这件事由 `knowledge.db` 的 `card.coordinate_key` **主键**兜着,
|
|
457
|
-
> 不是靠约定。`entity_id`
|
|
452
|
+
> 不是靠约定。`entity_id` 是版本历史和关联表使用的稳定别名。
|
|
458
453
|
|
|
459
454
|
四条要点:
|
|
460
455
|
|
|
461
456
|
- **卡片上记着它的坐标**(`card.object_id / action_id / scene_id` + front matter 的
|
|
462
|
-
`coordinate`)。坐标在这一层是**轴实体 id
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
- **不同坐标推同一个卡名 = 两张卡**(0069 之前它们会被按名字静默并成一张)。
|
|
467
|
-
撞名仍然报 warning,但它的后果从「身份错」退化成「标题重」。
|
|
457
|
+
`coordinate`)。坐标在这一层是**轴实体 id**,卡名只是显示。
|
|
458
|
+
- **判重的顺序是「先坐标,再认领,最后新建」**。如果按坐标未命中,就检查已有卡片能否认领,
|
|
459
|
+
最后才新建卡片。
|
|
460
|
+
- **不同坐标可以使用同一个卡名**。撞名会返回 warning。
|
|
468
461
|
- **落位落库**(`card_knowledge`,0063 §4.5):`section` / `ordinal` 是**关联**的属性。
|
|
469
|
-
|
|
470
|
-
0069 之前 `disputed`(「有相反的说法」)渲染进正文后与确定的事实长得一样。
|
|
462
|
+
召回命中**章节**之后,按这一节取它落位的知识(含四档状态与出处引文)。
|
|
471
463
|
|
|
472
464
|
**坐标不替代图。** 图是**从 Knowledge 派生的可选关系索引**,回答的是「通天塔依赖哪些表」
|
|
473
465
|
这类任意关系与反向关系;坐标回答的是「这条知识关于什么」。见
|
|
@@ -479,15 +471,11 @@ Document ──▶ Knowledge × N ──▶ 坐标 (对象 × 动作 × 场景)
|
|
|
479
471
|
(身份是 `(entity_kind, entity_id, version)`)+ 一行 `blob`(正文按 sha256 内容寻址)。
|
|
480
472
|
正文完全相同的重复写入**不产生新版本**,只更新 front matter 那类记账字段。
|
|
481
473
|
`listVersions` / `cardVersions` 返回新→旧,并把当前 head 标成 `isCurrent: true`;
|
|
482
|
-
`versionId`
|
|
483
|
-
拒掉)。
|
|
474
|
+
`versionId` 就是**整数版本号的字符串形式**。
|
|
484
475
|
|
|
485
476
|
**回滚 = 用历史版本的正文重新写一次**:回滚前会把当时的 head 再记一版,所以历史只增不减,
|
|
486
477
|
**回滚本身也可回滚**。回滚到当前版本是 no-op。
|
|
487
478
|
|
|
488
|
-
`memory/<库 id>/source-versions/` 与 `card-versions/` 是**旧的文件式快照**:仍然被读
|
|
489
|
-
(迁移把它们当历史导入),但**不再被写**。
|
|
490
|
-
|
|
491
479
|
### 起编译的语义(0066)
|
|
492
480
|
|
|
493
481
|
`POST /knowledge/rebuild` **立即返回** `202 { runId, queued }` —— 它只回答「这一趟的编号
|
|
@@ -497,7 +485,7 @@ Document ──▶ Knowledge × N ──▶ 坐标 (对象 × 动作 × 场景)
|
|
|
497
485
|
```jsonc
|
|
498
486
|
{ "progress": { "runId": "rebuild_…", "startedAt": "…", "finishedAt": "…",
|
|
499
487
|
"steps": [ /* 四段 */ ], "outcome": "索引 v21:…",
|
|
500
|
-
"report": { /*
|
|
488
|
+
"report": { /* RebuildReport */ } } }
|
|
501
489
|
```
|
|
502
490
|
|
|
503
491
|
`?runId=<编号>` 指名要哪一趟;不给编号时给**正在跑**的那一趟(没有在跑就给最近结束的那一趟)。
|
package/eval/README.md
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
# Tita Knowledge Retrieval Evaluation
|
|
2
2
|
|
|
3
3
|
`evaluate-retrieval.mjs` 对同一份已经编译好的 Knowledge Store,逐条运行
|
|
4
|
-
`fts`、`vector`、`hybrid`,输出 Recall、MRR、nDCG
|
|
4
|
+
`fts`、`vector`、`hybrid`,输出 Recall、MRR、nDCG、弃答准确率和 p50/p95 latency。它不自动
|
|
5
5
|
下载公开数据集,也不会改写知识库;公开数据集需要先转换为本插件的 qrels 格式。
|
|
6
6
|
|
|
7
7
|
## qrels 格式
|
|
8
8
|
|
|
9
9
|
每行一个 JSON 对象,`relevant_unit_ids` 使用编译后的稳定 `unitId`,例如
|
|
10
10
|
`metric:sales_amount`。可以附加 `include_problems` 和 `subset`,用于分组评测文本、
|
|
11
|
-
图片 Markdown
|
|
11
|
+
图片 Markdown、表格截图等场景。`subset` 当前保留在输入中;按子集运行时先分别生成
|
|
12
|
+
qrels 文件,runner 不自动输出子集汇总。
|
|
12
13
|
|
|
13
14
|
```json
|
|
14
15
|
{"id":"q1","query":"销售额如何计算","relevant_unit_ids":["metric:sales_amount"],"subset":"text"}
|
|
16
|
+
{"id":"q2","query":"库内没有依据的问题","relevant_unit_ids":[],"subset":"abstention"}
|
|
15
17
|
```
|
|
16
18
|
|
|
19
|
+
空 `relevant_unit_ids` 明确表示“不应召回”。必须提供这个字段,避免把漏标注误当作
|
|
20
|
+
弃答样本。正例的 Recall、MRR、nDCG 只使用有正例的查询计算;弃答样本单独输出
|
|
21
|
+
`abstention.count`、`falseAnswers`(任何命中均计为误召回)和 `accuracy`。
|
|
22
|
+
只有弃答样本时,正例指标为 `null`。接口失败会使评测失败,不会当作成功弃答。
|
|
23
|
+
|
|
17
24
|
## 本地运行
|
|
18
25
|
|
|
19
26
|
先在 UI 点击一次「编译」,再运行:
|
|
@@ -21,7 +28,7 @@
|
|
|
21
28
|
```bash
|
|
22
29
|
pnpm --filter dsh-data-domain-knowledge build
|
|
23
30
|
node plugins/dsh-data-domain-knowledge/eval/evaluate-retrieval.mjs \
|
|
24
|
-
--root "$HOME/.tita-
|
|
31
|
+
--root "$HOME/.dsh/tita-agent/domain_knowledge/default" \
|
|
25
32
|
--qrels plugins/dsh-data-domain-knowledge/eval/queries.example.jsonl
|
|
26
33
|
```
|
|
27
34
|
|
|
@@ -29,10 +36,10 @@ node plugins/dsh-data-domain-knowledge/eval/evaluate-retrieval.mjs \
|
|
|
29
36
|
|
|
30
37
|
```bash
|
|
31
38
|
TITA_EVAL_PROVIDER=wemm-python \
|
|
32
|
-
TITA_EVAL_PYTHON="$HOME/.tita-
|
|
33
|
-
TITA_EVAL_MODEL="$HOME/.tita-
|
|
39
|
+
TITA_EVAL_PYTHON="$HOME/.dsh/tita-agent/resource/python/bin/python" \
|
|
40
|
+
TITA_EVAL_MODEL="$HOME/.dsh/tita-agent/resource/models/WeMM-Embedding-2B-Quantized" \
|
|
34
41
|
node plugins/dsh-data-domain-knowledge/eval/evaluate-retrieval.mjs \
|
|
35
|
-
--root "$HOME/.tita-
|
|
42
|
+
--root "$HOME/.dsh/tita-agent/domain_knowledge/default" \
|
|
36
43
|
--qrels ./queries.jsonl
|
|
37
44
|
```
|
|
38
45
|
|
|
@@ -61,12 +68,13 @@ checkpoint 编译后再跑同一份 qrels。每次比较固定知识卡片、qre
|
|
|
61
68
|
评测,但它仍然是模型级评测,不是 Tita 端到端评测。
|
|
62
69
|
3. Tita 专属 golden set:建议先人工标注 100–200 条查询,至少包含指标口径、表/字段
|
|
63
70
|
语义、同义词、跨语言、图片中的 UI/图表信息、hard negative 和“不应召回”样本。
|
|
64
|
-
|
|
71
|
+
有答案的 query 标注 1–3 个正例 unitId;不应召回的 query 使用空集合。每轮发布前
|
|
72
|
+
固定这份集合,新增样本走版本控制。
|
|
65
73
|
|
|
66
74
|
## 指标与门槛
|
|
67
75
|
|
|
68
76
|
主指标使用 `nDCG@10`、`Recall@10`、`MRR@10`,辅助看 `Recall@5/20`;同时记录
|
|
69
|
-
|
|
77
|
+
弃答准确率和误召回数。另行测量向量编译吞吐(units/min)、模型常驻内存、`derived.db` 大小和
|
|
70
78
|
向量复用率。多模态集合要单独报告 text→image、image→text、text+image 三类结果,
|
|
71
79
|
不能只看总平均。
|
|
72
80
|
|
|
@@ -74,3 +82,6 @@ checkpoint 编译后再跑同一份 qrels。每次比较固定知识卡片、qre
|
|
|
74
82
|
至少应在语义改写和图片子集上带来可观增益;具体阈值在首轮 100–200 条标注跑完后再
|
|
75
83
|
根据置信区间确定,不预先假设量化版一定优于 BF16。最终结果同时保存 qrels、配置、
|
|
76
84
|
模型 revision、硬件和原始 JSON,确保可复现。
|
|
85
|
+
|
|
86
|
+
runner 关闭 cross-encoder 重排,比较原始召回路线。完整 Rerank 链路的质量要另行
|
|
87
|
+
测量。自动化回归测试使用小型本地语料和模型替身,不构成真实模型质量门槛的验收结果。
|
|
@@ -56,8 +56,8 @@ if (!limits.length || !modes.length) usage('invalid --k or --modes')
|
|
|
56
56
|
const lines = (await readFile(args.qrels, 'utf8')).split(/\r?\n/).map(line => line.trim()).filter(Boolean).filter(line => !line.startsWith('#'))
|
|
57
57
|
const qrels = lines.map((line, index) => {
|
|
58
58
|
const item = JSON.parse(line)
|
|
59
|
-
const relevant = item.relevant_unit_ids ?? item.relevant
|
|
60
|
-
if (!item.query || !Array.isArray(relevant)
|
|
59
|
+
const relevant = item.relevant_unit_ids ?? item.relevant
|
|
60
|
+
if (!item.query || !Array.isArray(relevant)) throw new Error(`qrels line ${index + 1} needs query and relevant_unit_ids (empty means abstain)`)
|
|
61
61
|
return { ...item, relevant_unit_ids: [...new Set(relevant.map(String))] }
|
|
62
62
|
})
|
|
63
63
|
if (!qrels.length) throw new Error('qrels is empty')
|
|
@@ -93,26 +93,35 @@ try {
|
|
|
93
93
|
// is disabled and the raw fused ranking is measured.
|
|
94
94
|
const response = await runtime.recall(qrel.query, maxLimit, qrel.include_problems === true, mode, undefined, { rerank: false })
|
|
95
95
|
latencies.push(performance.now() - started)
|
|
96
|
+
if (!response.ok) throw new Error(`${qrel.id ?? qrel.query}: ${response.error?.code ?? 'RECALL_FAILED'}`)
|
|
96
97
|
if (response.data.backend === 'fts' && mode !== 'fts') fallbackCount += 1
|
|
97
|
-
rows.push({ hits: response.data.hits, relevant: new Set(qrel.relevant_unit_ids) })
|
|
98
|
+
rows.push({ hits: response.data.hits, relevant: new Set(qrel.relevant_unit_ids), subset: qrel.subset ?? 'default' })
|
|
98
99
|
}
|
|
99
100
|
const metrics = {}
|
|
100
101
|
for (const limit of limits) {
|
|
101
102
|
let recall = 0
|
|
102
103
|
let mrr = 0
|
|
103
104
|
let score = 0
|
|
104
|
-
|
|
105
|
+
const positiveRows = rows.filter(row => row.relevant.size > 0)
|
|
106
|
+
for (const row of positiveRows) {
|
|
105
107
|
const hits = row.hits.slice(0, limit)
|
|
106
108
|
recall += hits.filter(hit => row.relevant.has(hit.unitId)).length / row.relevant.size
|
|
107
109
|
const rank = hits.findIndex(hit => row.relevant.has(hit.unitId))
|
|
108
110
|
mrr += rank < 0 ? 0 : 1 / (rank + 1)
|
|
109
111
|
score += ndcg(row.hits, row.relevant, limit)
|
|
110
112
|
}
|
|
111
|
-
|
|
112
|
-
metrics[`
|
|
113
|
-
metrics[`
|
|
113
|
+
const divisor = positiveRows.length || 1
|
|
114
|
+
metrics[`recall@${limit}`] = positiveRows.length ? Number((recall / divisor).toFixed(4)) : null
|
|
115
|
+
metrics[`mrr@${limit}`] = positiveRows.length ? Number((mrr / divisor).toFixed(4)) : null
|
|
116
|
+
metrics[`ndcg@${limit}`] = positiveRows.length ? Number((score / divisor).toFixed(4)) : null
|
|
117
|
+
}
|
|
118
|
+
const negativeRows = rows.filter(row => row.relevant.size === 0)
|
|
119
|
+
const falseAnswers = negativeRows.filter(row => row.hits.length > 0).length
|
|
120
|
+
output.modes[mode] = {
|
|
121
|
+
metrics, positiveCount: rows.length - negativeRows.length,
|
|
122
|
+
abstention: { count: negativeRows.length, falseAnswers, accuracy: negativeRows.length ? Number((1 - falseAnswers / negativeRows.length).toFixed(4)) : null },
|
|
123
|
+
latencyMs: { p50: percentile(latencies, 0.5), p95: percentile(latencies, 0.95) }, fallbackCount,
|
|
114
124
|
}
|
|
115
|
-
output.modes[mode] = { metrics, latencyMs: { p50: percentile(latencies, 0.5), p95: percentile(latencies, 0.95) }, fallbackCount }
|
|
116
125
|
}
|
|
117
126
|
} finally {
|
|
118
127
|
runtime.close()
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
{"id":"q-agent-architecture","query":"知识编译与召回的 Agent 架构","relevant_unit_ids":["concept:agent_architecture"],"subset":"text"}
|
|
2
2
|
{"id":"q-ui-architecture","query":"Tita 数据 Agent 的界面和架构","relevant_unit_ids":["concept:agent_architecture","concept:ui_reference"],"subset":"text-image"}
|
|
3
|
+
{"id":"q-no-evidence","query":"火星香蕉的年度产量是多少","relevant_unit_ids":[],"subset":"abstention"}
|