DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

fushui-menghua /

fushui-menghua/dsh-memory-graph-chiyo

Verified

可回溯、会遗忘、会睡觉整理的 AI 记忆图:每条记忆必须挂原话锚点,四层衰减,夜间自动归档噪声并强化重要记忆。零依赖,JSONL 存储。

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@49a629da

dsh-memory-graph-chiyo

可回溯、会遗忘、会睡觉整理的记忆内核。给 AI agent 用的长期记忆图。

tests license

为什么又一个记忆库

现在的开源记忆方案大致五条路(2026 年现状):

路线 代表 记忆形态 检索 短板
A. 向量 RAG 传统向量库 文本块 向量相似 谁说的、什么时候、还算不算数,全丢
B. 抽取 + 混合检索 Mem0 结构化事实卡 语义+关键词+实体 事实是模型重写的,原文不可回溯
C. 时序知识图谱 Zep / Graphiti 实体关系图 + 时间区间 图遍历 + 时间过滤 状态变化处理最强,但重
D. OS 分层记忆 Letta / MemGPT 内存页 + 归档 模型自己搬页 依赖模型自律,容易漂
E. 本体图谱 Cognee 本体 + 图 图查询 要设计 schema,接入成本高

本项目走 B+C 的混合,但多三件事:

  1. 锚点强制(anchors) —— fact / plan 必须能指回原话片段,否则拒收。
  2. 四层衰减 —— instant → short → long → cold;不是只增不减的仓库。
  3. 夜间整理(consolidation) —— 归档重复与墓碑,把提过多次、规则承诺类升层。

一句话:它记得住,也忘得掉,而且每晚自己整理。

能力清单

能力 说明
锚点强制 fact/plan 必须带原话;impression 可无
写入即去重 规范化文本相同 → 合并 mentionCount
四层衰减 short→long(提 3 次满 2 天);长期不用 →cold
重要度 提及 + 召回 + 锚点 + 类别 + 新鲜度加权,召回即反哺
召回 字符 bigram + 关键词 + 重要度 + 新鲜度;过滤冷层/归档/过期
跨 scope 召回 多 scope 合并打分,结果带 scope 来源
关系边 person/relationship/because/derivedFrom/supports/contradicts;召回可沿边扩展一跳(进出边都算)
plan 生命周期 有 validTo,过期自动 expired,过期后不再召回
即时记忆 醒 6h → 睡 6h → 墓碑;精确复活;复活 3 次升级成 fact
共享记忆 propose → approve → 跨会话可见 → revoke;未批准不可召回
夜间整理 归档重复/墓碑/极小陈旧;强化规则承诺类
体检 分层、类别、锚点覆盖率、90 天陈旧数
上下文压缩(带锚点) 超阈值折叠旧轮次 → 摘要 + 锚点 + 原文可 expand() 取回;工具输出先掐头去尾
规则抽取 从原话认出「主人定的规矩」和「她自己的承诺」,自动生成带锚点的规则节点
敏感过滤 路径 / QQ号 / 凭据 / 令牌写入前拒收,可逐类放行
锚点强校验 传了原始消息时,引文必须真的在里面,防模型编造
幂等去重 idempotencyKey / mentionKey,同一件事换说法也只记一次
人物层 登记、别名解析、合并提议与审批
时段轨迹 / 漏检扫描 回看某段时间发生了什么;找出没被任何锚点引用过的话
人格旋钮(可选) 六个性格旋钮,带单步/每日/漂移三重刹车(角色扮演层,非记忆)
星图可视化 零依赖 SVG + Mermaid 输出,可直接贴 README
自动抽取管道 extractAndWrite:从对话抽规则/事实 → 敏感过滤 → 锚点校验 → 幂等去重 → 落盘
提示词装配 assembleContext:按 token 预算分区拼装(记得的事/在办的事/印象/共享)
快照导入导出 整个数据目录导成单个 JSON,可还原(换机器、误删恢复)
关系强度衰减 边有 weight,默认半年半衰期,低于阈值自动摘边
共享审计与配额 每日提名上限、依赖级联撤销、独立审计日志
store 缓存 按文件 mtime 失效,写入即失效,召回不必全量解析
矛盾检测 喜欢/不喜欢这类翻转 → 旧的标 superseded,只召回新的
多进程写锁 目录级锁 + 超时 + 陈旧锁清理
损坏修复 scanStore / repairStore,坏行剔除并备份原文件
TypeScript 类型 内置 index.d.ts
性能基准 npm run bench:2000 节点写入 ~1400 条/s、召回 0.42ms
情绪记忆 心情时间线(含原因/强度)、近七天分布、给记忆打情绪标签
做梦 从真实记忆挑素材 → 生成写梦提示词(或模板梦)→ 记录并保留素材引用
自己的待办 加/完成/放弃/挑下一件/统计,给提示词用的摘要
补录协议 只允许 fact、一次≤2 条、证据三元组、整批原子、召回权重 0.8
权限模型 主人/agent/群/陌生人 × scope 模式,读写分离
人物熟悉度 熟悉度增长 + 半衰期衰减,合并后关系自动重指
交互式星图 单文件 HTML:缩放/拖拽/过滤/搜索/看锚点,离线可用
召回基线 npm run eval → hit@1 / hit@3
命令行 memory-graph health/recall/recall-all/nightly/shared-*/scan/repair
零依赖 只用 Node 内置模块

