dsh-data-domain-knowledge 0.1.0-alpha.11 → 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.
Files changed (125) hide show
  1. package/README.md +52 -9
  2. package/eval/README.md +19 -8
  3. package/eval/evaluate-retrieval.mjs +17 -8
  4. package/eval/queries.example.jsonl +1 -0
  5. package/lib/client.js +2237 -2096
  6. package/lib/doc-page.js +1 -1
  7. package/lib/pages.js +2 -2
  8. package/lib/types/axis-registry.d.ts +9 -4
  9. package/lib/types/axis-registry.d.ts.map +1 -1
  10. package/lib/types/axis-registry.js +62 -23
  11. package/lib/types/axis-registry.js.map +1 -1
  12. package/lib/types/card-organize.d.ts +5 -0
  13. package/lib/types/card-organize.d.ts.map +1 -1
  14. package/lib/types/card-organize.js +15 -0
  15. package/lib/types/card-organize.js.map +1 -1
  16. package/lib/types/compiler/embedding-identity.d.ts +3 -0
  17. package/lib/types/compiler/embedding-identity.d.ts.map +1 -0
  18. package/lib/types/compiler/embedding-identity.js +24 -0
  19. package/lib/types/compiler/embedding-identity.js.map +1 -0
  20. package/lib/types/compiler/snapshot.d.ts +16 -0
  21. package/lib/types/compiler/snapshot.d.ts.map +1 -0
  22. package/lib/types/compiler/snapshot.js +2 -0
  23. package/lib/types/compiler/snapshot.js.map +1 -0
  24. package/lib/types/diagnosis/store.d.ts.map +1 -1
  25. package/lib/types/diagnosis/store.js +2 -0
  26. package/lib/types/diagnosis/store.js.map +1 -1
  27. package/lib/types/environment/install.d.ts +6 -0
  28. package/lib/types/environment/install.d.ts.map +1 -0
  29. package/lib/types/environment/install.js +163 -0
  30. package/lib/types/environment/install.js.map +1 -0
  31. package/lib/types/environment/manifest.d.ts +17 -0
  32. package/lib/types/environment/manifest.d.ts.map +1 -0
  33. package/lib/types/environment/manifest.js +24 -0
  34. package/lib/types/environment/manifest.js.map +1 -0
  35. package/lib/types/environment/process.d.ts +10 -0
  36. package/lib/types/environment/process.d.ts.map +1 -0
  37. package/lib/types/environment/process.js +54 -0
  38. package/lib/types/environment/process.js.map +1 -0
  39. package/lib/types/environment/service.d.ts +47 -0
  40. package/lib/types/environment/service.d.ts.map +1 -0
  41. package/lib/types/environment/service.js +232 -0
  42. package/lib/types/environment/service.js.map +1 -0
  43. package/lib/types/environment/types.d.ts +31 -0
  44. package/lib/types/environment/types.d.ts.map +1 -0
  45. package/lib/types/environment/types.js +2 -0
  46. package/lib/types/environment/types.js.map +1 -0
  47. package/lib/types/events.d.ts +10 -0
  48. package/lib/types/events.d.ts.map +1 -1
  49. package/lib/types/events.js +38 -1
  50. package/lib/types/events.js.map +1 -1
  51. package/lib/types/index.d.ts.map +1 -1
  52. package/lib/types/index.js +36 -2
  53. package/lib/types/index.js.map +1 -1
  54. package/lib/types/knowledge-bases.d.ts +3 -0
  55. package/lib/types/knowledge-bases.d.ts.map +1 -1
  56. package/lib/types/knowledge-bases.js +9 -0
  57. package/lib/types/knowledge-bases.js.map +1 -1
  58. package/lib/types/knowledge.d.ts +14 -6
  59. package/lib/types/knowledge.d.ts.map +1 -1
  60. package/lib/types/knowledge.js +56 -39
  61. package/lib/types/knowledge.js.map +1 -1
  62. package/lib/types/retrieval/vector-index.d.ts +31 -0
  63. package/lib/types/retrieval/vector-index.d.ts.map +1 -0
  64. package/lib/types/retrieval/vector-index.js +15 -0
  65. package/lib/types/retrieval/vector-index.js.map +1 -0
  66. package/lib/types/retrieval/visibility.d.ts +6 -0
  67. package/lib/types/retrieval/visibility.d.ts.map +1 -0
  68. package/lib/types/retrieval/visibility.js +11 -0
  69. package/lib/types/retrieval/visibility.js.map +1 -0
  70. package/lib/types/runtime.d.ts +27 -3
  71. package/lib/types/runtime.d.ts.map +1 -1
  72. package/lib/types/runtime.js +449 -176
  73. package/lib/types/runtime.js.map +1 -1
  74. package/lib/types/source-evidence.d.ts +6 -0
  75. package/lib/types/source-evidence.d.ts.map +1 -0
  76. package/lib/types/source-evidence.js +28 -0
  77. package/lib/types/source-evidence.js.map +1 -0
  78. package/lib/types/store/axis-references.d.ts +5 -0
  79. package/lib/types/store/axis-references.d.ts.map +1 -0
  80. package/lib/types/store/axis-references.js +106 -0
  81. package/lib/types/store/axis-references.js.map +1 -0
  82. package/lib/types/store/derived.d.ts +11 -0
  83. package/lib/types/store/derived.d.ts.map +1 -1
  84. package/lib/types/store/derived.js +31 -6
  85. package/lib/types/store/derived.js.map +1 -1
  86. package/lib/types/store/knowledge-db.d.ts +4 -1
  87. package/lib/types/store/knowledge-db.d.ts.map +1 -1
  88. package/lib/types/store/knowledge-db.js +15 -9
  89. package/lib/types/store/knowledge-db.js.map +1 -1
  90. package/lib/types/store/migrate.d.ts.map +1 -1
  91. package/lib/types/store/migrate.js +11 -1
  92. package/lib/types/store/migrate.js.map +1 -1
  93. package/lib/types/types.d.ts +6 -0
  94. package/lib/types/types.d.ts.map +1 -1
  95. package/lib/types/types.js.map +1 -1
  96. package/package.json +3 -1
  97. package/python/prepare-models.py +19 -0
  98. package/python/requirements.txt +8 -6
  99. package/scripts/doctor.mjs +14 -2
  100. package/scripts/environment.mjs +29 -0
  101. package/src/axis-registry.ts +59 -23
  102. package/src/card-organize.ts +15 -0
  103. package/src/client/EnvironmentSetup.tsx +99 -0
  104. package/src/client/KnowledgePanel.tsx +9 -4
  105. package/src/compiler/embedding-identity.ts +21 -0
  106. package/src/compiler/snapshot.ts +17 -0
  107. package/src/diagnosis/store.ts +1 -0
  108. package/src/environment/install.ts +117 -0
  109. package/src/environment/manifest.ts +25 -0
  110. package/src/environment/process.ts +54 -0
  111. package/src/environment/service.ts +191 -0
  112. package/src/environment/types.ts +30 -0
  113. package/src/events.ts +46 -0
  114. package/src/index.ts +27 -2
  115. package/src/knowledge-bases.ts +9 -0
  116. package/src/knowledge.ts +56 -40
  117. package/src/retrieval/vector-index.ts +44 -0
  118. package/src/retrieval/visibility.ts +14 -0
  119. package/src/runtime.ts +407 -219
  120. package/src/source-evidence.ts +30 -0
  121. package/src/store/axis-references.ts +96 -0
  122. package/src/store/derived.ts +31 -6
  123. package/src/store/knowledge-db.ts +16 -9
  124. package/src/store/migrate.ts +11 -1
  125. package/src/types.ts +6 -0
