@scotthuang/engram 0.7.6 → 0.8.1
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 +40 -0
- package/dist/src/__tests__/face-auto-dryrun.d.ts +12 -0
- package/dist/src/__tests__/face-auto-dryrun.js +166 -0
- package/dist/src/__tests__/face-auto-dryrun.js.map +1 -0
- package/dist/src/__tests__/promotion-dryrun.d.ts +6 -0
- package/dist/src/__tests__/promotion-dryrun.js +105 -0
- package/dist/src/__tests__/promotion-dryrun.js.map +1 -0
- package/dist/src/config.d.ts +7 -0
- package/dist/src/config.js +20 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/index.js +147 -20
- package/dist/src/index.js.map +1 -1
- package/dist/src/promotion.d.ts +52 -0
- package/dist/src/promotion.js +140 -0
- package/dist/src/promotion.js.map +1 -0
- package/dist/src/recall.d.ts +24 -7
- package/dist/src/recall.js +126 -15
- package/dist/src/recall.js.map +1 -1
- package/dist/src/settle.d.ts +4 -5
- package/dist/src/settle.js +74 -28
- package/dist/src/settle.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,6 +21,43 @@ OpenClaw Plugin for hierarchical semantic memory.
|
|
|
21
21
|
./stop.sh
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
### 人脸服务常驻(推荐)
|
|
25
|
+
|
|
26
|
+
人脸识别服务(InsightFace buffalo_l)建议配置为开机自启常驻进程,这样微信发图时能自动识别人脸。
|
|
27
|
+
|
|
28
|
+
**资源开销:**
|
|
29
|
+
|
|
30
|
+
| 状态 | RSS 内存 | CPU |
|
|
31
|
+
|------|---------|-----|
|
|
32
|
+
| 模型未加载(空闲) | ~240 MB | ~0% |
|
|
33
|
+
| 模型已加载(空闲) | ~1.85 GB | ~0% |
|
|
34
|
+
| 推理中 | ~1.85 GB | 单核 |
|
|
35
|
+
|
|
36
|
+
模型在首次检测时延迟加载,后续每张图片检测耗时 260-380ms。
|
|
37
|
+
|
|
38
|
+
**launchd 配置(macOS):**
|
|
39
|
+
|
|
40
|
+
plist 文件位于 `~/Library/LaunchAgents/com.engram.face-service.plist`。
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# 查看服务状态
|
|
44
|
+
launchctl list | grep engram
|
|
45
|
+
|
|
46
|
+
# 启动服务
|
|
47
|
+
launchctl load ~/Library/LaunchAgents/com.engram.face-service.plist
|
|
48
|
+
|
|
49
|
+
# 停止服务
|
|
50
|
+
launchctl unload ~/Library/LaunchAgents/com.engram.face-service.plist
|
|
51
|
+
|
|
52
|
+
# 查看日志
|
|
53
|
+
tail -f /Users/scotthuang/github/engram/.logs/face-service.log
|
|
54
|
+
|
|
55
|
+
# 健康检查
|
|
56
|
+
curl http://localhost:8765/health
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
服务配置了崩溃自动重启(10s 冷却),异常退出后会自动恢复。
|
|
60
|
+
|
|
24
61
|
### 查看日志
|
|
25
62
|
|
|
26
63
|
```bash
|
|
@@ -29,6 +66,9 @@ tail -f .logs/backend.log
|
|
|
29
66
|
|
|
30
67
|
# 实时查看前端日志
|
|
31
68
|
tail -f .logs/frontend.log
|
|
69
|
+
|
|
70
|
+
# 实时查看人脸服务日志(常驻模式)
|
|
71
|
+
tail -f .logs/face-service.log
|
|
32
72
|
```
|
|
33
73
|
|
|
34
74
|
## 📁 项目结构
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 图片自动人脸识别注入 — 本地模拟测试
|
|
3
|
+
*
|
|
4
|
+
* 用 memory-engram/images/ 中已存储的图片模拟微信发图场景,
|
|
5
|
+
* 验证 faceStore.detectAndMatch() + 上下文构建逻辑。
|
|
6
|
+
*
|
|
7
|
+
* 不依赖 OpenClaw,不修改任何数据,只做检测和打印。
|
|
8
|
+
* 需要 Python 人脸服务已启动(localhost:8765)。
|
|
9
|
+
*
|
|
10
|
+
* 用法: npx tsx src/__tests__/face-auto-dryrun.ts
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 图片自动人脸识别注入 — 本地模拟测试
|
|
3
|
+
*
|
|
4
|
+
* 用 memory-engram/images/ 中已存储的图片模拟微信发图场景,
|
|
5
|
+
* 验证 faceStore.detectAndMatch() + 上下文构建逻辑。
|
|
6
|
+
*
|
|
7
|
+
* 不依赖 OpenClaw,不修改任何数据,只做检测和打印。
|
|
8
|
+
* 需要 Python 人脸服务已启动(localhost:8765)。
|
|
9
|
+
*
|
|
10
|
+
* 用法: npx tsx src/__tests__/face-auto-dryrun.ts
|
|
11
|
+
*/
|
|
12
|
+
import { FaceStore } from "../../face/src/face-store.js";
|
|
13
|
+
const WORKSPACE = process.env.WORKSPACE_DIR || `${process.env.HOME}/.openclaw/workspace`;
|
|
14
|
+
const faceStore = new FaceStore(WORKSPACE);
|
|
15
|
+
// ---- 测试用例 ----
|
|
16
|
+
const TEST_CASES = [
|
|
17
|
+
// Scott + Wandy 缆车合影 (faces=2)
|
|
18
|
+
{
|
|
19
|
+
label: "Scott + Wandy 白云山缆车",
|
|
20
|
+
imagePath: `${WORKSPACE}/memory-engram/images/2026-03/29/20260329_024148_83b84e.jpg`,
|
|
21
|
+
},
|
|
22
|
+
// Scott + Wandy 地铁(Wandy 睡着)(faces=2)
|
|
23
|
+
{
|
|
24
|
+
label: "Scott + Wandy 地铁",
|
|
25
|
+
imagePath: `${WORKSPACE}/memory-engram/images/2026-03/29/20260329_024151_ae582b.jpg`,
|
|
26
|
+
},
|
|
27
|
+
// Wandy 单人 九龙泉 (faces=1)
|
|
28
|
+
{
|
|
29
|
+
label: "Wandy 九龙泉",
|
|
30
|
+
imagePath: `${WORKSPACE}/memory-engram/images/2026-03/29/20260329_024144_70213a.jpg`,
|
|
31
|
+
},
|
|
32
|
+
// 一家三口火锅 (faces=6,含多人)
|
|
33
|
+
{
|
|
34
|
+
label: "一家三口火锅聚餐",
|
|
35
|
+
imagePath: `${WORKSPACE}/memory-engram/images/2026-03/29/20260329_192738_963e15.jpg`,
|
|
36
|
+
},
|
|
37
|
+
// Season 冰淇淋 (faces=0 in metadata, 但应该能检测到)
|
|
38
|
+
{
|
|
39
|
+
label: "Season 吃冰淇淋",
|
|
40
|
+
imagePath: `${WORKSPACE}/memory-engram/images/2026-04/10/20260410_204737_955aa8.jpg`,
|
|
41
|
+
},
|
|
42
|
+
// Wandy 海边沙滩 (faces=0 in metadata)
|
|
43
|
+
{
|
|
44
|
+
label: "Wandy 海边玩沙",
|
|
45
|
+
imagePath: `${WORKSPACE}/memory-engram/images/2026-04/06/20260406_165533_7e65e2.jpg`,
|
|
46
|
+
},
|
|
47
|
+
// 暴雨预警截图 — 应该无人脸
|
|
48
|
+
{
|
|
49
|
+
label: "暴雨预警截图(无人脸)",
|
|
50
|
+
imagePath: `${WORKSPACE}/memory-engram/images/2026-03/29/20260329_191026_b9b9fb.jpg`,
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
// ---- 模拟 before_prompt_build 中的人脸上下文构建 ----
|
|
54
|
+
async function buildFaceContext(imagePaths) {
|
|
55
|
+
const registry = await faceStore.loadRegistry();
|
|
56
|
+
if (registry.persons.length === 0)
|
|
57
|
+
return "";
|
|
58
|
+
const relationMap = new Map();
|
|
59
|
+
for (const p of registry.persons) {
|
|
60
|
+
if (p.relation)
|
|
61
|
+
relationMap.set(p.id, p.relation);
|
|
62
|
+
}
|
|
63
|
+
const allFaceLines = [];
|
|
64
|
+
let unknownCount = 0;
|
|
65
|
+
for (const imgPath of imagePaths) {
|
|
66
|
+
const matches = await faceStore.detectAndMatch(imgPath);
|
|
67
|
+
for (const m of matches) {
|
|
68
|
+
if (m.status === "matched") {
|
|
69
|
+
const rel = m.personId ? relationMap.get(m.personId) : "";
|
|
70
|
+
const relStr = rel ? `(${rel},` : "(";
|
|
71
|
+
allFaceLines.push(`- ${m.name}${relStr}${(m.confidence * 100).toFixed(0)}% 置信度)`);
|
|
72
|
+
}
|
|
73
|
+
else if (m.status === "uncertain") {
|
|
74
|
+
allFaceLines.push(`- 疑似 ${m.name}(${(m.confidence * 100).toFixed(0)}%,不确定)`);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
unknownCount++;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (unknownCount > 0) {
|
|
82
|
+
allFaceLines.push(`- ${unknownCount} 张未知人脸`);
|
|
83
|
+
}
|
|
84
|
+
if (allFaceLines.length === 0)
|
|
85
|
+
return "";
|
|
86
|
+
return [
|
|
87
|
+
`<face-recognition>`,
|
|
88
|
+
`图片中识别到以下人物:`,
|
|
89
|
+
...allFaceLines,
|
|
90
|
+
`请结合以上信息理解图片内容。如用户问"这是谁",优先使用识别结果回答。`,
|
|
91
|
+
`</face-recognition>`,
|
|
92
|
+
].join("\n");
|
|
93
|
+
}
|
|
94
|
+
// ---- 主流程 ----
|
|
95
|
+
async function main() {
|
|
96
|
+
console.log("═══════════════════════════════════════════════════════════════");
|
|
97
|
+
console.log(" 图片自动人脸识别注入 — 本地模拟测试");
|
|
98
|
+
console.log("═══════════════════════════════════════════════════════════════");
|
|
99
|
+
// 1. 检查人脸服务
|
|
100
|
+
const available = await faceStore.isServiceAvailable();
|
|
101
|
+
console.log(`\n人脸服务状态: ${available ? "✅ 在线" : "❌ 离线"}`);
|
|
102
|
+
if (!available) {
|
|
103
|
+
console.log("请先启动 Python 人脸服务: cd face/service && python app.py");
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
// 2. 检查注册人物
|
|
107
|
+
const registry = await faceStore.loadRegistry();
|
|
108
|
+
console.log(`已注册人物: ${registry.persons.length}`);
|
|
109
|
+
for (const p of registry.persons) {
|
|
110
|
+
console.log(` ${p.id}: ${p.name} (relation=${p.relation}, samples=${p.sampleCount})`);
|
|
111
|
+
}
|
|
112
|
+
// 3. 逐个测试
|
|
113
|
+
console.log("\n───────────────────────────────────────────────────────────────\n");
|
|
114
|
+
for (const tc of TEST_CASES) {
|
|
115
|
+
console.log(`📸 ${tc.label}`);
|
|
116
|
+
console.log(` ${tc.imagePath}`);
|
|
117
|
+
const startMs = Date.now();
|
|
118
|
+
try {
|
|
119
|
+
const context = await buildFaceContext([tc.imagePath]);
|
|
120
|
+
const elapsed = Date.now() - startMs;
|
|
121
|
+
if (context) {
|
|
122
|
+
console.log(` ⏱️ ${elapsed}ms`);
|
|
123
|
+
console.log(` ${context.split("\n").map(l => ` ${l}`).join("\n")}`);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
console.log(` ⏱️ ${elapsed}ms — 无人脸检测到`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
console.log(` ❌ 检测失败: ${err}`);
|
|
131
|
+
}
|
|
132
|
+
console.log();
|
|
133
|
+
}
|
|
134
|
+
// 4. 模拟微信发图的完整 prompt
|
|
135
|
+
console.log("───────────────────────────────────────────────────────────────");
|
|
136
|
+
console.log("📱 模拟微信发图场景(Scott+Wandy 缆车合影)\n");
|
|
137
|
+
const mockPrompt = `[media attached: ${TEST_CASES[0].imagePath} (image/jpeg)]
|
|
138
|
+
|
|
139
|
+
To send an image back to the user, use this format: 
|
|
140
|
+
Keep caption in the text body.
|
|
141
|
+
|
|
142
|
+
Conversation info (untrusted metadata):
|
|
143
|
+
channel: weixin
|
|
144
|
+
|
|
145
|
+
Sender (untrusted metadata):
|
|
146
|
+
{"name":"Scott","id":"wxid_xxx"}`;
|
|
147
|
+
// 提取图片路径
|
|
148
|
+
const imagePathMatches = [...mockPrompt.matchAll(/\[media attached:\s*([^\s\]]+)\s*\(image\//gi)];
|
|
149
|
+
const imagePaths = imagePathMatches.map(m => m[1]);
|
|
150
|
+
console.log(` 提取到 ${imagePaths.length} 张图片: ${imagePaths.join(", ")}`);
|
|
151
|
+
const startMs = Date.now();
|
|
152
|
+
const faceContext = await buildFaceContext(imagePaths);
|
|
153
|
+
console.log(` 检测耗时: ${Date.now() - startMs}ms`);
|
|
154
|
+
if (faceContext) {
|
|
155
|
+
console.log(`\n === 将注入给 LLM 的 prependContext ===\n`);
|
|
156
|
+
console.log(faceContext);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
console.log(`\n (无人脸信息注入)`);
|
|
160
|
+
}
|
|
161
|
+
console.log("\n═══════════════════════════════════════════════════════════════");
|
|
162
|
+
console.log(" 模拟完成(未修改任何数据)");
|
|
163
|
+
console.log("═══════════════════════════════════════════════════════════════\n");
|
|
164
|
+
}
|
|
165
|
+
main().catch(console.error);
|
|
166
|
+
//# sourceMappingURL=face-auto-dryrun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"face-auto-dryrun.js","sourceRoot":"","sources":["../../../src/__tests__/face-auto-dryrun.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 晋升评分引擎模拟测试
|
|
3
|
+
*
|
|
4
|
+
* 使用真实的 recall-hits.json 数据,模拟 6 维评分 + 筛选,不执行真实晋升
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
// 直接导入 promotion 模块
|
|
9
|
+
import { rankPromotionCandidates, filterPromotionCandidates, PROMOTION_PRESETS, DEFAULT_WEIGHTS, } from "../promotion.js";
|
|
10
|
+
// ---- 加载真实数据 ----
|
|
11
|
+
const WORKSPACE = process.env.WORKSPACE_DIR || join(process.env.HOME || "", ".openclaw/workspace");
|
|
12
|
+
const recallHitsPath = join(WORKSPACE, "memory-engram", "recall-hits.json");
|
|
13
|
+
let hits;
|
|
14
|
+
try {
|
|
15
|
+
const raw = readFileSync(recallHitsPath, "utf-8");
|
|
16
|
+
const parsed = JSON.parse(raw);
|
|
17
|
+
hits = {};
|
|
18
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
19
|
+
if (typeof value === "number") {
|
|
20
|
+
hits[key] = { recallCount: 1, firstHit: value, lastHit: value, settled: false, queryHashes: [], recallDays: [], totalScore: 0, maxScore: 0, dailyCount: 0, conceptTags: [] };
|
|
21
|
+
}
|
|
22
|
+
else if (typeof value === "object" && value !== null) {
|
|
23
|
+
const entry = value;
|
|
24
|
+
if (entry.recallCount == null && entry.hitCount != null) {
|
|
25
|
+
entry.recallCount = entry.hitCount;
|
|
26
|
+
}
|
|
27
|
+
if (entry.recallCount == null)
|
|
28
|
+
entry.recallCount = 0;
|
|
29
|
+
if (!entry.queryHashes)
|
|
30
|
+
entry.queryHashes = [];
|
|
31
|
+
if (!entry.recallDays)
|
|
32
|
+
entry.recallDays = [];
|
|
33
|
+
if (entry.totalScore == null)
|
|
34
|
+
entry.totalScore = 0;
|
|
35
|
+
if (entry.maxScore == null)
|
|
36
|
+
entry.maxScore = 0;
|
|
37
|
+
if (entry.dailyCount == null)
|
|
38
|
+
entry.dailyCount = 0;
|
|
39
|
+
if (!entry.conceptTags)
|
|
40
|
+
entry.conceptTags = [];
|
|
41
|
+
hits[key] = entry;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
console.error(`Failed to load ${recallHitsPath}: ${err}`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
console.log("═══════════════════════════════════════════════════════════════");
|
|
50
|
+
console.log(" Engram 晋升评分模拟测试(Dry-Run)");
|
|
51
|
+
console.log("═══════════════════════════════════════════════════════════════");
|
|
52
|
+
console.log(`\n数据源: ${recallHitsPath}`);
|
|
53
|
+
console.log(`总条目: ${Object.keys(hits).length}`);
|
|
54
|
+
console.log(`已晋升: ${Object.values(hits).filter(e => e.settled || e.promotedAt).length}`);
|
|
55
|
+
console.log(`权重: ${JSON.stringify(DEFAULT_WEIGHTS)}`);
|
|
56
|
+
// ---- 排名 ----
|
|
57
|
+
const ranked = rankPromotionCandidates(hits);
|
|
58
|
+
console.log(`\n─── 全部候选排名(${ranked.length} 条)───\n`);
|
|
59
|
+
console.log("排名 | 文件名 | 综合分 | freq | rel | div | rec | cons | conc | rcl | sig | queries | days | age(d)");
|
|
60
|
+
console.log("─────┼────────────────────┼─────────┼────────┼────────┼────────┼────────┼────────┼────────┼──────┼──────┼─────────┼──────┼───────");
|
|
61
|
+
for (let i = 0; i < ranked.length; i++) {
|
|
62
|
+
const c = ranked[i];
|
|
63
|
+
const w = DEFAULT_WEIGHTS;
|
|
64
|
+
console.log(` ${String(i + 1).padStart(2)} | ${c.key.padEnd(18)} | ${c.score.toFixed(4).padStart(7)} | ` +
|
|
65
|
+
`${(c.components.frequency * w.frequency).toFixed(3).padStart(6)} | ` +
|
|
66
|
+
`${(c.components.relevance * w.relevance).toFixed(3).padStart(6)} | ` +
|
|
67
|
+
`${(c.components.diversity * w.diversity).toFixed(3).padStart(6)} | ` +
|
|
68
|
+
`${(c.components.recency * w.recency).toFixed(3).padStart(6)} | ` +
|
|
69
|
+
`${(c.components.consolidation * w.consolidation).toFixed(3).padStart(6)} | ` +
|
|
70
|
+
`${(c.components.conceptual * DEFAULT_WEIGHTS.conceptual).toFixed(3).padStart(6)} | ` +
|
|
71
|
+
`${String(c.recallCount).padStart(4)} | ${String(c.signalCount).padStart(4)} | ${String(c.uniqueQueries).padStart(7)} | ${String(c.uniqueDays).padStart(4)} | ${c.ageDays.toFixed(1).padStart(6)}`);
|
|
72
|
+
}
|
|
73
|
+
// ---- 三档预设筛选 ----
|
|
74
|
+
for (const mode of ["core", "deep", "rem"]) {
|
|
75
|
+
const preset = PROMOTION_PRESETS[mode];
|
|
76
|
+
const config = { mode, ...preset };
|
|
77
|
+
const eligible = filterPromotionCandidates(ranked, config);
|
|
78
|
+
console.log(`\n─── ${mode.toUpperCase()} 模式筛选结果(minScore=${config.minScore}, minHits=${config.minRecallCount}, minQueries=${config.minUniqueQueries})───`);
|
|
79
|
+
if (eligible.length === 0) {
|
|
80
|
+
console.log(" (无候选通过筛选)");
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
for (const c of eligible) {
|
|
84
|
+
console.log(` ✓ ${c.key} score=${c.score.toFixed(4)} signals=${c.signalCount} recalls=${c.recallCount} queries=${c.uniqueQueries} days=${c.uniqueDays}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
console.log(` 总计: ${eligible.length} / ${ranked.length} 通过`);
|
|
88
|
+
}
|
|
89
|
+
// ---- 分析旧数据特征 ----
|
|
90
|
+
console.log("\n─── 旧数据分析 ───\n");
|
|
91
|
+
const noQueryData = ranked.filter(c => c.uniqueQueries === 0);
|
|
92
|
+
const noScoreData = ranked.filter(c => c.avgScore === 0);
|
|
93
|
+
const noTagData = ranked.filter(c => {
|
|
94
|
+
const entry = hits[c.key];
|
|
95
|
+
return !entry.conceptTags || entry.conceptTags.length === 0;
|
|
96
|
+
});
|
|
97
|
+
console.log(`无 queryHashes 数据: ${noQueryData.length} / ${ranked.length} (diversity 维度=0)`);
|
|
98
|
+
console.log(`无 totalScore 数据: ${noScoreData.length} / ${ranked.length} (relevance 维度=0)`);
|
|
99
|
+
console.log(`无 conceptTags 数据: ${noTagData.length} / ${ranked.length} (conceptual 维度=0.5 fallback)`);
|
|
100
|
+
console.log(`\n结论: 旧数据只有 frequency + recency 两个维度有效值,其余均为默认值。`);
|
|
101
|
+
console.log(`随着 0.8.0 积累新的 recall 数据(queryHashes, scores, #tags),评分精度会逐步提升。`);
|
|
102
|
+
console.log("\n═══════════════════════════════════════════════════════════════");
|
|
103
|
+
console.log(" 模拟完成(未执行任何写入操作)");
|
|
104
|
+
console.log("═══════════════════════════════════════════════════════════════\n");
|
|
105
|
+
//# sourceMappingURL=promotion-dryrun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promotion-dryrun.js","sourceRoot":"","sources":["../../../src/__tests__/promotion-dryrun.ts"],"names":[],"mappings":"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"}
|
package/dist/src/config.d.ts
CHANGED
|
@@ -50,6 +50,13 @@ export type MemorySystemConfig = {
|
|
|
50
50
|
/** 精确匹配:sessionKey 等于这些值时跳过召回 */
|
|
51
51
|
sessionExact: string[];
|
|
52
52
|
};
|
|
53
|
+
/** 晋升评分配置 */
|
|
54
|
+
promotion: {
|
|
55
|
+
/** 晋升模式:off 禁用 | core 每天3am | rem 每6h | deep 每12h */
|
|
56
|
+
mode: "off" | "core" | "rem" | "deep";
|
|
57
|
+
/** 每次晋升上限,默认 10 */
|
|
58
|
+
limit: number;
|
|
59
|
+
};
|
|
53
60
|
};
|
|
54
61
|
export declare const DEFAULTS: MemorySystemConfig;
|
|
55
62
|
/**
|
package/dist/src/config.js
CHANGED
|
@@ -30,6 +30,10 @@ export const DEFAULTS = {
|
|
|
30
30
|
sessionPatterns: [],
|
|
31
31
|
sessionExact: [],
|
|
32
32
|
},
|
|
33
|
+
promotion: {
|
|
34
|
+
mode: "rem",
|
|
35
|
+
limit: 10,
|
|
36
|
+
},
|
|
33
37
|
};
|
|
34
38
|
function parseStringArray(value) {
|
|
35
39
|
if (Array.isArray(value)) {
|
|
@@ -46,6 +50,20 @@ function parseSkipRecallConfig(prefixes, patterns, exact) {
|
|
|
46
50
|
sessionExact: parseStringArray(exact),
|
|
47
51
|
};
|
|
48
52
|
}
|
|
53
|
+
function parsePromotionConfig(raw) {
|
|
54
|
+
if (typeof raw === "object" && raw !== null) {
|
|
55
|
+
const obj = raw;
|
|
56
|
+
const validModes = ["off", "core", "rem", "deep"];
|
|
57
|
+
const mode = typeof obj.mode === "string" && validModes.includes(obj.mode)
|
|
58
|
+
? obj.mode
|
|
59
|
+
: DEFAULTS.promotion.mode;
|
|
60
|
+
const limit = typeof obj.limit === "number" && obj.limit > 0
|
|
61
|
+
? obj.limit
|
|
62
|
+
: DEFAULTS.promotion.limit;
|
|
63
|
+
return { mode, limit };
|
|
64
|
+
}
|
|
65
|
+
return { ...DEFAULTS.promotion };
|
|
66
|
+
}
|
|
49
67
|
/**
|
|
50
68
|
* 检查 sessionKey 是否应该跳过记忆召回
|
|
51
69
|
* 匹配规则:前缀匹配 OR 正则匹配 OR 精确匹配
|
|
@@ -120,12 +138,14 @@ export function parseConfig(raw) {
|
|
|
120
138
|
logDir: typeof raw.logDir === "string" ? raw.logDir : undefined,
|
|
121
139
|
saveStagingFile: typeof raw.saveStagingFile === "boolean" ? raw.saveStagingFile : true,
|
|
122
140
|
skipRecall: parseSkipRecallConfig(raw.skipRecallSessionPrefixes, raw.skipRecallSessionPatterns, raw.skipRecallSessionExact),
|
|
141
|
+
promotion: parsePromotionConfig(raw.promotion),
|
|
123
142
|
};
|
|
124
143
|
logger.info(`[engram:config] Parsed: shortTermDays=${config.shortTermDays} halfLifeDays=${config.halfLifeDays} recallTopK=${config.recallTopK} vectorWeight=${config.vectorWeight} textWeight=${config.textWeight}`);
|
|
125
144
|
logger.info(`[engram:config] Embedding: model=${config.embedding.model} dims=${config.embedding.dimensions} hasApiKey=${!!config.embedding.apiKey} baseUrl=${config.embedding.baseUrl.slice(0, 40)}`);
|
|
126
145
|
logger.info(`[engram:config] Condense: model=${config.condense.model} hasApiKey=${!!config.condense.apiKey}`);
|
|
127
146
|
logger.info(`[engram:config] QueryRewrite: enabled=${config.queryRewrite.enabled} timeoutMs=${config.queryRewrite.timeoutMs}`);
|
|
128
147
|
logger.info(`[engram:config] SkipRecall: prefixes=[${config.skipRecall.sessionPrefixes.join(",")}] patterns=[${config.skipRecall.sessionPatterns.join(",")}] exact=[${config.skipRecall.sessionExact.join(",")}]`);
|
|
148
|
+
logger.info(`[engram:config] Promotion: mode=${config.promotion.mode} limit=${config.promotion.limit}`);
|
|
129
149
|
logger.info(`[engram:config] LogDir: ${config.logDir || "(none, console only)"}`);
|
|
130
150
|
return config;
|
|
131
151
|
}
|
package/dist/src/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
|