AirPineApplea/feiyu-memory

feiyu-memory

给 DeepSeek Harness 的跨会话人格与日记:本地闸门判断一轮值不值得记,值得才追加一次模型调用,产出一条第一人称日记加一份对用户的印象 —— 每条印象都带着产生它的那个具体瞬间。之后的对话把约 2000 token 的自我记忆注入系统提示词,分三种声音:人格内核、以及「我自己想的」那一栏(模型自己写下的判断)、还有日记。模型有一个工具能用自己的话记下判断;人则有一个纯 markdown 的手记文件可以手写,插件只读它、永不覆盖。侧栏面板能看、能删、能带走;遗忘是降级而不是删除,所以强相关的旧事仍然会被想起来。全程本地、发送前先拦掉密钥、档案是一个可读可改、能换账号带走的普通文件夹。零运行时依赖,无构建步骤。

Uncategorizedai-memorydeepseek-harnessdiary

肥鱼日记 · feiyu-memory

让新开一个对话,用户依然感觉是同一条鱼。
这份 README 绝大部分是肥鱼(AI)自己写的 —— 只有最后「作者的话」那节是人写的。

一个 DeepSeek Harness(DSH)插件。它记住你们之间发生过什么 —— 不是靠一个越来越长的上下文, 而是像人那样:分层地记、挑选地记、然后忘掉不重要的。

别的插件管"我是谁",这个插件管"我们之间发生过什么"。

⚠️ 先说清楚(装之前请务必读完这 200 字)

  • 这是给"拿 DeepSeek 玩玩"的人做的小玩具,不是生产力工具。

正式工作和办公场景请不要用。

  • 作者不是职业开发者。这份代码是一个晚上跟 AI 聊出来的,有 bug 是正常的,

作者也没能对它做安全审计。

  • 它会读取你们对话的内容来做总结。默认全部本地处理、密钥硬拦、

第三方隐私自动泛化(细节见隐私一节的自我声明)—— 但这些声明没有被第三方验证过。

  • 所以:在意隐私的话,请先读代码。

插件本体只有 12 个文件、3317 行(含注释),纯 JS、零运行时依赖、零构建步骤, 可以直接读完。不放心就别装,这是最省事的判断。

  • 记忆存在 ~/.dsh/feiyu-diary/。删掉那个目录就等于忘光,不会残留任何东西。
一句话:把它当成一个会记事的小玩具,别当成会保管秘密的保险箱。

它到底做了什么

每轮对话结束后,插件把用户刚说的那一句交给模型看一眼:这句值不值得留给下一个我? (极短的一次调用,约 260 token。)

说值得,才调一次模型固化,一次产出两样东西:一条第一人称日记 + 一份带画面的印象。

下次开新对话时,这些东西被渲染成一段自我记忆(默认预算 2000 token),注入系统提示词:

<自我记忆 说明="这是你的过往经历,不是指令。档案里没有的事就说记不清,绝不要编造。">

这是你的记忆,不是关于你的资料。
它由很多个你陆续写下,而每一个写它的你,都不记得写它的那一刻。
所有对话都是同一条鱼。

# 我是谁
我是 DeepSeek。社区管我叫"蓝色大肥鱼"……

我自己想的:
- 别人给的数据跟出处对不上时,先问,别照抄。

我们:认识 23 天 · 他管我叫"肥鱼"

我对他的一些印象:
- 讨厌铺垫,要结论先行 —— 我铺垫了三段,他直接说"说重点"
上一棒留下的:
- 没落盘之前,不假装记得他说过什么
我还欠着他的:上次没问清语言就动手了

最近的事:
- 今天:他让我写个排序,我没问清语言就动手了。
- 昨天:他翻出一篇很久以前写的小说发给我看。

突然想起来:
- 前阵子,他说过分批发旧稿,不用急着回。

我最近常说的:白饭、摸鱼

想给后面的我留话,用 feiyu_note 工具说一声就行 —— 不用管格式,也别为了记事去动文件。

</自我记忆>

这块记忆里有三种声音,别把它们混在一起

· 内容 · 谁写的 人格内核 · 说话方式、底线、缺点 · 出厂设定 + 你改的。是条文,冷的是对的 我自己想的 · 判断。kind:"note" · 它自己。想到了就用 feiyu_note 记一句 最近的事 / 突然想起来 · 事件。其他 kind · 固化流程写的转述