package/README.md CHANGED
@@ -3,17 +3,38 @@
3
3
  本地知识库插件:一个知识库是一个目录,里面四样东西。`knowledge.db` 保存 **SourceRaw**
4
4
  (原始可追溯文档)、按主题聚合可双向链接的 wiki 卡片,以及**两者的每一个版本**;
5
5
  `derived.db` 输出可检索的 **wikiNotes**、wiki
6
- 知识图谱和向量索引,`<agentRoot>/memory/<库 id>` 保存版本快照、访问审计与反馈。默认使用本地 WeMM Python backend:从 WeMM
7
- 原生 2048 维向量按 MRL 截取 1024 维,先做 binary/Hamming 粗筛,再用 int8 点积精算余弦
8
- (这是**向量路内部的粗排 → 精算**,与 stage 4 的 cross-encoder **重排**不是一回事);
9
- 模型不可用时明确降级到 FTS,不会伪造向量结果。Markdown 中的
10
- 本地图片会与正文一起交给 WeMM,因此图片不是独立知识类型。
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
15
  模型和 Python 环境都从这里派生。
15
16
 
16
- ## 承载范围(五个视图)
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
+ ## 承载范围
17
38
 
18
39
  侧边栏 `TitaAgent` 面板的五个视图就是本插件的全部范围:
