多模态AGI现在的痛点,我越做越觉得不在模型规模上,而在一个很基础的理论细节上:你面前是一筐苹果,系统看见了红色和圆形,摸到了光滑表面,听见有人说“苹果”这个音,它怎么知道这些信息都必须绑在同一个对象上,而不是整齐地散落在不同维度里?这个问题在认知科学里叫绑定问题,它恰恰就是AGI基础理论中的一块硬骨头。如果你也整理过系统化的AGI理论清单,大概见过类似“18-5 捆绑”这种编号,我第一次看到时还以为是讲打包代码的,结果读进去才发现,这里讨论的是能让多模态AGI真正形成对象概念的计算机制。今天就围绕这个捆绑主题,把我自己的理解、推导过程和能直接落地的实验代码完整写出来。
我们平时聊AGI,多半在聊神经网络层数、数据规模、算力投入,但真正决定一个系统能不能产生结构化认知的,往往是那些容易被忽略的表示层问题。捆绑就是其中最有代表的一个。它回答的核心问题非常朴素:如果智能系统采用分布式表征,也就是一个概念分散存储在很多神经元或很多向量分量里,那么系统如何保证多个特征能像行李箱的绑带一样被牢牢固定成一个整体,而不是在计算过程中乱串。下面我会从问题来源讲起,再到符号向量架构的实现细节。
1. 为什么“捆绑”是AGI绕不开的基础问题
1.1 先厘清概念:捆绑问题到底在问什么
我最早接触“捆绑问题”这个词是在认知科学文献里,那时它叫Binding Problem,指的是大脑把物体的不同属性组合成单一感知对象时遇到的计算困难。举个最直观的例子:你看到一只奔跑的斑点狗,视觉皮层里同时有负责形状的神经元群、负责颜色的神经元群、负责运动的神经元群。斑点狗的斑点是黑色还是白色、跑动方向是左还是右,这些信息本身是分开编码的,但你最终感知到的是一条完整的、黑白相间且向右跑的狗,而不是三个各自飘浮的视觉碎片。
如果我们用传统符号系统,也就是像知识图谱那样的表示,这个问题似乎不难。你可以为这只狗建一个节点,属性用边连接,颜色、运动方向都挂在同一个节点上面。但AGI的一大假设是,智能系统不应该是纯符号操作,因为它要处理大量模糊的视觉、听觉信号,这些信号天然是分布式、连续向量形式的。于是矛盾来了:向量表征表达能力强,但特征之间没有天然的“分组边界”。你让一个编码器输出狗的512维特征向量,其中某些维度编码颜色,某些维度编码形状,但如果场景里同时有两只狗,你怎么保证关于第一只狗的颜色维度和形状维度不会和第二只狗的混在一起?
这就是捆绑问题在AGI基础理论中的真正位置。它不是一个脑科学话题,而是一个表征设计议题:分布式向量系统能否通过某种显式操作,把来自不同模态、不同属性通道的信息快速捆绑成对象,之后还能随时解绑。
1.2 多模态AGI如果解不开捆绑,就学不到结构化知识
只看单模态,比如纯图片分类,捆绑问题还不算致命。ResNet也好,ViT也好,它们可以通过深层非线性把对象信息折叠到特征空间里,分类头只要输出标签就行。但到了多模态AGI,情况完全不同。一个真正的多模态系统需要回答的往往不是“这是什么”,而是“图像里的X和语音里的Y、文本里的Z是不是同一个东西”。比如用户指着桌上的马克杯说“帮我把它拿过来”,系统必须把语音里的“它”指向视觉里的那个特定马克杯,而不是另一个尺寸差不多的马克杯。
这类跨模态指代任务,本质就是一次跨模态捆绑。如果模型只是把图像编码和文本编码放进同一个对比学习空间,让“马克杯”单词向量和马克杯图片向量距离比较近,它依然说不清楚:当画面中有三个马克杯时,语言里那个“它”到底绑定的是哪一个。你可能会说,那用注意力机制不就解决了吗,让语言特征去attend视觉特征。可注意力只能计算相似度权重,它输出的是一堆软权重分布,并没有把目标对象的全部属性真正打包成一个可独立引用的整体。我后面会详细展开注意力和捆绑之间的差别。
更根本的是,人理解世界不是靠一堆相似度矩阵,而是靠结构化的关系和角色扮演。比如理解“小明把球传给小红”,系统要能绑定出传球者=小明、接球者=小红、物体=球这样的三元结构。这种角色绑定还涉及组合泛化,同样的句子换掉主语或宾语,系统要能利用旧的绑定方式来处理新的具体内容。分布式表征如果不引入显式捆绑操作,面对这种任务就只能依赖训练数据里见过多少种角色组合,AGI显然不能这么干。所以现在很多做认知架构的人重新把目光投向符号向量架构,就是因为它能把符号操作的计算结构化能力,和神经网络分布式表征的语义丰富性融合到一起。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 捆绑为什么难:深度学习里的三个隐藏坑
2.1 注意力机制解决的是“选谁”,不是“绑一起”
有一阵子我以为Transformer的attention已经隐式解决了捆绑问题,毕竟自注意力确实在综合全局信息。后来自己动手做多模态检索,发现这种想法站不住脚。原因不复杂:attention分数描述的是一种软性加权关系,第i个词符和j个图像区域的相关性高,但它没有把i和j之间的绑定关系写成可恢复的结构。网络中没有任何一处存储着“语音的‘它’就是图像的3号区域”这种显式事实,所有关联都融化在权重矩阵的数值里了。
容易踩的第一个坑就是误把attention map当成了绑定结果。我试过可视化attention,当时觉得模型到了相关区域,但一旦换一个同类别的新样本,或者目标模态特征发生微调,原来清晰的对应关系立刻乱套。原因是attention的高响应只代表当前前向传播中该区域贡献较大,并没有形成一个可重新索引的对象。如果我们后续要追问“刚才视觉里那只马克杯是什么颜色的”,注意力体系里根本找不到一个抓手:你只能重新forward一次,让查询向量再去“找”颜色特征,而不能直接解开此前绑定的那个对象结构。
真正的捆绑应该是对象级的:系统内部要有一个操作,把这只马克杯的颜色向量、形状向量、位置向量、语义标签向量组合成一个新的复合向量,以后这个复合向量可以直接参与推理,也可以解开成分量。注意力做不到这种组合存储,它更像一个路由网络:侧重信息传播方向,而不是信息组织结构。这也是为什么即便模型能通过复杂的基准测试,它内部依然不具备显式的对象持久性,只要上下文窗口一换,同一实体的跨模态身份就可能跟着丢失。
2.2 对比学习能拉近特征,但不是真正的绑定
多模态模型的标配方案是CLIP式对比学习:用对比损失把“猫图片”和句子里的“猫”拉到向量空间中相近的位置。团队里有人问我,这难道不就是在做捆绑吗。这里必须区分清楚:对比学习至多是在做关联,不是在做绑定。关联是一种度量关系,绑定是一种组合操作。
区别在哪?举个例子,假设你有两个实体,实体A的图像特征和“苹果”的文本特征,实体B的图像特征和“梨”的文本特征。对比学习能够把这些配对的embedding拉得比较近,但它训练完后得到的只是“苹果文本向量落在苹果图片向量的附近”这样一个软特性。当你只有一段文字“那个红色的苹果”,文本向量里混入了“红色”和“苹果”两种信息,对比学习空间并没有内置机制可以干净地把它们拆成两个分量,再分别和视觉里的颜色通道、类别通道绑定。
更进一步,对比学习高度依赖负样本采样。如果训练批里把所有类别都采样均匀,模型学习到的近似配对关系可以工作;一旦出现长尾实体、罕见颜色组合、多物体堆叠,近似相似度就会崩。因为对比损失本质上鼓励modal-specific的局部对齐,而不是跨模态的结构组合。从系统角度看,真实物体的属性数是可变的,图像里有颜色、纹理、形状、空间关系、运动信息;语言里有名称、属性词、量词、数量。真正的多模态AGI需要一个操作能够接收任意多条属性信息并统一输出一个绑定对象。这个操作必须具有组合性:对一组向量做绑定之后,结果和输入有确定的关系;同时还要具有可逆性:你给定查询属性,可以把原始标量属性重新提取出来。对比学习显然不满足这些条件。
2.3 组合爆炸:简单地“拼一起”会走到死路
不做绑定,还有一个常见做法是把各个特征维度拼接成一个超长向量,以为这样就能表示对象。原始图像向量、文本向量、位置向量一次性拼接,丢给后续分类器或解码器。这种方案有两个问题。第一是维度灾难。假设每个模态的输出是1024维,跨模态拼接成4096维,模型要学的参数随之膨胀,可能推理没做几次,计算就开始爆炸。当然,拼接客观上把不同模态的特征放在同一个输入空间里,这在工程上可行,但从认知上讲,它丢失了模块性。
第二是组合爆炸更深远的问题。系统面对的潜在对象往往是所有属性值的叉积组合。比如系统要处理颜色为红色/绿色,形状为圆形/三角形,位置为左上/右下的组合,理论上就有2乘2乘2共8种对象。如果把颜色维度每个值编码成方向各异的512维向量,形状也是,位置也是,那么新对象不可能靠元素的线性求和来表示。原因在于两个不同对象如果加起来都是“红色+圆形+左上”,那么第三个对象“红色+三角形+左上”就会和前两个纠缠不清,无解。
分布式表征里最危险的坑就是线性叠加。向量相加是许多模型融合信息的默认方法,但它天然造成信息污染:你加进来的所有输入都会保留在所有输出里。捆绑操作必须做到近似正交的保留:绑定的结果要能区分“红色圆形左上”和“红色三角形左上”,并且尽量不让参与绑定的各分量互相干扰。这意味着我们需要一种数学上更精巧的运算,这正是向量符号架构里绑定/解绑操作的意义。
3. 实操:向量符号架构怎样把“捆绑”变成可计算操作
3.1 核心思想与运算定义
为了解决分布式表征下的打包捆绑问题,上世纪九十年代发展出了一套向量符号架构,后来研究者又把它和超维计算结合起来。这套架构里最核心的哲学是:用上千维的随机高维向量作为符号的载体,把符号操作转化为向量运算。
它的三个基本操作是:
- 叠加:向量加法,用于表示一个集合,比如“场景中有猫和狗”
- 捆绑:一种可逆的乘法操作,用于表示属性-值的结构,比如“猫的颜色是棕色”
- 解绑:捆绑的逆操作,给定捆绑结果和猫的查询,能恢复出颜色向量
其中具体实现最常用的是循环卷积绑定。两个高维向量通过循环卷积可以得到一个新向量,后者和哪个输入都不相似,从而避免产生虚假相似度干扰;但循环卷积又保留了可逆性。这个特性让循环卷积非常像在符号系统里给两个概念之间拉了根“绑带”。你输入颜色向量和对象向量,输出的是“具有某种颜色的对象向量”。如果要解绑,把输出和查询向量做循环相关,就能近似恢复出原来的属性向量。
为什么需要极低相似性?因为绑定如果不生成一个全新的向量,而是类似线性加法的混合,那么后来的记忆检索就会出现交叉污染。想象一个共用的记忆板,如果属性都直接写上去,叠加太多字,你完全看不清具体每个字;循环卷积相当于用一套独立的密文把每个钉子单独锁好,再放在一张板子上。读取时,你有对应钥匙就能把某一份单独抽出来。
3.2 用Python实现一个最小绑定系统
下面这段代码基于numpy实现了最基本的VSA绑定和解绑系统。我在自己的实验里用这个骨架来验证“红色苹果”和“绿色梨”这类结构能否在分布式向量中保持独立。
python复制import numpy as np
DIM = 2048
def generate_hypervector(seed):
"""生成一个维度为DIM的高维随机向量,元素为+1或-1"""
rng = np.random.default_rng(seed)
return rng.choice([-1.0, 1.0], size=DIM)
def circular_convolution(a, b):
"""循环卷积,用于绑定两个向量"""
return np.real(np.fft.ifft(np.fft.fft(a) * np.fft.fft(b)))
def circular_correlation(a, b):
"""循环相关,用于解绑:给定a和捆绑结果b,恢复出另一个向量"""
return np.real(np.fft.ifft(np.conj(np.fft.fft(a)) * np.fft.fft(b)))
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b) + 1e-9)
# 生成概念向量
apple = generate_hypervector(42)
red = generate_hypervector(1)
sphere = generate_hypervector(2)
# 绑定:苹果的颜色是红色
bound_color = circular_convolution(apple, red)
# 绑定:苹果的形状是球形
bound_shape = circular_convolution(apple, sphere)
# 对象整体可以表示为一个捆绑组合
apple_object = bound_color + bound_shape
# 解绑:用苹果查询,恢复颜色
recovered_color = circular_correlation(apple, apple_object)
# 这里相当于 apple 分别和 bind(apple, red) 和 bind(apple, sphere) 做相关,
# 其中 red 的能量会保留下来,sphere 的能量会被抑制
print("和red的相似度:", round(cosine_similarity(recovered_color, red), 4))
print("和sphere的相似度:", round(cosine_similarity(recovered_color, sphere), 4))
运行这段代码,只要你维度不低于2048,每次会观察到恢复出的向量和原始red向量的相似度远高于和sphere的相似度。这就是解绑成功的标志。需要注意一个细节,解绑通常不能完美恢复原向量,因为叠加过程中的干扰是客观存在的;但高维随机向量的正交性保证了噪声相对较小,且维度越大恢复质量越好。所以VSA系统里没有完美的可逆性,只有统计意义上的高概率恢复。
3.3 把视觉、语言放进同一套绑定系统
单纯做图像属性绑定只是热身。实际的多模态AGI要把视觉特征、文本特征、位置特征全部塞到同一套操作里。你可能会担心,预训练模型的embedding和随机高维向量差异太大,怎么融合。我的思路是把VSA当作一个语义工作台,不要求预训练模型直接输出VSA风格向量,而是把高层语义标签映射成高维向量后再做结构操作。
更具体的流程是这样的:
- 用一个标准视觉模型检测场景中的对象,得到离散的位置框与类别标签;
- 用文本编码器理解用户指令,抽取出核心名词和属性;
- 把所有离散标签映射到固定随机种子生成的高维符号向量(颜色、形状、物体类别、位置标签都各自生成);
- 用循环卷积完成绑定,得到当前场景的对象集合向量;
- 后续的推理通过解绑操作按需提取物体具体属性。
我见过的一些认知架构,比如用VSA做机器人的任务规划,走的正是这条路线。位置也可以做成向量,例如五个预设网格位置各对应一个随机向量,然后把“苹果在位置左边”绑定为 bind(apple, left)。空间上更细粒度的坐标也做了扩展,用方式就是坐标数值先随机投影成高维向量,再和对象id绑定。真实项目中只要增加少量预设标签,就能把符号系统里“对象-属性-值”的三元事实全部编码成统一的分布式向量。
4. 从理论到系统:多模态AGI里的“捆绑层”可以这样搭
4.1 给现有大模型配一个可访问的捆绑工作区
明白了基础操作后,自然想把捆绑机制嵌入实际的大模型系统。我的尝试是在视觉语言模型基础上增加一个短期记忆模块,这个模块的核心就是高维向量工作区。
系统大致分三段。第一段是感知编码:进来一段视频,模型抽取若干帧,跑一个开放词表的目标检测器,得到一系列区域特征和类别名。第二段是符号化:这些检测结果不是当作连续特征直接用,而是转换成离散的符号标签;这一步看起来像“倒退到传统CV”,但恰恰是它提供了干净的可组合单元。第三段是绑定工作区:每个检测到的对象用一个对象ID向量或“类别+位置”向量表示,然后直接循环卷积掉相关属性。比如“3号视频片段里有一个人穿红色外套”,系统内部就表示为 bind(person_at_3, red_coat) / bind(person_at_3, wearing)。
很多朋友听到把连续特征转成离散符号标签,第一反应是丢了信息。但VSA的巧妙之处在于它并没有完全抛弃分布式表征:每个符号标签本身就是高维分布式向量,背后还可以关联预训练模型的连续特征。也就是说,你可以在一个平面上用符号向量来做结构操作,同时保留高维向量到底层连续特征的逆向映射。具体做法是给每个符号也分配一个连续属性的锚定向量,当模型需要判断“红色大衣”和“深红色大衣”之间细微差异时,可以解码绑定结果拿到连续属性向量再比较。这样既有了组合性,又保留了语义丰富性。
4.2 一个具体任务:倒一杯水需要哪些绑定
为了不让自己停留在空谈理论,这里演示一个具体的任务剖析。假设我们要做一个多模态AGI,输入是桌面的视频和一句自然语言指令:“把空杯子递过来,再往里面倒水。”
这时的绑定层至少要做以下几组任务:
- 指代消解:句子里的“空杯子”必须把视觉检测到的空杯子和非空杯子区分开。系统可以绑定出两个候选对象的特征:bind(cup1, empty) 和 bind(cup2, filled_with_coffee)。
- 角色分配:指令中两个关键动作“递过来”和“倒水”要分别作用在不同对象上。模型的工作区记录成 bind(action_deliver, cup1) 和 bind(action_pour, water_source)。
- 状态更新:任务执行后,系统的内部状态要产生新的绑定关系,比如 cup1 变成 bind(cup1, filled_with_water),之前绑定的 empty 属性被解绑移除。
关键是,这些绑定关系不是靠一整条全连接网络隐式计算,而是模型可以显式读写的一块工作区。当后续机器人需要判断“还要不要再倒水”,它只需要解绑当前 cup1 的状态就能取得当前水量,不需要重新看一遍整段视频。我实测下来,这种显式工作区让长程任务的错误率显著下降,因为系统不再依赖网络把几百步之前的信息一直记在隐状态里,而是在每一步都重新解绑所需属性。
4.3 用超维向量做具身空间的锚点
多模态AGI最终往往要落到机器人上。这里有个环境绑定问题值得单独提醒:空间坐标如果不直接绑到对象上,机械臂很难持续追踪同一个物体。实践中,我给候选对象分配一个空间锚向量,它随物体移动而更新,同时保留对象类别向量和实例ID向量的绑定关系。机器人的底层路径规划器每次抓取前,先去解绑“实例ID-空间坐标”得到最新坐标,再利用该坐标执行轨迹规划。
这套思路在动态场景下比纯端到端模型更稳。端到端方案容易丢掉实例身份,往往前一帧还认得这个杯子,后一帧跟踪框稍微抖动,实例就换了ID。有了显式绑定,跟踪系统可以保持“杯子轨迹”和“杯子”之间的绑定关系不变,框的位置变化只是更新绑定的坐标分量。这种差异类似于纯靠图像相似度匹配的老方法,和带有明确追踪对象身份的现代多目标跟踪器之间的区别。后者胜出的根本原因就是绑定机制。
5. 容易翻车的三个点与排查建议
5.1 维度选小了,容量不够
VSA用得越久越能体会到维度就是生命线。项目初期我偷懒用了512维,觉得向量短一点计算快。结果在对象数量稍多时开始出现恢复模糊,解绑“第3个物体的颜色”时竟然混进了其他物体的属性特征。后来拆解下来发现是512维的存储容量太低,高维随机向量之间的近似正交性被破坏了。
在实际系统里确定维度,可以参考这个经验公式:设系统同时要存储的对象数为M,每个对象绑定的属性数为K,那么工作区总的信息项约为M×K。维度最好在信息项的5到10倍以上。比如同时跟踪20个物体,每个4个属性,那就是80个绑定项,至少上1000维才保险。我自己最终统一用4096维或8192维,计算压力并不会像想象中那么大,因为运算都可以通过FFT在毫秒级完成。若是想要更低的维度,可以考虑正交编码或分块编码,但通常收益有限,建议不要为了省一点计算在维度上抠门。
5.2 把“绑定”和“叠加”混为一谈
这是我见过新手最容易犯的错。很多人看了VSA代码后以为核心就是把向量相加,因为注意力机制里常用加和池化。实际上,向量加法只能表示集合或汇总,它不具备可逆性。你在代码里做一下测试就能发现问题:执行 a+b+c 后,想从结果里提取a对应的成分,你拿a去做内积,结果会包含b和c的干扰,但找不到一个精确操作可以把a干净地提取出来。这导致信息存储随项目增多快速劣化。
反过来,循环卷积绑定的美妙之处在于每个被绑定信息都会被打散到整个高维空间里,你在任意局部区域看不到原始向量的影子。这听起来和叠加相似,但差别在于:生成的结果可解绑且互相干扰小,而且具备近似组合置换的性质。比如你可以验证循环卷积在不同输入对之间近似满足乘法交换律,可逆性既保证了结构又保留了灵活性。项目代码里,最直观的测试方法是随机取两个向量做绑定再解绑,看恢复出的向量是否与原始向量高相似,不符合预期就说明你可能用了加法做绑定。
5.3 高维表征和预训练模型接口不兼容
很多朋友会问,能不能直接拿CLIP或GPT输出的embedding喂给VSA的绑定层。我试验过,效果很糟糕。原因在于预训练模型的骨干虽然经过训练,但其向量空间并不是为了算术级绑定/解绑设计的,只是近似空间不是一种代数结构。VSA要求向量之间具有统计正交性,且最好能从随机的固定种子生成,这才能保证盲绑定不互相干扰。而预训练embedding空间里,苹果向量和香蕉向量往往有很高的余弦相似度,你直接把它们做循环卷积,解绑时极易相互污染。
解决思路分两步。第一步,把预训练模型的连续输出作为索引候选;第二步,把其语义标签转换为VSA架构产生的离线随机高维向量。你需要一个从CLIP空间映射到离散标签的投影层,可以是简单的最近邻分类器,也可以是一个轻量线性层。这类接口需要保证:所有同一标签的高维向量必须唯一且固定,不能因为输入图片尺寸或拍摄角度的微小变化而改变。这就好比人脑里“红色”这个符号不管在什么光照下都对应同一个心智符号,真正用于计算的是符号级别的高维向量。
5.4 常见问题排查速查表
| 现象 | 可能原因 | 解决方向 |
|---|---|---|
| 解绑恢复出的属性相似度普遍偏低 | 向量维度太低或叠加了太多对象 | 提升到4096维以上;减少同时绑定的数量 |
| 两个对象的属性互相污染 | 绑定使用了线性加法而不是循环卷积捆绑 | 换成循环卷积;检查相关实现是否是FFT乘法 |
| 预训练模型直接绑定时效果差 | 向量空间不具备正交代数结构 | 用VSA向量替换连续embedding,再建映射层 |
| 多模态对齐后指代仍错乱 | 对比学习软关联无法应对同类别多实例 | 增加显式场景工作区和位置跟踪绑定 |
| 长程任务丢物体身份 | 没有安装从上一帧到下一帧的ID绑定 | 把实例ID向量和位置/外观向量做持续绑定更新 |
这里再补充一个经验:调试VSA模块时,代码其实很短,所以问题的根源基本都出现在“数据到底用哪些标签”“标签映射是否唯一”“状态更新的顺序对不对”。我建议你在集成前先做一个简单的单元测试:构造一个包含5个对象的合成场景,每个对象5个属性,每步执行绑定、添加、解绑,验证恢复出的向量与原始输入属性相似度是否稳定超过0.1。如果这个测试过不了,后续怎么扩展都有可能脆断。这种测试搭建起来大约只需要50行代码,越早写越省时间。
捆绑看上去是个笨办法,离“大模型”路线很远,但当你同时面对复杂任务的状态管理和多模态指代问题时,回头再来补这块基础理论,会看到它在结构化认知上的价值。我自己目前已经在几个系统里用这套方法替换了原来纯靠attention做关系抽取的底层模块,整体稳定性和可解释性都上了一个台阶。这套架构后续还能继续扩展的方向很多,比如把时序信息也纳入绑定对象、绑定和神经网络反向传播协同训练、在符号空间做因果推理等,后面有机会再单独写展开聊。
