feat: JspaceAI 自主智慧架构

基于第一性原理 + Anthropic 2026 J-space 论文实现的具身智慧系统。

核心架构:
- ODE 动力系统 + 并行专家 + J-space 工作空间广播
- 12 个异构专家(视觉/屏幕/听觉/语言/鼠标/跨模态)
- workspace 256 维 + LayerNorm + RK4 积分

自主心智(最重要的能力):
- 好奇心驱动探索(内在奖励 + 世界模型)
- 跨会话状态持久化(海洋不蒸发)
- 自我模型(知道自己会什么不会什么)
- 元学习(自适应学习率 + 策略选择)

具身 Agent(完整神经系统):
- 感知层:摄像头 + 麦克风 + 屏幕 + 键盘 + 鼠标
- 大脑皮层(workspace)+ 小脑(运动控制)+ 中枢神经(门控)
- 海马体(情景记忆)+ 基底神经节(动作选择)
- 执行器:鼠标控制 + 键盘输出 + 音频播放 + 屏幕绘制

多模态支持:
- 原生图像/音频/视频/文本/键盘/鼠标 6 种模态
- 跨平台(macOS/Windows/Linux)

外挂模块系统:
- 可热插拔的外部能力(小模型/知识库/工具)
- 核心心智不依赖外挂,断开后继续工作

守护进程:
- 用户主动 start/stop(不自启)
- 后台静默运行,持续感知学习
- 状态自动保存,跨会话继续

J-lens 可解释性:
- 观测模型内部每个 ODE 子步的想法
- Directed Modulation 验证 workspace 因果作用
- Selectivity 验证(ablate workspace)

小模型蒸馏:
- 接 GPT-2/Qwen 等迁移理解能力
- 蒸馏完成后小模型可断开

验证结果:
- 连续序列:JSpace 胜 Flat 39.7%
- 语言进化:loss 3.95→2.40
- workspace ||w||:v1 0.05 → v2 16.0
- 实时五通道感知 + 具身闭环运行
This commit is contained in:
2026-07-07 09:19:31 +08:00
commit e782ef4db1
30 changed files with 7446 additions and 0 deletions

101
jspaceai/task.py Normal file
View File

@@ -0,0 +1,101 @@
"""
玩具任务:连续时间序列预测
生成多模态时间序列——不同时段由不同的潜在规则驱动:
时段 At mod 4 ∈ [0,1)):正弦波 + 慢漂移
时段 Bt mod 4 ∈ [1,2)):快速振荡
时段 Ct mod 4 ∈ [2,3)):脉冲信号
时段 Dt mod 4 ∈ [3,4)):组合信号
任务:给定 x_t预测 x_{t+1}。
设计意图:
- 不同时段需要不同的"专家"处理——验证工作空间能否学到分工
- 模式切换时需要工作空间广播给正确的专家——验证 J-space 路由
- 扁平 MLP 在模式切换时会糊掉,工作空间架构应该更鲁棒
"""
from __future__ import annotations
import numpy as np
import torch
from torch.utils.data import Dataset
class ContinuousSequenceTask:
"""生成连续多模态时间序列"""
def __init__(self, input_dim: int = 8, seq_len: int = 64, seed: int = 42):
self.input_dim = input_dim
self.seq_len = seq_len
self.rng = np.random.default_rng(seed)
# 每个时段有自己的参数
self.phase_len = 16 # 每个模式持续 16 步
self.phase_params = self._gen_phase_params()
def _gen_phase_params(self) -> list[dict]:
"""4 个时段,每段不同参数"""
params = []
for i in range(4):
params.append({
'freq': self.rng.uniform(0.1, 0.5), # 振荡频率
'phase': self.rng.uniform(0, 2 * np.pi), # 相位
'drift': self.rng.uniform(-0.02, 0.02), # 慢漂移
'amp': self.rng.uniform(0.3, 1.0), # 振幅
'noise': self.rng.uniform(0.01, 0.05), # 噪声
})
return params
def generate_sequence(self, n_steps: int) -> np.ndarray:
"""生成长度为 n_steps 的序列"""
x = np.zeros((n_steps, self.input_dim), dtype=np.float32)
state = np.zeros(self.input_dim, dtype=np.float32)
for t in range(n_steps):
phase_idx = (t // self.phase_len) % 4
p = self.phase_params[phase_idx]
# 每个维度独立演化,但共享相位
for d in range(self.input_dim):
d_offset = d * 0.3
if phase_idx == 0:
# 正弦 + 漂移
state[d] = p['amp'] * np.sin(p['freq'] * t + p['phase'] + d_offset) + p['drift'] * t
elif phase_idx == 1:
# 快速振荡
state[d] = p['amp'] * np.sin(p['freq'] * 3 * t + p['phase'] + d_offset)
elif phase_idx == 2:
# 脉冲
pulse = 1.0 if (t % 5 == 0) else 0.0
state[d] = p['amp'] * pulse + 0.1 * np.sin(p['phase'] + d_offset)
else:
# 组合
state[d] = (p['amp'] * 0.5 * np.sin(p['freq'] * t + p['phase'] + d_offset)
+ p['amp'] * 0.3 * np.cos(p['freq'] * 2 * t + d_offset))
state[d] += self.rng.normal(0, p['noise'])
x[t] = state
# 归一化到 [-1, 1]
x = np.tanh(x)
return x
def generate_batch(self, batch_size: int, n_steps: int | None = None) -> torch.Tensor:
"""生成一个 batch 的序列"""
n_steps = n_steps or self.seq_len
batch = np.stack([self.generate_sequence(n_steps) for _ in range(batch_size)])
return torch.from_numpy(batch)
class SequenceDataset(Dataset):
"""用于 DataLoader 的数据集"""
def __init__(self, task: ContinuousSequenceTask, n_samples: int, seq_len: int):
self.data = [task.generate_sequence(seq_len) for _ in range(n_samples)]
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
return torch.from_numpy(self.data[idx])