ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

OpenHuman 潜意识工厂 Phase 4 架构解析:多世界实例的 Factory/Registry 生命周期、Heartbeat 扇出与逐实例 JSON-RPC 设计

OpenHuman 潜意识工厂 Phase 4 架构解析:多世界实例的 Factory/Registry 生命周期、Heartbeat 扇出与逐实例 JSON-RPC 设计 OpenHuman 潜意识工厂 Phase 4 架构解析多世界实例的 Factory/Registry 生命周期、Heartbeat 扇出与逐实例 JSON-RPC 设计【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman本文以仓库内设计文档 docs/plans/subconscious-factory/phase-4-factory-registry-rpc.md 为主体结合同目录的前后阶段文档与仓库中真实存在的配置 Schema、about_app 模块源码展开解读。该文档属于Subconscious factory潜意识工厂重构计划的第四阶段核心目标是打通“制造潜意识”的统一入口用factory.rs实例化任意一组 world、让 heartbeat 统一驱动它们、并通过 JSON-RPC 暴露逐实例的状态与触发能力。读者读完本文后将能完整理解这套多世界潜意识层的装配模型、生命周期管理与向后兼容的协议扩展思路。一、为什么需要 Factory一个引擎里塞了两个世界OpenHuman 的 subconscious潜意识 / 深度反思层是一个离线、cron 驱动的循环它消费“某个 world 如何变化”的压缩视图产出用于引导系统其余部分的高密度输出。按照 subconscious-factory/README.md 的目标形态未来会有两个甚至更多worldmemory——用户连接的各类记忆源Gmail/Slack/Notion/文件夹构成的高层世界基于 baseline checkpoint 观察memory_diff由精简决策 agent 做反思to-do、goal、notify_user、委派tinyplace——tiny.place 编排世界观察经过 20:1 压缩的执行历史与累积世界态差异由无工具 steering 综合输出STEERING_DIRECTIVE给 reasoning core。当前实现的痛点全部集中在单个subconscious/engine.rstick_inner是一个硬编码的“复合体”——stage 0 调用orchestration::ops::run_orchestration_reviewtinyplace 世界stage 1–3 再跑 memory 世界memory_diff → context scout → decision agent。结果是一个 tick lock、一个熔断器、一个状态对象、一个 baseline store却服务着两个互不相关的世界它们拿不到各自的 cadence、provider 签名、halt 状态和 status也无法在不动这个复合体的情况下新增第三个世界。Phase 4 正是在 phase 1SubconsciousProfiletrait 泛型SubconsciousInstancerunner、phase 2抽取 memory profile、phase 3用profiles/tinyplace.rs包装 orchestration review打好的地基上解决“多个实例如何被创建、登记、驱动、对外暴露”的问题。按设计文档的表述其目标是the make subconscious surface — instantiate any set of worlds, drive them from the heartbeat, expose per-instance status/trigger over JSON-RPC.二、4.1factory.rsSubconsciousKind与唯一的装配点设计文档给出工厂层的核心契约如下#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all snake_case)] pub enum SubconsciousKind { Memory, TinyPlace } impl SubconsciousKind { pub fn id(self) - static str; // memory | tinyplace pub fn parse(s: str) - OptionSelf; /// Which kinds should run for this config (bootstrap set). pub fn enabled_kinds(config: Config) - VecSelf { // Memory ⇐ heartbeat.enabled mode ! Off (todays gate) // TinyPlace ⇐ orchestration.enabled (todays gate) } } pub fn make_subconscious(kind: SubconsciousKind, config: Config) - SubconsciousInstance;几个值得注意的工程决策枚举即目录id()返回的memory/tinyplace字符串会被用作 store 的命名空间前缀、日志前缀与 RPC 中的 instance 名这一点在 phase 1 的SubconsciousProfile::id契约中已有同样约定。parse用于从 RPC 请求参数等外部输入反查类型。serde(rename_all snake_case)保证 JSON-RPC 载荷里的大小写风格与项目其余 serde 类型一致。“新增一个世界 一个 profile 文件 一个 match 分支 一行enabled_kinds”。文档强调make_subconscious是 profile 被构造的唯一位置——测试与 trigger RPC 也必须经由它从而把“如何造实例”收敛到单点避免散落各处的Arc::new(...::new(config))。门控逻辑对应到仓库现有配置 Schema 是能一一印证的heartbeat.enabled即 src/openhuman/config/schema/heartbeat_cron.rs 中HeartbeatConfig.enabledopt-in注释明确“ticks may call hosted models and integration APIs depending on routing and enabled collectors”“mode ! Off” 对应HeartbeatConfig.subconscious_mode: SubconsciousMode其默认值是Off并带有is_enabled()辅助方法同文件还实现了向后兼容的解析当subconscious_mode未显式设置时会回退到遗留的enabled inference_enabled语义src/openhuman/config/schema/subconscious.rs 则说明当前实际存在 “engine selection” 概念local/ 兼容遗留的medulla印证了文档中所述的心跳 tick 已走 observe/reflect/commit 的认知管线。这些字段的存在意味着 phase 4 的enabled_kinds只是把已有的两组门控重新解释成“启动哪组 world 实例”的集合而非引入新的开关面。三、4.2registry.rs从“单例引擎”到“键控注册表”现状是global.rs里一个OnceLockArcMutexOptionSubconsciousEngine——同一时刻只能有一个引擎。Phase 4 的目标形态是static REGISTRY: OnceLockMutexHashMapSubconsciousKind, ArcSubconsciousInstance;设计文档明确了三组生命周期方法3.1get_or_init_instance(kind)——惰性按需构造沿用今天get_or_init_engine的“先 load config 再 insert”流程每个 kind 首次被触及时才构建避免启动阶段为从未启用的世界白白加载配置与 profile。注意每个 value 是ArcSubconsciousInstance不是MutexOption..——文档给的理由非常明确实例内部已有的tick_lock/state互斥量已经序列化了需要序列化的部分而 status 读取路径按 invariant 5 必须保持无锁因此外层再包一层可变 Option 只会引入多余竞争点。3.2bootstrap_after_login()——登录后启动整个 enabled 集合流程不变式保持不变先用BOOTSTRAPPEDswap 守卫保证只执行一次随后初始化enabled_kinds(config)的每一个成员、启动 heartbeat以及保持现状的opt-in trigger orchestrator。enabled_kinds是集合语义的体现——当未来新增第三个世界如 per-team world、channels world时只要它的 profile 写好了这行集合逻辑就会自动把它纳入登录后的启动序列。3.3stop_heartbeat_loop()/reset_engine_for_user_switch()——用户切换的全量重建用户切换工作空间时需要中止 heartbeat → 关闭 trigger orchestrator →清空整张 map从而让下一次 bootstrap 针对新的 workspace 重建每一个实例。这比今天的单例切换更彻底因为 memory 与 tinyplace 的 KV 状态都挂在各自实例的命名空间下逐个实例重建才不会让旧工作空间的残留状态污染新用户。3.4 过渡期的向后兼容别名文档规定在 RPC 处理器全部迁移完成前保留get_or_init_engine()作为get_or_init_instance(Memory)的deprecated alias迁移完毕再删除。这是一个值得借鉴的渐进式重构手法——调用方可以零成本地逐点切换到新 API而不是在一个提交里原子性地改完所有触点。四、4.3 Heartbeat 扇出一次心跳驱动所有到期实例heartbeat/engine.rs目前在自己的 interval 上调用单一引擎的tick()。改造后每个 heartbeat interval遍历 registry对每个cadence 已到期now - last_tick_at cadence的实例执行tick()——phase 1 已为每个实例维护独立的last_tick_at与 cadence 键因此这一步是纯读判断不同世界互不干扰多个实例的 tick并发执行每个实例tokio::spawn并与既有的 cancel/abort 语义 join文档给出动机示例“a slow memory tick must not delay a tinyplace review”——memory 世界一次耗时的反思绝不应当阻塞 tinyplace 世界按时产出评审heartbeat 原有的 event-planner 职责meetings/reminders保持不变。这里继承自 phase 1 的一个结构性好处值得强调tick_inner那种“一个 tick 里手工编排两个世界”的顺序耦合被彻底拆散cadence 成为 profile 的属性SubconsciousProfile::cadence(self, config)调度 shell 只负责“谁到期就 tick 谁”。这也与 phase 1 中“runner 内保留 cadence loop trigger、tick lock、generation 计数、TICK_TIMEOUT、provider gate、rate-cap halt 等调度器/熔断器关注点”的分层一致——profile 决定一个世界“做什么”runner/registry/heartbeat 决定它“何时被做、并行地做”。五、4.4 RPC surfacesubconscious命名空间的向后兼容扩展RPC 契约的扩展遵循“今天的 UI 与调用方不被破坏”的硬约束两处改动都是增量的。5.1subconscious.status保留顶层字段 新增instances变更项说明顶层字段保持不变数据来自memory实例——现有 UI 继续工作零改动instances: [SubconsciousStatus]新增字段已注册的每个 kind 一行每行再带instance: memory \| tinyplace标识换句话说既有消费者看到的是和以前一模一样的 status 结构想感知多世界的调用方则读新增的instances数组。5.2subconscious.trigger可选kind参数值语义memory默认今天的既有行为完全不变tinyplace定向触发 tinyplace 实例的反思all触发全部注册实例触发仍是fire-and-forgetspawn 后立刻返回不阻塞调用方等待反思结果。5.3 读取路径的约束invariant 5 的落地状态读取严格保持 SQLite-only、且永不触碰 tick mutex每个实例的last_tick_at来自命名空间化的 KVmemory:last_tick_at/tinyplace:last_tick_atphase 1 的store.rs已完成键前缀化与遗留键迁移进程内的计数器failures、halt reason来自实例的status()——它只拿细粒度的state互斥量绝不拿tick_lock。因此“看状态”永远不会与“正在 tick”的反思过程互相阻塞。前端消费这些新字段属于 phase-7-ui.md 的范围Subconscious 页的 instance cards、TinyPlace Orchestration 页的 steering header文档明确标注不是 Rust 工作的阻塞项——因为向后兼容的协议扩展可以先于 UI 落地并被现有 UI 安全忽略。六、4.5about_app面向用户的描述同步更新设计文档的最后一项是一个仓库规约要求用户可见的功能变更必须同步更新 about_app 文案对应模块 src/openhuman/platform/about_app。subconscious 的对外描述将从“单一引擎”更新为per-world 实例的口径memory→ memory awareness记忆感知tinyplace→ tiny.place orchestration steering编排引导。这条看似“收尾”的规定实际上保证了即便内部架构从单引擎变成工厂多实例用户在“关于”页读到的产品叙事仍与真实行为一致——描述的最小单元从“引擎”切换成“实例”。七、贯穿始终的不变式重构的红线Phase 4 的每一处改动都必须让 README 中列出的六条不变式存活。与本阶段最相关的是不变式内容Phase 4 中的落点1. 隔离Isolationsubconscious 永不主动外联tinyplace profile 保持无工具 provider chatmemory profile 的 agent 工具集继续通过subconscious_agent_tool_surface_has_no_channel_or_effect_tools之类测试守卫2. Taint对外部内容做出反应的 tick 记为SubconsciousTaintedmemory 由 diff 是否携带外部内容决定tinyplace 恒为 tainted3. 只在成功时推进被 supersede 的 tick 丢弃结果registry 层不改动这一语义逐实例保留4. Quiet tick 零成本observe()为空就不调 LLM逐实例判定互不牵连5. status 不碰 tick 锁subconscious.status只读 SQLite见上文 5.3registry 用Arc而非MutexOption..正是为此6. 向后兼容旧 DB 键迁移到memory:命名空间RPC 保留镜像 memory 实例的 legacy 顶层字段4.4 的 status 顶层字段即该不变式的协议侧体现尤其 invariant 5 在 registry 设计上的推论最值得记住正因为实例状态必须锁外可读注册表里存放的才必须是ArcSubconsciousInstance内部细粒度锁负责写串行化而不是一个大而全的MutexOptionEngine。八、在整条时间线中的位置与验收路径Subconscious factory 被拆成七个可分别编译、可分别提交的阶段见 subconscious-factory/README.md 的 phase 表phase 1–3 引入抽象并做纯抽取无行为变化SubconsciousProfiletrait、泛型实例 runnertick 本体是一条tinyagents CompiledGraph见 phase-1-profile-and-engine.md、按命名空间分键的 store、memory 与 tinyplace 两个 profile**phase 4本文**把“单个引擎”升级为“工厂 注册表 扇出 逐实例 RPC”是全计划从抽象走向可运行多实例的转折点phase 5 补齐测试矩阵与迁移测试、更新 README/文档并负责 rolloutphase-5-tests-and-docs.mdphase 6 落到 tinyagents 侧的上游能力补齐deadline、cancel token、checkpoint GC见 phase-6-tinyagents-reuse.mdphase 7 由前端消费逐实例字段phase-7-ui.md。对测试工程而言phase 4 的验收重点是get_or_init_instance的惰性构造语义、bootstrap_after_login的幂等守卫、用户切换时全 map 清空后按新 workspace 重建、heartbeat 扇出下“慢 memory tick 不阻塞 tinyplace”的并发性以及 status/trigger 在单实例与all两种模式下的行为一致性。整体上这是把“今天的单一 subconscious 引擎”演化为“一个按 world 生长的实例集合”的关键一役——新增第三个世界从此只是“一个 profile 文件 一个 match 分支 一行 enabled 集合”而不再是一场对巨型复合tick_inner的手术。【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进