079project 1.0.0 → 2.0.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/GroupStarter.cjs +211 -35
- package/README.md +3 -3
- package/loggerworker.cjs +202 -0
- package/main_Serve.cjs +157 -66
- package/main_Study.cjs +217 -68
- package/package.json +1 -1
- package/todo-list.txt +86 -0
- package/wikitext/wikitext-103-all.txt +0 -0
- package/wikitext/.gitattributes +0 -27
- package/wikitext/README.md +0 -344
- package/wikitext/describtion.txt +0 -1
package/main_Study.cjs
CHANGED
|
@@ -79,6 +79,7 @@ async function batchAddPoints(graph, pointsArr, batchSize = 500) {
|
|
|
79
79
|
await new Promise(resolve => setImmediate(resolve));
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
+
/*
|
|
82
83
|
// 反触发机制
|
|
83
84
|
async function antiTrigger(onContinue, onExit) {
|
|
84
85
|
const PORT = global.config.emitExitport || 8641;
|
|
@@ -145,6 +146,7 @@ async function antiTrigger(onContinue, onExit) {
|
|
|
145
146
|
}, 10000);
|
|
146
147
|
}
|
|
147
148
|
}
|
|
149
|
+
*/
|
|
148
150
|
function verifySystemConsistency(sourceRuntime, targetRuntime) {
|
|
149
151
|
console.log('[VERIFY] 开始验证系统一致性...');
|
|
150
152
|
console.log(`[VERIFY] 源词表大小: ${sourceRuntime.vocabManager.vocab.length}, 目标: ${targetRuntime.vocabManager.vocab.length}`);
|
|
@@ -163,12 +165,104 @@ const readline = require('readline');
|
|
|
163
165
|
|
|
164
166
|
app.use(bodyParser.json());
|
|
165
167
|
app.use(bodyParser.urlencoded({ extended: true }));
|
|
168
|
+
// ...existing code...
|
|
166
169
|
app.use(express.static(path.join(__dirname, 'public')));
|
|
167
170
|
|
|
168
171
|
// 持久化路径
|
|
169
172
|
const SAVE_PATH = path.join(__dirname, 'runtime_data.json');
|
|
170
173
|
|
|
171
|
-
|
|
174
|
+
// 新增:会话管理器(以对话为尺度管理记忆)
|
|
175
|
+
class SessionManager {
|
|
176
|
+
constructor({ idleMs = 10 * 60 * 1000, maxSessions = 200 } = {}) {
|
|
177
|
+
this.idleMs = idleMs; // 会话空闲超时,自动切新会话
|
|
178
|
+
this.maxSessions = maxSessions; // 最近保留的会话数量上限(用于遗忘窗口)
|
|
179
|
+
this.sessions = new Map(); // sessionId -> { start, lastActivity, messageCount }
|
|
180
|
+
this.current = null;
|
|
181
|
+
}
|
|
182
|
+
now() { return Date.now(); }
|
|
183
|
+
_newId() { return `S${Date.now()}_${Math.floor(Math.random() * 1e6)}`; }
|
|
184
|
+
|
|
185
|
+
startNewSession(meta = {}) {
|
|
186
|
+
const id = this._newId();
|
|
187
|
+
const ts = this.now();
|
|
188
|
+
this.sessions.set(id, {
|
|
189
|
+
start: ts,
|
|
190
|
+
lastActivity: ts,
|
|
191
|
+
messageCount: 0,
|
|
192
|
+
...meta
|
|
193
|
+
});
|
|
194
|
+
this.current = id;
|
|
195
|
+
this._truncateIfNeeded();
|
|
196
|
+
return id;
|
|
197
|
+
}
|
|
198
|
+
ensureActive() {
|
|
199
|
+
const ts = this.now();
|
|
200
|
+
if (!this.current || !this.sessions.has(this.current)) {
|
|
201
|
+
return this.startNewSession();
|
|
202
|
+
}
|
|
203
|
+
const s = this.sessions.get(this.current);
|
|
204
|
+
if (ts - s.lastActivity > this.idleMs) {
|
|
205
|
+
return this.startNewSession({ reason: 'idle-timeout' });
|
|
206
|
+
}
|
|
207
|
+
return this.current;
|
|
208
|
+
}
|
|
209
|
+
useSession(sessionId) {
|
|
210
|
+
if (!sessionId) return this.ensureActive();
|
|
211
|
+
if (!this.sessions.has(sessionId)) {
|
|
212
|
+
const ts = this.now();
|
|
213
|
+
this.sessions.set(sessionId, { start: ts, lastActivity: ts, messageCount: 0 });
|
|
214
|
+
}
|
|
215
|
+
this.current = sessionId;
|
|
216
|
+
return sessionId;
|
|
217
|
+
}
|
|
218
|
+
touch(sessionId = this.current) {
|
|
219
|
+
if (!sessionId) return;
|
|
220
|
+
const s = this.sessions.get(sessionId);
|
|
221
|
+
if (s) s.lastActivity = this.now();
|
|
222
|
+
}
|
|
223
|
+
incMessage(sessionId = this.current) {
|
|
224
|
+
if (!sessionId) return;
|
|
225
|
+
const s = this.sessions.get(sessionId);
|
|
226
|
+
if (s) {
|
|
227
|
+
s.messageCount = (s.messageCount || 0) + 1;
|
|
228
|
+
s.lastActivity = this.now();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
getActiveSessionId() {
|
|
232
|
+
return this.ensureActive();
|
|
233
|
+
}
|
|
234
|
+
// 返回最近的会话ID(按 lastActivity 降序)
|
|
235
|
+
getRecentSessionIds(limit = this.maxSessions) {
|
|
236
|
+
const entries = Array.from(this.sessions.entries());
|
|
237
|
+
entries.sort((a, b) => (b[1].lastActivity || 0) - (a[1].lastActivity || 0));
|
|
238
|
+
return entries.slice(0, limit).map(([id]) => id);
|
|
239
|
+
}
|
|
240
|
+
_truncateIfNeeded() {
|
|
241
|
+
const ids = this.getRecentSessionIds(this.maxSessions);
|
|
242
|
+
const keep = new Set(ids);
|
|
243
|
+
for (const id of this.sessions.keys()) {
|
|
244
|
+
if (!keep.has(id)) this.sessions.delete(id);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
export() {
|
|
248
|
+
return {
|
|
249
|
+
config: { idleMs: this.idleMs, maxSessions: this.maxSessions },
|
|
250
|
+
current: this.current,
|
|
251
|
+
sessions: Array.from(this.sessions.entries())
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
import(obj) {
|
|
255
|
+
if (!obj) return;
|
|
256
|
+
const { config, current, sessions } = obj;
|
|
257
|
+
if (config) {
|
|
258
|
+
this.idleMs = config.idleMs ?? this.idleMs;
|
|
259
|
+
this.maxSessions = config.maxSessions ?? this.maxSessions;
|
|
260
|
+
}
|
|
261
|
+
this.sessions = new Map(Array.isArray(sessions) ? sessions : []);
|
|
262
|
+
this.current = current || null;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// ...existing code...
|
|
172
266
|
|
|
173
267
|
|
|
174
268
|
class SnapshotManager {
|
|
@@ -232,7 +326,12 @@ class SnapshotManager {
|
|
|
232
326
|
wordGraph: Array.from(this.runtime.wordGraph.points.values()),
|
|
233
327
|
kvm: Array.from(this.runtime.kvm.memory.entries()),
|
|
234
328
|
vocab: this.runtime.vocabManager.vocab,
|
|
235
|
-
|
|
329
|
+
// 修正:序列化为 [word, [[sessionId,count], ...]]
|
|
330
|
+
wordAccessLog: Array.from(this.runtime.wordAccessLog.entries()).map(([w, per]) =>
|
|
331
|
+
[w, per instanceof Map ? Array.from(per.entries()) : (Array.isArray(per) ? [['legacy', per.length]] : [])]
|
|
332
|
+
),
|
|
333
|
+
// 新增:保存会话状态
|
|
334
|
+
sessions: this.runtime.session.export()
|
|
236
335
|
};
|
|
237
336
|
|
|
238
337
|
// 写入临时文件,然后原子重命名以确保数据完整性
|
|
@@ -337,9 +436,25 @@ class SnapshotManager {
|
|
|
337
436
|
// 恢复词访问日志
|
|
338
437
|
console.log('[SNAPSHOT] 恢复词访问日志...');
|
|
339
438
|
if (data.wordAccessLog) {
|
|
340
|
-
|
|
439
|
+
const restored = new Map();
|
|
440
|
+
for (const [word, per] of data.wordAccessLog) {
|
|
441
|
+
if (Array.isArray(per) && per.length > 0 && Array.isArray(per[0])) {
|
|
442
|
+
restored.set(word, new Map(per));
|
|
443
|
+
} else if (Array.isArray(per)) {
|
|
444
|
+
restored.set(word, new Map([['legacy', per.length]]));
|
|
445
|
+
} else {
|
|
446
|
+
restored.set(word, new Map());
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
this.runtime.wordAccessLog = restored;
|
|
450
|
+
}
|
|
451
|
+
// 恢复会话信息
|
|
452
|
+
if (data.sessions) {
|
|
453
|
+
this.runtime.session.import(data.sessions);
|
|
454
|
+
} else {
|
|
455
|
+
// 无会话信息时,创建一个遗留会话
|
|
456
|
+
this.runtime.session.startNewSession({ reason: 'snapshot-legacy' });
|
|
341
457
|
}
|
|
342
|
-
|
|
343
458
|
console.timeEnd('snapshotRestore');
|
|
344
459
|
console.log(`[SNAPSHOT] 成功从快照恢复: ${snapshotId}`);
|
|
345
460
|
return true;
|
|
@@ -802,15 +917,21 @@ class Runtime {
|
|
|
802
917
|
this.transformer = null;
|
|
803
918
|
this.vocabManager = global.vocabmanager;
|
|
804
919
|
this.spider = new Spider();
|
|
920
|
+
|
|
921
|
+
// 新:以“会话”为尺度的访问日志与会话管理
|
|
922
|
+
this.session = new SessionManager({
|
|
923
|
+
idleMs: this.config.sessionIdleMs || 10 * 60 * 1000,
|
|
924
|
+
maxSessions: this.config.memoryRecentSessions || 200
|
|
925
|
+
});
|
|
926
|
+
// Map<word, Map<sessionId, count>>
|
|
805
927
|
this.wordAccessLog = new Map();
|
|
928
|
+
|
|
806
929
|
this.initWordGraph();
|
|
807
|
-
this.forgetTimer = setInterval(() => this.forgetWords(), 350 * 1000);
|
|
808
|
-
this.MAX_MEME_WORDS = 100;
|
|
809
|
-
this.MIN_OVERLAP = 2;
|
|
810
|
-
|
|
811
|
-
this.activationStats = new Map(); // 记录激活关系
|
|
930
|
+
this.forgetTimer = setInterval(() => this.forgetWords(), 350 * 1000);
|
|
931
|
+
this.MAX_MEME_WORDS = 100;
|
|
932
|
+
this.MIN_OVERLAP = 2;
|
|
933
|
+
this.activationStats = new Map();
|
|
812
934
|
this.isclone = false;
|
|
813
|
-
// 添加系统资源监控
|
|
814
935
|
this.systemLoad = {
|
|
815
936
|
lastCpuUsage: process.cpuUsage(),
|
|
816
937
|
lastCheckTime: Date.now(),
|
|
@@ -926,12 +1047,14 @@ class Runtime {
|
|
|
926
1047
|
}
|
|
927
1048
|
|
|
928
1049
|
// 记录词语点被访问
|
|
929
|
-
logWordAccess(word) {
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
|
|
1050
|
+
logWordAccess(word, sessionId) {
|
|
1051
|
+
const sid = sessionId || this.session.getActiveSessionId();
|
|
1052
|
+
let perSession = this.wordAccessLog.get(word);
|
|
1053
|
+
if (!perSession) {
|
|
1054
|
+
perSession = new Map();
|
|
1055
|
+
this.wordAccessLog.set(word, perSession);
|
|
933
1056
|
}
|
|
934
|
-
|
|
1057
|
+
perSession.set(sid, (perSession.get(sid) || 0) + 1);
|
|
935
1058
|
}
|
|
936
1059
|
registerClone() {
|
|
937
1060
|
Runtime.cloneRegistry.add(this);
|
|
@@ -939,62 +1062,65 @@ class Runtime {
|
|
|
939
1062
|
// 不自动销毁
|
|
940
1063
|
}
|
|
941
1064
|
|
|
942
|
-
|
|
1065
|
+
dispose() {
|
|
943
1066
|
this.graph.points.clear();
|
|
944
1067
|
this.wordGraph.points.clear();
|
|
945
1068
|
this.kvm.memory.clear();
|
|
946
1069
|
if (this.wordAccessLog) this.wordAccessLog.clear();
|
|
947
1070
|
if (this.forgetTimer) clearInterval(this.forgetTimer);
|
|
948
|
-
// 其它属性也可清空
|
|
949
1071
|
}
|
|
1072
|
+
// 将遗忘策略改为“最近N个会话窗口”
|
|
950
1073
|
forgetWords() {
|
|
951
|
-
const now = Date.now();
|
|
952
|
-
const windowMs = 350 * 1000;
|
|
953
|
-
|
|
954
|
-
// 只保留窗口内访问
|
|
955
|
-
for (const [key, times] of this.wordAccessLog.entries()) {
|
|
956
|
-
const recent = times.filter(t => now - t <= windowMs);
|
|
957
|
-
this.wordAccessLog.set(key, recent);
|
|
958
|
-
}
|
|
959
|
-
|
|
960
1074
|
// 保护:收集所有被KVM引用的词
|
|
961
1075
|
const protectedWords = new Set();
|
|
962
1076
|
for (const [, words] of this.kvm.memory.entries()) {
|
|
963
|
-
if (Array.isArray(words))
|
|
964
|
-
for (const w of words) protectedWords.add(w);
|
|
965
|
-
}
|
|
1077
|
+
if (Array.isArray(words)) for (const w of words) protectedWords.add(w);
|
|
966
1078
|
}
|
|
967
1079
|
|
|
968
|
-
// 若词表过小,直接跳过遗忘,避免崩塌
|
|
969
1080
|
const vocabSize = this.vocabManager.vocab.length;
|
|
970
1081
|
if (vocabSize < 1000) {
|
|
971
1082
|
console.log('[FORGET] 词表过小,跳过本轮遗忘');
|
|
972
1083
|
return;
|
|
973
1084
|
}
|
|
974
1085
|
|
|
975
|
-
|
|
1086
|
+
const recentSessions = this.session.getRecentSessionIds(this.config.memoryRecentSessions || 200);
|
|
1087
|
+
const recentSet = new Set(recentSessions);
|
|
1088
|
+
|
|
976
1089
|
const stats = [];
|
|
977
|
-
for (const [word,
|
|
1090
|
+
for (const [word, perSession] of this.wordAccessLog.entries()) {
|
|
978
1091
|
if (!this.wordGraph.points.has(word)) continue;
|
|
979
1092
|
if (!this.vocabManager.word2idx.has(word)) continue;
|
|
980
1093
|
if (protectedWords.has(word)) continue;
|
|
981
|
-
|
|
1094
|
+
|
|
1095
|
+
// 统计最近会话窗口内的使用次数
|
|
1096
|
+
let count = 0;
|
|
1097
|
+
if (perSession instanceof Map) {
|
|
1098
|
+
for (const [sid, c] of perSession.entries()) {
|
|
1099
|
+
if (recentSet.has(sid)) count += c || 0;
|
|
1100
|
+
}
|
|
1101
|
+
} else if (Array.isArray(perSession)) {
|
|
1102
|
+
// 兼容旧格式(时间戳数组),视作一个遗留会话
|
|
1103
|
+
count = perSession.length;
|
|
1104
|
+
}
|
|
1105
|
+
stats.push({ word, count });
|
|
982
1106
|
}
|
|
983
1107
|
if (stats.length === 0) return;
|
|
984
1108
|
|
|
985
1109
|
stats.sort((a, b) => a.count - b.count);
|
|
986
1110
|
|
|
987
|
-
//
|
|
988
|
-
const maxForgetRate = 0.001;
|
|
1111
|
+
// 每轮最多遗忘 0.1%(更保守)
|
|
1112
|
+
const maxForgetRate = 0.001;
|
|
989
1113
|
const n = Math.max(1, Math.floor(stats.length * maxForgetRate));
|
|
1114
|
+
const toForget = stats.slice(0, n).filter(s => s.count === 0).map(s => s.word);
|
|
1115
|
+
|
|
1116
|
+
if (toForget.length === 0) return;
|
|
990
1117
|
|
|
991
|
-
const toForget = stats.slice(0, n).map(s => s.word);
|
|
992
1118
|
for (const word of toForget) {
|
|
993
1119
|
this.wordGraph.points.delete(word);
|
|
994
1120
|
this.vocabManager.vocab = this.vocabManager.vocab.filter(w => w !== word);
|
|
995
1121
|
this.vocabManager.updateMappings();
|
|
996
1122
|
this.wordAccessLog.delete(word);
|
|
997
|
-
console.log(`[FORGET]
|
|
1123
|
+
console.log(`[FORGET] 淘汰词语点(无最近会话使用): ${word}`);
|
|
998
1124
|
|
|
999
1125
|
// 同步清理所有模因节点的词表
|
|
1000
1126
|
for (const [memeID, words] of this.kvm.memory.entries()) {
|
|
@@ -1010,9 +1136,6 @@ class Runtime {
|
|
|
1010
1136
|
}
|
|
1011
1137
|
}
|
|
1012
1138
|
}
|
|
1013
|
-
|
|
1014
|
-
// 不在这里调用 runMainLoop,避免循环内触发再次遗忘
|
|
1015
|
-
// this.runMainLoop();
|
|
1016
1139
|
}
|
|
1017
1140
|
// 修改 initWordGraph 方法
|
|
1018
1141
|
initWordGraph() {
|
|
@@ -2571,10 +2694,10 @@ class controller {
|
|
|
2571
2694
|
}
|
|
2572
2695
|
// 处理用户输入
|
|
2573
2696
|
async handleInput(text) {
|
|
2697
|
+
const sid = this.runtime.session.ensureActive();
|
|
2698
|
+
this.runtime.session.incMessage(sid);
|
|
2574
2699
|
const words = text.toLowerCase().split(' ').filter(w => w.length > 0);
|
|
2575
2700
|
this.runtime.processInput(words, { addNewWords: false });
|
|
2576
|
-
// 用模因网络参与推理
|
|
2577
|
-
//console.log('[DEBUG] 当前所有模因节点:', this.runtime.kvm.memory);
|
|
2578
2701
|
return await this.runtime.generateResponseWithMemes(words);
|
|
2579
2702
|
}
|
|
2580
2703
|
// 启动自主学习
|
|
@@ -2648,15 +2771,23 @@ let saveQueued = false;
|
|
|
2648
2771
|
|
|
2649
2772
|
// 保存所有点、图、词表等到硬盘
|
|
2650
2773
|
function saveAll(runtime) {
|
|
2774
|
+
// 规范化 wordAccessLog 为 [word, [[sessionId, count], ...]]
|
|
2775
|
+
const serializedWordAccess = Array.from(runtime.wordAccessLog.entries()).map(([w, per]) => {
|
|
2776
|
+
if (per instanceof Map) return [w, Array.from(per.entries())];
|
|
2777
|
+
if (Array.isArray(per)) return [w, [['legacy', per.length]]]; // 兼容旧格式
|
|
2778
|
+
return [w, []];
|
|
2779
|
+
});
|
|
2780
|
+
|
|
2651
2781
|
// 只更新内存缓存
|
|
2652
2782
|
latestRuntimeData = {
|
|
2653
2783
|
memes: runtime.graph.getAllPoints(),
|
|
2654
2784
|
wordGraph: Array.from(runtime.wordGraph.points.values()),
|
|
2655
2785
|
kvm: Array.from(runtime.kvm.memory.entries()),
|
|
2656
2786
|
vocab: runtime.vocabManager.vocab,
|
|
2657
|
-
wordAccessLog:
|
|
2787
|
+
wordAccessLog: serializedWordAccess,
|
|
2788
|
+
// 新增:会话信息持久化
|
|
2789
|
+
sessions: runtime.session.export()
|
|
2658
2790
|
};
|
|
2659
|
-
// 标记有保存请求
|
|
2660
2791
|
saveQueued = true;
|
|
2661
2792
|
}
|
|
2662
2793
|
// 定时真正写入硬盘,只保存最新的
|
|
@@ -2669,6 +2800,7 @@ setInterval(() => {
|
|
|
2669
2800
|
}
|
|
2670
2801
|
}, 10000); // 每10秒最多写盘一次
|
|
2671
2802
|
// 从硬盘恢复
|
|
2803
|
+
// 从硬盘恢复
|
|
2672
2804
|
function loadAll(runtime) {
|
|
2673
2805
|
if (!fs.existsSync(SAVE_PATH)) return;
|
|
2674
2806
|
const data = JSON.parse(fs.readFileSync(SAVE_PATH, 'utf-8'));
|
|
@@ -2678,19 +2810,34 @@ function loadAll(runtime) {
|
|
|
2678
2810
|
runtime.wordGraph.addPoint(point.pointID, point.connect);
|
|
2679
2811
|
}
|
|
2680
2812
|
}
|
|
2681
|
-
// 3. 修改 loadAll 中的数据恢复
|
|
2682
2813
|
if (data.kvm) {
|
|
2683
2814
|
for (const [k, v] of data.kvm) {
|
|
2684
2815
|
runtime.kvm.set(k, Array.isArray(v) ? v : [String(v)]);
|
|
2685
|
-
// 确保一定是数组
|
|
2686
2816
|
}
|
|
2687
2817
|
}
|
|
2688
2818
|
if (data.vocab) {
|
|
2689
2819
|
runtime.vocabManager.vocab = data.vocab;
|
|
2690
2820
|
runtime.vocabManager.updateMappings();
|
|
2691
2821
|
}
|
|
2822
|
+
// 恢复会话
|
|
2823
|
+
if (data.sessions) {
|
|
2824
|
+
runtime.session.import(data.sessions);
|
|
2825
|
+
}
|
|
2826
|
+
// 恢复词访问日志(新格式 Map<word, Map<sessionId, count>>)
|
|
2692
2827
|
if (data.wordAccessLog && runtime.wordAccessLog) {
|
|
2693
|
-
|
|
2828
|
+
const restored = new Map();
|
|
2829
|
+
for (const [word, per] of data.wordAccessLog) {
|
|
2830
|
+
if (Array.isArray(per) && per.length > 0 && Array.isArray(per[0])) {
|
|
2831
|
+
// 新格式:[[sid, count], ...]
|
|
2832
|
+
restored.set(word, new Map(per));
|
|
2833
|
+
} else if (Array.isArray(per)) {
|
|
2834
|
+
// 旧格式的 timestamps 数组 -> 合并为 legacy 会话
|
|
2835
|
+
restored.set(word, new Map([['legacy', per.length]]));
|
|
2836
|
+
} else {
|
|
2837
|
+
restored.set(word, new Map());
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
runtime.wordAccessLog = restored;
|
|
2694
2841
|
}
|
|
2695
2842
|
console.log(`[LOAD] 系统状态已从 ${SAVE_PATH} 恢复`);
|
|
2696
2843
|
}
|
|
@@ -3041,17 +3188,28 @@ async function main() {
|
|
|
3041
3188
|
ctrlA.runtime.memeBarrier.start();
|
|
3042
3189
|
}, 1000 * 60 * 12);
|
|
3043
3190
|
// API路由 - 只做学习,不返回结果
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3191
|
+
app.post('/api/chat', async (req, res) => {
|
|
3192
|
+
try {
|
|
3193
|
+
const { message, sessionId } = req.body || {};
|
|
3194
|
+
// 支持从Header透传会话
|
|
3195
|
+
const headerSid = req.headers['x-session-id'];
|
|
3196
|
+
const sid = sessionId || headerSid || global.ctrlA.runtime.session.ensureActive();
|
|
3197
|
+
|
|
3198
|
+
// 使用/续接会话并计数
|
|
3199
|
+
global.ctrlA.runtime.session.useSession(sid);
|
|
3200
|
+
global.ctrlA.runtime.session.incMessage(sid);
|
|
3201
|
+
|
|
3202
|
+
const words = String(message || '').toLowerCase().split(/\s+/).filter(w => w.length > 0);
|
|
3203
|
+
global.ctrlA.runtime.processInput(words);
|
|
3204
|
+
global.ctrlA.runtime.updateAttentionLinks();
|
|
3205
|
+
|
|
3206
|
+
res.set('X-Session-Id', sid);
|
|
3207
|
+
res.status(204).end();
|
|
3208
|
+
} catch (error) {
|
|
3209
|
+
res.status(500).json({ error: error.message });
|
|
3210
|
+
console.error('Error in /api/chat:', error);
|
|
3211
|
+
}
|
|
3212
|
+
});
|
|
3055
3213
|
|
|
3056
3214
|
app.get('/api/status', (req, res) => {
|
|
3057
3215
|
res.json({ status: 'running', timestamp: new Date().toISOString() });
|
|
@@ -3208,16 +3366,7 @@ function applyModelParams(runtime) {
|
|
|
3208
3366
|
}
|
|
3209
3367
|
// 如果直接运行此文件,启动主函数
|
|
3210
3368
|
if (require.main === module) {
|
|
3211
|
-
|
|
3212
|
-
() => main().catch(console.error), // onContinue
|
|
3213
|
-
() => {
|
|
3214
|
-
// onExit: 保存数据
|
|
3215
|
-
try {
|
|
3216
|
-
if (global.ctrl && global.ctrl.runtime) saveAll(global.ctrl.runtime);
|
|
3217
|
-
} catch (e) { }
|
|
3218
|
-
}
|
|
3219
|
-
);
|
|
3220
|
-
*/
|
|
3369
|
+
|
|
3221
3370
|
main().catch(console.error)
|
|
3222
3371
|
}
|
|
3223
3372
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "079project",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "a GNN-GA BASED ai that might pass the turing test,which use little resources.its startpoint initialize it and you can start it as ```node mainStarter.cjs```",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
package/todo-list.txt
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
GitHub Copilot
|
|
2
|
+
|
|
3
|
+
下面把你提出的 v2.0 需求整理成清晰的 TODO-list(每项附带子任务、优先级、复杂度估算、首要改动点与下一步行动建议)。便于逐步实现与分支/PR 管理。
|
|
4
|
+
|
|
5
|
+
------------------1) 记忆尺度:从“时间”切换为“对话”----------------
|
|
6
|
+
- 子任务:
|
|
7
|
+
- 定义“对话会话ID”与会话边界(消息计数或换话题检测)。
|
|
8
|
+
- 将 KVM/wordAccessLog/快照/遗忘策略改为按会话维度索引与过期。
|
|
9
|
+
- 修改 forgetWords、saveAll/loadAll 与 snapshot 逻辑以支持会话分片。
|
|
10
|
+
- 优先级:高;复杂度:中
|
|
11
|
+
- main_Study.cjs 中 KVM、forgetWords、SnapshotManager、save/load 函数。
|
|
12
|
+
- 下一步:设计会话ID格式并写出迁移方案(兼容老快照)。
|
|
13
|
+
|
|
14
|
+
2) .copy -> 基于 hash 的差量 copy(递归分区哈希)
|
|
15
|
+
- 子任务:
|
|
16
|
+
- 定义对象哈希(图节点、连接、KVM 值、词表段)规则。
|
|
17
|
+
- 实现递归分区哈希算法(分层哈希,按子图/词块分区)。
|
|
18
|
+
- 实现差量 copy/patch 接口(只拷贝不同分区)。
|
|
19
|
+
- 优先级:高;复杂度:大
|
|
20
|
+
- 首要改动:实现新模块 lib/deltaCopy.js,替换 cloneSystem、runtimeToPlain/plainObjToRuntime。
|
|
21
|
+
- 下一步:写单元测试验证哈希一致性与补丁正确性。
|
|
22
|
+
|
|
23
|
+
3) 增强轮换学习(减少用户等待)
|
|
24
|
+
- 子任务:
|
|
25
|
+
- 设计三副本轮换协议(leader/worker 与暂停/热替换流程)。
|
|
26
|
+
- 将 scheduleCrossLearning 改为更细粒度的 checkpoint/lock-free 切换(差量同步)。
|
|
27
|
+
- 添加短暂停机降级策略与快速回滚。
|
|
28
|
+
- 优先级:高;复杂度:中-大
|
|
29
|
+
- 首要改动:main_Study 中 scheduleCrossLearning、controller.updateRuntime、Redis 发布逻辑。
|
|
30
|
+
- 下一步:定义状态机与 API(swap、freeze、apply-delta)。
|
|
31
|
+
|
|
32
|
+
4) 强化 anti-trigger 与日志系统(崩溃连锁触发定位) ---------------------
|
|
33
|
+
- 子任务:
|
|
34
|
+
- 完善 antiTrigger:崩溃链路检测、重试与安全退出钩子。
|
|
35
|
+
- 引入结构化日志(文件+rotating)与异常追踪(stack + context)。
|
|
36
|
+
- 在关键路径增加崩溃快照(错误发生时自动 dump 最小快照)。
|
|
37
|
+
- 优先级:高;复杂度:中
|
|
38
|
+
- 首要改动:antiTrigger 函数、setupExitHandler、SnapshotManager.createSnapshot、新增 logger 模块(winston 或 pino)。
|
|
39
|
+
- 下一步:定义日志格式与最小 crash dump 方案。
|
|
40
|
+
|
|
41
|
+
5) 新增对抗学习网络(人机识别评分器)
|
|
42
|
+
- 子任务:
|
|
43
|
+
- 设计对抗模块接口:判别器(discriminator)输出拟人化评分与训练回路。
|
|
44
|
+
- 用现有 KVM/graph 生成“人类样本”与“机器样本”数据集。
|
|
45
|
+
- 将判别器输出作为主模型训练/奖励信号的一部分(强化学习回路)。
|
|
46
|
+
- 优先级:中;复杂度:大
|
|
47
|
+
- 首要改动:新增模块 lib/adversary.js + Runtime 中训练/评估接入点。
|
|
48
|
+
- 下一步:先实现轻量判别器(简单特征+小分类器)做 POC。
|
|
49
|
+
|
|
50
|
+
6) 实现真正的爬虫模块(抓取+清洗)
|
|
51
|
+
- 子任务:
|
|
52
|
+
- 新建爬虫模块(支持并发、robots、速率限制、去重、Pipeline 清洗)。
|
|
53
|
+
- 集成 HTML 解析、正文提取、语言检测、去噪与词形归一化。
|
|
54
|
+
- 将抓取结果发送到 spider.fetchArticles 的存储/队列。
|
|
55
|
+
- 优先级:中;复杂度:中-大
|
|
56
|
+
- 首要改动:新增目录 crawler/(fetcher、parser、cleaner、storage)。修改 Spider 以支持外部数据源。
|
|
57
|
+
- 下一步:先实现单域抓取与清洗流水线 POC。
|
|
58
|
+
|
|
59
|
+
7) 硬盘型数据库构型(部分图结构磁盘化、自动加载)
|
|
60
|
+
- 子任务:
|
|
61
|
+
- 研究 LMDB/LevelDB/rocksdb 方案,设计图分片策略(按节点度、热度、hash-range)。
|
|
62
|
+
- 实现图分片接口(swap-in/out)、接近边界时触发预加载侦测。
|
|
63
|
+
- 修改 GraphDB/KVM 支持异步加载与缓存回退策略。
|
|
64
|
+
- 优先级:高(随着图变大必须);复杂度:大
|
|
65
|
+
- 首要改动:KVM 类扩展、GraphDB 重构为内存+持久层混合(lib/storage-adapter.js)。
|
|
66
|
+
- 下一步:选定数据库(建议 LMDB 或 RocksDB),实现最小存储适配层。
|
|
67
|
+
|
|
68
|
+
8) 探索硬件加速(FPGA / 模拟运算)
|
|
69
|
+
- 子任务:
|
|
70
|
+
- 梳理热点(哪些计算最耗时:信号扩散、多源比对、距离计算)。
|
|
71
|
+
- 制定可被加速的计算接口(向量化、批处理、FPGA-friendly 格式)。
|
|
72
|
+
- 建立 POC:把最小工作负载移到 GPU/FPGA 模拟(或借助 SIMD/Native addon)。
|
|
73
|
+
- 优先级:低(研究/POC);复杂度:非常大(外部依赖)
|
|
74
|
+
- 首要改动:抽象计算层(lib/computeAdapter),便于未来替换为硬件实现。
|
|
75
|
+
- 下一步:先做性能分析与热点剖析,确定优先加速模块。
|
|
76
|
+
|
|
77
|
+
交付建议(短期优先级)
|
|
78
|
+
- 阶段 1(2–4 周):1、3、4(最小破坏性改造) + 日志模块 + 单元测试覆盖关键函数。
|
|
79
|
+
- 阶段 2(4–8 周):2(差量 copy 实现)+ 7(存储适配 POC)+ 6(爬虫基础)。
|
|
80
|
+
- 阶段 3(8–16 周):5(对抗学习)+ 8(硬件加速 POC)+ 全面整合与回归测试。
|
|
81
|
+
|
|
82
|
+
我可以马上开始:
|
|
83
|
+
- A) 生成分解后的 issue 列表与每项具体 code-change patch(推荐先做阶段1)。
|
|
84
|
+
- B) 直接在工作区创建 logger 模块并改造 antiTrigger + setupExitHandler(优先级高)。
|
|
85
|
+
|
|
86
|
+
请选择要我现在执行的下一步(A / B / 或 指定某个任务编号)。
|
|
File without changes
|
package/wikitext/.gitattributes
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
|
2
|
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
|
3
|
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
|
4
|
-
*.bin.* filter=lfs diff=lfs merge=lfs -text
|
|
5
|
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
|
6
|
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
|
7
|
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
|
8
|
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
|
9
|
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
|
10
|
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
|
11
|
-
*.model filter=lfs diff=lfs merge=lfs -text
|
|
12
|
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
|
13
|
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
|
14
|
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
|
15
|
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
|
16
|
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
|
17
|
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
|
18
|
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
|
19
|
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
|
20
|
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
21
|
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
|
22
|
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
|
23
|
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
|
24
|
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
|
25
|
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
|
26
|
-
*.zstandard filter=lfs diff=lfs merge=lfs -text
|
|
27
|
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|