@scotthuang/engram
v0.11.1
Published
分层语义记忆系统 - OpenClaw Plugin
Readme
Engram - 分层语义记忆系统
OpenClaw Plugin for hierarchical semantic memory.
🚀 快速启动
一键启动所有服务
# 首次运行会自动创建虚拟环境并安装依赖
./start.sh启动后访问:
- 前端:http://localhost:3210
- 后端:http://localhost:8765
停止服务
./stop.sh人脸服务常驻(推荐)
人脸识别服务(InsightFace buffalo_l)建议配置为开机自启常驻进程,这样微信发图时能自动识别人脸。
资源开销:
| 状态 | RSS 内存 | CPU | |------|---------|-----| | 模型未加载(空闲) | ~240 MB | ~0% | | 模型已加载(空闲) | ~1.85 GB | ~0% | | 推理中 | ~1.85 GB | 单核 |
模型在首次检测时延迟加载,后续每张图片检测耗时 260-380ms。
launchd 配置(macOS):
plist 文件位于 ~/Library/LaunchAgents/com.engram.face-service.plist。
# 查看服务状态
launchctl list | grep engram
# 启动服务
launchctl load ~/Library/LaunchAgents/com.engram.face-service.plist
# 停止服务
launchctl unload ~/Library/LaunchAgents/com.engram.face-service.plist
# 查看日志
tail -f /Users/scotthuang/github/engram/.logs/face-service.log
# 健康检查
curl http://localhost:8765/health服务配置了崩溃自动重启(10s 冷却),异常退出后会自动恢复。
查看日志
# 实时查看后端日志
tail -f .logs/backend.log
# 实时查看前端日志
tail -f .logs/frontend.log
# 实时查看人脸服务日志(常驻模式)
tail -f .logs/face-service.log📁 项目结构
face/- 人脸和声纹识别模块service/- 后端服务 (FastAPI + Python)web/- 前端界面 (React + Vite)
src/- 核心记忆系统代码scripts/- 工具脚本
🔧 手动启动(可选)
如果需要单独启动前端或后端:
# 仅启动后端
cd face/service
./start.sh
# 仅启动前端
cd face/web
./start.sh📋 环境要求
- Node.js (推荐 LTS 版本)
- Python 3.12
- macOS / Linux
📦 功能模块
人脸识别
- 注册人脸
- 识别照片中的人脸
- Gallery 展示和测试
声纹识别
- 注册声纹
- 识别语音中的说话人
- Gallery 语音测试
记忆系统
- 短期记忆
- 长期记忆
- 语义检索
- 自动浓缩
- 写入侧自动化噪音过滤(HEARTBEAT / news-cron / 天气推送等 cron session 自动跳过)
方案文档
架构
短期记忆 (BM25 + jieba)
↓ 凌晨 Cron 沉淀
画像层 (LLM 抽取 + 摘要压缩)
↓ 有价值条目
向量层 (lancedb + text-embedding-v3)
↓ 超过 7 天
归档层 (cold-storage, 不索引)文件结构
src/
├── index.ts # Plugin 入口 (register)
├── config.ts # 配置定义
├── recall.ts # Auto-Recall (双路召回)
├── settle.ts # 沉淀逻辑 (Cron 5步)
├── bm25.ts # BM25 索引 (jieba-wasm 分词)
├── vector.ts # 向量存储 (lancedb + embedding)
├── profile.ts # 画像管理
├── image-store.ts # 图片存储
├── logger.ts # 日志系统
scripts/
├── sim-recall.ts # 模拟召回环境(见下方)
├── self-evolving.ts # 自进化模块(召回质量自动分析,见下方)
├── self-evolving.md # [自动生成] 召回质量分析报告
├── self-evolving-errors.md # [自动生成] 错题集(仅不通过的 case)
├── .self-evolving-checkpoint.json # [自动生成] 增量分析 checkpoint
├── config.md # workspace 路径配置
├── condense_shortterm.cjs # 短期记忆精简工具
├── cleanup-short-term.ts # 短期记忆噪音清理(一次性清除 cron 日志)
├── clean-cron-weather-news.ts # 天气/新闻导入 cron 流水清理(可重复运行)
├── manual-condense.ts # 手动补 condense(修复遗漏的 session)开发
npm install安装到 OpenClaw
openclaw plugins install @scotthuang/engram更新插件
# 更新到最新版本
openclaw plugins update engram
# 重启 Gateway 加载新版本
openclaw gateway restart配置
{
plugins: {
slots: { memory: "engram" },
entries: {
"engram": {
enabled: true,
config: {
shortTermDays: 7,
halfLifeDays: 30,
recallTopK: 3,
minScore: 0.01,
}
}
}
}
}CLI
openclaw memory-sys settle # 手动触发沉淀
openclaw memory-sys profile # 查看画像
openclaw memory-sys stats # 统计信息自进化模块 (self-evolving)
自动分析 OpenClaw 每天的召回日志,评估 query 与最终召回结果是否匹配,借助 LLM 判断召回质量,生成分析报告和错题集。
流程
触发自进化 → 分析新增召回日志 → 生成/追加报告 → 生成错题集 → 保存 checkpoint增量机制
通过 scripts/.self-evolving-checkpoint.json 记录每个日志文件已处理到第几个召回块,每次触发只分析新增的召回日志。适合定时器反复触发。
- 首次运行(无 checkpoint):自动全量分析
- 后续运行:只分析上次 checkpoint 之后新增的召回块
--full:忽略 checkpoint,清空旧报告全量重新分析
产出文件
| 文件 | 说明 |
|------|------|
| scripts/self-evolving.md | 完整分析报告(所有 case,包含通过和不通过) |
| scripts/self-evolving-errors.md | 错题集(仅包含不通过的 case,附问题分类统计) |
| scripts/.self-evolving-checkpoint.json | 增量 checkpoint(记录每个日期已处理的召回块数量) |
用法
# 分析今天新增的召回日志(增量)
npx tsx scripts/self-evolving.ts
# 分析指定日期(增量)
npx tsx scripts/self-evolving.ts --date 2026-03-24
# 分析最近 N 天(增量)
npx tsx scripts/self-evolving.ts --days 3
# 分析所有日志(增量)
npx tsx scripts/self-evolving.ts --all
# 忽略 checkpoint,全量重新分析
npx tsx scripts/self-evolving.ts --full
# 仅分析不写文件(预览)
npx tsx scripts/self-evolving.ts --dry-run命令行选项
选项:
--date <YYYY-MM-DD> 分析指定日期的日志(增量)
--all 分析所有日志(增量)
--days <N> 分析最近 N 天的日志(默认 1,增量)
--full 忽略 checkpoint,全量重新分析
--dry-run 仅分析不写文件
--threshold <N> 低于此评分才记录详细 case(默认 3)
-v, --verbose 详细输出
-h, --help 显示帮助错题集
错题集 (self-evolving-errors.md) 从报告中提取所有不通过的 case,包含:
- 问题分类统计表(BM25 / 向量 / 查询重写 / 权重 / 时间衰减等分类)
- 每个错题的:原始查询、查询重写、实际召回 vs 理想召回、问题描述、原因分析、改进措施
- 按日期分组,由旧到新排列
典型使用场景
- 日常定时触发:每天/每小时执行
npx tsx scripts/self-evolving.ts,只分析新增日志 - 全量重建:修改评估逻辑后,用
--full重新分析所有历史日志 - 查看问题趋势:打开
self-evolving-errors.md查看错题集和问题分类统计
模拟召回环境 (sim-recall)
独立的命令行召回测试环境,复用项目真实代码(RecallEngine + VectorStore + BM25Index),连接真实的 LanceDB 和 LLM 接口,用于在本地快速测试和迭代召回策略,无需发 npm 包。
原理
scripts/sim-recall.ts
├── 读取 ~/.openclaw/openclaw.json → 获取 API Key、模型配置
├── 读取 scripts/config.md → 获取 workspace 路径
├── import src/recall.ts → RecallEngine(完整召回流水线)
├── import src/vector.ts → VectorStore(LanceDB + Embedding)
├── import src/bm25.ts → BM25Index(jieba-wasm 分词)
├── import src/config.ts → parseConfig(配置解析)
├── import src/logger.ts → Logger(日志系统)
└── import src/profile.ts → ProfileManager(画像注入)与 OpenClaw 线上环境完全一致:同样的 jieba 分词、同样的 LLM query rewrite、同样的双路召回 + 分数融合 + MMR 重排。
前置条件
~/.openclaw/openclaw.json中已配置 engram 插件(包含 embedding/queryRewrite 的 API Key)scripts/config.md中已配置正确的 workspace 路径- 安装依赖:
npm install
基本用法
# 单次查询
npm run sim -- "你的查询内容"
# 详细日志模式(输出完整的召回流水线日志)
npm run sim:v -- "你的查询内容"
# 交互模式(持续输入查询,适合批量调试)
npm run sim:i命令行选项
npx tsx scripts/sim-recall.ts [选项] "查询内容"
选项:
-i, --interactive 交互模式(持续输入查询)
--no-rewrite 跳过 LLM 查询重写,直接用原始 query
--no-vector 仅 BM25 短期记忆(不查向量数据库)
--no-bm25 仅 Vector 长期记忆(不查 BM25)
--top-k <N> 覆盖 recallTopK(默认 3)
--min-score <N> 覆盖 minScore 阈值(默认 0.01)
-v, --verbose 输出完整的调试日志
-h, --help 显示帮助使用示例
# 测试股票相关记忆的召回
npm run sim -- "看看股票相关的有哪些文档"
# 跳过 LLM 重写,直接测试原始 query 的召回效果
npx tsx scripts/sim-recall.ts --no-rewrite "002109 K线"
# 只看 BM25 短期记忆的命中情况
npx tsx scripts/sim-recall.ts --no-vector --no-rewrite "002109"
# 只看向量长期记忆的命中情况
npx tsx scripts/sim-recall.ts --no-bm25 "股票查询偏好"
# 调整 topK 和 minScore
npx tsx scripts/sim-recall.ts --top-k 10 --min-score 0.05 "Wandy"
# 交互模式 + 详细日志,适合反复调试
npx tsx scripts/sim-recall.ts --interactive --verbose输出说明
每次查询会输出:
- 初始化信息 — workspace 路径、短期记忆/向量数据库位置、配置参数
- 召回流水线(verbose 模式)— query rewrite 结果、BM25 命中数、Vector 候选数、融合排序、MMR 重排
- 最终结果 — Top-K 条记忆,标注来源(
[短期]/[长期])、类别标签、得分
典型调试流程
- 先用
npm run sim:v -- "查询"看完整日志,定位问题在 BM25 还是 Vector - 分别用
--no-vector和--no-bm25隔离测试 - 用
--no-rewrite对比 query rewrite 前后的召回差异 - 修改
src/下的代码后,直接再跑npm run sim验证效果,无需重新编译或发包
短期记忆噪音清理 (cleanup-short-term)
一次性清理已有短期记忆文件中的自动化运行日志(HEARTBEAT、news-cron、天气推送、备份日志等),匹配 30+ 种噪音 pattern。
注意:v0.9.0 起已在写入侧拦截自动化 session,此脚本仅用于清理历史数据。
用法
# 预览模式(不修改文件,仅显示将被删除的条目)
npx tsx scripts/cleanup-short-term.ts --dry-run
# 正式清理
npx tsx scripts/cleanup-short-term.ts天气/新闻导入噪音清理 (clean-cron-weather-news)
清理短期记忆中的天气晨报、news-knowledge-base 定时导入等 cron 执行流水。只删"纯流水"行,保留有价值的内容(故障排查、配置变更、任务创建等)。
可重复运行——每次只处理尚未清理的噪音行,已清理过的文件不会被重复修改。适合加入定时任务定期执行。
用法
# 预览模式(不修改文件)
npx tsx scripts/clean-cron-weather-news.ts
# 正式清理
npx tsx scripts/clean-cron-weather-news.ts --apply覆盖的噪音类型
- 天气晨报发送/查询流水(
天气晨报 发送成功、广州天气 查询发送) - news-knowledge-base 定时导入(
news-import-hourly 执行、定时任务 新闻导入) - news-import 新闻导入流水(
news-import 新闻导入 | 36氪 虎嗅)
保护规则
包含以下关键词的行不会被删除:排查/故障/失败/异常/修复/bug/方案/讨论/测试/调试/配置/创建/问题/错误/中断/超时/限制/ACP/subagent/spawn
手动 Condense (manual-condense)
当 session 因 hook 遗漏(如之前缺少 command:reset 监听)或其他异常未被自动 condense 时,可以用此脚本手动补救——从 JSONL session 文件中提取对话,调用 LLM 精简后写入 short-term/ 目录。
用法
# 基本用法:指定 session 文件路径,自动从文件名推断日期
npx tsx scripts/manual-condense.ts <session-file-path>
# 指定目标日期(覆盖自动推断)
npx tsx scripts/manual-condense.ts <session-file-path> <YYYY-MM-DD>示例
# 补救一个因 /reset 未触发 condense 而遗漏的 session
npx tsx scripts/manual-condense.ts \
~/.openclaw/agents/main/sessions/7045fe60-bbf7-43a8-9d74-c378570733c6.jsonl.reset.2026-03-23T20-10-42.346Z \
2026-03-23处理流程
读取 JSONL session → 提取 user/assistant 消息 → 清理 metadata/噪音
→ 分段(每段 ≤5000 字符) → 调用 MiniMax LLM 精简
→ 合并 + 去重 → 追加写入 short-term/YYYY-MM-DD.md特性
- 消息提取:自动解析 JSONL 格式,过滤系统消息、命令、HEARTBEAT 等噪音
- 分段处理:长对话自动切分,避免 token 溢出
- 去重保护:写入前检查指纹,避免重复追加
- 日期推断:从
.reset.YYYY-MM-DDThh-mm-ss文件名自动提取日期 - 标记来源:写入时带
(manual-condense)标签,便于区分自动/手动记录
