Monty / 千脑理论(Thousand Brains Project)学习笔记
本文整理自对 Numenta 发起的 Thousand Brains Project 开源项目 Monty 的源码精读,
并给出对 lightmem(LIMS 光明记忆)的借鉴与改造建议。
- 源码路径若无特别说明,均相对 Monty 仓库根目录 (本机克隆于
C:\codeartswork\tbp.monty,
来自 GitCode 镜像gh_mirrors/tb/tbp.monty,MIT 许可)。- 本文档目的:为 lightmem 的参考系组织 / 多信号融合 / 记忆组织设计提供可参考的工程范式。
- 免责:源码行号对应克隆时的 main 分支快照,仓库演进后可能变化,引用前请以当前代码为准。
0. 背景:千脑理论与 Monty
0.1 作者与理论
- Jeff Hawkins(杰夫·霍金斯) :Palm / Handspring 创始人,后转向神经科学,与 Donna Dubinsky 共同创办
Numenta(2005)。 - 《On Intelligence》(2004,中译《人工智能的未来》) 提出 HTM(Hierarchical Temporal Memory)。
- 《A Thousand Brains: A New Theory of Intelligence》(2021,中译《千脑智能》) 提出 千脑理论。
- 核心主张:
- 皮质柱即完整模型 :新皮层约 15 万个皮质柱(cortical column),每个柱独立学习"整个世界"的模型,
而非各学一部分再拼接。 - 参考系(Reference Frame) :借用大脑的网格细胞 / 位置细胞机制,每个皮质柱记录"物体特征相对于自己
的位置"。 - 通过运动学习(sensorimotor) :智能体主动移动传感器(手、眼)探测物体,用"移动---预测---校正"学习
物体三维结构。 - 投票(Voting):成千上万皮质柱各自给出假设,通过投票达成共识,解释大脑对噪声与遮挡的鲁棒性。
- 新旧脑理论:旧脑负责情绪/本能/生存,新脑(新皮层)负责智能与知识;智能 = 学习世界模型。
- 皮质柱即完整模型 :新皮层约 15 万个皮质柱(cortical column),每个柱独立学习"整个世界"的模型,
0.2 作者的开源项目谱系
| 阶段 | 项目 | 说明 |
|---|---|---|
| HTM 时代 | NuPIC (numenta/nupic,Python) |
2013 年开源的 HTM 官方实现 |
| htm.core(C++,社区维护) | 性能重写版 | |
| nupic.torch(PyTorch) | HTM 与深度学习结合 | |
| 千脑理论 | Thousand Brains Project --- Monty | 2024 年开源,MIT 许可,是千脑理论的直接工程实现 |
0.3 Monty 是什么
- 一个感觉---运动学习框架 :用可堆叠的"学习模块(Learning Module,≈皮质柱)" + 参考系 + 投票,
做物体/姿态识别。 - 当前为 early beta,主要用于研究验证。
- Monty 与 lightmem 的领域差异(很关键,别当同类):
| 维度 | Monty | lightmem (LIMS) |
|---|---|---|
| 输入 | 传感器流(视觉/触觉) | 文本、对话、工具结果 |
| 记忆单位 | 物体模型图(节点 pose+features,边=位移) | 结构化文本事实(五类 memory_kind) |
| 目标 | 识别物体与姿态 | 多租户共享的长期记忆存取 |
| 多租户/权限/投毒/双时态 | 没有 | 是核心(§4/§7) |
结论:表示与融合机制可借鉴,安全与合规部分没有现成可抄。
0.4 环境与可运行性(重要结论)
- 官方只支持 Linux / x86_64 ;依赖 Python 3.8 + conda +
habitat-sim(仅 conda/Linux)。
官方 getting-started 顶部明确警告:This guide will not work on Windows。 - Windows 的官方路线是 WSL + Ubuntu + Miniconda。
- 仓库另提供 uv 路线 (
.python-version= 3.13,simulator_mujocoextra,可跳过 Habitat),但官方标注为
实验性 / 暂不支持 (uv.lockprototype)。 - 本机与实验机为何跑不通:
| 环境 | 结论 |
|---|---|
| Windows 本机 | 虚拟化未开启 → WSL 不可用;Python 3.12 与 Monty 需要的 numpy<=1.23.5 冲突(numpy 1.23 无 3.12 wheel);Habitat-Sim 无 Windows 支持 |
| Linux 机 192.168.0.86 | 磁盘仅约 4.2G 可用 、内存 4G 且无 swap;官方 conda 环境(pytorch 1.13.1 + habitat-sim ≥5G)+ YCB 数据集装不下 |
- 因此本文改为源码精读,不依赖运行环境即可学习机制。
0.5 面向初学者的 Demo / 教程
- 没有网页 / 一键 notebook 式 demo :官方把真实 demo 列为未来计划(
docs/future-work/monty-demos.md仅一句占位)。 - 有分级教程 + 可直接运行的实验配置 :
- 入门组:
running-your-first-experiment、pretraining-a-model、running-inference-with-a-pretrained-model、
unsupervised-continual-learning、multiple-learning-modules - 进阶组(标注
[No Habitat Required],对初学者更友好):using-monty-in-a-custom-application、
using-monty-for-robotics、running-an-experiment-from-a-different-repository - 配置目录:
src/tbp/monty/conf/experiment/tutorial/,最轻的是first_experiment.yaml
→python run.py experiment=tutorial/first_experiment
- 入门组:
- 免装环境的直观材料 :仓库
docs/figures/how-monty-works/下有 11 个 gif
(sensor_moves.gif、object_moves.gif、voting_rf_transform.gif、burst_sampling.gif等);
官方 YouTube 亦有逐步讲解视频。
1. 仓库导航
1.1 目录地图
| 路径 | 作用 |
|---|---|
src/tbp/monty/frameworks/ |
核心:models(学习模块/证据匹配)、agents、environments、motor、sensors、loggers |
src/tbp/monty/conf/experiment/ |
Hydra 实验配置,跑 benchmark 用 |
src/tbp/monty/sensor_modules/ |
传感器模块(把原始感知转成统一 CMP 格式) |
docs/theory/ |
理论(WIP,README 让看论文) |
docs/how-monty-works/ |
实现原理,学习重点 |
docs/overview/glossary.md |
术语表,先读 |
docs/figures/how-monty-works/ |
原理配图与动画 |
benchmarks/ |
评测结果与任务定义 |
run.py / run_parallel.py |
入口脚本 |
1.2 概念 → 代码映射
| 千脑理论概念 | Monty 里对应物 |
|---|---|
| 皮质柱 | Learning Module → frameworks/models/evidence_matching/learning_module.py |
| 大脑各区域互联(heterarchy) | CMP 协议 + 模块堆叠 |
| 参考系 | graph_memory.py(LTM) + object_model.py(网格) |
| 物体模型(带位置的特征图) | object_model.py 的 GridObjectModel |
| 投票 | learning_module.py 的 send_out_vote / receive_votes |
| 运动/探索策略 | motor_policies.py、motor_system.py |
| 特征@姿态(统一语言) | CMP,见 src/tbp/monty/cmp.py |
1.3 建议学习顺序
docs/overview/glossary.md→ 建立术语docs/how-to-use-monty/getting-started.md→ 装环境、跑通docs/how-monty-works/implementation-overview.md→ 整体架构docs/how-monty-works/learning-module/evidence-based-learning-module.md→ 当前最优 LM- 读代码:先
abstract_monty_classes.py,再evidence_matching/下的 model / learning_module / graph_memory - 跑 benchmark(
conf/experiment/)观察投票收敛
2. 源码精读
第 1 讲:内存里到底存了什么
LM 的记忆分短期 buffer 与长期 graph memory 。长期记忆容器是 EvidenceGraphMemory
(src/tbp/monty/frameworks/models/evidence_matching/graph_memory.py),但它几乎只是"存/取/更新"的接口,
真正的数据在 GridObjectModel。
1.1 三张稀疏表(核心)
GridObjectModel.__init__(src/tbp/monty/frameworks/models/object_model.py)定义三个 4 维稀疏张量:
| 字段 | 含义 | 维度含义 |
|---|---|---|
_observation_count |
每个体素被观测几次 | 前 3 维 = 体素索引,第 4 维 = 计数 |
_feature_grid |
每个体素内特征的平均值 | 前 3 维 = 体素索引,第 4 维 = 特征向量 |
_location_grid |
每个体素内位置的平均值 | 前 3 维 = 体素索引,第 4 维 = xyz |
用稀疏张量省内存。这就是"参考系 + 网格"的落地:物体被离散成 3D 体素网格,每个格子记住
"那里观测到什么特征、平均位置在哪、看过几次"。
1.2 从网格到图:top-k 体素
_build_graph_from_grids 只做一件事:取观测次数最高的 k 个体素 (_get_top_k_voxel_indices,
k = max_nodes),把它们的平均位置/特征变成图的节点。
这是"constrained graph"的实现:观测多的区域留更多节点,平坦/少变区域被稀疏掉。
对应
grid_types_blue_mug.png、graph_constrains.png。
1.3 一个硬约束:越界 >10% 就拒绝
_update_grids 先判断多少观测落在网格外,若超过 10% 就抛 GridTooSmallError、整次更新作废 。
这实现了 max_size 约束------小模型装不下大物体,于是大物体靠"多个 LM 各自建不同分辨率模型"协作。
对应 grid_with_same_size.png。
1.4 更新时先变换再入库
update_model 第一步是 apply_rf_transform_to_points:把新观测从"身体参考系"变换到"模型参考系" ,
再并入网格。每次学习都要先做坐标对齐。
1.5 假设空间
Hypotheses(hypotheses.py)是四个平行数组,每个下标 = 一个假设:
evidence : 每个假设的当前证据分
locations : 该假设下,传感器在【模型参考系】中的位置
poses : 该假设对应的 3×3 旋转矩阵
possible : 该假设是否仍可能
每个物体(graph_id)各持有一份。整段识别过程,本质就是在每个物体各自的假设空间里不断加减 evidence。
第 2 讲:一次 matching step 发生了什么
入口 matching_step(learning_module.py):
if 是纯位置步: # is_location_only_step
_displace_hypotheses # 只平移假设,不改证据
return
buffer 记录位移
_compute_possible_matches(...)
if 没有任何可能匹配: 终止 = "no_match"
核心在 _update_possible_matches:
- 对每个已知物体分别更新证据 (
_update_evidence),彼此独立,可选多线程并行。 - 每次
_update_evidence做三件事:- 若该物体还没有假设空间,先建空的;
- 位移(displace) :把每个假设的位置按"这一步移动了多少"推进(
_displace_hypotheses)------证据不变,只搬位置; - 更新证据 (
hypotheses_updater.update_evidence):拿新观测特征与模型特征比,加减 evidence。
- 全部物体更新完后:
_threshold_possible_matches过滤 →_calculate_most_likely_hypothesis选 MLH。
关键直觉(对应
evidence_update2.png):"如果我在模型的位置 X、物体朝向 Y,那么移动 D 之后我应该到了 Z。"
位移 + 旋转假设 = 新的搜索位置。
对应动画 :sensor_moves.gif / object_moves.gif、evidence_update1.png / evidence_update2.png、movement_transform.gif。
一句话 :记忆 = 体素网格三张表 + top-k 图;推理 = 在"物体×姿态×位置"假设空间里,
用移动推进位置,用特征比对加证据,谁证据高谁就是答案。
第 3 讲:证据分怎么算
每个假设的 evidence 由**姿态证据(pose)+ 特征证据(feature)**相加。
3.1 特征证据:绝不给负分
核心在 DefaultFeatureEvidenceCalculator.calculate(feature_evidence/calculator.py):逐节点算存储特征与观测特征的差异:
- 数值特征 :绝对差
|stored - query| - 循环特征(HSV 的色相 H):取环上最小距离
- 分类特征 (
object_id):不等则为 1
然后最关键的一行:
feature_evidence = clip(tolerance - difference, 0, inf) / tolerance
含义:差异 < tolerance 才给正证据,完美匹配 = 1,超过 tolerance = 0------永远不扣分 。
最后按 feature_weights 加权平均。pose_vectors/pose_fully_defined 被排除,由姿态证据单独处理。
3.2 姿态证据:用"自定义距离"搜索
_calculate_evidence_for_new_locations(hypotheses_displacer.py):
- 先把观测的姿态向量按当前假设旋转过去(
rotate_pose_dependent_features)。 - 在图上找搜索位置的最近 K 个节点(KDTree)。
- 不用圆形半径 ,而用
get_custom_distances结合表面法向与曲率------沿表面方向搜得远、沿法向很快变远 ;
曲率决定"扁"还是"圆"。对应radius.png。 - 距离超过
max_match_distance的节点被 mask,该假设证据置 -1。
3.3 合并:取最大值,不是平均
pose_evidence + feature_evidence 后取 np.max(...)。
代码注释解释得很清楚:只要搜索半径内有一个好匹配就给高分 ,附近存在不匹配的点不影响------
这是对"特征快速变化区域 + 噪声位置"的鲁棒设计。
3.4 累积:有界 vs 无界
evidence = past_evidence * past_weight + new_evidence * present_weight
若 past_weight + present_weight == 1 → 有界 ;默认两者都为 1 → 无界累积,旧证据永不遗忘 。
文档明确说"未来有界更合理,尤其 agent 换物体时旧证据应失效"------与 lightmem"遗忘要显式化"同构。
3.5 别给"没希望"的假设浪费算力
evidence_update_threshold:默认 x_percent_threshold → 只更新"证据 ≥ 当前最高分 − 最高分·x%"的假设。
3.6 假设从哪来
_get_all_informed_possible_poses(hypotheses_updater.py):用观测的表面法向 + 曲率方向 ,
与模型每个节点存储的 pose_vectors 对齐,反推可能的旋转。因为曲率方向有 180° 歧义 ,每个位置通常得到
2 个旋转假设 ;平坦面/球面(两主曲率相等)则沿法向轴采样 N 个 。对应 evidence_init_all.png。
第 4 讲:投票(多模块共识)
4.1 发送
send_out_vote:证据经缩放(最高=1,最低=-1)后,凡超过 vote_evidence_threshold 的假设,
打包成 vote(location 相对身体 + pose_vectors + confidence),并附上本 LM 的 sensed_pose_rel_body。
4.2 接收
receive_votes → _update_evidence_with_vote:
- 把收到的 vote 位置建 KDTree。
- 对本 LM 的每条假设位置,找最近 3 个 vote。
- 取半径内最大 vote 证据(
np.ma.max),太远的被 mask。 - 并入本 LM 证据:有界时加权平均,无界时累加。
4.3 为什么需要参考系变换
vote 里的位置是相对投票者身体 的。接收方要结合双方的 sensed_pose_rel_body 算出相对位移,
把 vote 转到自己的参考系 才能比较------这就是 voting_rf_transform.gif 演示的"投票位置的参考系变换"。
一句话:投票让"每个物体一个假设空间"从各自为战变成互相背书,多个 LM 快速收敛到一致答案。
四讲总览:
观测 → 转移到模型参考系(update_model)
→ 每个物体:位移推进假设位置(_displace)
→ 姿态证据 + 特征证据(只加不减、半径内取max)
→ 累积 evidence(有界/无界由权重决定)
→ 多 LM 间投票(参考系变换后加热彼此假设)
→ 选 MLH、阈值筛 possible_matches
→ 姿态唯一 or 对称稳定 → 输出(物体, 姿态)
→ match / new_object / timeout
贯穿始终的两条原则 :① 一切先对齐参考系 再比较;② 只加证据不扣分、取最佳匹配。
第 5 讲:怎么判断"已经识别出来了"
5.1 选出 MLH
_calculate_most_likely_hypothesis:对每个物体取 argmax(evidence) 拿本物体头号姿态假设,
再跨物体比,证据最高的即 MLH ,返回 {graph_id, location, rotation, scale, evidence}。
记忆为空时退化成 new_object0。
5.2 哪些物体还算"可能"
_threshold_possible_matches 按证据分布决定候选物体列表:
- 证据分散(
std > 0.1)或最高证据 < 0:阈值th = max_ge − max_ge·x%,只保留证据 > th 的物体; - 记忆里只有 1 个物体:证据 ≥ 0 就算可能;
- 物体证据差不多:全部保留。
5.3 姿态是否"唯一"
_check_for_unique_poses 要求两条件同时成立:
- 位置唯一 :所有可能位置到其中心最大距离 <
path_similarity_threshold; - 旋转唯一 :所有可能旋转与 MLH 旋转夹角 ≤
pose_similarity_threshold(用旋转矩阵迹arccos((tr−1)/2))。
5.4 对称物体:用"连续稳定"代替"唯一"
圆柱、球类物体本来就有多个等价姿态 。_check_for_symmetry:
- 比较"这一步的可能假设集"与"上一步的"重叠是否 > 90%;
- 重叠 →
symmetry_evidence += 1,否则清零 (必须连续累积); - 累积到
required_symmetry_evidence即判定"对称"。
5.5 收尾与终止
get_unique_pose_if_available:位置/旋转唯一 或 对称成立 → 输出(location, rotation, scale),
写入detected_pose;否则返回 None("认出了物体但姿态未定")。update_terminal_condition:若候选物体不是恰好 1 个 ,就把所有姿态假设possible清空(先不解析姿态),
再交给父类按证据/步数决定terminal_state。set_detected_object决定结局:match→ 取候选里的物体 ID(识别成功);no_match/ 无候选 →new_object{n}(当新物体学进记忆);- 评估模式下超时但证据够 → 用 MLH,否则
None(不更新记忆)。
对应可视化:
possible_matches.png(候选收缩)、hyp_driven_example.png(用假设驱动探索)。
第 7 讲:从零学习新物体与 Burst Sampling
7.1 什么时候学新物体
收敛阶段 set_detected_object 返回 new_object{n} 时(见第 5 讲),LM 把本次 episode 收集到的位置/特征建成新模型。
- 建模入口
_build_graph(src/tbp/monty/frameworks/models/evidence_matching/graph_memory.py):
新建GridObjectModel→build_model(locations, features)→ 存入models_in_memory[graph_id][input_channel];
若GridTooSmallError则放弃(呼应第 1 讲的 10% 越界约束)。 - 加载预训练图用
_add_graph_to_memory(同文件):加载后把稀疏张量重新coalesce()。 - 对已有物体的追加观测用
_extend_graph(同文件)。
7.2 为什么需要 Burst Sampling
- 问题:刚接触一个新物体/新朝向时,系统不知道"物体在哪、朝向如何"。传统做法
_get_all_informed_possible_poses只在曲率方向对齐下生成 2 个 假设;遇到对称物体或曲率不明确时
假设太少、覆盖不足。 - 若在每个节点上都穷举所有朝向,假设数会爆炸。
- Burst Sampling 的思路:不确定时"爆发"生成一批假设,再用证据趋势淘汰 ------类似粒子滤波的重采样,
但是确定性实现。
7.3 实现:BurstSamplingHypothesesUpdater.update_evidence
src/tbp/monty/frameworks/models/evidence_matching/burst_sampling.py,每步在假设已位移之后执行:
_sample_count决定"保留几条旧、新建几条新":- 新建数 =
round(节点数 × sampling_multiplier),按通道 cap 到num_hyps_per_node并取整; - 旧假设的保留/删除交给
EvidenceSlopeTracker+deletion_trigger_slope。
- 新建数 =
_sample_existing_hypotheses:按斜率确定性保留(不是随机重采样)。_sample_new_hypotheses:只从 top-k 特征匹配最高的节点采样新假设------避免为低证据节点浪费算力。- 合并旧 + 新(
Hypotheses.concatenate),并tracker.update记录证据。
sampling_burst_steps:连续爆发若干步(每步递减),模拟"对不确定区域连续多采样"。- 每个节点生成几条假设由
_num_hyps_per_node决定:pose_fully_defined→ 2;否则 →umbilical_num_poses。
7.4 关键角色:EvidenceSlopeTracker
- 跟踪每个假设证据的斜率(趋势) ,用趋势 而非瞬时值决定删除
(src/tbp/monty/frameworks/models/evidence_matching/evidence_slope_tracker.py)。 - 好处:避免"某一步偶然高分"的错误假设被保留;上升趋势的假设值得保留。
- 对应图示
burst_sampling.gif。
7.5 与无监督学习的关系(官方 future-work)
- 现状:无监督下"新建参考系(模型)"的触发是"所有已知物体证据都为负、且超过最少步数"
(docs/future-work/learning-module-improvements/unsupervised-learning-with-burst-sampling.md)。 - 问题:burst sampling 下这个条件可能永远达不到 ------因为 burst 总会制造新假设并产生正证据
(不同物体的 1cm 局部补丁往往相似)。 - 官方建议:用 burst sampling 的持续时间本身作为"该建新模型"的信号。
- 状态:尚未默认启用。
第 8 讲:运动与探索策略
- LM 不决定"怎么动" ;
motor_system+motor_policies决定。但 LM 通过"候选"影响探索方向。 - 主要策略(
src/tbp/monty/frameworks/models/motor_policies.py):
| 类 | 作用 |
|---|---|
InformedPolicyRandomWalk |
带少量信息的随机游走 |
PredefinedPolicy |
预设轨迹(测试用) |
JumpToGoal |
直接跳到目标 |
InformedPolicy |
假设驱动:用当前假设规划下一个动作 |
NaiveScanPolicy |
朴素扫描 |
SurfacePolicy |
沿物体表面探索(保持接触,利用曲率) |
SurfacePolicyCurvatureInformed |
曲率引导的表面探索 |
- 假设驱动的判别性动作 :LM 用
get_top_two_mlh_ids/
get_top_two_pose_hypotheses_for_graph_id(learning_module.py)给出"两个还在竞争的候选",
motor 选择能区分它们的动作------这就是主动感知(active sensing)。 - 对应图示
hyp_driven_example.png、policies.png。
小结 :识别的完整闭环是"感知 → 假设 → 投票 → 收敛 → (识别成功 | 建新模型) ",
而"下一步怎么动"由运动策略根据当前假设主动决定,让不确定性下降最快。
3. CMP 消息与传感器模块(第 6 讲)
3.1 CMP 一句话定义
"Features at a pose"(某个姿态下的特征) (docs/overview/architecture-overview/cortical-messaging-protocol.md)。
所有组件(SM、LM、motor)都遵守它,因此可以任意拼接。pose = 3D 位置(相对身体)+ 3D 旋转;特征分两类:
- 形态学特征(morphological,随姿态变) :
pose_vectors(3×3 正交向量 = 表面法向 + 两个曲率方向)、
pose_fully_defined、on_object - 非形态学特征(non-morphological,不随姿态变) :color、texture、curvature,或 LM 层的
object_id
3.2 Message 类
Message(src/tbp/monty/cmp.py)是 CMP 的落地,字段:
location / morphological_features / non_morphological_features / confidence / pass_message /
sender_id / sender_type / process_features_in_lm。
构造时 _check_all_attributes 强制校验:pose_vectors 必须 (3,3)、pose_fully_defined 必须 bool、
location (3,)、confidence ∈ [0,1]。辅助方法固定语义:
get_surface_normal()= 第 0 个 pose 向量get_curvature_directions()= 第 1、2 个
3.3 同一个 Message,四种语义
| 发送方 | 语义 | 内容 |
|---|---|---|
| SM | 感知 percept | 观测到的特征@姿态 |
| LM | 假设/最可能感知 | 物体 ID + 姿态 |
| LM→motor | 目标 goal | 想去的位置/朝向 |
| LM↔LM | 投票 vote | 只含候选姿态 + 物体 ID,不含模态特征 |
Goal是Message的子类,允许 None 值,另带goal_tolerances。
3.4 传感器模块 = transform 流水线
SensorModule(src/tbp/monty/sensor_modules/sensor_module.py)自身不做具体处理 ,
而是把 SensorObservation 依次过一串可配置的 Transform,产出 Message percept。
关键在 update_state:用 agent 身体位姿 + 传感器相对位姿,算出传感器实际位姿:
position = agent.position + rotate(agent.rotation, sensor.position)
rotation = agent.rotation * sensor.rotation
这就是"相对身体"坐标的来源------所有 pose 建立在身体公共参考系上。
3.5 数据进入 LM 的链路 + 关键开关
SM: observation → transforms → Message(percept)
→ (connectivity) → LM 收到 percepts,存 buffer
→ matching_step 用它更新证据
matching_step 里过滤:
python
feature_percepts = [p for p in percepts if p.process_features_in_lm]
只有 process_features_in_lm=True 的消息才参与证据更新;否则只当"位置同步"(如纯移动步)。
3.6 sensed_pose_rel_body 从哪来
send_out_vote 从 buffer 取 buffer.get_current_pose(input_channel="first")------即最近一次 SM 感知的相对
身体位姿 。投票时靠它计算两个 LM 之间的位移,把 vote 从对方参考系变换到自己参考系。
3.7 一条重要边界:模型永不共享
协议文档明确写:
"At no point do we communicate structural model information between learning modules."
即:LM 之间只交换"特征@姿态/目标/投票",永不共享各自模型结构 。
这对 lightmem 是直接可用的设计论据------共享线索与姿态,不搬运完整记忆结构,既省带宽也降低投毒攻击面。
4. 对 lightmem 的映射与改造建议
4.1 映射总表
| Monty 机制(源码依据) | lightmem 落点 | 关系 |
|---|---|---|
graph memory:节点+位移边 (object_model.py) |
§3.2 ReferenceFrame | 可升级(当前是扁平维度) |
特征证据"只加不减 + 取 max"(calculator.py、hypotheses_displacer.py) |
§3.4 VoteFusion | 可借鉴算子 |
| 证据有界/无界 vs 换物体需失效 | §5.3 遗忘契约 | lightmem 更完善,反向验证 |
| buffer(STM)→LTM 的 episode 边界 | §2.2 / §3.5 L0→L1 | 可借鉴触发时机 |
CMP "同一 Message 多语义"(cmp.py) |
§4.1 统一 Schema | 同构 |
投票需参考系变换(cortical-messaging-protocol.md) |
§3.2 visibility=shared_user | 关键补充 |
4.2 建议 1:ReferenceFrame 从"扁平坐标"升级为"带位移边的记忆图"(高价值)
- Monty 依据 :graph memory 的节点是
pose+features,边是 displacement(从 A 到 B 需要的关系/动作)。 - lightmem 现状 :§3.2 是一组独立维度,记忆之间没有关系。
- 具体改法 :新增边表,让记忆可"跳转",关系类型建议
causal / temporal / task-flow / entity-alias。 - 收益 :支撑 §3.13 后台整合与多跳检索。
- 风险:边会膨胀,需与 §5 容量预算一起治理(可只对 L2 长期记忆建边)。
4.3 建议 2:VoteFusion 融合算子借鉴"只加不减 + 相对容差"(中价值)
- Monty 依据 :
feature_evidence = clip(tolerance − diff, 0, ∞) / tolerance------不匹配记 0,绝不给负分 ;
半径内取 max 而非平均。 - lightmem 现状 :§3.4 已是 rank 融合,接近融合需
(top1−top2)/top1 < 20%且top1 ≥ 0.6。 - 具体改法 :
- 明确------每个信号只贡献正向名次分,弱信号缺失记 0,不反向扣分;
- 把
20%显式定义为相对容差(tolerance),超容差候选"记 0"而非"扣分"。
- 保留差异 :lightmem 的"绝对分下限 0.6 禁止融合"是 Monty 没有的,应保留。
4.4 建议 3:用"参考系漂移"补强遗忘排序(中价值,反向借鉴)
- Monty 痛点 :evidence 默认无界累积、不遗忘,文档自承"换物体时旧证据应失效,有界更合理"。
- lightmem 现状 :§5.3 已有"遗忘观测契约 + 衰减与失效解耦",比 Monty 完善。
- 具体改法 :把 Monty 暴露的问题变成显式规则------排序衰减不应只由时间驱动 ;
当reference_frame的entity/scene/task与当前查询显著不同时,即使记忆"很新",排序分也应快速衰减。
4.5 建议 4:显式定义 L0→L1 的落库边界(低风险)
- Monty 依据 :buffer 只存当前 episode,episode 结束才 flush 进 LTM。
- lightmem 现状:§3.5/§3.13 是"持续捕获 → 压缩 → 整合",边界偏模糊。
- 具体改法 :定义显式 flush 事件------会话结束 / 话题切换 / 任务完成 / L0 容量阈值触发,而非随时写。
4.6 建议 5:把"投票参考系变换"制度化为多 Agent 共享的强制前置(高价值,安全相关)
- Monty 依据 :vote 是"相对发送者身体"的,接收方必须变换到自己 参考系;
且投票不是 bag-of-features,而依赖特征在世界的相对排布。 - lightmem 现状 :§3.2
shared_user让同用户下多 Agent 共享,但同一事实在不同 Agent 的
entity/scene 语境下可能指代不同。 - 具体改法 :跨 Agent 融合前强制做实体消解 (§3.14 EntityLinker)作为"参考系对齐";
未对齐的记忆只并列展示,禁止融合。 - 收益:直接加固 §7.5 投毒防护与共享安全。
4.7 建议 6:§3.4 的"候选池"显式化为查询级假设集(低价值,锦上添花)
- Monty 依据:每个物体维护假设空间(多 evidence),最后收敛。
- 具体改法 :把每次查询 top-k 结果显式记为一个"假设集",允许"触发澄清 → 再观测 → 收敛"。
4.8 不建议照搬(重要边界)
Monty 完全没有 多租户、权限、投毒、双时态------所以 §3.2 硬过滤、§4 双时态、§7 安全没有现成可抄,必须自研 。
反过来,Monty 的"模型永不共享 "原则可作为 §3.2 / §7.5 的设计论据。
4.9 优先级建议
- 建议 5 (参考系对齐,安全)与 建议 2(只加不减算子)------改动小、收益直接;
- 建议 1(记忆位移边)------价值最高但需配套存储与容量治理;
- 建议 3/4------规则层微调,低成本;
- 建议 6------可选增强。
5. 待落实的 lightmem.md 草稿(3 段)
以下草稿尚未落盘 到
lightmem.md,供评审后再决定插入。建议标为v1.6;三段均不触碰 §4.1 单一真源样例。
草稿 1 ------ 插入位置:§3.2 参考系坐标模块 之后(新起 §3.2.1)
markdown
### 3.2.1 记忆位移边(Memory Displacement Edges,拟新增 v1.6)
**职责:** 在扁平坐标之外,为记忆之间建立带类型、带权重的"位移边",支撑多跳召回与关系推理。
**依据:** 吸收《千脑智能》参考系思想------Monty 的物体图中,节点是"特征@姿态",边是 displacement。
**边字段(单一真源):**
| 字段 | 说明 |
|---|---|
| `from_memory_id` / `to_memory_id` | 边的两端(ULID) |
| `relation` | `causal` / `temporal` / `task-flow` / `entity-alias` |
| `weight` | `[0,1]`,进入 §3.4 软排序 |
| `created_at` | 边建立时间(只增) |
**约束(安全):** 位移边只用于软排序与多跳召回,不得跨越 §3.2 硬过滤边界;多跳设跳数上限 N(默认 2)
与权重衰减;L1 默认不建边,仅 L2 长期记忆建边。
草稿 2 ------ 插入位置:§3.2.1 之后(或并入 §3.14 实体链接)
markdown
### 3.2.2 跨 Agent 参考系对齐(强制前置,拟新增 v1.6)
**职责:** 跨 Agent 共享的记忆融合前,强制先做"参考系对齐",防止同一实体在不同上下文中被误合并。
**规则:**
- 凡 `visibility ∈ {shared_user, tenant, cross_tenant}` 的跨 Agent 融合,必须先经 §3.14 实体消解对齐
`entity/scene/task`。
- **未对齐的记忆只并列展示,禁止融合、禁止互相覆盖**;对齐失败时降级为"待人工确认"。
**依据:** Monty 中 vote 是"相对发送者身体"的,接收方必须变换到自己的参考系;且投票依赖特征在世界的相对排布。
草稿 3 ------ 插入位置:§3.4 投票融合模块 之后(新起 §3.4.1)
markdown
### 3.4.1 只加不减与相对容差(融合算子,拟新增 v1.6)
**职责:** 明确各融合信号的计分方向与容差语义,避免弱信号反向拖累整体。
**规则:**
- **只加不减:** 每个融合信号只贡献正向名次分;信号缺失或不匹配时记 `0`,不得记负分。
- **相对容差:** §3.4"接近融合"的 `(top1 - top2)/top1 < 20%` 中的 `20%` 明确定义为相对容差;
超出容差的候选按 `0` 计(不扣分)。
- **保留绝对下限:** `top1 ≥ 绝对分下限(默认 0.6)` 为融合硬门槛,低于下限禁止融合。
**依据:** Monty 特征证据 `clip(tolerance - diff, 0, inf) / tolerance`(不匹配即 0),
且搜索半径内取 max 而非平均。
6. 附录
6.1 术语表(精简)
| 术语 | 含义 |
|---|---|
| Learning Module (LM) | 学习模块,对应皮质柱 |
| Sensor Module (SM) | 传感器模块,把原始观测转成 CMP 消息 |
| CMP | 皮质消息协议,"features at a pose" |
| Reference Frame | 参考系,记录特征相对位置 |
| Graph Memory | LTM,物体模型图(节点 + 位移边) |
| GridObjectModel | 体素网格 + 三张稀疏表 + top-k 图 |
| Hypotheses | 每个物体的假设空间(evidence/location/pose/possible) |
| MLH | Most Likely Hypothesis,最可能假设 |
| Displacement | 位移,两次观测间的位置变化 |
| Vote | LM 间的横向投票(候选姿态 + 物体 ID) |
| Episode / Step / Epoch | 一次物体交互 / 一次移动+观测 / 一个训练轮次 |
6.2 关键图示索引(docs/figures/how-monty-works/)
| 图 | 对应机制 |
|---|---|
sensor_moves.gif / object_moves.gif |
传感器/物体移动与观测变化 |
evidence_update1.png / evidence_update2.png |
证据随移动累积 |
movement_transform.gif |
位移的参考系变换 |
voting_rf_transform.gif |
投票的参考系变换 |
burst_sampling.gif |
突发放采样(新物体建模) |
grid_types_blue_mug.png / graph_constrains.png |
网格与约束图 |
grid_with_same_size.png |
网格尺寸约束 |
radius.png / search_radius.png |
搜索半径与自定义距离 |
evidence_init_all.png |
假设初始化 |
possible_matches.png |
候选收缩 |
hyp_driven_example.png |
假设驱动探索 |
overview_diagram.png / scaling.png |
CMP 拓扑与扩展方式 |
6.3 参考
- 书籍:Jeff Hawkins,《千脑智能》(A Thousand Brains, 2021)
- 项目:Thousand Brains Project --- Monty(MIT 许可)
- 仓库内文档:
docs/overview/glossary.md、docs/how-monty-works/learning-module/、
docs/overview/architecture-overview/cortical-messaging-protocol.md - 关联设计文档:本仓
lightmem.md(§3.2 参考系、§3.4 投票融合、§4.1 统一 Schema、§5.3 固有价值)