Initial spark-mind: heartbeat + memory + persona + mind on Spark X2.5-4B
This commit is contained in:
commit
709d7ce17d
10 files changed
+991
No files matched your search
+109
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Memory System — 4 слоя памяти (концепт Animus):
|
||||
* short-term / working / core self / long-term
|
||||
* Хранение: SQLite (7 таблиц) + LanceDB для long-term (векторный поиск).
|
||||
*
|
||||
* В MVP: short-term + working + core self — в SQLite.
|
||||
* long-term — в LanceDB (или Qdrant на a2000 для прода).
|
||||
*/
|
||||
|
||||
export interface Thought {
|
||||
id: string;
|
||||
text: string;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export interface ContactNotepad {
|
||||
contactId: string;
|
||||
block: string;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
export interface SelfObservation {
|
||||
id: string;
|
||||
text: string;
|
||||
createdAt: number;
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
export interface LongTermMemory {
|
||||
id: string;
|
||||
text: string;
|
||||
type: 'fact' | 'experience' | 'procedure' | 'outcome';
|
||||
createdAt: number;
|
||||
embedding?: number[];
|
||||
}
|
||||
|
||||
export class MemorySystem {
|
||||
private recentThoughtsList: Thought[] = [];
|
||||
private notepads = new Map<string, ContactNotepad>();
|
||||
private selfObservationsList: SelfObservation[] = [];
|
||||
private longTerm: LongTermMemory[] = [];
|
||||
|
||||
constructor(private recentCount: number) {}
|
||||
|
||||
// === Short-term: последние мысли/опыт/сообщения ===
|
||||
addThought(text: string): Thought {
|
||||
const t: Thought = { id: `th-${Date.now()}`, text, createdAt: Date.now() };
|
||||
this.recentThoughtsList.unshift(t);
|
||||
if (this.recentThoughtsList.length > this.recentCount) this.recentThoughtsList.pop();
|
||||
return t;
|
||||
}
|
||||
|
||||
recentThoughts(): Thought[] {
|
||||
return this.recentThoughtsList.slice(0, this.recentCount);
|
||||
}
|
||||
|
||||
// === Working memory: notepad по контактам ===
|
||||
updateNotepad(contactId: string, block: string) {
|
||||
this.notepads.set(contactId, { contactId, block, updatedAt: Date.now() });
|
||||
}
|
||||
|
||||
getNotepad(contactId: string): string {
|
||||
return this.notepads.get(contactId)?.block ?? '';
|
||||
}
|
||||
|
||||
// === Core self: накопленная самосознательность ===
|
||||
addSelfObservation(text: string, tags: string[] = []): SelfObservation {
|
||||
const o: SelfObservation = { id: `so-${Date.now()}`, text, createdAt: Date.now(), tags };
|
||||
this.selfObservationsList.push(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
getAllSelfObservations(): SelfObservation[] {
|
||||
return this.selfObservationsList;
|
||||
}
|
||||
|
||||
// === Long-term: факты/опыт/процедуры/исходы + векторный поиск ===
|
||||
addLongTerm(text: string, type: LongTermMemory['type']): LongTermMemory {
|
||||
const m: LongTermMemory = { id: `lt-${Date.now()}`, text, type, createdAt: Date.now() };
|
||||
this.longTerm.push(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Поиск по long-term по эмбедду (в прода заменяется на LanceDB/Qdrant query). */
|
||||
searchLongTerm(queryEmbedding: number[], topK = 3): LongTermMemory[] {
|
||||
// cosine similarity — заглушка, в прода: LanceDB.search
|
||||
const scored = this.longTerm
|
||||
.filter(m => m.embedding)
|
||||
.map(m => ({ m, score: cosine(queryEmbedding, m.embedding!) }))
|
||||
.sort((a, b) => b.score - a.score)
|
||||
.slice(0, topK)
|
||||
.map(x => x.m);
|
||||
return scored;
|
||||
}
|
||||
|
||||
/** Консолидация: перенос недавних мыслей в long-term (по спецификации Animus). */
|
||||
consolidate(recent: Thought[]): void {
|
||||
for (const t of recent) {
|
||||
// эвристика: только «значимые» мысли (по тегам/ключевым словам)
|
||||
this.addLongTerm(t.text, 'experience');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cosine(a: number[], b: number[]): number {
|
||||
let dot = 0, na = 0, nb = 0;
|
||||
for (let i = 0; i < a.length; i++) { dot += a[i] * b[i]; na += a[i] * a[i]; nb += b[i] * b[i]; }
|
||||
return Math.sqrt(na) * Math.sqrt(nb) ? dot / (Math.sqrt(na) * Math.sqrt(nb)) : 0;
|
||||
}
|
||||
Reference in new issue
Block a user