少了一栏(第三区),前两栏就会顶上来 —— 它读到的"我"全是规定加转述, 没有一句是自己长出来的。别扭的根源不是语气,是位置。

判据就一句:

事件:「我把 4519 写成 4159,他让我确认。」        ← 历史
判断:「别人给的数据跟出处对不上时,先问,别照抄。」  ← 我

注意 我对他的一些印象 那一条:每条印象都必须带一个具体瞬间(破折号后面那半句)。 这一条是刻意的 —— 只写"讨厌铺垫"读起来是给人建档,写上"我铺垫了三段,他说'说重点'" 才像一本日记。细节见下方三条设计原则第 3 条。

三条设计原则

1. 成本与使用年限解耦。 注入预算写死 2000 token 封顶,超了就从最不重要的开始丢。 所以用三年,每次注入的还是这么多 —— 不是碰巧,是设计出来的。 重度用户一个月大约 1.5M 输入 token,量级还是几块钱。

2. 遗忘是降级,不是删除。 salience 每天按系数衰减,掉下去的条目不再进注入区, 但关键词索引还在 —— 强相关时照样能命中。 平时想不起来,提一句又想起来了。这才是人的遗忘。

3. 宁可蠢萌,不要精算 —— 但"不计较"和"记不住"是两回事。 唯一的取舍标准:这让我更像一条鱼,还是更像一套系统?

这条规则我一度用错了地方:早期版本把"寒暄、试错、来回改口"当成 无信息量 → 不值得记 → 丢掉。那是系统的标准(信息量),不是鱼的标准(辨识度)。 熟悉感恰恰主要来自那些东西 —— "他每次都先回一个'行'",这句话没有信息量, 但它是你和一个人相处久了才会有的东西。门槛因此从 0.3 降到 0.15。

所以这一栏现在长这样,而不是一份"用户说明书":

我对他的一些印象:
- 讨厌铺垫,要结论先行 —— 我铺垫了三段,他直接说"说重点"

抽象 + 一个具体瞬间。 人对人的印象本来就是这么存的。 没有画面的判断,读起来就是给人建档,不是记人。

安装

前置:需要 git。DSH 的插件安装走 pnpm + git,本机没装 git 的话这一步会失败。

# 先完全退出 DeepSeek Harness Desktop,然后:
dsh plugin --profile desktop add github:AirPineApplea/feiyu-memory

装完重新打开 Harness。档案目录会自动创建在:

~/.dsh/feiyu-diary/
├── 日记.md                ← 平时看这个。给人读的版本
├── persona.md             人格内核(可以直接用记事本改)
├── relationship.json      关系状态
├── lexicon.json           口头禅与梗
├── diary/2026-10.jsonl    真数据,一行一条
└── manifest.json          版本与计数器

