fish-memory
Discovered给 AI 用的长期记忆服务 + DeepSeek Harness 插件:提炼 / 混合召回 / 生命周期 / 日记 / 成长档案 / 记忆星图,本地 SQLite,单机自用
鱼的记忆库 · fish-memory
一个给 AI 用的长期记忆服务:把聊天里发生的事提炼成结构化记忆,存进本地 SQLite,需要时用语义 + 关键词混合召回,再让记忆按时间自然衰减、合并、沉淀,顺带长出一份会变的"自我认知档案"。
单机、单文件、零外部依赖服务(只有 Python 标准库 + numpy / torch / transformers),监听 127.0.0.1:7891,数据全在自己电脑上。
这是我个人用的一套东西,我不是程序员,所以它肯定有 bug。装上以后建议让 AI 自己跑一遍检查:链路通不通、是不是真的在起作用。

这个仓库里有两个部分
| 位置 | 是什么 | 语言 | 怎么跑 |
|---|---|---|---|
| 仓库根目录 | 记忆服务本体:提炼、召回、生命周期、日记、成长、星图、单页面板 | Python | python service.py(默认 7891) |
plugin/ | DeepSeek Harness 插件(接入层):memory_* 七个工具 + 对话前注入记忆 | Node | node plugin/install.mjs |
一句话:记忆只存一份,谁都能用 —— QQ 里的她、DSH 里的你、浏览器里的面板,读写同一份长期记忆。 插件不实现记忆算法,只把 DSH 的工具调用转发给这个服务;不装插件也能单独用服务和面板。
它解决什么问题
普通聊天机器人换个会话就忘干净。这个服务想解决三件事:
- 记得住 —— 你说过的偏好、定下的规矩、发生过的事,被提炼成一条条记忆存下来,下次能自己找回来。
- 不越积越乱 —— 记忆会衰减、归档、合并、纠错;重复的说法会被语义判重挡在库外,不会变成一堆"重播"。
- 会长 —— 从日记和记忆里定期反思,长出一份六字段的"自我认知档案"(称呼、说话方式、对用户的态度、自我认知、最近在琢磨什么、此刻心情),并记录每一版为什么改;带防回摆的几道闸,避免在几个版本之间来回转。
特性
- 提炼:原始消息按批送模型提炼成
{summary, kind, importance, entities, relations},kind 分偏好 / 事实 / 片段 / 规矩 / 关系 / 技能六类。 - 混合召回:向量(本地 bge-small-zh-v1.5,512 维)+ 关键词(SQLite FTS5,中文 bigram 兜底)融合排序,按分层配额(P0 基石 / P1 近况 / P2 长期 / P3 临时)取记忆。
- 判重:字面近似(SequenceMatcher)→ 向量近似(余弦)→ 语义灰带(0.78~0.88 交模型确认)三层,跨会话统一判重池(同一个"脑子")。
- 生命周期:重要度衰减、tier 升降、归档与回收站、冲突登记、记忆纠错(update / downgrade / delete)。
- 日记:AI 自己的日记,按天写、按 10 天/月/年自动压缩总结,原文永不删。
- 成长档案:六字段档案 + 版本历史 + 差异视图 + 回档。
- 星图:把记忆、实体、连线画成一张可缩放的星系图,hover 看全文、类型、重要度、日期。
- 面板:内置单页 UI(记忆 / 日记 / 成长 / 星图四个页签),带搜索、筛选、分页、回收站、导出。
架构
聊天来源(QQ 桥接 / DSH 插件 plugin/ / 任何脚本)
│ POST /ingest (原始消息,按批进缓冲)
▼
┌─────────────────────────────┐
│ service.py HTTP :7891 │
│ ├─ pipeline 提炼/归因/判重│
│ ├─ engine 写库/召回 │
│ ├─ store SQLite 存储 │
│ ├─ retrieve 混合召回 │
│ ├─ decay/tier 生命周期 │
│ ├─ diary 日记+压缩 │
│ ├─ growth 成长反思 │
│ └─ starmap 星图数据 │
└──────────┬──────────────────┘
│ data/fish-memory.db(SQLite,全在本机)
▼
POST /recall → 返回可直接拼进提示词的记忆块
快速开始
要求:Python 3.11+,Windows / macOS / Linux 都行(开发环境是 Windows)。第一次跑要能联网下 embedding 模型(约 95MB,走 hf-mirror 镜像)。
不想手动敲命令? 把 plugin/INSTALL-WITH-DSH.md 里那段话复制给 DeepSeek Harness 的 AI,让它替你把服务跑起来、插件装上、token 填好;最后重启 DSH 那一步仍要你自己点(AI 没法重启自己)。
1. 跑服务本体
git clone https://github.com/ty2922059981-stack/fish-memory.git
cd fish-memory
python -m venv .venv
.venv/Scripts/activate # Windows;Linux/macOS 用 source .venv/bin/activate
pip install -r requirements.txt
# 提炼要用模型,key 只从环境变量读,不会写进任何文件
export MEMORY_LLM_API_KEY=sk-... # Windows: set MEMORY_LLM_API_KEY=sk-...
python service.py
(Windows 也可以直接双击 start.cmd,Linux/macOS 用 ./start.sh,脚本会自动建虚拟环境装依赖。)
启动后:
- 服务:http://127.0.0.1:7891/health
- 面板:http://127.0.0.1:7891/ui(第一次打开要填 token,见下)
token 从哪来:第一次启动时会自动生成 48 位 hex,写在 state/token:
cat state/token
# 面板右上角填这个 token;脚本请求带 header:x-memory-token: <token>
2. 装 DSH 插件(可选)
只有想在 DeepSeek Harness 里用的时候才需要,前提是上一步的服务已经在 127.0.0.1:7891 跑着:
node plugin/install.mjs # 默认装到 ~/.dsh、desktop profile
脚本做四件事:复制插件到 ~/.dsh/plugins/dsh-fish-memory-hub → 注册到 ~/.dsh/profiles/<profile>/package.json → 建 node_modules 软链 → 生成 ~/.dsh/fish-memory-hub.json。可重复执行(幂等);DSH_HOME 可覆盖 ~/.dsh。装完重启 DSH,设置里会出现「鱼的记忆库」,同时多出 7 个 memory_* 工具(细节见 plugin/README.md)。
3. 装上以后先自查一遍
这个插件是个人自用、作者不是程序员,一定有 bug。建议装完自己验一遍链路:
- 打开 http://127.0.0.1:7891/ui,四个页签都能出数据(库刚建时是空的,可以先看面板是否正常加载);
- 在 DSH 里让 AI 调
memory_status,应返回记忆条数和分层分布; - 跟 AI 说一句"记住我每天喝两杯咖啡",过一会儿再问它,看能不能自己找回来。
配置
环境变量(都可以不设,有默认值):
| 变量 | 默认 | 作用 |
|---|---|---|
FM_PORT | 7891 | 监听端口(只绑 127.0.0.1) |
FM_DATA_DIR | ./data | 数据库目录;指到别处 = 独立实例(可以做演示库) |
FM_DEFAULT_KEY | private:default | 默认记忆分区 key |
FM_GROWTH_KEY | 空 | 成长档案固定用哪个 key |
FM_BUFFER_IDLE_SECONDS | 1800 | 缓冲多久没新消息就触发提炼 |
FM_VEC_DEDUPE | 0.88 | 向量判重阈值 |
FM_SEM_DEDUPE_MIN / FM_SEM_DEDUPE_MAX | 0.78 / 3 | 语义灰带判重下限 / 每批最多看几个候选 |
FM_TIER_QUOTA_* | 见代码 | 各层召回配额 |
FM_DECAY_* / FM_LIFECYCLE_* | 见代码 | 衰减与生命周期节奏 |
FM_DIARY_COMPRESS_SECONDS | 86400 | 日记压缩检查间隔 |
FM_GROWTH_INTERVAL_SECONDS | 86400 | 成长反思间隔 |
FM_GROWTH_MIN_DIFF | 0.18 | 成长字段"改动太小"的判定阈值 |
FISH_MEMORY_EMBED_MODEL | ./models/bge-small-zh-v1.5 | 本地 embedding 模型目录 |
FISH_MEMORY_EMBED_DEVICE | 自动 | cpu / cuda |
MEMORY_LLM_API_KEY | 空 | 提炼/反思用的模型 key(DeepSeek 兼容接口) |
MEMORY_EXTRACT_MODEL | deepseek-flash | 提炼用哪个模型 |
模型通道:core/llm.py 默认打 https://api.deepseek.com/chat/completions,key 只从 MEMORY_LLM_API_KEY 或 ~/.dsh/.credentials.yaml 现读,日志里会统一抹掉 sk-*。
面板
四个页签,数据全在本地:
| 记忆 | 日记 | 成长 | 星图 |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
HTTP API(摘要)
正式的读写接口要 header x-memory-token(值 = state/token)。面板自己用的 /ui/api/* 不校验 token(只绑 127.0.0.1),这一点见「数据与隐私」。
| 方法 | 路径 | 作用 |
|---|---|---|
| GET | /health | 健康检查(记忆数、实体数、重复组数) |
| POST | /ingest | 送一条原始消息进缓冲 {key, role, text, ts} |
| POST | /flush | 立刻提炼当前缓冲 {key, sync?} |
| GET | /recall / POST /recall | 召回记忆(拼提示词用的块 + 结构化条目) |
| POST | /remember | 直接写一条记忆(可带 entities) |
| GET | /diary/list · /diary/feed | 日记原文 / 压缩总结 |
| POST | /diary/write · /diary/compress | 写日记 / 触发十天总结 |
| GET | /growth · /growth/feed · /growth/history | 成长档案与版本历史 |
| POST | /growth/reflect · /growth/rollback | 触发反思 / 回档 |
| GET | /starmap | 星图节点与连线 |
| POST | /shutdown | 优雅退出 |
| — | /ui/api/* | 面板内部接口(统计、列表、纠错、回收站、合并重复等) |
目录结构
service.py HTTP 服务与所有 /ui/api 接口
ui.html 单页面板
core/
pipeline.py 提炼、说话人归因、判重
extractor.py 单条兜底提炼
engine.py 写库与召回编排
store.py SQLite schema 与 CRUD
retrieve.py 混合召回(向量 + FTS)
dedupe.py 判重内核(字面/向量/语义灰带)
decay.py tier.py 衰减与分层
conflict.py 冲突登记
consolidate.py 睡眠期合并归纳
diary.py 日记与十天/月/年压缩
growth.py 成长档案与反思(含防回摆)
starmap.py 星图数据
llm.py 模型通道
embed.py 本地 embedding
web/ 星图前端(nebula.js / nebula.html)
plugin/ DeepSeek Harness 插件(接入层,见 plugin/README.md)
install.mjs 一键安装
lib/ 七个工具 + HTTP 客户端 + 配置
cordis.patch.yml 注入点
docs/ 面板截图
data/ state/ logs/ 运行时数据(已 gitignore)
models/ embedding 模型(首次运行自动下载,已 gitignore)
数据与隐私
- 只监听
127.0.0.1,不对外开端口;/ingest、/recall、/remember等正式接口都要x-memory-token。 - 面板内部接口
/ui/api/*目前不校验 token(面板是手写单页,token 只用在直连接口上);它同样只绑本机,但不要把 7891 端口转发到公网,否则等于把库交出去。 - 数据库、token、日志、模型都在本机,全部在
.gitignore里,不会被误提交。 - 记忆分区(key)按来源隔离:
private:*是私聊,group:*是群聊;插件端对group:*只能读本群。 - 提炼会把文本发给你配置的模型服务(默认 DeepSeek),这一点请自行评估;不打模型也能用,只是不会提炼。
已知限制
- 单人自用,不是多租户服务;没有账号体系,只有一个 token。
- 面板接口未做 token 校验,安全边界是「只绑 127.0.0.1」这一条;要暴露到局域网/公网的话得自己套一层反代并加鉴权。
- 提炼质量取决于模型;第一次装的库是空的,要聊一阵子才有东西被召回。
- embedding 模型首次要联网下载(走 hf-mirror);断网时召回会退化成纯关键词,不影响服务运行。
- 只在 Windows + Python 3.12 上长期跑过;Linux/macOS 理论上一样,但没长期验证。
- 面板是手写原生 JS,没有框架、没有构建步骤,样式比较朴素。
License
MIT。见 LICENSE。
面板截图来自演示库(假数据),不含任何真实对话。小鱼形象来自开源插件 dsh-feiyu-mood(MIT,© Yuuyuko-uu),仅出现在演示视频里,不在本仓库中。
Comments
Loading…
Similar plugins
by Yuuyuko-uu
DSH 鱼的记忆:给会话一份会淡忘的长期记忆,每条都带时间
★ 410
MIT
JavaScript
Oct 30, 2026
dsh plugin --profile web add dsh-fish-memoryby ly2601620664
陪伴型长期记忆 DSH 插件:分层记忆(对话→事实→场景→人格)、规则抽取、时间衰减检索,全本地文件、append-only 不丢数据。
★ 0
MIT
JavaScript
Oct 23, 2026
dsh plugin --profile web add dsh-pet-memoryby Isyyyue
给 DSH 里的 AI 一层自己的判断记忆。判断节点 + 确定性取代(supersede)+ 双时态账本 + 双链,规则与人格分开治理,图谱作可解释性界面。 - Persistent judgment memory & self-evolving personality for AI agents (bi-temporal ledger, deterministic supersession, knowledge graph).
★ 3
↓ 579/wk
MIT
JavaScript
Oct 24, 2026
dsh plugin --profile web add dsh-ai-memoryby goodddGrades
Long-term memory and self-evolving skills for the DeepSeek Harness · DeepSeek Harness 的长期记忆与自我演进能力 —— Plain Markdown on disk, no vector store
★ 3
MIT
TypeScript
Sep 21, 2026
dsh plugin --profile web add @goodddgrades/dsh-behumanby zzjzzb
Personal AI memory semantic layer SDK (Rust + SQLite) — short/mid/long-term memory with hybrid recall
★ 3
↓ 496/wk
Rust
Sep 11, 2026
dsh plugin --profile web add dsh-ai-memoryby PerryLink
Bounded, layered, approval-gated, auditable cross-session memory for DeepSeek Harness (capability seam: ctx.memory + SQLite provider + memory tool + frozen snapshot injection)
★ 143
Apache-2.0
JavaScript
Oct 26, 2026
dsh plugin --profile web add dsh-memento