给桥接用(QQ / 微信机器人)

如果你在用桥接 + DSH 人格机器人,用适配层两行接入:

import { createBridgeMemory } from 'dsh-memory-graph-chiyo/bridge';
const bm = createBridgeMemory({ dir: './memory', scope: 'agent:chiyo' });

bm.beforeTurn({ query: 用户这句话 });   // 拼进提示词
bm.afterTurn({ messages: [用户, 回复] }); // 自动抽记忆
bm.nightly({ apply: true });            // 每天整理

除了记忆,还可以给她情绪、梦和待办:

bm.mood.set({ label: '暖', reason: '被夸了一句' });   // 记心情
bm.dream.seed();                                      // 挑入梦素材
bm.dream.record({ text: '梦见下雨…', mood: '暖' });    // 记梦
bm.tasks.add({ text: '整理星图分类' });                // 加待办
bm.tasks.pickNext();                                  // 下一件

详见 docs/BRIDGE.md。

安装

作为库(推荐给开发者)

npm i dsh-memory-graph-chiyo

作为 DSH 插件(推荐给 DSH 用户)

dsh plugin --profile web add dsh-memory-graph-chiyo

装上后 DSH 会注册 5 个工具:memory_write / memory_recall / memory_health / memory_nightly / memory_shared。 数据默认在 ~/.dsh/memory-graph,默认 scope agent:memory(可在 plugin 配置里改)。

插件与库是同一个包:import 用 ./src/index.js,DSH 走 ./plugin.js 的 apply(ctx)。

npm i dsh-memory-graph-chiyo

要求 Node ≥ 20。

快速开始

import { createMemory } from 'dsh-memory-graph-chiyo';

const mem = createMemory({ dir: './memory-data' });

// 1) 写:fact 必须带锚点
mem.write('user:alice', {
  nodes: [
    { kind: 'fact', text: '她喜欢下雨天', anchors: [{ quote: '我最喜欢下雨了' }] },
    { kind: 'fact', text: '她怕黑', anchors: [{ quote: '我怕黑' }] },
  ],
});

// 2) 建立关系边(目标必须已存在)
const fear = mem.load('user:alice').find((n) => /怕黑/.test(n.text));
mem.write('user:alice', {
  nodes: [{ kind: 'fact', text: '睡觉要留一盏小灯', anchors: [{ quote: '留个灯' }], relations: [{ type: 'because', targetId: fear.id }] }],
});

// 3) 召回(hops=1 沿关系扩展)
const hits = mem.recall('user:alice', { query: '怕黑', hops: 1 });

// 4) 跨 scope 召回
mem.recallAcross(['user:alice', 'agent:chiyo'], { query: '下雨' });

// 5) 计划(3 天后自动过期)
mem.write('user:alice', { nodes: [{ kind: 'plan', text: '周末去看海', anchors: [{ quote: '周末去海边' }], validDays: 3 }] });

// 6) 共享记忆:提名 → 批准 → 可召回
const s = mem.proposeShared({ text: '雨天适合听老唱片', sourceScope: 'group:demo' });
mem.approveShared(s.id, { by: 'owner' });
mem.recallShared({ query: '雨天' });

// 7) 睡一觉:推进层/即时/计划 + 整理 + 体检
const report = mem.nightly(['user:alice', 'agent:chiyo'], { apply: true });

上下文压缩(带锚点)

普通压缩的毛病:摘要写完,原话就找不回来了。这里给摘要挂 anchors(被折叠事件的 id), 被折叠的原文默认从 shadowed 返回,随时能取回。

import { createCompactor } from 'dsh-memory-graph-chiyo';

const comp = createCompactor({
  windowTokens: 128000,   // 模型上下文窗口
  thresholdRatio: 0.3,    // 超过 30% 才压
  keepTurns: 10,          // 保留最近 10 轮
  pruner: { thresholdChars: 8000, headChars: 6000, tailChars: 1500 },
  // summarizer: async (events) => '用你的模型写摘要',  // 可选,默认是确定性抽取
});

const r = await comp.compact(events);
// r.compacted     是否真的压了
// r.events        新上下文:摘要块 + 最近 N 轮
// r.anchors       被折叠事件的 id 列表(摘要里也写了一份)
// r.shadowed      被折叠的原文,存哪儿由你决定
// r.beforeTokens / r.afterTokens

// 想核对摘要对不对:
for (const e of comp.expand(r)) console.log(e.id, e.text);

// 审计每次压缩:
console.log(comp.stats());
// [{ at, beforeK, afterK, freedK, folded, keptTurns }]

三层策略(跟她实际在用的那套一致):

层 做什么 什么时候
prune 工具输出掐头去尾 单条超过 thresholdChars
compact 旧轮次折叠成摘要 总占用超过 windowTokens × thresholdRatio
stats 记录放掉多少、留几轮 每次压缩后

