OpenHuman 源码深度解构:一个 Rust 驱动的本地优先 AI 个人助手
OpenHuman 源码深度解构:一个 Rust 驱动的本地优先 AI 个人助手
版本:v0.54.7 | 技术栈:Rust + Tauri + React/TypeScript | 基于源码:openhuman-main
引言
OpenHuman 是由 tinyhumansai 开源(GNU 协议)的桌面端 AI 个人助手,定位是"Personal AI super intelligence"。它不是另一个终端 AI 工具——它有桌面 Mascot(会说话、会做表情、能加入 Google Meet)、20 分钟自动同步 118+ 服务的记忆树、本地 SQLite 存储、以及一个叫 TokenJuice 的 token 压缩引擎。
技术选型上,OpenHuman 选择了 Rust 作为后端核心,Tauri 作为桌面壳层,React/TypeScript 作为前端。整个项目约 0.54.7 版本,Rust 源码横跨约 80 个子模块,Cargo.toml 依赖列表读起来像一本"现代 Rust 生态全景图"。
本文从源码出发,多维度解构这个系统的设计。
一、项目结构总览
openhuman-main/
├── src/
│ ├── main.rs # openhuman-core 二进制入口
│ ├── rpc/ # JSON-RPC 分发层
│ └── openhuman/ # 核心业务逻辑(~80 个子模块)
│ ├── agent/ # Agent 编排、会话、工具调用
│ ├── memory/ # Memory Tree + 向量搜索 + SQLite
│ ├── tokenjuice/ # Token 压缩引擎
│ ├── subconscious/ # 后台定时思考引擎
│ ├── inference/ # 模型路由(云端 + 本地 Ollama)
│ ├── composio/ # 118+ OAuth 集成(后端代理)
│ ├── vault/ # 本地文件夹知识库(NotebookLM 风格)
│ ├── scheduler_gate/ # 电池/CPU 感知的后台任务调度器
│ ├── voice/ # STT (whisper.cpp) + TTS (piper)
│ ├── desktop_companion/ # Mascot 会话协调器
│ ├── screen_intelligence/ # 屏幕截图 + 视觉理解
│ ├── wallet/ # Ethereum 钱包集成
│ ├── webhooks/ # 入站 Webhook 处理
│ └── ...(约 60 个其他模块)
├── app/
│ ├── src/ # React/TypeScript 前端
│ └── src-tauri/ # Tauri 桌面壳层(Rust)
│ ├── src/cdp/ # Chrome DevTools Protocol 客户端
│ └── recipes/ # WebView 注入脚本
└── tests/ # 集成测试(E2E + 单元)
Cargo.toml 声明了一个主二进制 openhuman-core 和若干工具二进制(slack-backfill、gmail-backfill-3d、memory-tree-init-smoke、inference-probe),lib crate 是 openhuman_core。
二、Agent 域:多 Agent 编排架构
src/openhuman/agent/ 是"大脑",模块注释的第一句话:
“This domain owns the core ‘brain’ of OpenHuman. It coordinates how LLMs interact with the system via tools, manages conversation history, and handles autonomous behaviors like trigger triage and episodic memory indexing.”
2.1 核心组件
Dispatcher 是 OpenHuman 一个有意思的设计——它支持三种工具调用格式:
- XML:
<tool>...</tool>格式,用于不原生支持 function calling 的模型 - JSON:OpenAI function calling 标准格式
- P-Format(PFormat):一种更紧凑的自研格式,降低 token 消耗
这让 OpenHuman 能适配更广泛的模型,包括不支持 function calling 的小型本地模型。
2.2 Triage:高性能触发器分类器
agent/triage/ 是一个专门的子系统,用于分类和响应外部触发(Webhook、cron 任务)。注释说明:
“A high-performance pipeline for classifying and responding to external triggers using small local models.”
这意味着当一个 Gmail Webhook 触发时,不是直接走完整的 Agent 循环,而是先通过 Triage 快速分类(用小模型,低延迟),决定是否需要唤起主 Agent。
三、Memory Tree:四阶段知识图谱构建
Memory Tree 是 OpenHuman 最核心的差异化特性,灵感来自 Karpathy 的 LLM Knowledgebase 工作流。整个流水线分四个阶段建设(对应 Issue #707~#710):
3.1 评分系统的三区间设计
Phase 2 的评分有一个精妙的三区间门控:
pub const DEFAULT_DROP_THRESHOLD: f32 = 0.3; // 总分 < 0.3 → 丢弃
pub const DEFAULT_DEFINITE_KEEP: f32 = 0.85; // 便宜信号 ≥ 0.85 → 直接保留,不调用 LLM
pub const DEFAULT_DEFINITE_DROP: f32 = 0.15; // 便宜信号 ≤ 0.15 → 直接丢弃,不调用 LLM
这意味着只有评分在 0.15~0.85 之间的"边界区间" chunk 才需要 LLM 参与判断。大量明显是垃圾(系统日志噪音)或明显是干货(正文内容)的 chunk 直接通过正则信号处理,不消耗 LLM token。
3.2 Chunker 的稳定 ID 设计
Chunker 生成的 ID 是确定性的(deterministic),相同内容在不同时间摄取产生相同 ID,这是实现高效重复摄取去重的基础——只需对比 ID 就知道内容是否已存在,不需要重读内容。
3.3 Obsidian Wiki 输出
Memory Tree 的最终产物:
- SQLite 本地数据库(向量 + 关键词 + 关系图)
- Markdown 文件(与 Obsidian 兼容,可以直接在 Obsidian 中打开和编辑)
- 层级摘要树(source → topic → global 三层)
四、TokenJuice:三层规则覆盖的 Token 压缩
src/openhuman/tokenjuice/ 是 vincentkoc/tokenjuice 的 Rust 移植版,声称可减少 80% 的 token 消耗。
4.1 三层规则优先级
规则优先级:Builtin < User < Project(高优先级覆盖低优先级)。
4.2 实际压缩效果示例
reduce.rs 中的 rewrite_git_status_line 函数展示了一个具体的压缩策略——把 git status 的冗余输出压缩为精简格式:
// 原始: "On branch main" → 删除(毫无信息量)
// 原始: "(use \"git add <file>...\" to update what will be committed)" → 删除
// 原始: "Changes not staged for commit:" → 压缩为 "Changes not staged:"
// 原始: "Changes to be committed:" → 压缩为 "Staged changes:"
对于 cat、sed、head、bat 等文件内容检查工具,is_file_content_inspection_command() 识别后走专用的文件内容压缩路径,不做通用压缩。
4.3 240 字符的 Passthrough 门槛
输出少于 240 字符时直接透传,不做任何压缩处理。这个常量 TINY_OUTPUT_MAX_CHARS 的存在防止了对短输出做无意义的规则匹配(命中不了任何规则,浪费 CPU)。
五、Subconscious Engine:后台定时思考循环
src/openhuman/subconscious/ 是 OpenHuman 的"后台大脑"——即使用户没在对话,它也在定时运行,评估任务、产生 Reflection、创建 Escalation。
5.1 Generation Counter:防止 tick 重叠
pub struct SubconsciousEngine {
tick_generation: AtomicU64, // 单调递增
...
}
如果新 tick 在老 tick 仍在飞行时启动,老 tick 的 in_progress 条目被标记为 cancelled,结果被丢弃。这防止了 LLM 调用慢于 interval 时的状态累积问题。
5.2 持久化 last_tick_at:重启后恢复断点
注释说明了为什么要持久化这个时间戳:
“Without this, every restart cold-starts the LLM, which sees the same memory-tree rows again and re-emits near-duplicate reflections.”
last_tick_at 保存在 SQLite 的 subconscious_state 表中。重启后 Situation Report 只会包含该时间点之后的新增 Memory Tree 行,避免重复产生近似内容的 Reflection。
六、Inference 域:云端 + 本地混合路由
src/openhuman/inference/ 是所有推理相关能力的统一入口:云端 LLM、本地 Ollama、语音 STT/TTS、情绪分析。
6.1 ModelTier:基于内存的本地模型分级
当前 MVP 版本锁定了最高 Ram2To4Gb tier(Gemma 3 1B),更高 tier 的代码已有但对用户屏蔽。device_supports_local_ai() 用 total_ram_gb() >= 8 作为默认启用本地 AI 的门槛——这是推荐,不是硬限制。
6.2 Embedding 维度锁定
注释中有一个关键约束:
// bge-m3 — 1024 dims required by memory tree's on-disk format
// and 8192-token context for long-chunk embeds.
embedding_model_id: "bge-m3",
Memory Tree 的磁盘格式固定使用 1024 维向量(bge-m3 输出维度)。如果未来要换 embedding 模型,需要迁移存量向量——这是一个有意识的技术债务决策。
6.3 情绪分析(Sentiment)
inference/sentiment.rs 说明 inference 域不只是做文本生成,还承担了情绪分析任务,结果(SentimentResult)被 Agent 和 meet_agent 消费,用于调整 Mascot 的表情和响应风格。
七、Composio 集成层:后端代理模式
OpenHuman 的 118+ 集成通过 Composio 实现,但架构选择有意思——Rust core 不直接调用 Composio API:
这个设计的用意:
- OpenHuman 后端拥有 Composio API key——用户不需要自己注册 Composio 账号
- 后端做 HMAC 验证——防止 Webhook 伪造
- 一个订阅(OpenHuman)包含所有集成——对用户来说是"一个账号"而非"N 个 API key"
代价是:用户使用托管模式时,数据会经过 OpenHuman 后端。文档提到可以通过配置 direct mode + 自己的 Composio API key 绕过后端。
7.1 Auto-fetch 的 20 分钟周期
composio/periodic.rs 实现了每 20 分钟的自动同步循环:
- 遍历所有已连接的 Composio 集成
- 调用各 Provider 的
sync()方法拉取新数据 - 新数据直接摄入 Memory Tree 流水线(Phase 1 → Phase 4)
结果:用户醒来打开 OpenHuman,Agent 已经知道昨晚的 Gmail、Notion 更新,不需要手动告知。
八、Vault:NotebookLM 风格的本地文件夹知识库
src/openhuman/vault/ 对标 Google NotebookLM 的本地版本。
注释:
“A Vault points at a local directory; on vault.sync we walk it, route files to extractors by extension, and feed them into the memory pipeline under namespace vault:. Per-file dedup uses (path, mtime, content hash) so re-syncs only touch what changed.”
去重逻辑用 (path, mtime, content_hash) 三元组:
path相同 +mtime相同:文件没变,跳过path相同 +mtime变了:重新读取,检查content_hash(防止 touch 产生的假阳性)- 新
path:新文件,摄入
支持格式按扩展名路由到不同 extractor,PDF 支持是可选 feature(rag-pdf = ["dep:pdf-extract"])。
九、Scheduler Gate:电池感知的后台任务调度
src/openhuman/scheduler_gate/ 解决了一个实际问题:后台 AI 任务(Memory Tree 摘要、Embedding、Subconscious tick)在笔记本电量低时不应该全速运行。
信号采样(每 30 秒刷新):
power_state:是否接通 AC 电源,或电量 ≥ 80%cpu_usage:近期全局 CPU 使用率,< 70% 为"足够空闲"deployment_mode:服务器/容器宿主机直接走 Aggressive
wait_for_capacity() 是一个 async future,在 Aggressive/Normal 下立即 resolve,在 Throttled 下睡眠,在 Paused 下持续轮询(用户切换回来立即恢复)。
实现使用了 starship-battery crate(battery crate 的维护分支),以及 sysinfo 的 CPU 监控——Cargo.toml 注释专门解释了选择 starship-battery 而非原始 battery 的原因。
十、Voice 域:端到端语音管线
OpenHuman 的语音能力完整到令人惊讶——不是调用云 API,而是本地运行:
macOS 优化:Cargo.toml 中 whisper-rs 在 macOS 下额外开启 metal feature,使用 Metal GPU 加速推理。
Windows TLS 策略:注释解释了为什么 Windows 用 native-tls(SChannel)而非 rustls:
“Windows: tokio-tungstenite uses native-tls (schannel) so wss:// connections honor the Windows cert store, including corporate CAs installed by AV / TLS-inspection proxies.”
这是一个很实际的企业用户场景考量——公司 TLS 审查代理会安装自签证书,Rustls 不查系统证书库,SChannel 会查。
十一、CDP 层:WebView 内容扫描
app/src-tauri/src/cdp/ 实现了一个完整的 Chrome DevTools Protocol 客户端,用于扫描 Tauri 内嵌的 WebView(Discord、Telegram、WhatsApp、Slack、LinkedIn 等)。
/// Remote debugging host
pub const CDP_HOST: &str = "127.0.0.1";
pub const CDP_PORT: u16 = 19222; // 注意:不是 9222
注释解释了为什么端口是 19222 而不是标准的 9222:
“Port was 9222 originally but collided with ollama’s 127.0.0.1:9222 listener (silent CDP-attach failure → blank child webviews).”
和 Ollama 的端口冲突是一个很典型的"两个开源项目都选了同一个’不常见’端口"问题。更改后需要同时更新 lib.rs 和 cdp/mod.rs,注释里有明确提示。
recipes/ 目录下的每个平台(discord/、telegram/、whatsapp/、linkedin/ 等)都有一个 manifest.json 和可选的 recipe.js,定义了如何注入 JavaScript 来提取内容。
十二、安全与隐私架构
12.1 本地加密
src/openhuman/encryption/ 和 src/openhuman/vault/ 使用:
- AES-256-GCM(
aes-gcmcrate) - ChaCha20-Poly1305(
chacha20poly1305crate) - Argon2(密钥派生,
argon2crate)
Vault 数据(连接的账户凭证、本地知识库)加密存储在本地 SQLite 中,密钥通过 Argon2 从用户主密码派生。
12.2 Linux Landlock 沙箱
Cargo.toml 中有一个 feature:
[features]
sandbox-landlock = ["dep:landlock"]
Linux 上可选启用 Landlock(内核级文件系统访问控制),为核心进程提供系统调用级别的沙箱隔离。sandbox-bubblewrap 是另一个可选沙箱后端(通过 bwrap)。
12.3 敏感数据过滤(Sentry)
Cargo.toml 的 Sentry 集成注释说明了 before_send 过滤器:
sentry = { version = "0.47.0", features = ["backtrace", "contexts", "panic", "tracing", ...] }
tests/observability_smoke.rs 中的 smoke test 专门验证这个过滤器在发送崩溃报告前是否正确过滤了敏感数据。
十三、技术债务与工程决策
13.1 html2md 被移除——性能问题复盘
Cargo.toml 中有一段很罕见的注释,完整记录了一次性能问题的根因分析:
# (Removed `html2md` dep. dhat-rs profiling on real Gmail inboxes
# showed `html2md::walk` and `html2md::tables::handle` allocating
# ~894 MB peak heap on a 10 KB HTML input from Otter.ai-style emails
# (deeply-nested table-as-layout HTML). Cause: recursive walker holding
# per-frame Vec state across nesting layers + 5 sequential
# `regex::replace_all` passes in `clean_markdown` each producing a
# fresh full-size String. ...
# We now use a linear-time tag-and-entity stripper (`fast_html_to_text`
# in providers/gmail/post_process.rs) and prefer the email's
# `text/plain` MIME part when available.)
10KB HTML 产生 894MB 堆分配——这是 html2md 对深度嵌套 table 布局 HTML 的已知性能问题。OpenHuman 用 profiling(dhat-rs)定位到了根因,用线性时间的 tag stripper 替换,同时优先使用 text/plain MIME 部分。这种在 Cargo.toml 里用注释记录 WHY 的做法值得学习。
13.2 Embedding 维度锁定的技术债务
前文提到 Memory Tree 的磁盘格式固定 1024 维(bge-m3),这是一个已知的技术债务:未来换 embedding 模型需要全量重新向量化历史数据。相比之下 Hermes Agent 的 MemoryProvider 抽象可以更灵活地切换后端。
13.3 MVP 模型 Tier 锁定
pub const MVP_MAX_TIER: ModelTier = ModelTier::Ram2To4Gb;
is_mvp_allowed() 方法只对 Ram2To4Gb 返回 true。更高 tier 的代码完整存在(4-8GB、8-16GB、16+GB),但被 MVP gate 屏蔽。这是一个典型的"代码写好了,产品决策还没到"的 feature flag 模式。
十四、可观测性基础设施
OpenHuman 有生产级的可观测性配置:
| 工具 | 用途 |
|---|---|
tracing + tracing-subscriber |
结构化日志(替代 log crate) |
tracing-appender |
异步文件追加写入(不阻塞主路径) |
prometheus |
metrics 采集(无 default features,按需启用) |
opentelemetry + opentelemetry-otlp |
分布式追踪(OTLP 协议推送) |
sentry |
崩溃报告(含 before_send 过滤) |
tests/observability_smoke.rs 是一个专门验证可观测性路径的 smoke test,使用 Sentry 的 TestTransport 在不发网络请求的情况下验证事件过滤逻辑。
十五、优缺点分析
优点
1. Memory Tree 的工程质量
四阶段流水线(摄取→评分→摘要树→检索)、确定性 chunk ID、三区间 LLM 节省策略——这不是"先做再说"的实现,而是有完整 LLD 文档(docs/MEMORY_ARCHITECTURE_LLD.md)指导的设计。评分系统特别精妙:只有"边界区间"才调用 LLM,明显垃圾和明显干货用正则处理,大幅降低摄取成本。
2. TokenJuice 的三层规则架构
Builtin/User/Project 三层优先级覆盖,让用户和项目都可以自定义压缩规则。Rust 移植避免了 Node.js 的性能开销,240 字符 passthrough 门槛防止了过度处理短输出。
3. Scheduler Gate 的实用性
电池感知的四级调度策略(Aggressive/Normal/Throttled/Paused)是真正的工程考量,不是 PPT 上的 feature。LlmPermit 的 cooperative 设计让后台任务自愿退出而不是被强制中断。
4. 完整的端到端语音管线
本地 whisper.cpp + piper,无需外部 API,Mascot 口型同步,Google Meet 集成——这是一套完整的本地 Voice AI 基础设施,不依赖任何云服务。
5. 性能问题的主动复盘记录
html2md 的 894MB 堆分配问题被完整记录在 Cargo.toml 注释里,包括 profiling 方法、根因、解决方案。这种"为什么做了这个决定"的文档化习惯在开源项目中很少见。
6. 供应链安全意识
Cargo.toml 的 profile.release 中有:
debug = "line-tables-only"
split-debuginfo = "packed"
只保留文件+行号调试信息(不含完整类型信息),用于 Sentry 崩溃符号化,同时保持发布二进制的体积可控。
缺点
1. Composio 后端依赖是核心风险
118+ 集成通过 OpenHuman 后端代理,这意味着服务可用性依赖 tinyhumansai 的后端。用户数据(至少触发事件)经过第三方后端。direct mode 存在但需要用户自己维护 Composio 账号,学习成本不低。
2. Embedding 维度硬编码是长期技术债
1024 维(bge-m3)锁定在磁盘格式里。随着 embedding 模型快速迭代(更高质量的 embedding 普遍超过 1024 维),未来的模型迁移成本会很高。Hermes 的 MemoryProvider 抽象在这一点上更有弹性。
3. MVP Tier 锁定影响本地 AI 价值
当前 MVP 只有 Gemma 3 1B,8GB RAM 以上设备无法用到更强的本地模型。对于宣称"强大的本地 AI"的产品,这是一个 credibility gap。
4. 架构复杂度高,贡献门槛陡
80 个子模块,Rust 异步,Tokio、axum、rusqlite、Tauri 全栈,加上 React/TypeScript 前端。CONTRIBUTING.md 里的先决条件已经让大多数人望而却步:Git、Node.js 24+、pnpm 10.10.0、Rust 1.93.0、CMake、Ninja、ripgrep,以及各平台桌面构建依赖。
5. 单体 RPC 架构的可扩展性
所有模块的 RPC 注册在 core::all 中统一注册,随着模块增加,编译时间和启动时间会线性增长。目前 v0.54.7 是单进程,没有服务拆分路径。
6. Tauri CEF 的平台差异
CEF(Chromium Embedded Framework)在不同平台的行为不完全一致,cef_preflight.rs、cef_profile.rs 的存在说明有专门的跨平台处理逻辑。CDP port 冲突(9222 vs Ollama)这类问题在多平台上可能还有更多。
7. Early Beta 稳定性
README 明确标注"Early Beta: Under active development. Expect rough edges.",v0.54.7 版本号高但实际成熟度仍有限。E2E 测试脚本(app/scripts/e2e-*.sh)覆盖了登录、支付、Gmail、Telegram 等关键流程,说明基础功能是有测试的,但整体稳定性保障尚在建设中。
结语
OpenHuman 代表了 AI 个人助手的一个不同路径:不是"更好的命令行工具",而是"真正住在你桌面上、了解你生活的 AI"。Memory Tree 的四阶段流水线、TokenJuice 的压缩引擎、Scheduler Gate 的电池感知调度——这些都是有工程深度的设计,不是 Demo 级别的实现。
但它的最大赌注是 Composio 后端依赖和 Memory Tree 的工程复杂度——前者是商业风险,后者是维护成本。能否在保持"Simple, UI-first & Human"的产品承诺的同时,支撑起这个技术债务栈,是它能否成功的核心问题。
本文基于 openhuman v0.54.7 源码,核心文件包括 Cargo.toml、src/openhuman/agent/mod.rs、src/openhuman/memory/mod.rs、src/openhuman/memory/tree/、src/openhuman/tokenjuice/、src/openhuman/subconscious/engine.rs、src/openhuman/inference/presets.rs、src/openhuman/composio/mod.rs、src/openhuman/vault/mod.rs、src/openhuman/scheduler_gate/mod.rs、src/openhuman/voice/mod.rs、src/openhuman/desktop_companion/mod.rs、app/src-tauri/src/cdp/mod.rs。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)