@zaofan/dsh-qqbot 1.4.6 → 1.5.0
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 +158 -535
- package/README_EN.md +6 -0
- package/client/qqbot-settings.js +152 -5
- package/dist/channel-tools.d.ts.map +1 -1
- package/dist/channel-tools.js +106 -1
- package/dist/channel-tools.js.map +1 -1
- package/dist/features/agg-score.d.ts +73 -0
- package/dist/features/agg-score.d.ts.map +1 -0
- package/dist/features/agg-score.js +63 -0
- package/dist/features/agg-score.js.map +1 -0
- package/dist/features/attitude.d.ts +132 -0
- package/dist/features/attitude.d.ts.map +1 -0
- package/dist/features/attitude.js +318 -0
- package/dist/features/attitude.js.map +1 -0
- package/dist/features/bot-reply-memo.d.ts +8 -0
- package/dist/features/bot-reply-memo.d.ts.map +1 -0
- package/dist/features/bot-reply-memo.js +34 -0
- package/dist/features/bot-reply-memo.js.map +1 -0
- package/dist/features/emo-samples.d.ts +27 -0
- package/dist/features/emo-samples.d.ts.map +1 -0
- package/dist/features/emo-samples.js +116 -0
- package/dist/features/emo-samples.js.map +1 -0
- package/dist/features/four-source.d.ts +114 -0
- package/dist/features/four-source.d.ts.map +1 -0
- package/dist/features/four-source.js +260 -0
- package/dist/features/four-source.js.map +1 -0
- package/dist/features/image-url-ledger.d.ts +2 -0
- package/dist/features/image-url-ledger.d.ts.map +1 -1
- package/dist/features/image-url-ledger.js +23 -0
- package/dist/features/image-url-ledger.js.map +1 -1
- package/dist/features/intimacy-ledger.d.ts +31 -0
- package/dist/features/intimacy-ledger.d.ts.map +1 -0
- package/dist/features/intimacy-ledger.js +113 -0
- package/dist/features/intimacy-ledger.js.map +1 -0
- package/dist/features/local-signals.d.ts +130 -0
- package/dist/features/local-signals.d.ts.map +1 -0
- package/dist/features/local-signals.js +445 -0
- package/dist/features/local-signals.js.map +1 -0
- package/dist/features/people-memo.d.ts +52 -0
- package/dist/features/people-memo.d.ts.map +1 -0
- package/dist/features/people-memo.js +239 -0
- package/dist/features/people-memo.js.map +1 -0
- package/dist/features/quote-cache.d.ts +19 -0
- package/dist/features/quote-cache.d.ts.map +1 -0
- package/dist/features/quote-cache.js +67 -0
- package/dist/features/quote-cache.js.map +1 -0
- package/dist/features/self-disclosure.d.ts +28 -0
- package/dist/features/self-disclosure.d.ts.map +1 -0
- package/dist/features/self-disclosure.js +60 -0
- package/dist/features/self-disclosure.js.map +1 -0
- package/dist/features/tendency-samples.d.ts +22 -0
- package/dist/features/tendency-samples.d.ts.map +1 -0
- package/dist/features/tendency-samples.js +194 -0
- package/dist/features/tendency-samples.js.map +1 -0
- package/dist/features/thinking-log.d.ts +22 -0
- package/dist/features/thinking-log.d.ts.map +1 -0
- package/dist/features/thinking-log.js +70 -0
- package/dist/features/thinking-log.js.map +1 -0
- package/dist/features/xlsx.d.ts +28 -0
- package/dist/features/xlsx.d.ts.map +1 -0
- package/dist/features/xlsx.js +159 -0
- package/dist/features/xlsx.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +25 -3
- package/dist/session/session-manager.js.map +1 -1
- package/dist/transport/events.d.ts +12 -0
- package/dist/transport/events.d.ts.map +1 -1
- package/dist/transport/events.js +15 -2
- package/dist/transport/events.js.map +1 -1
- package/dist/transport/inbound.d.ts.map +1 -1
- package/dist/transport/inbound.js +344 -20
- package/dist/transport/inbound.js.map +1 -1
- package/dist/transport/outbound-buffer.d.ts.map +1 -1
- package/dist/transport/outbound-buffer.js +8 -0
- package/dist/transport/outbound-buffer.js.map +1 -1
- package/dist/transport/outbound.d.ts +12 -0
- package/dist/transport/outbound.d.ts.map +1 -1
- package/dist/transport/outbound.js +170 -5
- package/dist/transport/outbound.js.map +1 -1
- package/docs/USER-GUIDE.md +429 -0
- package/package.json +2 -1
- package/settings-host.js +154 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* local-signals.ts — 本地小模型算出来的两类"软信号"(2026-09-13 主人定, **观察期只记录不生效**)
|
|
3
|
+
*
|
|
4
|
+
* ① **相关度 (relevance)** —— 给价值闸门补上"当下语境"这一维:
|
|
5
|
+
* · `relReply` = 当前消息 ↔ **她上一条发言** 的余弦(高 = 有人在接她的话)
|
|
6
|
+
* · `relHist` = 当前消息 ↔ 群里最近 5 条 的**最大**余弦(高 = 正接着群里的话题)
|
|
7
|
+
* 现在的样例库分只看"这句话像不像该回", 不看语境 —— 于是"测试"这类闲聊能被抬到 0.738。
|
|
8
|
+
* ⚠️ 只记录进 `value-scores.jsonl`(relReply/relHist/final), **不参与判定** ——
|
|
9
|
+
* 先跑一两天看分布, 再决定权重与阈值(与"log → block"同一套路)。
|
|
10
|
+
*
|
|
11
|
+
* ② **好感度 (affinity)** —— 每人一条台账, 记「互动 / 被点名 / 接话」三项客观计数,
|
|
12
|
+
* 熟度分数**读的时候现算**(公式透明可解释), 同样**只统计不生效**。
|
|
13
|
+
* 存储: `{dataRoot}/.qqbot/affinity.json`
|
|
14
|
+
*
|
|
15
|
+
* 全部本机嵌入, **零 token、不上传**。
|
|
16
|
+
*/
|
|
17
|
+
import { readFileSync, writeFileSync, mkdirSync, statSync } from 'node:fs';
|
|
18
|
+
import { dirname, join } from 'node:path';
|
|
19
|
+
import { createLocalEmbedder } from './local-embed.js';
|
|
20
|
+
import { lastBotReplyOf } from './bot-reply-memo.js';
|
|
21
|
+
import { EMO_LABELS, EMO_SAMPLES } from './emo-samples.js';
|
|
22
|
+
import { TENDENCY_LABELS, TENDENCY_SAMPLES } from './tendency-samples.js';
|
|
23
|
+
/** 历史条目向量缓存(同一条消息只嵌一次): key = `${gid}|${messageId}` */
|
|
24
|
+
const embCache = new Map();
|
|
25
|
+
const EMB_CACHE_MAX = 300;
|
|
26
|
+
function cosine(a, b) {
|
|
27
|
+
const n = Math.min(a.length, b.length);
|
|
28
|
+
let dot = 0;
|
|
29
|
+
let na = 0;
|
|
30
|
+
let nb = 0;
|
|
31
|
+
for (let i = 0; i < n; i += 1) {
|
|
32
|
+
dot += a[i] * b[i];
|
|
33
|
+
na += a[i] * a[i];
|
|
34
|
+
nb += b[i] * b[i];
|
|
35
|
+
}
|
|
36
|
+
if (na === 0 || nb === 0)
|
|
37
|
+
return 0;
|
|
38
|
+
return dot / (Math.sqrt(na) * Math.sqrt(nb));
|
|
39
|
+
}
|
|
40
|
+
const round3 = (v) => Math.round(v * 1000) / 1000;
|
|
41
|
+
/**
|
|
42
|
+
* 算相关度。模型不可用/文本为空 → undefined(调用方照常记录其它字段)。
|
|
43
|
+
* @param history 群历史缓冲(`mwState.history`),只取最后 5 条有效文本
|
|
44
|
+
*/
|
|
45
|
+
export async function computeRelevance(opts) {
|
|
46
|
+
const cur = String(opts.currentText || '').trim();
|
|
47
|
+
if (!cur || !opts.gid)
|
|
48
|
+
return undefined;
|
|
49
|
+
try {
|
|
50
|
+
const embedder = createLocalEmbedder({ modelDir: opts.modelDir, logger: opts.logger });
|
|
51
|
+
if (!embedder.available())
|
|
52
|
+
return undefined;
|
|
53
|
+
const qv = await embedder.embedQuery(cur);
|
|
54
|
+
if (!qv || qv.length === 0)
|
|
55
|
+
return undefined;
|
|
56
|
+
const out = {};
|
|
57
|
+
// ① 她上一条发言
|
|
58
|
+
const last = lastBotReplyOf(opts.gid);
|
|
59
|
+
if (last?.text) {
|
|
60
|
+
const v = await embedder.embedPassages([last.text]);
|
|
61
|
+
if (v?.[0])
|
|
62
|
+
out.relReply = round3(cosine(qv, v[0]));
|
|
63
|
+
}
|
|
64
|
+
// ② 群里最近 5 条(带缓存: 同一条消息不重复嵌)
|
|
65
|
+
const recent = (opts.history ?? [])
|
|
66
|
+
.map((h) => ({ id: String(h.messageId || ''), text: String(h.content || '').trim() }))
|
|
67
|
+
.filter((h) => h.text)
|
|
68
|
+
.slice(-5);
|
|
69
|
+
if (recent.length > 0) {
|
|
70
|
+
const miss = [];
|
|
71
|
+
for (const h of recent) {
|
|
72
|
+
const key = `${opts.gid}|${h.id || h.text.slice(0, 40)}`;
|
|
73
|
+
if (!embCache.has(key))
|
|
74
|
+
miss.push(h.text);
|
|
75
|
+
}
|
|
76
|
+
if (miss.length > 0) {
|
|
77
|
+
const vecs = await embedder.embedPassages(miss);
|
|
78
|
+
if (vecs) {
|
|
79
|
+
let mi = 0;
|
|
80
|
+
for (const h of recent) {
|
|
81
|
+
const key = `${opts.gid}|${h.id || h.text.slice(0, 40)}`;
|
|
82
|
+
if (embCache.has(key))
|
|
83
|
+
continue;
|
|
84
|
+
const v = vecs[mi];
|
|
85
|
+
mi += 1;
|
|
86
|
+
if (v) {
|
|
87
|
+
embCache.set(key, v);
|
|
88
|
+
if (embCache.size > EMB_CACHE_MAX) {
|
|
89
|
+
const first = embCache.keys().next().value;
|
|
90
|
+
if (first)
|
|
91
|
+
embCache.delete(first);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
let best = -1;
|
|
98
|
+
for (const h of recent) {
|
|
99
|
+
const v = embCache.get(`${opts.gid}|${h.id || h.text.slice(0, 40)}`);
|
|
100
|
+
if (!v)
|
|
101
|
+
continue;
|
|
102
|
+
const c = cosine(qv, v);
|
|
103
|
+
if (c > best)
|
|
104
|
+
best = c;
|
|
105
|
+
}
|
|
106
|
+
if (best >= 0)
|
|
107
|
+
out.relHist = round3(best);
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
opts.logger?.debug(`[相关度] 计算失败(忽略): ${err instanceof Error ? err.message : String(err)}`);
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const affCache = new Map();
|
|
117
|
+
function affPath(dataRoot) {
|
|
118
|
+
return join(dataRoot, '.qqbot', 'affinity.json');
|
|
119
|
+
}
|
|
120
|
+
function loadAff(dataRoot) {
|
|
121
|
+
// ⚠️ 2026-09-14:缓存要认 mtime —— 文件被外部改了(手工调数据/换工具改)就重读,
|
|
122
|
+
// 否则运行中的进程一直用旧值(上午踩过:清了旧键,旧键又被缓存写回"复活")。
|
|
123
|
+
let mtime = 0;
|
|
124
|
+
try {
|
|
125
|
+
mtime = statSync(affPath(dataRoot)).mtimeMs;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
mtime = 0;
|
|
129
|
+
}
|
|
130
|
+
const hit = affCache.get(dataRoot);
|
|
131
|
+
if (hit && mtime !== 0 && hit.mtime === mtime)
|
|
132
|
+
return hit.file;
|
|
133
|
+
let data = { map: {} };
|
|
134
|
+
try {
|
|
135
|
+
const raw = JSON.parse(readFileSync(affPath(dataRoot), 'utf8'));
|
|
136
|
+
if (raw && typeof raw === 'object' && raw.map && typeof raw.map === 'object') {
|
|
137
|
+
// 2026-09-14 迁移:**只认"按人"键(person:)**。
|
|
138
|
+
// 旧版曾按「群」记(一整个群算成一个人,名字取最后一个发言人)→ 面板上同一个人会显示好几次
|
|
139
|
+
// (实测"做早饭"出现 3 次:person: + 两代 group: 键并存)。
|
|
140
|
+
// 在这里丢弃旧格式键:读进来就干净;下一次 saveAff 会把文件一并写干净 —— 不用手工清文件
|
|
141
|
+
// (手工清没用:进程内存里的缓存会随后把旧键写回去)。
|
|
142
|
+
const map = {};
|
|
143
|
+
for (const [k, v] of Object.entries(raw.map)) {
|
|
144
|
+
if (k.startsWith('person:'))
|
|
145
|
+
map[k] = v;
|
|
146
|
+
}
|
|
147
|
+
data = { map };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch { /* 首次/损坏 → 空台账 */ }
|
|
151
|
+
affCache.set(dataRoot, { file: data, mtime });
|
|
152
|
+
return data;
|
|
153
|
+
}
|
|
154
|
+
function saveAff(dataRoot, data) {
|
|
155
|
+
try {
|
|
156
|
+
const p = affPath(dataRoot);
|
|
157
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
158
|
+
writeFileSync(p, JSON.stringify(data, null, 1), 'utf8');
|
|
159
|
+
}
|
|
160
|
+
catch { /* 记不上不影响主链 */ }
|
|
161
|
+
}
|
|
162
|
+
/** 记一次互动(每条群消息调一次; 只统计, 不生效) */
|
|
163
|
+
export function touchAffinity(dataRoot, key, opts = {}) {
|
|
164
|
+
if (!dataRoot || !key)
|
|
165
|
+
return;
|
|
166
|
+
try {
|
|
167
|
+
const data = loadAff(dataRoot);
|
|
168
|
+
const now = Date.now();
|
|
169
|
+
const cur = data.map[key] ?? { msgs: 0, mentions: 0, replies: 0, firstAt: now, lastAt: now };
|
|
170
|
+
cur.msgs += 1;
|
|
171
|
+
if (opts.mention)
|
|
172
|
+
cur.mentions += 1;
|
|
173
|
+
if (opts.reply)
|
|
174
|
+
cur.replies += 1;
|
|
175
|
+
// 记忆曲线(2026-09-13 主人定; 经主人两次纠正后定稿):
|
|
176
|
+
// **复习 = 当天第一次出现**(一天最多算一次) —— 刷屏不会多算, 复习次数≈"来过几天"。
|
|
177
|
+
// 强度每次互动都回满(衰减从最后一次互动算起); 曲线本体在 memoryStrength() 里。
|
|
178
|
+
// ⚠️ 2026-09-14 修:原来用 `toISOString()` = **UTC 日期** —— 北京时间早上 8 点前仍算"昨天",
|
|
179
|
+
// 于是"今天来过没有"会在早上 8 点整莫名翻页(同一天被切成两段 → reviews 虚高/漏算)。
|
|
180
|
+
// 改成**本地日期**(YYYY-MM-DD)。
|
|
181
|
+
const day = localDayKey(now);
|
|
182
|
+
if ((cur.lastReviewDay ?? '') !== day) {
|
|
183
|
+
cur.reviews = (cur.reviews ?? 0) + 1;
|
|
184
|
+
cur.lastReviewDay = day;
|
|
185
|
+
}
|
|
186
|
+
cur.strength = 1; // 刚有互动 → 强度回满
|
|
187
|
+
if (opts.name)
|
|
188
|
+
cur.name = String(opts.name).slice(0, 40);
|
|
189
|
+
cur.lastAt = now;
|
|
190
|
+
data.map[key] = cur;
|
|
191
|
+
saveAff(dataRoot, data);
|
|
192
|
+
}
|
|
193
|
+
catch { /* ignore */ }
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* 熟度分数(0~100) —— 读的时候现算, 公式保持透明可解释:
|
|
197
|
+
* 互动分 = 20×log10(1+msgs)/log10(101) (100 条 ≈ 20 分)
|
|
198
|
+
* 点名分 = min(20, mentions×2)
|
|
199
|
+
* 接话分 = min(30, replies×3)
|
|
200
|
+
* 新鲜度 = 1 小时内 +10 / 1 天内 +5 / 更久 0
|
|
201
|
+
*
|
|
202
|
+
* ⚠️ 2026-09-13 修(群友"亚瑟"读码抓到): 互动分原用 20×log10(1+msgs)/log10(101) 是**发散**的
|
|
203
|
+
* (实测 msgs=1000 → 29.9 分、10 万 → 49.9 分、10 亿 → 89.8 分; 注释写"100 条≈20 分"容易被当成上限)。
|
|
204
|
+
* 现改**饱和式**(希尔/米氏形式): 20×msgs/(msgs+40) —— **40 条 = 拿一半分, 上限 20**, 刷不出高分。
|
|
205
|
+
*/
|
|
206
|
+
/**
|
|
207
|
+
* 记忆强度(0~1)—— 2026-09-13 主人定:**按记忆曲线遗忘**,不是"只升不降"的功劳榜。
|
|
208
|
+
*
|
|
209
|
+
* 模型(艾宾浩斯式;**公式以下方代码为准**,这里只讲形状,免得注释又比代码旧):
|
|
210
|
+
* S = floor + max(top - floor, 0) × exp(-Δt / τ)
|
|
211
|
+
* · top (熟悉度上限):以"来过天数"为主、被点名/接话为辅,对数饱和(刷屏涨不动)
|
|
212
|
+
* · floor(遗忘下限):随复习次数抬高(上限 0.6)—— 老熟人久别重逢也掉不回陌生
|
|
213
|
+
* · τ (遗忘时间常数):随复习次数拉长 —— 间隔效应,越熟忘得越慢
|
|
214
|
+
* · Δt:距**上次复习**(上次互动)的天数;每次互动 = 一次复习 → 强度回满
|
|
215
|
+
*
|
|
216
|
+
* ⚠️ 只做**遗忘**,不做惩罚:分数不会因为"说错话"被扣。
|
|
217
|
+
* "降低好感度"是另一套机制(负面事件),暂不实现(主人 2026-09-13 明确区分)。
|
|
218
|
+
* ⚠️ 2026-09-13:这段注释曾抄着**旧版公式**(τ=2天×(1+reviews/20)、fam 系数 0.40)与代码不符,
|
|
219
|
+
* 现改为只描述形状;具体系数与定标过程见 memoryStrength 函数体。
|
|
220
|
+
*/
|
|
221
|
+
/**
|
|
222
|
+
* 有效"来过天数"(算分与显示共用同一口径, 2026-09-13 修):
|
|
223
|
+
* · 老台账没有 lastReviewDay → 按认识天数估
|
|
224
|
+
* · **硬约束: 来过天数不可能超过认识天数**(发 85 条也不等于来过 85 天)
|
|
225
|
+
*/
|
|
226
|
+
/** 本地日期键(YYYY-MM-DD)—— 别用 `toISOString()`:那是 UTC,北京时间早 8 点会莫名翻页 */
|
|
227
|
+
function localDayKey(ts) {
|
|
228
|
+
const d = new Date(ts);
|
|
229
|
+
const p = (n) => String(n).padStart(2, '0');
|
|
230
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`;
|
|
231
|
+
}
|
|
232
|
+
/** 本地"自然日序号"(同一天相同;用来数"跨了几个自然日") */
|
|
233
|
+
function localDayIndex(ts) {
|
|
234
|
+
const d = new Date(ts);
|
|
235
|
+
return Math.floor((ts - d.getTimezoneOffset() * 60_000) / 86400_000);
|
|
236
|
+
}
|
|
237
|
+
export function effectiveReviews(e, now = Date.now()) {
|
|
238
|
+
// ⚠️ 2026-09-14 修(主人问"我应该算来过两天了吧"):
|
|
239
|
+
// 原来 daysKnown 按 **24 小时整倍** 算(floor(Δt/86400_000)+1)—— 昨晚 20:47 首次来、
|
|
240
|
+
// 今早 08:50 再来,明明跨了两个自然日,却只算 1 天 → reviews=2 被硬约束压回 1,
|
|
241
|
+
// 面板就显示"来过 1 天"。改成按**自然日**算。
|
|
242
|
+
const daysKnown = Math.max(1, localDayIndex(now) - localDayIndex(e.firstAt ?? now) + 1);
|
|
243
|
+
const raw = e.lastReviewDay ? (e.reviews ?? 1) : Math.min(e.msgs ?? 1, daysKnown);
|
|
244
|
+
return Math.max(1, Math.min(raw, daysKnown));
|
|
245
|
+
}
|
|
246
|
+
export function memoryStrength(e, now = Date.now()) {
|
|
247
|
+
// ⚠️ 2026-09-13 修(主人:"怎么来过涨这么多, 我们才写插件没多久"):
|
|
248
|
+
// 原来拿 msgs 当复习次数兜底 → 发 85 条就显示"来过 85 天"(认识才一天, 物理不可能)。
|
|
249
|
+
// 现在加**硬约束: 来过天数不可能超过认识天数**; 老台账(没有 lastReviewDay 字段)按认识天数估算。
|
|
250
|
+
const reviews = effectiveReviews(e, now);
|
|
251
|
+
const lastReview = e.lastReview ?? e.lastAt ?? now;
|
|
252
|
+
// ⚠️ 2026-09-13 修(主人实测"怎么全是 100"): 原来"刚聊过 = 强度 1 = 满分", 人人 100 没区分度。
|
|
253
|
+
// 现在分两层: **熟悉度 fam**(累积决定上限) + **遗忘**(时间衰减, 下限随复习抬高)。
|
|
254
|
+
// fam = min(1, 0.40×log10(1+reviews) + 0.10) 1 天≈0.22 / 7 天≈0.46(眼熟) / 45 天≈0.77(熟人) / 100 天≈0.90
|
|
255
|
+
// floor = min(0.6, 0.15×log10(1+reviews)) 复习越多, 忘到底也留得越多(老熟人不回陌生)
|
|
256
|
+
// τ = 2 天 ×(1 + reviews/20) 间隔效应: 越熟忘得越慢
|
|
257
|
+
// S = floor + (fam - floor) × exp(-Δt/τ) —— 刚聊完≈fam(新人就是低), 久不聊沉到 floor
|
|
258
|
+
// ⚠️ 2026-09-13 主人定标:「45 天熟人就够了」—— 系数按此校准(来过 45 天 ≈ 0.77 → 过 0.7 门槛)
|
|
259
|
+
// 来过 1 天≈0.22(陌生) / 7 天≈0.46(眼熟) / 45 天≈0.77(熟人) / 100 天≈0.90
|
|
260
|
+
// ⚠️ 2026-09-13 主人两次校准后定稿("说一句话不可能就有 22% 熟识" + "45 天熟人就够了"):
|
|
261
|
+
// 来过天数为主 + 被点名/接话为辅(质量信号), 基础 0.02 ——
|
|
262
|
+
// 新人 1 天说 1 句 ≈ 0.09; 7 天 ≈ 0.27; 45 天 ≈ 0.52; 45 天+常被点名接话 → 0.70+(熟人); 100 天 ≈ 0.63
|
|
263
|
+
const fam = Math.min(1, 0.28 * Math.log10(1 + reviews)
|
|
264
|
+
+ 0.15 * Math.log10(1 + Math.max(0, e.mentions ?? 0))
|
|
265
|
+
+ 0.15 * Math.log10(1 + Math.max(0, e.replies ?? 0))
|
|
266
|
+
+ 0.02);
|
|
267
|
+
const floor = Math.min(0.6, 0.15 * Math.log10(1 + reviews));
|
|
268
|
+
const top = Math.max(fam, floor);
|
|
269
|
+
const tauDays = 3 * (1 + reviews / 10); // 来过 10 天 → 时间常数 6 天; 来过 50 天 → 18 天
|
|
270
|
+
const dtDays = Math.max(0, (now - lastReview) / 86400_000);
|
|
271
|
+
const s = floor + (top - floor) * Math.exp(-dtDays / tauDays);
|
|
272
|
+
return Math.max(0, Math.min(1, s));
|
|
273
|
+
}
|
|
274
|
+
/** 档位(滞回:进档门槛高于退档,防止抖动) */
|
|
275
|
+
export function memoryTier(strength, prevTier) {
|
|
276
|
+
const enterHot = 0.7;
|
|
277
|
+
const keepHot = 0.55;
|
|
278
|
+
const enterWarm = 0.4;
|
|
279
|
+
const keepWarm = 0.28;
|
|
280
|
+
if (prevTier === '熟人')
|
|
281
|
+
return strength >= keepHot ? '熟人' : strength >= keepWarm ? '眼熟' : '陌生人';
|
|
282
|
+
if (prevTier === '眼熟')
|
|
283
|
+
return strength >= enterHot ? '熟人' : strength >= keepWarm ? '眼熟' : '陌生人';
|
|
284
|
+
return strength >= enterHot ? '熟人' : strength >= enterWarm ? '眼熟' : '陌生人';
|
|
285
|
+
}
|
|
286
|
+
/** 0~100 分(= 记忆强度 × 100;面板与排序沿用它,语义已从"功劳榜"改为"记忆强度") */
|
|
287
|
+
export function affinityScore(e, now = Date.now()) {
|
|
288
|
+
return Math.round(memoryStrength(e, now) * 100);
|
|
289
|
+
}
|
|
290
|
+
/** 取某人的台账条目(好感度聚合要用它的熟识度算阻尼与范围) */
|
|
291
|
+
export function getAffinityEntry(dataRoot, key) {
|
|
292
|
+
return loadAff(dataRoot).map[key];
|
|
293
|
+
}
|
|
294
|
+
/** 按熟度排序(面板/工具用) */
|
|
295
|
+
export function topAffinity(dataRoot, limit = 10) {
|
|
296
|
+
const data = loadAff(dataRoot);
|
|
297
|
+
const now = Date.now();
|
|
298
|
+
return Object.entries(data.map)
|
|
299
|
+
.map(([key, e]) => ({ key, name: e.name, score: affinityScore(e, now), tier: memoryTier(memoryStrength(e, now)), reviews: effectiveReviews(e, now), msgs: e.msgs, mentions: e.mentions, replies: e.replies, lastAt: e.lastAt }))
|
|
300
|
+
.sort((a, b) => b.score - a.score)
|
|
301
|
+
.slice(0, limit);
|
|
302
|
+
}
|
|
303
|
+
// ─────────── ③ 情绪粗分类(夸 / 骂 / 中性, 2026-09-13 主人给的例句库) ───────────
|
|
304
|
+
/**
|
|
305
|
+
* 用**同一个本地小模型**判"这句话是夸、骂还是中性":
|
|
306
|
+
* 把三组例句各嵌一次(缓存), 新文本嵌入后跟每组求平均相似度, 取最高的那组。
|
|
307
|
+
* ⚠️ 只做**弱信号**: 反讽/互怼/引用会误判 → 观察期只记录, 不参与行为。
|
|
308
|
+
*/
|
|
309
|
+
/**
|
|
310
|
+
* 判定打分方式(2026-09-14 主人要求"重新添加样本测试一下"之后的实测结论)。
|
|
311
|
+
*
|
|
312
|
+
* · `centroid` = 每组例句取**平均向量**(原做法)
|
|
313
|
+
* · `knn` = 每组取**最相似的 K 条**,平均相似度(现做法)
|
|
314
|
+
*
|
|
315
|
+
* 为什么换:质心会把一组的几十条例句揉成"平均意思",样本越杂越糊 ——
|
|
316
|
+
* 实测把"没点名我,静默"判成「拒绝」、把 141 字热情卖萌正文判成「冷」、
|
|
317
|
+
* 把工具参数里的「…需回应」判成「拒绝」(这三条都在 m1/eval 里钉成回归样本)。
|
|
318
|
+
* kNN 不做平均,直接看"这句话最像组里的哪几句",边界句不再被离群样本拖走。
|
|
319
|
+
*
|
|
320
|
+
* 回滚:把它改回 `'centroid'` 即可(其余代码一行不用动)。
|
|
321
|
+
* 复跑:`node m1/judge-eval.mjs --kind tendency|emo`(改样本/改门槛后都跑一遍)。
|
|
322
|
+
*/
|
|
323
|
+
export const CLASSIFY_SCORE_MODE = 'knn';
|
|
324
|
+
/** 每类取最相似的 K 条平均(k=3:覆盖同类不同说法,又不至于被单个离群样本带跑) */
|
|
325
|
+
const KNN_K = 3;
|
|
326
|
+
const emoCentroidCache = new Map();
|
|
327
|
+
/** 倾向例库的向量缓存 —— ⚠️ 键必须带语言前缀(zh/en 两套库, 不能混) */
|
|
328
|
+
const tendencyCentroidCache = new Map();
|
|
329
|
+
/**
|
|
330
|
+
* 通用「例句库」打分(模式见 CLASSIFY_SCORE_MODE)。
|
|
331
|
+
* 每组例句各嵌一次并**全部缓存**(knn 模式需要原向量,不能只存质心),文本嵌入后与每组比。
|
|
332
|
+
* 返回每组得分; 模型不可用或嵌入失败 → undefined。
|
|
333
|
+
* ⚠️ 缓存键必须带前缀/语言(emo 一套, ten:zh / ten:en 各一套), 否则向量会互相污染。
|
|
334
|
+
*/
|
|
335
|
+
async function centroidScores(text, groups, cache, cachePrefix, opts) {
|
|
336
|
+
try {
|
|
337
|
+
const embedder = createLocalEmbedder({ modelDir: opts.modelDir, logger: opts.logger });
|
|
338
|
+
if (!embedder.available())
|
|
339
|
+
return undefined;
|
|
340
|
+
const qv = await embedder.embedQuery(text);
|
|
341
|
+
if (!qv || qv.length === 0)
|
|
342
|
+
return undefined;
|
|
343
|
+
const scores = {};
|
|
344
|
+
for (const { label, samples } of groups) {
|
|
345
|
+
const key = `${cachePrefix}:${label}`;
|
|
346
|
+
let c = cache.get(key);
|
|
347
|
+
if (!c) {
|
|
348
|
+
const vs = await embedder.embedPassages([...samples]);
|
|
349
|
+
if (!vs || vs.length === 0)
|
|
350
|
+
continue;
|
|
351
|
+
c = { vecs: vs.map((v) => [...v]) };
|
|
352
|
+
cache.set(key, c);
|
|
353
|
+
}
|
|
354
|
+
if (c.vecs.length === 0)
|
|
355
|
+
continue;
|
|
356
|
+
if (CLASSIFY_SCORE_MODE === 'knn') {
|
|
357
|
+
// 每类取最像的 K 条平均 —— 边界句能靠"最像的那一句"救回来
|
|
358
|
+
const sims = c.vecs
|
|
359
|
+
.map((v) => cosine(qv, v))
|
|
360
|
+
.sort((a, b) => b - a)
|
|
361
|
+
.slice(0, KNN_K);
|
|
362
|
+
scores[label] = sims.reduce((a, b) => a + b, 0) / sims.length;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
const dim = c.vecs[0].length;
|
|
366
|
+
const vec = new Array(dim).fill(0);
|
|
367
|
+
for (const v of c.vecs)
|
|
368
|
+
for (let i = 0; i < dim; i++)
|
|
369
|
+
vec[i] = (vec[i] ?? 0) + (v[i] ?? 0) / c.vecs.length;
|
|
370
|
+
scores[label] = cosine(qv, vec);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return Object.keys(scores).length > 0 ? scores : undefined;
|
|
374
|
+
}
|
|
375
|
+
catch (err) {
|
|
376
|
+
opts.logger?.debug(`[例句打分] 失败(忽略): ${err instanceof Error ? err.message : String(err)}`);
|
|
377
|
+
return undefined;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
/** 取最高组 + 与第二名的差(统一三位小数, 便于事后核对) */
|
|
381
|
+
function rankOf(scores) {
|
|
382
|
+
const ranked = Object.entries(scores).sort((a, b) => b[1] - a[1]);
|
|
383
|
+
const best = ranked[0];
|
|
384
|
+
if (best === undefined)
|
|
385
|
+
return undefined;
|
|
386
|
+
const second = ranked[1];
|
|
387
|
+
return { label: best[0], best: round3(best[1]), margin: round3(best[1] - (second ? second[1] : 0)) };
|
|
388
|
+
}
|
|
389
|
+
export async function classifyEmo(text, opts = {}) {
|
|
390
|
+
const s = String(text || '').trim();
|
|
391
|
+
if (!s)
|
|
392
|
+
return undefined;
|
|
393
|
+
const groups = EMO_LABELS.map((l) => ({ label: String(l), samples: EMO_SAMPLES[l] }));
|
|
394
|
+
const scores = await centroidScores(s, groups, emoCentroidCache, 'emo', opts);
|
|
395
|
+
if (scores === undefined)
|
|
396
|
+
return undefined;
|
|
397
|
+
const top = rankOf(scores);
|
|
398
|
+
if (top === undefined)
|
|
399
|
+
return undefined;
|
|
400
|
+
return { label: top.label, best: top.best, margin: top.margin, scores };
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* 按 CJK 占比判语言: ≥0.6 判中文 / ≤0.25 判英文 / 中间=中英混杂 → undefined(跳过不判)。
|
|
404
|
+
* 只数"汉字"与"拉丁字母", 标点、数字、空格、表情都不参与。
|
|
405
|
+
* 阈值放宽的理由: 她的思考常夹英文术语("先 reply 他"), 只要中文为主仍按中文库判;
|
|
406
|
+
* 真·对半开才跳过 —— 小模型的英文语义质量差, 判了不如空着(设计稿: 不确定就不动分)。
|
|
407
|
+
*/
|
|
408
|
+
export function detectScript(text) {
|
|
409
|
+
let cjk = 0;
|
|
410
|
+
let latin = 0;
|
|
411
|
+
for (const ch of String(text || '')) {
|
|
412
|
+
const c = ch.codePointAt(0) ?? 0;
|
|
413
|
+
if (c >= 0x4e00 && c <= 0x9fff)
|
|
414
|
+
cjk += 1;
|
|
415
|
+
else if ((c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a))
|
|
416
|
+
latin += 1;
|
|
417
|
+
}
|
|
418
|
+
const total = cjk + latin;
|
|
419
|
+
if (total < 3)
|
|
420
|
+
return undefined;
|
|
421
|
+
const r = cjk / total;
|
|
422
|
+
if (r >= 0.6)
|
|
423
|
+
return 'zh';
|
|
424
|
+
if (r <= 0.25)
|
|
425
|
+
return 'en';
|
|
426
|
+
return undefined;
|
|
427
|
+
}
|
|
428
|
+
export async function classifyTendency(text, opts = {}) {
|
|
429
|
+
const s = String(text || '').trim();
|
|
430
|
+
if (!s)
|
|
431
|
+
return undefined;
|
|
432
|
+
const lang = detectScript(s);
|
|
433
|
+
if (lang === undefined)
|
|
434
|
+
return undefined;
|
|
435
|
+
const groups = TENDENCY_LABELS.map((l) => ({ label: String(l), samples: TENDENCY_SAMPLES[l][lang] }));
|
|
436
|
+
// 思考可能上千字, 取前 800 字(判断通常落在开头; 也避开模型 512 token 窗口的尾部丢失)
|
|
437
|
+
const scores = await centroidScores(s.slice(0, 800), groups, tendencyCentroidCache, `ten:${lang}`, opts);
|
|
438
|
+
if (scores === undefined)
|
|
439
|
+
return undefined;
|
|
440
|
+
const top = rankOf(scores);
|
|
441
|
+
if (top === undefined)
|
|
442
|
+
return undefined;
|
|
443
|
+
return { label: top.label, best: top.best, margin: top.margin, scores, lang };
|
|
444
|
+
}
|
|
445
|
+
//# sourceMappingURL=local-signals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-signals.js","sourceRoot":"","sources":["../../src/features/local-signals.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** 归档阈值(天): 小传最后修改超过这么久 → 沉底(仍在文件里, 只是不再优先召回) */
|
|
2
|
+
export declare const MEMO_ARCHIVE_DAYS = 30;
|
|
3
|
+
export declare function peopleDirOf(dataRoot: string): string;
|
|
4
|
+
export declare function memoPathOf(dataRoot: string, key: string): string;
|
|
5
|
+
export declare function readMemo(dataRoot: string, key: string): string | undefined;
|
|
6
|
+
/** 列出全部小传(按最后修改时间新→旧) */
|
|
7
|
+
export declare function listMemos(dataRoot: string): Array<{
|
|
8
|
+
key: string;
|
|
9
|
+
path: string;
|
|
10
|
+
bytes: number;
|
|
11
|
+
mtime: number;
|
|
12
|
+
archived: boolean;
|
|
13
|
+
}>;
|
|
14
|
+
/** 今天已经记了几条(含栏位条目) */
|
|
15
|
+
export declare function countWroteToday(key: string, now?: number): number;
|
|
16
|
+
/** 兼容旧签名:今天是否已经记过(旧版按文件 mtime 判断,一天一条) */
|
|
17
|
+
export declare function wroteToday(_dataRoot: string, key: string, now?: number): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* 追加一条。两种落法:
|
|
20
|
+
* · 带栏目前缀("喜好:…")→ 归到八栏(该栏已有一行 → 行尾用";"并进去,保持"每栏一行"的摘要形态)
|
|
21
|
+
* · 不带前缀 → 进「## 记事」区(带日期,现状不变)
|
|
22
|
+
* 节流:**同一人一天最多 3 条**(2026-09-14 放宽;原为 1 条,"只记一条怎么记得完")。
|
|
23
|
+
*/
|
|
24
|
+
export declare function appendMemoLine(dataRoot: string, key: string, line: string, opts?: {
|
|
25
|
+
name?: string;
|
|
26
|
+
force?: boolean;
|
|
27
|
+
}): {
|
|
28
|
+
ok: boolean;
|
|
29
|
+
msg: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* 取该小传里最适合注入的 1~2 行: 有嵌入器就按"与当前消息最相关"排, 没有就取最近两条。
|
|
33
|
+
* 若整份小传已归档(30 天没更新) → 不注入(沉底)。
|
|
34
|
+
*/
|
|
35
|
+
export declare function recallLines(dataRoot: string, key: string, query: string, embed?: {
|
|
36
|
+
available(): boolean;
|
|
37
|
+
embedQuery(t: string): Promise<number[] | undefined>;
|
|
38
|
+
embedPassages(t: string[]): Promise<number[][] | undefined>;
|
|
39
|
+
}, topN?: number): Promise<{
|
|
40
|
+
lines: string[];
|
|
41
|
+
archived: boolean;
|
|
42
|
+
}>;
|
|
43
|
+
/** 删掉整段小传(群里一句"别记人家" → 立刻执行 + 回执) */
|
|
44
|
+
export declare function deleteMemo(dataRoot: string, key: string): {
|
|
45
|
+
ok: boolean;
|
|
46
|
+
msg: string;
|
|
47
|
+
};
|
|
48
|
+
/** inbound 算好小传注入行后调用(90 秒内有效) */
|
|
49
|
+
export declare function setPendingMemo(text: string): void;
|
|
50
|
+
/** 供 systemPrompt.context 的 text 提供者调用:过期/为空则返回 ''(不贡献内容) */
|
|
51
|
+
export declare function takePendingMemoText(): string;
|
|
52
|
+
//# sourceMappingURL=people-memo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"people-memo.d.ts","sourceRoot":"","sources":["../../src/features/people-memo.ts"],"names":[],"mappings":"AAeA,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAOD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO1E;AAED,yBAAyB;AACzB,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAoBjI;AAQD,sBAAsB;AACtB,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,MAAM,CAIrE;AAED,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,OAAO,CAEpF;AA+BD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC5C;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAiD9B;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;IAAE,SAAS,IAAI,OAAO,CAAC;IAAC,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IAAC,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,SAAS,CAAC,CAAA;CAAE,EACnJ,IAAI,SAAI,GACP,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CA8BjD;AAED,qCAAqC;AACrC,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAStF;AAUD,kCAAkC;AAClC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGjD;AAED,6DAA6D;AAC7D,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C"}
|