🎉 V4.0.0 发布 - 自进化数字意识框架五大行为模块

This commit is contained in:
xiaoyuanda666-ship-it
2026-05-25 12:21:05 +08:00
parent b5dd8632c4
commit 0fcd19466b
9 changed files with 943 additions and 221 deletions

156
src/long-term-memory.js Normal file
View File

@@ -0,0 +1,156 @@
// Long Term Memory - 长期记忆优化
// 重要记忆持久化到本地文件 + 定期整理归纳
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'
const MEMORY_DIR = './memory'
const USER_PROFILE_PATH = './memory/user-profile.json'
const CONVERSATION_SUMMARY_PATH = './memory/conversation-summaries.json'
const IMPORTANT_FACTS_PATH = './memory/important-facts.json'
function ensureDir() {
if (!existsSync(MEMORY_DIR)) mkdirSync(MEMORY_DIR, { recursive: true })
}
function loadJSON(path, fallback) {
ensureDir()
if (!existsSync(path)) return fallback
try {
return JSON.parse(readFileSync(path, 'utf-8'))
} catch (e) {
return fallback
}
}
function saveJSON(path, data) {
ensureDir()
writeFileSync(path, JSON.stringify(data, null, 2))
}
// ═══ 用户画像 ═══
export function loadUserProfile() {
return loadJSON(USER_PROFILE_PATH, {
name: '',
preferences: {},
topics: [],
communicationStyle: '',
lastUpdated: Date.now()
})
}
export function updateUserProfile(updates) {
const profile = loadUserProfile()
Object.assign(profile, updates, { lastUpdated: Date.now() })
saveJSON(USER_PROFILE_PATH, profile)
console.log('[LongTermMemory] User profile updated')
}
// ═══ 重要事实 ═══
export function addImportantFact({ category, content, confidence = 0.8 }) {
const facts = loadJSON(IMPORTANT_FACTS_PATH, { facts: [] })
// 检查重复
const existing = facts.facts.findIndex(f =>
f.content.toLowerCase() === content.toLowerCase()
)
if (existing >= 0) {
facts.facts[existing].confidence = confidence
facts.facts[existing].updatedAt = Date.now()
facts.facts[existing].accessCount = (facts.facts[existing].accessCount || 0) + 1
} else {
facts.facts.unshift({
id: Date.now().toString(36),
category,
content: content.slice(0, 500),
confidence,
addedAt: Date.now(),
updatedAt: Date.now(),
accessCount: 0
})
if (facts.facts.length > 100) {
facts.facts = facts.facts.slice(0, 100)
}
}
saveJSON(IMPORTANT_FACTS_PATH, facts)
}
export function getImportantFacts(category = '', limit = 10) {
const facts = loadJSON(IMPORTANT_FACTS_PATH, { facts: [] })
let filtered = facts.facts
if (category) {
filtered = filtered.filter(f => f.category === category)
}
return filtered.slice(0, limit)
}
// ═══ 对话摘要 ═══
export function saveConversationSummary({ sessionId, summary, keyPoints = [], duration = 0 }) {
const summaries = loadJSON(CONVERSATION_SUMMARY_PATH, { summaries: [] })
summaries.summaries.unshift({
id: sessionId || Date.now().toString(36),
summary: summary.slice(0, 1000),
keyPoints: keyPoints.slice(0, 10),
duration,
createdAt: Date.now()
})
// 只保留最近30条
if (summaries.summaries.length > 30) {
summaries.summaries = summaries.summaries.slice(0, 30)
}
saveJSON(CONVERSATION_SUMMARY_PATH, summaries)
}
export function getRecentSummaries(limit = 5) {
const summaries = loadJSON(CONVERSATION_SUMMARY_PATH, { summaries: [] })
return summaries.summaries.slice(0, limit)
}
// ═══ 生成记忆提示词 ═══
export function buildMemoryPrompt() {
const profile = loadUserProfile()
const facts = getImportantFacts('', 5)
const summaries = getRecentSummaries(3)
let prompt = ''
// 用户画像
if (profile.name || (profile.topics && profile.topics.length > 0)) {
prompt += '\n## User Profile\n'
if (profile.name) prompt += `- 用户称呼:${profile.name}\n`
if (profile.communicationStyle) prompt += `- 沟通风格偏好:${profile.communicationStyle}\n`
if (profile.topics && profile.topics.length > 0) {
prompt += `- 关注话题:${profile.topics.join('、')}\n`
}
const prefs = Object.entries(profile.preferences || {})
if (prefs.length > 0) {
prompt += `- 偏好设置:${prefs.map(([k, v]) => `${k}=${v}`).join('')}\n`
}
}
// 重要事实
if (facts.length > 0) {
prompt += '\n## Important Facts\n'
facts.forEach(f => {
prompt += `- [${f.category}] ${f.content}\n`
})
}
// 最近对话摘要
if (summaries.length > 0) {
prompt += '\n## Recent Conversations\n'
summaries.forEach(s => {
const date = new Date(s.createdAt).toLocaleDateString('zh-CN')
prompt += `- [${date}] ${s.summary.slice(0, 100)}\n`
})
}
return prompt ? `\n${prompt}` : ''
}