仿生记忆插件 Biomimetic Memory Plugin(MVP)
一套可插拔的 AI 记忆层:热路径纯内存(< 5 ms) + DNA 式不可变冷归档(严格异步), 端到端打通「M1 归档决策 → M2 待机巩固 → M4 编码封存 → M3 指针/双通道召回 → M6 表达融合」。 运行期零第三方依赖,不含任何真实生化能力(
RealDNABackend仅为预留接口)。
| 项 | 状态 |
|---|---|
| 版本 | bmp 0.1.0(M1/M2/M3/M4/M6 全链路已实现) |
| 运行环境 | Python ≥ 3.9(实测 3.10.6),运行期零依赖,测试仅需 pytest |
| 归档后端 | mock(完整)/ object(完整,可接 S3/OSS/GCS)/ mock_stub(骨架)/ real(仅占位) |
| 真实 DNA 合成/测序 | ❌ 未实现(明确不在 MVP 范围,见 docs/BACKENDS.md) |
| 测试 | 25 个测试文件 / 312 passed,全量 pytest -q:0 failed / 0 xfail / 0 skip |
| 破坏性验证 | ✅ 已执行:注入"解码侧破坏"与"热路径 +10ms"均使测试变红,且字节级还原(见 docs/DELIVERY_REPORT.md §7) |
| 性能门禁 | 热路径 p95 < 5 ms、快通道 p95 < 2 ms、冷路径 p95 < 2 s(含 80 ms 后端延迟注入)、4000 指针选择性查询 p95 < 2 ms |
| 已知遗留 | 无 P0/P1 缺口:D-01~D-06 全部关闭(D-05 常量外置于最终提交完成) |
| 交付报告 | docs/DELIVERY_REPORT.md:缺陷时间线、修复证据、性能与验收结论 |
按需阅读:能不能用 / 进度 → 二;能力边界 → 三、四;跑起来 → §1;架构图 → 一;技术细节 → §1–§13;测试与报告 → docs/TEST_PLAN.md、docs/DELIVERY_REPORT.md。
零、安装为 DSH 插件
安装命令(源码安装,无需 NPM)
dsh plugin --profile web add github:JunGu-12138/Biomimetic-Memory-Plugin
插件仓库根目录即插件包(
package.json+cordis.patch.yml+index.mjs),dsh plugin add会把仓库克隆到 profile 的node_modules/dsh-bmp-memory并自动挂载为bmp-memory(见cordis.patch.yml)。
前置要求
| 依赖 | 版本 | 说明 |
|---|---|---|
| DSH | 支持 cordis 插件(package.json 的 dsh.bundle.patch) |
通过 cordis.patch.yml 挂载为 bmp-memory |
| Node.js | ≥ 18 | index.mjs 为 ESM(node:readline / node:child_process) |
| Python | ≥ 3.9 | 记忆引擎随包内嵌(src/bmp/**),无需 pip install,零第三方依赖 |
| (可选)虚拟环境 | — | 用 BMP_PYTHON 指向 venv 里的 python |
环境变量
| 变量 | 默认 | 说明 |
|---|---|---|
BMP_PYTHON |
python |
python 可执行文件(venv 请写全路径) |
BMP_SRC |
随包 ./src |
覆盖 python 引擎目录 |
BMP_DATA_DIR |
~/.dsh/bmp-memory |
归档与索引数据目录 |
BMP_LOG_LEVEL |
WARNING |
python 侧日志级别 |
BMP_MIN_SCORE |
0.15 |
检索最低相关度,低于该值返回「无匹配」 |
BMP_MAX_CAPTURE_CHARS |
1500 |
自动捕获单条长度上限 |
本插件注册的工具
| 工具 | 作用 |
|---|---|
bmp_remember |
显式记住:直接归档 + 立即验证可召回,返回 address / pointer_id / retrievable |
bmp_recall |
双通道召回(summary_hint 快通道 + archive_address 冷通道,失败自动降级) |
bmp_search |
只查索引(不碰归档),返回带 score 的候选,供阈值过滤 / rerank |
bmp_verify |
验证某条事实是否真的可召回 |
bmp_update |
修正记忆:新归档 + 新指针,旧指针失活(旧链保留) |
bmp_forget |
遗忘:失活指针,归档保留可审计 |
bmp_consolidate |
触发一轮待机巩固 |
bmp_memory_status |
健康 / 索引规模 / 队列深度 / p50-p95 延迟与成功率 |
安装后自检
# 1) 插件是否被识别
dsh plugin --profile web list
# 2) 端到端自检(不依赖宿主 UI):ping → remember → search → 噪声拦截
# <profile 目录> = DSH 的 profile 路径,例如 ~/.dsh/profiles/web
node <profile 目录>/node_modules/dsh-bmp-memory/index.mjs --selftest
# 期望最后一行:SELFTEST PASSED
在 DSH 里说「记住:PROJ-AI-MEDIA-2026 的工作区在 D:/work/ai-media」,工具返回中应出现
address=dna1.… 与 retrievable=true;新会话问「PROJ-AI-MEDIA-2026 工作区在哪」应能召回该事实。
仓库元信息
- 仓库需为公开仓库,并添加 GitHub topic
dsh-plugin - 仓库根目录
package.json声明包名dsh-bmp-memory(dsh plugin add据此识别插件) - 安装方式:
dsh plugin --profile web add github:JunGu-12138/Biomimetic-Memory-Plugin
社区声明:本项目为社区维护的开源插件,与 DeepSeek AI 无隶属关系,不代表官方,也不冒用官方名义。
一、架构图
┌─────────────────────────── 宿主AI框架 ───────────────────────────┐
│ after_turn(trace) before_recall(query) │
└───────────┬──────────────────────────────────────────┬──────────────────┘
│ 热路径(耗时 < 5 毫秒) │
┌────────▼─────────┐ ┌──────────▼───────────────┐
│ HotPathEngine │ │ M6 双通道召回模块 │
│ 显著性判定 + 缓冲区│ │ ① 摘要提示 快通道 │
│ M1 归档决策 │ │ ② 归档地址 冷通道 │
└────────┬─────────┘ └──────────┬───────────────┘
│ 非阻塞入队 │ 召回任务
┌───────────▼────────────────────────────────────────────▼──────────────┐
│ 异步运行时(守护进程工作线程,不阻塞同步请求) │
│ M2 待机巩固调度器 M3 冷召回工作线程 │
│ 空闲→限流→采样→对比(占位实现)→确认 触发→随机读取 │
│ →M4 封存→建立指针→更新权重 →解码→M6融合→返回结果 │
└───────────┬────────────────────────────────────────────┬──────────────┘
│ │
┌────────▼─────────┐ ┌────────────▼─────────────┐
│ M3 索引归档模块 │ │ M4 DNA编解码器 + 后端存储 │
│ 指针索引 │ │ 压缩→帧封装→加密→RS纠错→白化→四进制编码 │
│ (轻量指针/版本链) │ │ →GC/均聚物约束→前导码→归档地址 │
└──────────────────┘ └──────────────────────────┘
横切组件:配置中心 · 指标看板 · 追踪ID · 降级策略
降级链路:冷后端不可用 → 返回「暂不可还原」;解码失败 → 回退摘要提示; 密钥缺失 → 拒绝处理并告警(详见第 7 节)。
二、现在能不能用?(可用性判定 + 开发进度)
2.1 结论:可以用 —— 在 MVP 范围内,单机 Python 项目可直接接入
核心链路(写入 → 待机巩固 → 编码封存 → 冷召回 → 表达融合 → 降级 → 指标)已全部打通,并由 25 个测试文件 / 312 个用例守护,其中包含 1000 条编解码一致性、破坏性验证 A/B、性能门禁。
| 你的场景 | 能否用 | 说明 |
|---|---|---|
| 给对话式 Agent 加"长期记忆"(单机) | ✅ 可直接用 | 实现 3 个钩子(register_plugin / after_turn / before_recall),或直接用 InMemoryMemoryFramework 参考宿主 |
| 自建对象存储归档(S3/OSS/MinIO) | ✅ 可直接用 | 注入 ObjectStoreClient;建议覆写 get_range 成真正的 Range GET |
| 只想先联调链路,不落真数据 | ✅ 可用骨架 | backend.type = "mock_stub" + config/skeleton.json(写入按 failed 记账,召回自动降级) |
| 需要审计/回溯历史版本 | ✅ 可用 | 修正语义:新归档 + 新指针 active + 旧指针 active=false,旧链永久保留可读 |
| 多实例集群 / 数百 QPS | ❌ 暂不可用 | 索引在单进程内(可选 JSON 持久化),无分布式锁(见 §四 2.4) |
| 真实 DNA 长期归档 | ❌ 不可用 | RealDNABackend 仅预留接口,无合成/测序(见 docs/BACKENDS.md) |
| 需要 LLM 生成式回答 | ❌ 不可用 | 融合是确定性模板,naturalness 是启发式打分 |
| 强鉴权 / 严格多租户隔离 | ⚠️ 需宿主补 | tenant 只做检索过滤,权限模型由宿主负责 |
2.2 5 分钟上手(最小可用代码)
from bmp import BiomimeticMemoryPlugin, Config, MemoryItem
plugin = BiomimeticMemoryPlugin(Config.load()) # 读 config/default.json
# ① 写入(热路径,< 5 ms,纯内存)
plugin.observe_item(MemoryItem(text="我最喜欢的颜色是蓝色。", importance=0.9, role="user"))
# ② 待机巩固(异步:评分→采样→确认→编码封存→建指针→更权重)
report = plugin.consolidate_now(blocking=True)
print(report.sunk, report.addresses) # 1, ['dna1.ab.…']
# ③ 冷召回(双通道:summary_hint 快通道 + archive_address 冷通道,失败自动降级)
expr = plugin.recall_sync("我最喜欢什么颜色", explicit=True)
print(expr.text, expr.fidelity, expr.naturalness, expr.sources)
plugin.shutdown()
2.3 开发进度看板
MVP 需求:9/9 约束满足;登记缺陷:6/6 关闭(D-01~D-06);无 P0/P1 遗留。
| 模块 | 实现 | 测试 | 状态 |
|---|---|---|---|
| M1 归档决策器(五因子 / 分类型半衰期 / 惊讶门控) | ✅ | ✅ 33 例 | 完成 |
| M2 待机巩固调度(空闲触发 / 三重限流 / 异步 / 对比占位) | ✅ | ✅ | 完成 |
| M3 索引-归档接口层(7 字段指针 / 双通道 / 版本一致性 / RecallJob 状态机) | ✅ | ✅ | 完成 |
| M4 编解码器(压缩 / 加密 / RS / GC / 四进制 / 片段读 / 1000 条一致性) | ✅ | ✅ | 完成 |
M6 表达融合(证据池 / 三策略 / 来源与评分 / 【基于冷归档还原】) |
✅ | ✅ 16 例 | 完成 |
| 横切:配置中心 / 指标面板 / trace_id / 降级策略 | ✅ | ✅ | 完成 |
后端:mock / object / mock_stub / real(占位) |
✅ | ✅ | 完成 |
| 文档(8 份:README / ARCHITECTURE / INTERFACES / CONFIG / BACKENDS / TEST_PLAN / TEST_REPORT_TEMPLATE / DELIVERY_REPORT) | ✅ | — | 完成 |
| 测试资产 | ✅ 25 文件 / 312 用例 | ✅ 全绿 | 完成 |
| 破坏性验证(注入解码破坏 / 热路径 +10 ms) | ✅ 双红并字节级还原 | — | 完成 |
| 性能门禁(热路径 < 5 ms、快通道 < 2 ms、冷路径 < 2 s、4000 指针 < 2 ms) | ✅ | ✅ | 完成 |
2.4 可信度说明(为什么敢说"可以用")
| 阶段 | 事实 |
|---|---|
| 首次真实执行 | 28 个用例失败 → 揪出 5 个产品缺陷(帧 body_len 缺失、加密 tag 位置错误、软降级不记账、supersede 误增版本、通道命中率分母错误),全部修复 |
| 测试真实性审计 | 发现恒真断言 ×2、名义测试 ×1(ExplodingBackend 从未注入)、自证式度量 ×1(拿被测代码自报耗时当断言),已全部重写 |
| 破坏性验证 | 注入"解码侧破坏"与"热路径 +10 ms"均使测试变红,且注入前后 sha256 一致(证明测试有判别力、实验可重复) |
| 缺陷收敛 | D-01 倒排索引、D-02 异步归档、D-03 supersede 落盘、D-04 唯一 active、D-05 常量外置、D-06 端到端热路径指标 —— 全部关闭 |
完整证据链见
docs/DELIVERY_REPORT.md(缺陷时间线 + 修复要点 + 性能与验收结论)。
三、目前能做到什么
1.1 九条核心约束的达成情况
| # | 约束 | 现状 | 证据 / 说明 |
|---|---|---|---|
| 1 | 热路径开销 < 5 ms | ✅ observe() 满足⚠️ recall() 仅在索引规模小时满足 |
纯内存打分 + LRU + 无阻塞入队;PT-HOT-01/02 断言 p95;大索引下的快通道仍是 O(N) 扫描(缺陷 D-01) |
| 2 | DNA 归档严格异步 | ✅ 管线满足 ⚠️ 门面仍有同步写 API |
巩固与召回全部在 AsyncRuntime worker;PT-ASYNC-01 断言写入不在调用线程;archive_memory() 等同步入口待治理(D-02) |
| 3 | 归档不可变 + 指针版本一致 | ✅ 基本满足 | 内容寻址 + O_CREAT|O_EXCL/条件写 + ImmutabilityViolation;修正时新归档 + 新指针 active + 旧指针 active=false + 旧归档保留;rebuild() 会复活旧指针(D-03)、缺 item 级唯一 active 约束(D-04) |
| 4 | 编解码可逆、随机样本 100% | ✅ | 帧内 len+crc32 + ECC syndrome 复验 + HMAC;CT-CODEC-1000 要求 1000 条 100% 一致(含空/1B/UTF-8/不可压缩/边界长度) |
| 5 | 冷召回失败可降级 | ✅ | 后端不可用→暂不可还原;解码失败→summary_hint;密钥缺失→拒绝+告警;UT-DEG-01~04、FT-BACKEND/DECODE/KEY |
| 6 | 表达融合带来源与评分 | ✅ | text / sources / citations / fidelity / naturalness / provenance(【基于冷归档还原】) |
| 7 | 所有阈值外置 | ⚠️ 部分 | 主阈值全部在 config/default.json;仍有 6 组启发式常量硬编码(D-05) |
| 8 | 指标与日志齐全 | ✅ 基本满足 | p50/p95/p99、成功率、存储节省、Prometheus、JSON 日志 + trace_id;缺 hot_path.total_latency_ms(D-06) |
| 9 | 无真实生化依赖 | ✅ | dependencies = [];RealDNABackend 全方法抛 BackendUnavailable |
1.2 已实现的功能清单
A. 记忆写入与巩固(M1 / M2)
- 五因子归档决策:时效 0.30 / 频率 0.25 / 连接 0.20 / 紧迫 0.15 / 重要 0.10(权重、阈值全可配)。
- 分类型衰减半衰期:情景 2 天 / 程序 180 天 / 语义永久,支持逐类型覆盖。
- 惊讶门控:新颖度 + 极性冲突 → 越过阈值直接归档(一次性但反常的记忆不会被漏掉)。
- 三个动作档:
archive / defer / discard。 - 待机巩固调度器:空闲触发、三重限流(最小间隔 / 每小时配额 / 并发上限)、可复现的 ε-探索采样、确认下沉、调用封存、建指针、更新权重、结构化日志与指标。
- 事件钩子:
on_write/on_idle/on_retrieve(可同步/异步派发,异常隔离)。
B. 归档层(M4)
- 可逆编解码流水线:
压缩 → 帧 → 加密 → RS 纠错 → 白化 → 四进制映射 → GC/均聚物约束 → 前导 → 地址。 - 可配置:候选 profile 数、目标 GC 比例、均聚物上限、映射字母表、ECC 算法(RS / Hamming / 无)。
- 可逆压缩(zlib,仅当变小才用)与 密钥依赖加密(HMAC-SHA256-CTR + 截断 HMAC 标签;错钥/缺钥即失败)。
- 输出
codec_version与checksum = sha256(payload),写入归档元数据。 - 三个后端:本地不可变文件(
mock)、对象存储(object,含 Range 片段读取)、骨架占位(mock_stub);real仅接口。
C. 索引与召回(M3)
- 轻量指针:
pointer_id / archive_id / address / version / active / summary_hint / trigger_weights,永不存正文。 - 版本一致性:修正 → 新归档 + 新指针激活(
version+1、supersedes)+ 旧指针失活(superseded_by)+ 旧归档保留可审计。 - 双通道召回:
summary_hint快通道(微秒级、不触盘)+archive_address冷通道(异步RecallJob)。 RecallJob状态机:pending → running → done/degraded/failed/cancelled,终态不可覆盖、非法迁移留痕。- 冷召回全流程:触发 →
RecallJob→random_access→ 解码 → 融合 → 合并/送达(支持wait=False+ 回调送达)。
D. 表达融合(M6)
- 证据池承诺门控:保真度、降级、去重、容量四道闸;只表达已承诺证据。
evidence_first(原文 + 引用,保真最高)/scene_rebuild(按时间桶 + 主题切场景,自然度最高)/hybrid(先证据约束、再场景润色)。- 输出文本、
sources、citations、fidelity_score、naturalness_score,并标注【基于冷归档还原】(降级时标注【基于摘要提示还原】)。
E. 工程化
- 配置中心:
set/apply/reload+ 校验 + 版本号 + 变更审计 + 订阅回调 + 密钥脱敏。 - 指标面板:
render_text()/render_json()/render_prometheus()三种渲染,含 p50/p95/成功率/存储估算。 - 日志与 trace_id:
contextvars跨线程/异步传播,日志自动注入;span()轻量计时。 - 降级策略:三类失败语义统一分类、计数、告警(可注入
alert_sink)。
四、目前暂时做不到什么
2.1 明确不做(MVP 范围外)
| 项 | 说明 |
|---|---|
| 真实 DNA 合成与测序 | 无生化依赖、无合成/测序客户端;RealDNABackend 仅预留接口与契约(见 docs/BACKENDS.md) |
| 插入/删除错误纠错 | 只模拟替换错误(capabilities().indel_errors = False);indel 需要同步码或 consensus 对齐 |
| 用 LLM 生成/润色文本 | 融合是确定性模板,naturalness 是启发式打分,不调用任何模型 |
| 强鉴权与多租户隔离 | tenant 仅用于检索过滤,权限模型由宿主负责 |
| KMS / 密钥托管 | 加密为演示级(密钥来自配置或环境变量),无轮换策略与硬件保护 |
2.2 功能占位(已留接口、尚未实现)
| 项 | 现状 |
|---|---|
| 对比巩固(contrast consolidation) | PlaceholderContrastor:token 重叠 + 极性冲突的近似,placeholder=True 显式标注 |
| 自然度打分器 | 公式化启发式,FusionEngine 预留注入点 |
| 自定义存储 | 需自行实现 ColdArchiveBackend 或 ObjectStoreClient(get_range 需覆写才能真收益) |
2.3 工程化缺口(4 个 P0 已全部关闭,仅剩 1 项 P1)
| 编号 | 缺口 | 状态 |
|---|---|---|
| D-01(P0) | PointerIndex.search O(N) 全索引扫描 |
✅ 已修:倒排索引 token→{address} + 每指针 token 缓存;test_performance::test_fast_channel_scales_at_large_index 从 xfail 升级为硬门禁(4000 指针、选择性查询 p95 < 2 ms) |
| D-02(P0) | 门面暴露同步写归档 API | ✅ 已修:新增 archive_memory_async() / correct_memory_async()(返回 TaskHandle);同步版标注 ops/test only 并计数 api.sync_archive_call_total + WARN;bmp/tools.py 集中 *_sync 助手 |
| D-03(P0) | rebuild() 复活已 supersede 的旧指针 |
✅ 已修:correct() 把 supersedes 写入新链 metadata;rebuild() 先以 inactive 插入、再按版本链统一裁定 —— 与插入顺序无关 |
| D-04(P0) | 索引层未强制「同一 item 唯一 active」 | ✅ 已修:add() 自动退休同 trace_id 旧指针(superseded_by + history + 版本 +1) |
| D-05(P1) | 6 组启发式常量仍硬编码(检索打分权重、确认器保真度权重、相似度下限、fast_hit_threshold、max_scan、指针权重上限) |
✅ 已修:全部外置到 index.scoring.* / consolidation.confirm.fidelity_weights.* / consolidation.replay.{similarity_floor,max_scan} / scheduler.contrast.similarity_floor / recall.dual.fast_hit_threshold;tests/test_config_externalized.py 9 个用例逐个断言"改配置→行为变化" |
| D-06(P1) | 热路径度量未覆盖 hooks/trace 开销 | ✅ 已修:plugin.observe() 外层 LatencyBudget → hot_path.total_latency_ms,并把实测值写回 decision.total_latency_ms |
首跑还暴露了 5 个真实产品缺陷(帧
body_len缺失、加密 tag 位置、软降级不记账、supersede误增版本、通道命中率分母),全部已修复并有回归用例守护 —— 详见docs/DELIVERY_REPORT.md§2。
2.4 规模化与运维缺口
| 项 | 说明 |
|---|---|
| 单进程索引 | PointerIndex 在进程内 + 可选 JSON 持久化;多实例集群需外置索引(Redis/DB)+ 分布式锁 |
| 无后台 LRU 淘汰策略 | 索引按 index.max_pointers 淘汰最旧的,非 LRU |
| 无独立崩溃恢复 | 归档本身可重建指针,但作业/队列状态不持久化 |
| 无内置多语言检索 | 分词支持 ASCII + CJK 单字,无向量检索/语义召回 |
| 无权限审计日志 | 结构化日志只覆盖运行指标,非合规审计 |
| 单机验证范围 | 全量测试与破坏性验证均在单机完成:并发极限、长时间稳定性(>1 小时)未做压测 |
五、文档索引
| 文档 | 内容 |
|---|---|
ARCHITECTURE.md |
分层设计、模块划分、数据模型、时序流程 |
docs/INTERFACES.md |
接口文档(模型 / 后端 / 钩子 / M1-M6 / 降级) |
docs/CONFIG.md |
全部配置项、默认值、调参示例 |
docs/BACKENDS.md |
对象存储后端与真实 DNA 后端预留接口 |
docs/TEST_PLAN.md |
测试计划、60+ 用例清单(UT/IT/PT/CT/FT)、准入准出准则 |
docs/TEST_REPORT_TEMPLATE.md |
测试报告模板(由 scripts/test_report.py 自动填充) |
docs/DELIVERY_REPORT.md |
交付报告:里程碑完成度、5 个首跑缺陷、P0 关闭情况、破坏性验证证据、性能门禁 |
1. 安装与运行
pip install -e . # Python >= 3.9,无运行时依赖
pip install pytest # 可选,用于测试套件
pytest -q # 执行全套测试
python scripts/selftest.py # 无依赖的不变性自检程序
python scripts/run_demo.py # 带讲解的端到端演示
2. 使用示例
from bmp import BiomimeticMemoryPlugin, Config, Trace
plugin = BiomimeticMemoryPlugin(Config.load()) # 读取 config/default.json
# --- 热路径:同步执行,耗时 < 5 毫秒 -------------------------------------
decision = plugin.observe(Trace(text="我最喜欢的颜色是蓝色。", importance=0.9, role="user"))
print(decision.latency_ms, decision.queued)
# --- 冷路径:后台工作线程(空闲窗口触发,或手动触发) -----------
report = plugin.consolidate_now(blocking=True)
print(report.sunk, report.addresses)
# --- 冷召回:异步执行,出错时降级而不是直接抛出异常 ------------
expression = plugin.recall_sync("我最喜欢什么颜色", explicit=True)
print(expression.text, expression.fidelity, expression.naturalness, expression.citations[0].address)
plugin.shutdown()
接入宿主框架(适配 register_plugin / after_turn / before_recall):
from bmp.adapters.framework import InMemoryMemoryFramework
framework = InMemoryMemoryFramework(plugin) # 也可以使用你自己的适配器
framework.add_turn(["我住在柏林。"], importance=0.9)
plugin.consolidate_now(blocking=True)
print(framework.ask("我住在哪里?", explicit=True).text)
3. 基础骨架 API
宿主只依赖下面这一组稳定对外名称(详见 docs/INTERFACES.md):
from bmp import (
MemoryItem, ArchivePointer, ArchiveRecord, RecallJob, # 数据模型
ColdArchiveBackend, MockDNABackend, MockDNABackendStub, # 冷归档后端
HookEvent, Config, BiomimeticMemoryPlugin,
)
plugin = BiomimeticMemoryPlugin(Config.load("config/example.minimal.json"))
# ① 写入钩子:记忆被记录(热路径)
plugin.register_hook(HookEvent.ON_WRITE, lambda p: print("write", p.get("item").item_id))
# ② 待机钩子:巩固回合开始/结束
plugin.register_hook(HookEvent.ON_IDLE, lambda p: print("idle", p.get("phase")), mode="async")
# ③ 检索钩子:冷召回任务创建
plugin.register_hook(HookEvent.ON_RETRIEVE, lambda p: print("retrieve", p.get("query")))
plugin.observe_item(MemoryItem(text="我最喜欢的颜色是蓝色。", importance=0.9, role="user"))
plugin.consolidate_now(blocking=True)
print(plugin.recall_sync("最喜欢的颜色", explicit=True).text)
plugin.shutdown()
| 模型 | 含义 | 关键字段 |
|---|---|---|
MemoryItem |
宿主写入的记忆单元(Trace 的子类) | item_id(即 trace_id)、文本、租户标识、标签、重要度 |
ArchivePointer |
索引层轻量指针(Pointer 的子类) | record_address(归档地址)、摘要提示、权重、版本号、状态 |
ArchiveRecord |
归档记录描述符(不含原始载荷) | 地址、载荷字节数、符号数量、编码签名、配置模板 ID |
RecallJob |
冷召回任务 | 任务 ID、归档地址列表、状态、即时摘要、结果、超时毫秒数 |
class ColdArchiveBackend(ABC): # 统一冷归档接口
def write(self, payload, *, trace_id=None, hints=None) -> WriteResult
def read(self, address) -> ReadResult # 随机读取 + 解码
def random_access(self, address) -> StrandAccess # O(1) 根据地址读取链数据
def health(self) -> HealthStatus # 永远不抛出异常
MockDNABackend(工厂标识mock):完整实现 —— 本地不可变二进制文件 + 编码 + 噪声注入。MockDNABackendStub(工厂标识mock_stub):空骨架实现 —— 数据读写会抛出BackendUnavailable,health()做真实可用性检查(检测目录可写、编解码器可用)。使用config/skeleton.json可以先联调跑通全链路(热路径、钩子、指针、降级逻辑全部可用,归档写入标记为失败)。
$env:BMP_CONFIG = "config/skeleton.json" # 骨架联调配置
4. 各项保障对应的实现位置
| 保障能力 | 代码位置 |
|---|---|
| 归档是异步流程,不会阻塞同步路径 | core/hot_path.py、core/runtime.py、consolidation/worker.py、recall/worker.py |
| 热路径耗时 < 5ms | core/budget.py + 热路径延迟直方图 + 超时计数指标 |
| 归档数据不可修改 | archiving/mock_backend.py(新建排他 + 内容寻址)、archiving/object_backend.py(不存在才写入) |
| 轻量、带版本、可停用、可重建的指针 | index/pointer_index.py |
| 可逆编解码(比特流→四进制→GC / 均聚物约束→纠错码→地址) | archiving/codec.py、archiving/ecc.py、archiving/addresses.py |
统一后端接口 write/read/random_access/health |
archiving/backend.py(mock、对象存储、真实 DNA 三类后端) |
| 待机巩固流水线 | consolidation/{scorer,sampler,replay,confirmer,worker}.py |
| 冷召回 + 降级机制 | recall/{trigger,job,worker}.py |
证据优先 / 场景重建 / 混合模式,附带保真度、自然度评分 |
recall/fusion.py |
| 所有阈值都外置在配置文件 | config/default.json + config.py |
| 指标采集与结构化日志 | observability/metrics.py、observability/logging.py |
| 事件钩子(写入 / 待机 / 检索) | hooks.py + plugin.register_hook() |
| M1 归档决策(5 项因子、半衰期衰减、惊讶门控) | decision/scorer.py |
| M2 待机巩固(限流、异步、占位对比、M4 封存) | scheduler/scheduler.py、sealing.py |
| M3 轻量指针 + 双通道召回 + 版本一致修正 | index/interface.py、recall/dual.py |
| M6 表达融合(证据池、场景重建、混合策略、来源标注) | recall/fusion.py、recall/evidence.py |
5. 配置说明
所有配置都外置,配置加载优先级:
内置默认值 < config/default.json < Config.load(overrides=...) < 环境变量 BMP_OVERRIDES(JSON 字符串)
Config.load("my.json")
Config.load(overrides={"hot_path.budget_ms": 3.0})
# BMP_OVERRIDES='{"codec.profiles": 8, "recall.trigger.deadline_ms": 2500}'
核心配置分组:hot_path(热路径)、codec(编码模板、主种子、目标 GC 占比、最大均聚物长度、代价权重、纠错码参数)、backend(后端)、index(索引)、weights(衰减半衰期、增益系数)、consolidation(巩固窗口、批次、打分权重、回放阈值、确认阈值、重试)、recall(召回)、fusion(融合)、metrics(指标)、logging(日志)、storage_savings(存储优化)。
6. 后端存储
from bmp import (
ColdArchiveBackend, MockDNABackend, MockDNABackendStub,
ObjectStorageBackend, RealDNABackend, register_backend, DNACodec,
)
MockDNABackend(config, DNACodec(config)) # 'mock' 完整实现:本地不可变链文件
MockDNABackendStub(config, DNACodec(config)) # 'mock_stub' 骨架:仅接口 + 可用性检测
ObjectStorageBackend(config, DNACodec(config)) # 'object' 对接任意对象存储客户端(S3/OSS/GCS)
RealDNABackend(config, DNACodec(config)) # 'real' 占位:直接抛出后端不可用
register_backend("my_backend", MyBackend) # 注册自定义后端,之后配置 backend.type = "my_backend"
所有后端都继承自 ColdArchiveBackend,最少只需要实现 write / read / random_access / health;
可选实现 list_addresses / raw_meta / stats / capabilities,用于索引重建。
7. M4 编解码流水线
载荷 ──[可选zlib可逆压缩]──> 消息体
──[帧封装]─ 魔数|帧版本|标志|载荷长度|crc32|随机数 + 消息体
──[可选加密]─ 消息体 XOR HMAC-SHA256-CTR(密钥,随机数) + HMAC校验标签(头+体)
──[RS纠错码(GF256)]──> 系统码:原始数据 + 校验冗余
──[白化 splitmix64(模板种子)]──> 符号分布均匀化
──[四进制映射]─ 可配置字母表 + 翻转/补码变换
──[约束优化]─ 在16个候选模板里,选出GC、均聚物代价最低的方案
──[前导码]─ [模板ID,编码标志] 重复固定次数(固定映射)
──> 编码链 ──[生成地址]──> dna1.<区域>.<sha256前40位>
解码是严格逆流程;codec_flags 只携带 FLAG_ENCRYPTED(是否需要密钥),压缩标记放在帧头内,受纠错码和 HMAC 保护。
新增能力
| 能力 | 配置项 | 行为 |
|---|---|---|
| 可逆压缩 | codec.compression.{enabled,level,min_bytes} |
zlib deflate;只有压缩后体积更小才启用,标记写入帧头;解码按标记自动解压 |
| 密钥加密 | codec.encryption.{enabled,key,key_env,tag_bytes,nonce_bytes,deterministic} |
HMAC-SHA256-CTR 流加密(仅消息体)+ 截断 HMAC 标签;密钥错误 / 缺失 → 解码失败;默认确定性模式(相同内容生成相同地址,支持内容寻址去重) |
| 自定义四进制映射 | codec.mapping_table(ACGT 任意排列) |
映射表参与签名计算,不同映射表生成不同归档地址 |
| 编码版本 / 校验和 | codec.codec_version |
每次编解码返回 codec_version 和 checksum = sha256(原始载荷),同时写入后端元数据 |
| 片段随机读取 | random_access(address, offset=…, length=…) |
按符号偏移读取片段(本地文件 seek/read,对象存储 Range 分片拉取),返回 StrandAccess(offset, requested_length, total_symbols, is_fragment) |
enc = codec.encode(payload)
enc.codec_version # "m4.1"
enc.checksum # sha256(payload) 64位十六进制字符串
enc.compressed / enc.encrypted / enc.sealed_bytes
dec = codec.decode_with_report(enc.symbols)
assert dec.checksum == enc.checksum
frag = backend.random_access(enc.address, offset=100, length=256) # 读取片段
frag.symbols, frag.total_symbols, frag.is_fragment
一致性保证:tests/test_codec_consistency.py::test_one_thousand_random_payloads_roundtrip_100_percent
对 1000 条随机 / 边界载荷(空数据、1 字节、易压缩文本、UTF-8 JSON、不可压缩随机二进制)做断言:
载荷往返还原一致、校验和一致、编码版本一致、输出符号落在合法字母表内,要求 100% 通过。
解码三重校验:ECC 错码校验 → HMAC 校验(加密开启时)→ 帧长度 + CRC32。
8. 可观测性(配置中心 / 指标看板 / 日志 /trace_id)
from bmp.observability import trace_scope, current_trace_id
with trace_scope() as trace_id: # 作用域内所有日志自动带上追踪ID
plugin.observe(MemoryItem(text="…", importance=0.9, role="user"))
result = plugin.recall_dual("最喜欢的颜色", explicit=True)
assert result.trace_id == trace_id # 冷通道工作线程沿用同一个追踪ID
print(plugin.dashboard().render_text()) # 中文对齐看板(p50/p95/成功率/存储统计)
print(plugin.dashboard().render_json()) # 机器可读JSON格式
plugin.dashboard().render_prometheus() # prometheus抓取格式
plugin.set_config("fusion.max_evidence", 5) # 配置热更新、校验、审计
plugin.config_snapshot() # 配置版本、变更记录、脱敏后的完整配置
plugin.health()["config"] # 配置中心健康状态
- 配置中心
ConfigCenter:get/set/apply/reload、版本号、变更审计(路径 / 旧值 / 新值 / 来源 / 时间戳)、订阅回调、密钥自动脱敏(codec.encryption.key永远不会对外输出)。 - 指标看板
MetricsDashboard:一次性快照,三种渲染方式(文本 /json/prometheus)。 - 日志 + trace_id:基于
contextvars实现,跨线程、异步任务传递,绑定日志自动注入追踪 ID。 plugin.metrics_snapshot():p50/p95/p99 分位耗时、速率指标、存储指标;plugin.recent_logs()返回结构化日志环形缓冲区。
9. 降级语义(硬性约定)
| 场景 | 行为 | 告警 |
|---|---|---|
冷后端不可用(BackendUnavailable) |
返回 暂不可还原(冷归档不可用),不编造虚假内容 |
ERROR + alert.backend_unavailable_total |
| 解码失败(ECC/CRC/HMAC 校验失败) | 回退摘要提示,标记 degraded=True,降级原因 decode_failed |
WARNING + degrade.decode_failed_total |
| 密钥缺失 / 密钥错误 | 拒绝解析这条链,返回 暂不可还原(缺少解密密钥) |
ERROR + alert.key_missing_total |
| 无候选记录 / 超时 / 证据池为空 | 返回摘要提示或者「暂不可还原」,标记 degraded=True |
WARNING |
plugin.degradation.stats() 返回各降级原因计数;Expression.degraded_reason 和 DualRecallResult.reason/channel 让调用方可以编程区分故障类型;channel="unavailable" 代表硬故障。
10. 延迟边界(SLO)
| 流程 | 预算 | 监控指标 | 超时行为 |
|---|---|---|---|
热路径 observe() |
< 5 毫秒(默认 hot_path.budget_ms) |
hot_path.latency_ms p95 分位 |
计数 hot_path.budget_exceeded_total + WARN 告警,不重试 |
快通道 fast_recall() |
< 2 毫秒(纯内存) | m3.fast_channel_ms p95 分位 |
同上 |
| 冷召回端到端 | recall.trigger.deadline_ms(默认 4000 毫秒) |
m3.channel_total_ms p95 分位 |
超时触发降级,返回摘要提示 |
| 巩固回合 | 无硬上限,受 scheduler.min_interval_ms / max_rounds_per_hour / max_concurrent_rounds 限流 |
m2.round_ms |
直接拒绝新任务,不无限排队 |
| 归档写入 | 单条上限 scheduler.seal.max_payload_bytes(64 KB) |
m4.seal_ms |
重试 scheduler.retry.max_attempts 次后标记失败 |
不变约束:所有冷路径操作,都不能跑在同步请求线程内;observe()/recall() 只做内存计算 + 任务入队。
11. MVP 限制(版本限制)
- 不实现真实 DNA 流程:没有 DNA 合成、测序逻辑,无生化依赖;
RealDNABackend仅预留接口(见docs/BACKENDS.md)。 - 仅模拟替换错误:
capabilities().indel_errors = False;插入 / 删除错误需要同步码或者多序列比对共识,本版不支持。 - M3 对比巩固是占位实现:
PlaceholderContrastor用 token 重叠、极性冲突近似实现,显式标记placeholder=True。 - 内容生成是确定性模板:
naturalness只是启发式打分,不接入大模型;预留打分器注入接口。 - 单进程内存索引:
PointerIndex进程内,可选 JSON 持久化;多实例集群部署需要外置索引 + 分布式锁。 - 没有强鉴权、多租户隔离:
tenant只用来过滤检索结果,权限控制由宿主框架负责。 - 加密仅演示级别:HMAC-SHA256-CTR 确定性流加密,没有对接 KMS 密钥管理系统。
12. 验收测试命令
cd C:\dev\biomimetic-memory-plugin
pip install -e . ; pip install pytest
# 1) 全量测试(17+ 测试文件)
pytest -q
# 2) 关键里程碑单独验收
pytest -q tests/test_codec_consistency.py # 1000条编码解码一致性,要求100%通过
pytest -q tests/test_decision.py # M1 五因子、半衰期、惊讶门控
pytest -q tests/test_scheduler.py # M2 异步、限流、不阻塞
pytest -q tests/test_m3_interface.py # M3 指针、双通道、版本一致性
pytest -q tests/test_m6_fusion.py # M6 三策略、证据池、来源标注
pytest -q tests/test_hot_path.py # 热路径 p95 < 5ms
# 3) 不依赖pytest自检(降级、加密、片段读取、配置中心检查)
python scripts/selftest.py
# 4) 端到端演示(热写入 → 待机巩固 → 冷召回 → 指标看板)
python scripts/run_demo.py
13. 扩展开发指引
| 想要实现 | 做法 |
|---|---|
| 替换纠错码 ECC | 实现 ECCStrategy(encode、decode_detailed)或者使用 build_ecc 工厂 |
| 修改编码约束策略 | 继承 / 替换 DNACodec.assess 代价函数,通过 codec.cost_weights 配置 |
| 对接真实对象存储 | 实现 ObjectStoreClient(put_if_absent/get/head/list/get_range/health) |
| 对接真实 DNA 硬件 | 实现 ColdArchiveBackend,对接合成 / 测序服务;编解码器 DNACodec 可以复用 |
| 优化自然度评分 | 向 FusionEngine 注入自定义打分器(只有一处调用点) |
| 替换对比巩固模块 | 实现 Contrastor,传入 M2 调度器 |
| 自定义告警推送 | 给 DegradationPolicy 传入 alert_sink=(webhook、告警平台) |
No comments yet. Be the first to write one.