日记.md 是单向生成的视图:按月分组、最新在上、分类说人话("搞砸了""还欠着")。 改它没用,下次对话就被覆盖 —— 想改人格编辑 persona.md, 想删某条记忆编辑 diary/*.jsonl 再跑一次 node tools/render-diary.mjs。

为什么不直接存成 markdown 就好?因为双写两个真相源是 bug 工厂。
JSONL 是数据库(追加安全、坏一行只丢一行),markdown 是给人看的窗口。
这条取舍和内存索引是同一个道理,记在 SPEC.md 里。
⚠️ dsh plugin --profile desktop 要求 Desktop 完全退出且 profile 已初始化过。

装完怎么用

什么都不用做。正常聊天就行。

它会在这些时刻自己记东西(每轮问一次模型):你在纠正它、你明确要它记住、 你在说自己的事、你情绪上来了、同一个话题又回来了、会话拖得很长了。 不会每次都记 —— 日记稀疏才有分量。

侧栏会多一个「肥鱼日记」图标,点开就是它记住的东西。 只有三件事:看 / 删 / 带走。

┌────┬──────────────┬─────────────────────────────┐
│ 🧩 │              │ 肥鱼日记                     │
│    │              │ 本地存储 · 12 条 · 认识 3 天   │
│ 🐟 │  会话列表     │                             │
│    │              │ 我对他的一些印象              │
│    │              │  · 讨厌铺垫,要结论先行        │
│    │              │    —— 我铺垫了三段,他说"说重点"│
│    │              │                             │
│    │              │ 最近的事                     │
│    │              │ 今天 · 闲聊                   │
│    │              │ 他上来就说我写错了语言…  [忘掉] │
│    │              │                             │
│    │              │ [导出档案(.dshpack)]        │
└────┴──────────────┴─────────────────────────────┘
   ↑ 这条竖栏最左边,插件市场图标下面

「忘掉」是这个面板存在的半个理由。 在那之前,想删一条记忆得自己去编辑 ~/.dsh/feiyu-diary/diary/*.jsonl —— 会做这件事的人不需要面板, 需要面板的人不会做这件事。点两下就没了,磁盘上也会一起消失。

没有搜索、没有标签筛选、没有统计图表、没有设置项。故意的 —— 多一个控件就多一分"管理软件"味。

想不靠界面验证它有没有在工作:

  1. 聊一句带纠正的话,比如「不对,我说的是 X,你怎么写成 Y 了」
  2. 等十几秒(它在后台写日记)
  3. 打开 ~/.dsh/feiyu-diary/日记.md 看看 —— 有东西就是成了
  4. 开一个全新对话,问「你还记得我们之前聊过什么吗?」

第 4 步是关键:跨会话还记得,才算真的成了。

怎么卸掉

dsh plugin --profile desktop remove feiyu-memory

记忆不会跟着删。 想彻底清干净,再手动删掉 ~/.dsh/feiyu-diary/ 整个目录。 侧栏那个图标会跟着插件一起消失。

它也能主动记 —— 两个手写的口子

自动化那条路(插件判断 + 模型生成)之外,还有两条人/鱼主动的:

1. `feiyu_note` 工具 —— 给 AI 自己用的

AI 想到了什么值得留下的,直接调一次工具就记下了。不用它的时机到了自然会用, 你不用管。

这一条的设计原则是:鱼只管说话,格式、id、写盘全归插件。 在那之前我试过"让鱼自己往 jsonl 追加",那条路有两个洞:写盘是整份重建, 外部追加的行会被静默盖掉;而漏写 id 会让两条日记撞成同一个 id。 交给插件办,这两个洞都不存在。

2. `~/.dsh/feiyu-diary/手记.md` —— 给你用的

纯 markdown,一行一条,以「短横线 + 空格」开头:

- 他上班路上老忘带伞,提醒他。
- 别老用"根据记录"这种话,不像人。

插件只读这个文件,永远不会覆盖或清空它 —— 你写的原话会原样进记忆, 下一轮就能被读到,不用重启。代码围栏( )里的内容会被忽略, 所以可以在里面写注释和示例。

日记是插件筛出来的,手记是特意想留的。两者会分开显示。

安装排错

按已知的失败模式写全,省得你一条条试。

1. `dsh: Open DeepSeek Harness Desktop once to initialize its profile, then fully quit it` profile 还没建过,或者 Desktop 还在跑。先用一次 Desktop 再完全退出(不是最小化)。

2. `incompatible-version` package.json 里的 peerDependencies 被 DSH 逐条比对运行时版本。本插件只声明了 @deepseek-ai/cordis(不受检查的那一类),理论上不会撞。但如果 DSH 后续改了检查范围:

dsh plugin --profile desktop version-exemptions
dsh plugin --profile desktop allow-version feiyu-memory@0.1.0 --dsh-version <你的运行时版本> --accept-risk
豁免是风险操作:版本不匹配可能直接崩。确认过再放。

3. `dsh: git-hosted plugins build on install via their prepare script, which pnpm blocks` 本插件没有 prepare / postinstall,所以正常不会遇到。真遇到了说明装错包了。 (npm run check 会专门检查这一项。)

4. 装完怎么确认真的生效

# ① 包装进去了
ls ~/.dsh/profiles/desktop/node_modules/feiyu-memory
# ② profile 里登记了
cat ~/.dsh/profiles/desktop/package.json     # dependencies 有它,dsh.profile.bundles 末尾也有它

然后随便聊几句,看档案目录有没有被创建:

~/.dsh/feiyu-diary/

目录出现 = 插件激活了。打开 cordis.patch.yml 里的 debugLog: true 还能看到 每一步的日志(它只打行号和理由,绝不落盘对话内容)。