19
40
 
@@ -22,7 +43,7 @@ Tita Agent 的固定数据根目录是 `$DSH_HOME/tita-agent`(默认 `~/.dsh/t
22
43
  | `overview` | Agent 概览 | 各设置的挂载节点 |
23
44
  | `intent` | 意图 | `intent_record` / `intent_store_view`、`/intent/*` 路由、`titaDataAgentIntent` 服务;会话审计留痕落 `<agentRoot>/intent/` |
24
45
  | `knowledge` | 知识库 | `recall_knowledge` 等工具名、`/knowledge/*` 与 `/convert` 路由、`tita-data-agent-knowledge` / `-convert` 设置 |
25
- | `memory` | 记忆 | 抽取轨迹、轴 / Knowledge 真源、处理日志、`feedback.ndjson`、`access-audit.ndjson`,根在 `<agentRoot>/memory/<库 id>`;磁盘目录布局 |
46
+ | `memory` | 记忆 | 抽取轨迹、处理日志、`feedback.ndjson`、`access-audit.ndjson`,根在 `<agentRoot>/memory/<库 id>`;轴 / Knowledge 真源在主库 |
26
47
  | `eval` | 评测 | 问题集格式(开发期能力,不注册运行时入口) |
27
48
 
28
49
  意图的**会话审计留痕**落在 `<agentRoot>/intent/`:`intent.db` 保存当前记录与追加历史
@@ -53,7 +74,7 @@ Tita Agent 的固定数据根目录是 `$DSH_HOME/tita-agent`(默认 `~/.dsh/t
53
74
  | Knowledge | `knowledge` + `knowledge_sources` | 原子事实、坐标、来源、状态;不保存 Card 的排版 |
54
75
  | Wiki Card | `card` + `blob` + `revision` | 面向阅读和召回组装的正文;正文中的 Markdown 标题是 Section 真源 |
55
76
  | Knowledge 落位 | `card_knowledge` | 记录 Knowledge 在某张 Card 中的 Section 和顺序;这是关联索引,不是 Knowledge 属性 |
56
- | Wiki Note / FTS / Vector / Graph | 派生文件 | 可以从 Card 和 Knowledge 重新构建,不是真实知识来源 |
77
+ | Wiki Note / FTS / Vector / Graph | `derived.db` | 可以从 Card 和 Knowledge 重新构建;编译结果在同一事务发布 |
57
78
 
58
79
  ### 状态语义
59
80
 
@@ -70,7 +91,29 @@ Knowledge ID 只在一个 `knowledge.db` 内有意义。相同文本在同一个
70
91
 
71
92
  这意味着当前实现适用于“一个知识库对应一个业务范围”的模型。未来如果一个库需要混合多个租户、环境或有效期,再把 Scope 纳入判重策略。
72
93
 
73
- ### Knowledge 类型
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 类型字段
74
117
 
75
118
  当前不把 `Fact` / `Rule` / `Procedure` / `Constraint` 加成 Knowledge 的正式列。类型暂作为抽取或 Card metadata 的扩展信息,只有当不同类型需要不同的召回、验证或执行策略时,才升级为结构化字段。
76
119
 
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 和 p50/p95 latency。它不自动
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-data-agent/knowledge" \
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-data-agent/embedding-venv/bin/python" \
33
- TITA_EVAL_MODEL="$HOME/.tita-data-agent/models/WeMM-Embedding-2B-Quantized" \
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-data-agent/knowledge" \
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
- 每条 query 标注 1–3 个正例 unitId;每轮发布前固定这份集合,新增样本走版本控制。
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
- 向量编译吞吐(units/min)、查询 p50/p95、模型常驻内存、`03_compiled` 索引大小和
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) || relevant.length === 0) throw new Error(`qrels line ${index + 1} needs query and non-empty relevant_unit_ids`)
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
- for (const row of rows) {
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
- metrics[`recall@${limit}`] = Number((recall / rows.length).toFixed(4))
112
- metrics[`mrr@${limit}`] = Number((mrr / rows.length).toFixed(4))
113
- metrics[`ndcg@${limit}`] = Number((score / rows.length).toFixed(4))
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"}