dsh-engramory-recall 0.12.1 → 0.12.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/CHANGELOG.md +17 -0
- package/README.md +22 -0
- package/package.json +2 -1
- package/semantic.js +8 -7
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,23 @@
|
|
|
3
3
|
本项目的所有重要变更都记在这里。格式参照 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
|
|
4
4
|
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
5
5
|
|
|
6
|
+
## [0.12.2] — 2026-10-15
|
|
7
|
+
|
|
8
|
+
### 新增
|
|
9
|
+
|
|
10
|
+
- **embeddings 接缝的实测尺子**(`npm run bench:embed`):`--fake` 起本机假服务把管线与代价量清楚
|
|
11
|
+
(池子实际大小、每次检索耗时、HTTP 调用数、发出文本条数、缓存省下多少),`--real` 换成真端点量质量。
|
|
12
|
+
真库那半边要显式 `--store`,因为**它会把笔记片段发给端点**。
|
|
13
|
+
- 提供方模块现在也接受**默认导出对象**(`export default { rerank }`)——第三方提供方最自然的写法,
|
|
14
|
+
不必改成命名导出。命名导出照旧。
|
|
15
|
+
|
|
16
|
+
### 说明
|
|
17
|
+
|
|
18
|
+
- 假向量(哈希向量 = 最坏提供方)把融合表的结论变成实测:真库探针 hit@1 从 72.2%(词面)掉到
|
|
19
|
+
5.6%(`trust`)与 19.4%(`rrf`)—— `trust` 对垃圾提供方是灾难,**第一次接第三方接口建议先 `rrf`**。
|
|
20
|
+
- 缓存实测:26925 条候选只发出 1994 条(省 92.6%),因为同一篇笔记在不同查询里反复出现。
|
|
21
|
+
- 池子实际大小中位 31~39 条(不是 50):词面只回有分的文档,所以 `semanticPool` 是上限不是常态。
|
|
22
|
+
|
|
6
23
|
## [0.12.1] — 2026-10-15
|
|
7
24
|
|
|
8
25
|
### 新增
|
package/README.md
CHANGED
|
@@ -721,6 +721,27 @@ export ENGRAMORY_EMBED_MODEL=text-embedding-3-small
|
|
|
721
721
|
**一句实话**:这条路径的代码、测试、失败降级都有,但**还没有在真 key 上量过召回**(要花token,得你先点头)。
|
|
722
722
|
接缝本身的上限是量过的(上表 86.6%),提供方的质量只能真调一次才知道。
|
|
723
723
|
|
|
724
|
+
#### 真端点怎么量:`npm run bench:embed`
|
|
725
|
+
|
|
726
|
+
一条命令,两种模式:`--fake`(默认)起一个**本机假 embeddings 服务**,只读「管线与代价」;
|
|
727
|
+
`--real` 用 `providers/openai-embeddings.mjs` 的配置读法找真端点,那时质量列才是真的。
|
|
728
|
+
真库那半边要显式加 `--store ~/memory/engramory` —— 加了就意味着**你的笔记片段会发给那个端点**,
|
|
729
|
+
所以默认不开。
|
|
730
|
+
|
|
731
|
+
假向量(哈希向量 = 最坏提供方)跑出来的两组数字,正好把上面那张融合表变成实测:
|
|
732
|
+
|
|
733
|
+
| 卷子 | 词面 hit@1 / hit@4 | 假向量 + `trust` | 假向量 + `rrf` |
|
|
734
|
+
|---|---|---|---|
|
|
735
|
+
| 合成基准 704 条 | 50.4% / 67.5% | 18.3% / 25.4% | 26.8% / 43.6% |
|
|
736
|
+
| 真库探针 36 条 | 72.2% / 97.2% | 5.6% / 16.7% | 19.4% / 52.8% |
|
|
737
|
+
|
|
738
|
+
`trust` 对垃圾提供方是**灾难**(真库上 72.2% → 5.6%),`rrf` 也一样亏但守住一半。
|
|
739
|
+
所以:**不确定提供方靠不靠谱就别开 `trust`**(这也是第一次接第三方接口时的默认建议)。
|
|
740
|
+
|
|
741
|
+
代价侧(同一次运行数的):池子实际大小中位 31~39 条(不是 50,因为词面只回有分的文档)、
|
|
742
|
+
每次检索 p50 19~20 ms(假服务在本机,真延迟看端点);提供方按文本缓存让
|
|
743
|
+
**26925 条候选只发了 1994 条(省 92.6%)** —— 同一篇笔记在不同查询里反复出现时只付一次钱。
|
|
744
|
+
|
|
724
745
|
#### 复用 DSH 里已经配好的那条路由(`provider: "host-embed"`)
|
|
725
746
|
|
|
726
747
|
不想再填一遍环境变量:DSH 设置页 → 模型里配好的路由(`baseURL` + 模型 + API 密钥)可以**直接借来用**:
|
|
@@ -954,6 +975,7 @@ npm run bench:check # 合成基准 + 和 bench/expectations.json 对账(
|
|
|
954
975
|
npm run bench:bridges # 同义表覆盖率尺子:死值、覆盖、使用面、逐键消融(--ablate / --json / --store)
|
|
955
976
|
npm run bench:seam # 语义接缝的代价与天花板(四种坏提供方 + 作弊上界 + 融合模式对照)
|
|
956
977
|
npm run bench:ceiling # 池宽天花板:任一提供方在公开数据集上的上界 + 每查询要发多少东西
|
|
978
|
+
npm run bench:embed # embeddings 接缝:--fake 量管线与代价 / --real 用真端点量质量
|
|
957
979
|
npm run embed:check # 参考提供方自检:探一次 embeddings 接口,报维度与耗时(不打印密钥)
|
|
958
980
|
npm run bench:rewrite # 宿主模型当改写提供方:真调用量代价与收益(要本机有 dsh;--offline 只重算)
|
|
959
981
|
npm run bench:mcp # MCP 这一层:冷启动、每步往返、协议帧字节数
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-engramory-recall",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.2",
|
|
4
4
|
"description": "Local BM25 auto-recall, fail-closed write guard, static doctor and a memory panel for the Engramory markdown store — no network, no model, no daemon.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
"bench:check": "node bench/run.mjs --check",
|
|
83
83
|
"bench:seam": "node bench/semantic-seam.mjs",
|
|
84
84
|
"bench:ceiling": "node bench/pool-ceiling.mjs",
|
|
85
|
+
"bench:embed": "node bench/embed-live.mjs",
|
|
85
86
|
"bench:rewrite": "node bench/host-rewrite.mjs",
|
|
86
87
|
"bench:bridges": "node bench/bridge-coverage.mjs",
|
|
87
88
|
"bench:mcp": "node bench/mcp-overhead.mjs",
|
package/semantic.js
CHANGED
|
@@ -291,13 +291,14 @@ export async function loadProvider(config = {}, deps = {}) {
|
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
function normalizeModule(module, source) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
294
|
+
// 两种写法都收:命名导出(`export function rerank`)与默认导出对象(`export default { rerank }`)。
|
|
295
|
+
// 后者是第三方提供方最自然的写法(工厂函数 + 默认导出),不必逼人家改风格。
|
|
296
|
+
const fallback = String(source).split('/').pop();
|
|
297
|
+
for (const target of [module, module?.default]) {
|
|
298
|
+
if (!target || typeof target !== 'object') continue;
|
|
299
|
+
const name = String(target.name ?? module?.name ?? fallback);
|
|
300
|
+
if (typeof target.rerank === 'function') return { name, kind: 'rerank', rerank: target.rerank, source };
|
|
301
|
+
if (typeof target.expand === 'function') return { name, kind: 'expand', expand: target.expand, source };
|
|
301
302
|
}
|
|
302
303
|
return null;
|
|
303
304
|
}
|