保证不变大的保护:如果摘要比原文还长(窗口很小时会这样),会先截短;实在压不下去就跳过并返回 note,不会假装压过。

命令行

# 体检
npx memory-graph health --dir ./data --scope user:alice

# 召回
npx memory-graph recall --dir ./data --scope user:alice --query 下雨

# 跨 scope
npx memory-graph recall-all --dir ./data --scopes user:alice,agent:chiyo --query 下雨

# 夜间整理(dry-run / --apply)
npx memory-graph nightly --dir ./data --scopes user:alice --apply

# 共享记忆
npx memory-graph shared-list --dir ./data
npx memory-graph shared-approve --dir ./data --id s_xxx --by owner

配合系统计划任务,每天凌晨自动整理:

# Linux / macOS
0 3 * * * cd /path/to/app && npx memory-graph nightly --dir ./data --scopes user:alice --apply

存储

JSONL,按 scope 和月份分文件:

memory-data/
├─ user_alice/2026-11.jsonl
├─ agent_chiyo/2026-11.jsonl
└─ shared_global/2026-11.jsonl   ← 共享记忆独立存放
  • last-wins:同 id 以最后一条为准,改状态不改历史
  • 可 grep:你的记忆是你自己的
  • 崩溃安全:最多丢最后一行

核心概念

概念 说明
scope user:alice / agent:chiyo / group:demo,隔离单位
kind fact(有锚点)/ impression(主观)/ plan(有失效期)
layer instant / short / long / cold / permanent
anchors 原话片段,用于回溯与验证
relations 节点间的边,召回可扩散
status plan 专用:active / done / abandoned / expired

规则抽取 / 人物 / 时间线 / 体检 / 星图

// 规则:从原话里认出规矩与承诺
const rules = mem.extractRules('以后不要在深夜给我发消息', { speaker: 'owner' });
// → [{ kind:'fact', text:'以后不要在深夜给我发消息', cluster:'rule-owner', anchors:[...] }]
mem.write('user:alice', { nodes: rules });

// 人物:登记 → 别名解析 → 合并审批
mem.person.upsert({ name: '阿岚', aliases: ['小岚'] });
const p = mem.person.proposeMerge('阿岚', '岚岚');
mem.person.approveMerge(p.id, { by: 'owner' });

// 时间线:这段时间发生了什么 + 哪些话没进记忆
mem.episode({ scope: 'user:alice', from: Date.now() - 86400_000 });
mem.missedScan({ scope: 'user:alice', messages });

// 体检:六项指标
mem.healthReport({ scope: 'user:alice' });
// { checks: [锚点覆盖率, 重复率, 长期占比, 即时占比, 陈旧度, 归档与共享], ok, failed }

// 星图:SVG 或 Mermaid
const svg = mem.starMap(mem.load('user:alice'), { title: '她的记忆星图' });
const mmd = mem.mermaid(mem.load('user:alice'));

人格旋钮(可选,跟记忆无关)

⚠️ 这一层是角色扮演,不是记忆。记忆回答"发生过什么",人格回答"用什么性格说话"。 不需要的话完全不调用即可,不影响其它能力。

mem.persona.get();                    // { tsundere, playfulness, initiative, softness, snark, moodSwing }
mem.persona.tune('initiative', 0.05, { by: 'owner', reason: '希望更主动' });
mem.persona.summary();                // 「傲娇 中等;爱玩 偏高;主动 很高…」
mem.persona.revert();

三重刹车(防止人格一夜之间漂走):

单步 ≤ 0.05      · 每天最多 1 次      · 距基线累计偏移 ≤ 0.15

范围说明

  • 长期记忆:跨会话的节点、衰减、关系、整理(本项目的核心)
  • 上下文压缩:单次对话太长时腾出窗口,摘要带锚点可回溯(v0.3.0 起内置)

两者互补:压缩管"这一次对话装不下",整理管"跨天该忘什么"。

测试

npm test
# 47 tests: 锚点 / 召回 / 去重 / 即时记忆 / 整理 / 层推进 / 体检
         跨 scope / 共享审批 / plan 过期 / 关系边扩展 / nightly 全流程
         压缩 / 规则抽取 / 敏感过滤 / 锚点强校验 / 幂等键 / 人物合并 / 时间线 / 漏检
         自动抽取 / 提示词装配 / 快照往返 / 关系衰减 / 共享审计配额 / store 缓存
         矛盾检测 / 矛盾扫描 / 写锁超时 / 陈旧锁 / 损坏修复 / d.ts 完整 / 召回性能护栏

设计取舍

  • 不做嵌入向量:默认字符 bigram + 关键词 + 重要度,零依赖、可解释; 要语义检索可自行替换 recall(纯函数,好接 embedding)。
  • 不自动摘要:摘要会丢掉原话,而原话是这套系统的地基。
  • 不删除:归档只是 archived: true,永远可恢复。
  • 共享要审批:默认只能提名,批准后才跨会话可见。

License

MIT © 浮水梦华

—/ 5

No ratings yet

Verified DSH bundle

Commit 49a629da4c40

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout