工具大全
亲手实测作者:Coocon2026年9月26日7 次阅读约 11 分钟阅读

把 13.9 万个果蝇神经元搬进 Mac mini:不给任何输入,它会自己动起来吗?

把 13.9 万个果蝇神经元搬进 Mac mini:不给任何输入,它会自己动起来吗?

2026 年 3 月,Eon Systems 发了一篇「上传果蝇」:用 FlyWire 全脑连接组搭一个脉冲神经网络,接上物理仿真的果蝇身体,让它在虚拟世界里觅食、梳理、逃跑。演示很震撼,但关键的「神经元怎么变成动作」那一层没有开源。

我想弄清楚一个更朴素的问题:把这只果蝇的脑复刻出来以后,它能自己生成什么行为? 于是用他们用到的开源组件在一台 Mac mini 上拼了一套,给输入测了一轮,不给输入又测了一轮。

先给结论:

  • 给输入时,连接组本身就能把感觉转成可用的运动信号。 腿部尝到糖,0.66 秒后果蝇转向进食;复眼看到黑球逼近,1.89 秒巨纤维放电、身体后退。
  • 不给输入时,原模型完全静默——它是个被动的响应器,不会自己动。
  • 补上膜噪声 + 放电适应这两项「生理常识」后,它确实会自发地在静止、前进、后退、梳理、惊跳之间切换。但第一版的节奏像节拍器;第二版改了三处,节律才变得不规则、片段有长有短,更像活的动物。
  • 所有这些「行为」都经过一层我手写的低维接口(下行神经元 → 动作),不是运动神经元级别的仿真。这一点决定了你该怎么读下面的数字。

问题背景:「上传」到底上传了什么

我复刻用的组合由四块组成:前两块是 Eon 文章里用到的开源项目,flybody 是我额外加的飞行身体,最后一块 Eon 没有开源:

组件 作用 本文用法
FlyWire v783 + Shiu 2024 LIF 模型(Eon fly-brain) 138,639 个神经元、约 500 万条突触的全脑脉冲网络 原样使用,Brian2 C++ 后端
NeuroMechFly v2(flygym) MuJoCo 里的果蝇身体 + CPG 步态 行走、转向、后退
flybody(Janelia / DeepMind) 另一套身体,偏飞行 飞行素材,本文略过
下行神经元 → 运动指令 把脑的输出翻译成腿的动作 未开源,我自己写

FlyWire 只覆盖脑,不含腹神经索(相当于脊髓),所以脑和腿之间天然断了一截。脑能给出的最后一层信号是下行神经元(DN)的放电,怎么从 DN 走到关节力矩,每个复刻者都得自己补。

问题分析:「自动生成」要拆成两个问题

「复刻后能自动生成什么」其实是两件事:

  1. 刺激驱动:给感觉输入,脑能不能算出方向正确的运动信号?这检验的是连接组的「接线」。
  2. 自发行为:什么都不给,它会不会自己动?真实果蝇放在空盒子里也会走、停、梳理,这是动物和反射机器的分界线。

第二个问题更难,也更有意思。Shiu 2024 的 LIF 模型是为「刺激某群神经元,看哪些下游被激活」设计的,没有背景活动——没有输入就一个脉冲都没有。要它自己动,就得在方程上加东西,而加什么、加多少,都会直接影响结论。所以我给自己定了一条规则:只加有生理依据的最少项,每加一项都用数字说明它改变了什么。

技术方案与选型

脑的后端:Brian2 C++,排除 GPU。 我在本机实测了三种后端跑 0.1 秒脑时间:

后端 耗时
Brian2 C++(CPU) 1.26 s(首次另加约 8 s 编译)
PyTorch MPS(Apple GPU) 9.6 s
PyTorch CPU 36.8 s

MPS 没有 CSR 稀疏内核,只能退化成 gather + index_add,结果比 Brian2 慢 7 倍,批量跑还随 batch 线性变慢——稀疏矩阵乘向量是内存带宽受限的任务,统一内存的 GPU 占不到便宜。局域网里另一台机器是 Intel Arc 核显,没有 CUDA,预期不会好于 MPS,也排除了。真要加速只能租 NVIDIA 跑 Brian2CUDA。

感觉输入:只用味觉和触角机械感受,排除嗅觉与温湿度。 扫了一遍各感觉通道:嗅觉 ORN、温度、湿度感受神经元哪怕只给 30 Hz,就让约 8000 个神经元进入饱和态,而且左右刺激结果一样(嗅觉双侧投射),拿来导航等于没有方向。味觉和触角 JO 神经元的下行响应是左右分离的,可用。

下行接口:只读功能明确的几组 DN。 前进 DNp09/DNg100、转向 DNa01/DNa02 左右差、后退 MDN、梳理 DNg11/DNg12、逃逸 DNp01(巨纤维)。转向信号扣掉 DN 群体固有的约 +0.19 左偏——这个偏置是标定出来的,不扣掉果蝇会一直左转。

排除项: 不做运动神经元级仿真(没有腹神经索数据);flybody 的训练策略是 TF 2.8,Apple Silicon 装不上,只导出权重用 numpy 推理,行走策略因缺 3 GB 参考轨迹数据没做。

落地/实测过程

一、刺激驱动:连接组的接线是通的

先不接身体,直接刺激两组神经元各 0.3 秒脑时间:

刺激 被激活神经元 脉冲总数
糖味觉 GRN,200 Hz 384 5,125
P9 前进下行神经元,100 Hz 85 291

糖味觉 GRN 200 Hz 刺激 0.3 秒:全脑 13.9 万个神经元里有 384 个被激活,上图为它们的脉冲栅格,下图为每 5 ms 的脉冲总数

糖刺激扩散得很广(13.9 万里有 384 个被点亮),这符合「进食是全脑级决策」的直觉;刺激 P9 这种已经在输出端的神经元,涟漪就小得多。

然后把身体接上,做两个闭环:

味觉趋食:果蝇腿上的味觉神经元按左右浓度差放电 → 全脑 LIF → DN 左右差 → CPG 左右步幅。脑和身体每 15 ms 同步一次。3.48 秒的行为里,0.66 秒进入进食状态。

视觉逃逸:flygym 复眼画面 → flyvis(连接组约束的视觉网络)→ T4/T5 运动检测神经元映射到 FlyWire → LIF 脑。一个黑球从前左方加速逼近:

时间 事件
1.635 s 左侧 LPLC2(逼近检测)首次放电,峰值 6.2 Hz
1.830 s 右侧 LPLC2 放电,峰值 7.8 Hz
1.890 s 右侧巨纤维 DNp01 放电,峰值 66.7 Hz → 后退逃逸

视觉逃逸:左为 MuJoCo 里静立的果蝇和从前左方逼近的黑球,右上为两只复眼的画面,右侧三条曲线依次是 flyvis T4/T5 响应、FlyWire LPLC2 放电率、巨纤维 DNp01 放电(蓝左橙右)

LPLC2 → 巨纤维 → 逃逸这条通路完全是从连接组里「长」出来的,我只写了最后一步「巨纤维放电 = 后退」。另一类逼近检测神经元 LC4 和左侧巨纤维全程为 0,我目前的接口只看「有没有放电」,不区分左右。

二、自发行为 v1:加噪声,再加适应

原模型没有输入就静默。我在膜电位方程上加两项:

  • 膜噪声 σ:真实神经元有离子通道噪声,会自发放电;
  • 放电适应 a:每放一次电,一个慢电流 +b,按 τa 衰减。这让活动「自限」,形成一阵活动、一阵安静。

扫了 σ × b 九组(每组脑时间 1 秒),挑几组有代表性的:

σ b 全脑均率 活跃比例 群体率 CV 转向 DN 左/右
2 mV 0 4.03 Hz 17.9% 0.04 34 / 7 Hz
2 mV 3 mV 0.33 Hz 13.8% 1.03 2 / 4 Hz
3 mV 0 6.12 Hz 72.2% 0.04 39 / 7 Hz
3 mV 3 mV 1.29 Hz 74.4% 0.25 7 / 9 Hz
4 mV 0 9.46 Hz 88.9% 0.04 46 / 4 Hz

这张表里最有意思的是 b=0 那几行:只加噪声、不加适应,群体活动平得像一条直线(CV 0.04),转向 DN 却固定左偏 5 倍以上——果蝇会一直原地左转。原因是噪声被连接组结构放大后,找到了一个稳定吸引子;适应电流把它打破了,左右偏差消失,出现阵发。

选定 σ=2.5 mV、b=3 mV、τa=400 ms(全脑均率约 0.75 Hz,不饱和),接上身体空跑 12 秒:

自发行为 v1 空跑 12 秒:左为果蝇身体,右为解码出的行为条带、各组 DN 的 z 分数与全脑放电率

30 个片段,时间占比:静止 58%、前进 11%、梳理 15%、后退 8%、惊跳 9%;前进速度 12.4 mm/s,总路径 27.5 mm。没有任何感觉输入,它确实自己在走、在停、在梳理。

但把脑时间拉到 60 秒做统计,问题就暴露了:

  • 全脑阵发间隔中位 1.67 秒,变异系数只有 0.05——几乎是个节拍器;
  • 前进片段 82%、梳理片段 84% 恰好等于解码器设的最短时长 0.3 秒,最长的前进片段只有 0.42 秒;
  • 惊跳每分钟 7.1 次,多得离谱。

这说明 v1 的「行为」大部分是我加的东西决定的:节律来自单一的 τa,片段时长来自解码器参数,惊跳来自巨纤维单个神经元被噪声随机触发。

三、自发行为 v2:让连接组多说话,让我的参数少说话

针对这三点各改一处:

  1. 适应时间常数异质化:每个神经元的 τa 从对数正态分布里抽(中位 400 ms,5–95% 约 0.1~1.5 s),再加一个缓慢起伏的全脑「唤醒度」(OU 过程,τ=4 s)。
  2. 读 DN 的突触输入而不是脉冲:每组 DN 只有 1~24 个神经元,脉冲基本是点过程噪声;但每个 DN 的突触输入 g 汇总了上千个上游神经元,信号平滑得多。动作选择改用互相抑制 + 自兴奋的竞争单元,片段时长由动力学自然产生。
  3. 惊跳要求巨纤维 20 ms 内 ≥4 个脉冲(强同步驱动),单个噪声脉冲不算;巨纤维自身噪声调小到 0.5 mV(它是很粗的神经元,否则空闲时约 5 Hz 乱放电)。

同样 60 秒脑时间,两个随机种子:

指标 v1 v2 种子 0 v2 种子 1
阵发间隔中位 / CV 1.67 s / 0.05 2.25 s / 1.19 1.16 s / 1.16
群体率自相关峰 0.61 0.40 0.47
惊跳 / 分钟 7.1 2.0 1.0
前进片段 中位 / 最长 0.30 / 0.42 s 0.86 / 4.63 s 0.60 / 3.48 s
前进片段贴 0.3 s 下限 82% 0% 12%
前进片段 >1 s 0% 44% 29%
梳理片段 中位 / 最长 0.30 / 0.39 s 0.72 / 1.87 s 0.65 / 2.23 s
占比 静止/前进/后退/梳理/惊跳 57/12/14/13/5% 27/35/9/28/1% 33/29/13/24/1%

v1 与 v2 各 60 秒脑时间的对比:全脑阵发间隔、前进片段时长、梳理片段时长,每个点是一次阵发或一个片段,竖线为中位数,虚线为 v1 解码器的 0.3 秒下限。v1 全部挤在一条线上,v2(两个种子合并)散开

节律从「节拍器」变成了不规则(CV 0.05 → 1.2),前进可以连续走 3~4 秒,梳理可以持续 2 秒,惊跳降到每分钟 1~2 次。两个种子的占比有差异但量级一致,说明不是某次运气。

最后把 v2 接上身体空跑 30 秒(种子 0):46 个片段,静止 34%、前进 21%、后退 14%、梳理 30%,这 30 秒里没有惊跳;总路径 135 mm,而 v1 的 12 秒只走了 27.5 mm。

自发行为 v2 空跑 30 秒:右上行为条带里前进(绿)和梳理(蓝)片段明显变长;最下面灰线是全脑放电率,橙线是慢唤醒度

不过 v2 没有完全解决问题。看图最下面一栏:唤醒度(橙线)偏低的后半段,全脑阵发(灰线)又变回了比较整齐的节奏。异质适应让节律变松了,但单靠它还压不住;真实果蝇的不规则性可能还需要别的来源,比如神经调质或身体反馈。

实践效果:哪些是连接组的,哪些是我的

把这一轮实测收成一张归属表,这是我认为读这类「数字果蝇」演示时最该问的问题:

现象 来自连接组 来自我加的东西
糖 → 转向进食 味觉到 DN 的左右分离通路 糖浓度 → 放电率编码;DN 差 → CPG 步幅
黑球 → 后退 LPLC2 → 巨纤维通路与时序 巨纤维放电 = 后退
无输入时有活动 —(原模型静默) 膜噪声
活动一阵一阵 阵发在全脑的传播模式 适应电流及其时间常数分布
只加噪声时一直左转 DN 群体固有左偏 —
动作之间切换 各组 DN 输入的涨落 DN 分组、竞争单元参数
走路、梳理的具体动作 — CPG 步态、手写梳理/惊跳轨迹

所以准确的说法是:连接组 + 两项生理常识(噪声、适应),足以自发产生可解码、有持续时间结构的动作序列。 它还不能说明这只虚拟果蝇的行为统计和真实果蝇一致——我没有拿真实果蝇的自发行为数据做对照,这是下一步。

算力上,60 秒脑时间在 M4 上要跑 18~25 分钟(约 20 倍慢于实时),这决定了网页上只能放离线生成的视频,不能实时跑脑。

踩坑

  • 只加噪声不加适应,会得到一只永远左转的果蝇。 转向 DN 左 34 Hz、右 7 Hz,而且噪声越大越偏。不看左右分列的读数,只看「全脑有没有活动」就会错过。
  • 小群体的脉冲不能直接当信号。 DN 组只有 1~24 个神经元,100 ms 分箱里基本是点过程噪声。v1 用「相对均值」做阈值时,24 个神经元的梳理组几乎永远赢不了,只好改成组内 z 分数——而 z 分数又让各动作占比被人为拉平。v2 改读突触输入后信号平滑多了,但仍沿用组内 z 分数,占比被拉平这一点没有解决。
  • 启动瞬态会被误判成逃逸。 加噪声的网络在开头 0.5 秒有一次全局齐放,巨纤维跟着放电。必须预跑 0.5 秒丢掉。
  • 视觉网络要用真实画面预热。 flyvis 先看灰屏再切到场景,会产生一次强瞬态,足以让巨纤维放电触发假逃逸。
  • 嗅觉不是「最自然的输入」就能用。 直觉上果蝇靠闻找食物,但在这个模型里嗅觉输入让 8000 个神经元饱和、左右无差。先扫通道再选输入,别凭直觉。
  • 片段时长要看分布,不要只看视频。 v1 的 12 秒视频看起来挺像回事;拉到 60 秒一统计,八成片段卡在解码下限上。单段演示视频证明不了行为的真实性。

相关文章

MiniMax T2A v2 vs Azure Neural TTS 实测:同一段中英文本,延迟差了 6~10 倍

MiniMax T2A v2 vs Azure Neural TTS 实测:同一段中英文本,延迟差了 6~10 倍

我的视频工厂里同时接了 MiniMax 和 Azure 两条 TTS 链路,一直凭感觉觉得 MiniMax 更快,这次把它坐实:同一段中英文本、各 5 轮、统一输出 24kHz/单声道/16bit,MiniMax 合成中位延迟 1.0~2.2 秒、RTF 0.08~0.18(比实时快 5~12 倍),Azure 中位 6~21 秒、RTF 逼近 1.0,且长尾抖到 27 秒。两个原因都有证据:一是 Azure Neural 本身的合成节奏就接近实时,二是从大陆直连它的 eastasia 端点要跨太平洋,握手 TLS 抖到 0.8 秒。文末给出真实抓包、波形对照,以及『什么时候该忍 Azure』的判断。

ttsrtf+6
hands-on2026年9月5日8 min
120
Claude Code 报 Error: Reached max turns (1):无头护栏掐断时,文件可能已经写了

Claude Code 报 Error: Reached max turns (1):无头护栏掐断时,文件可能已经写了

claude -p 设了 --max-turns 或 --max-budget-usd,触顶时输出 Error: Reached max turns (1) 或 Error: Exceeded USD budget (0.01),exit 1。我在 2.1.270 和 2.1.280 上各跑了一轮:报错分别是 28 和 33 字节,不带换行,打在 stdout 而不是 stderr;json 模式下 result 字段直接缺失,jq -r .result 会打印字符串 null,而且 jq 退出码是 0。更要命的是「报失败≠没干活」:--max-turns 2 报错时 out.txt 已经写好;预算要等一次调用返回才检查,0.05 美元的预算实际花掉 0.0517,任务其实已完成却仍 exit 1;预算掐断还会留下 out.txt.tmp.* 残片。交互模式则完全不理 --max-turns。

claude-codeheadless+5
hands-on2026年9月25日10 min
64

DeepSeek 标称 1M、Claude Code 只认 200K:两个都测了,真正卡住你的是第三个数

DeepSeek 标称 1M 上下文,而 Claude Code 接上去之后对同一个模型报告 contextWindow 200000。我把两边都测了。DeepSeek 的真实上限是 1,048,576——字面的 2 的 20 次方,不是一百万整——而且这个额度**含**你的 max_tokens 输出预算,用一组对照实验坐实。针插在第 0 位、上下文 1,039,744 token 时仍被准确捞出。Claude Code 则在远低于此处就本地拒绝,25 毫秒、零 API 调用,而且它卡的**根本不是 token**:闸门在约 48 万字符。喂高熵文本,478,000 字符顺利通过、真实 token 高达 309,567——比它刚刚自称的 20 万窗口还多 55%。而日常使用里这三个数你一个都碰不到,因为 Bash 输出超过整 30,000 字符就压根不进上下文。

claude-code长上下文+5
hands-on2026年9月20日6 min
144

拿 DeepSeek 当 Claude Code 后端:功能全通,但成本显示虚高 38 倍

DeepSeek 提供 Anthropic 格式端点,三个环境变量就能让 Claude Code 转去调它。我在真机上把整条链跑了一遍:本地工具(Read / Write / Bash / Glob / Edit / 子代理)全部正常且副作用真实发生,所以结论是能用。但没人测过的那部分是——Claude Code 按 Claude Sonnet 的价目给 DeepSeek 的 token 计费。十次相同调用,Claude Code 报告花了 $1.71,DeepSeek 账户实际只扣了 ¥0.32(≈$0.045),虚高 38 倍,这是余额差不是价目表推算。另外:官方文档关于未知模型名的说法是错的(会 400 而不是回落),v4-pro 默认返回 thinking 块导致小 max_tokens 看起来是空响应,以及一个看着像 DeepSeek 的锅其实不是的失败。

claude-codedeepseek+5
hands-on2026年9月20日7 min
146