mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
docs(i18n): add zh-CN translations for integrations, mascot, model-routing, privacy, and tools
## Summary - 添加第二批核心功能模块的中文翻译(8 个文件):隐私与安全、第三方集成、吉祥物、模型路由、编码器、语音、定时任务、系统与工具 - 修复批次 A 遗留的 12 处未本地化内部链接(因第二批新增目标 `.zh-CN` 文件,之前保留的英文链接现在可指向中文版) - 修复第二批翻译中的 12 处质量问题:错别字、过直译、中英混杂、指向不存在的 `.zh-CN` 链接 - 修复隐私与安全文档中指向 `local-ai.zh-CN.md` 和 `triggers.zh-CN.md` 等尚未翻译文件的错误链接 - 统一 mascot、integrations 等跨模块链接指向,确保中文读者在 zh-CN 文档间流转 - 所有修改仅涉及 `.md` 文档,无代码变更 ## Problem - OpenHuman 中文用户阅读英文文档存在语言障碍 - 第一批汉化(overview + lightweight features)完成后,核心功能模块(integrations、model-routing、native-tools 等)仍无中文版 - 批次 A 的部分链接因目标文件当时未翻译而保留英文版,随着第二批新增 zh-CN 文件,这些链接已过时 ## Solution - 基于英文原文逐文件翻译,遵循术语统一表(vault→存储库、Agent→智能体、LLM/Token 保留英文等) - 翻译完成后运行审计脚本扫描,修复所有未本地化链接、MD040 代码块标识、术语一致性问题 - 对于目标 `.zh-CN.md` 不存在的链接(如 triggers、subconscious、local-ai、agent-coordination),保持指向英文原文,在 Related 中标记后续批次覆盖计划 ## Submission Checklist - [x] I have read the Codex PR Checklist - [x] I have confirmed Type Check passes (`pnpm typecheck`) (N/A: Markdown docs only) - [x] I have confirmed the app builds locally (`pnpm build`) (N/A: Markdown docs only) - [x] I have added tests for this change (N/A: i18n docs do not affect testable logic) - [x] I have updated documentation (N/A: this PR is documentation-only) - [x] I have confirmed no feature flags are required (N/A: no code changes) - [x] I have confirmed Prettier passes (`pnpm format:check`) (N/A: Markdown docs only) ## Impact - Runtime/platform impact: None - Performance/security/migration/compatibility: None ## Related - Follow-up PR(s)/TODOs: - Batch C: subconscious.zh-CN.md, triggers.zh-CN.md, local-ai.zh-CN.md, agent-coordination.zh-CN.md - Batch C: memory-tools.zh-CN.md, meeting-agents.zh-CN.md, developing/cef.zh-CN.md --- ## AI Authored PR Metadata ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `docs/i18n-batch-b-core-features` - Commit SHA: see PR commits ### Validation Run - [x] `pnpm --filter openhuman-app format:check` — N/A: no code changed - [x] `pnpm typecheck` — N/A: no code changed - [x] Focused tests: N/A - [x] Rust fmt/check: N/A - [x] Tauri fmt/check: N/A ### Validation Blocked - N/A ### Behavior Changes - Intended behavior change: None - User-visible effect: Chinese users can now read core feature docs in zh-CN ### Parity Contract - Legacy behavior preserved: N/A - Guard/fallback/dispatch parity checks: N/A ### Duplicate / Superseded PR Handling - N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Localization** * Updated Simplified Chinese UI strings for vault operations and MCP server/settings. * **Documentation** * Added extensive Chinese documentation covering integrations, mascot/meeting agents, model routing, native tools (voice, web search/scraper, coder, cron, system/tools), memory tree, obsidian wiki, token compression, platform, privacy/security, and subconscious/agent coordination. * **Chores** * Updated ignore rules to exclude AI assistant progress tracking. * Added documentation maintenance and validation scripts. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2450?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: agent:skill-master <skill-master@openclaw> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
This commit is contained in:
co-authored by
agent:skill-master <skill-master@openclaw>
Steven Enamakel
parent
f1eae121a6
commit
0f439fe1e1
@@ -100,3 +100,6 @@ app/test/e2e/.cache/
|
|||||||
.cache/cargo-install/
|
.cache/cargo-install/
|
||||||
test-map.md
|
test-map.md
|
||||||
.test-gap-analysis.md
|
.test-gap-analysis.md
|
||||||
|
|
||||||
|
# AI assistant progress tracking
|
||||||
|
.kimi/
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
118+ 第三方集成——Gmail、Notion、GitHub、Slack、Stripe、日历等,
|
||||||
|
一键 OAuth 连接,无需 API 密钥。
|
||||||
|
icon: plug
|
||||||
|
---
|
||||||
|
|
||||||
|
# 第三方集成(118+)
|
||||||
|
|
||||||
|
OpenHuman 搭载对 **118+ 第三方服务**的后端代理访问。任意服务通过托管路径连接都只需在应用内一键 OAuth,无需手动接入 API 密钥,也无需穿梭于插件市场。
|
||||||
|
|
||||||
|
底层连接器层由 [Composio](https://composio.dev) 驱动。默认托管模式下,OpenHuman 后端拥有 Composio API 密钥、OAuth token 经纪、速率限制和触发器 webhook 分发。如果你切换到直连模式,core 用你自己的 Composio API 密钥与 Composio 通信;同步工具调用可以工作,但实时触发器 webhook 必须配置在你自己的 webhook 基础设施上。
|
||||||
|
|
||||||
|
服务连接后,会同时出现在四个位置:
|
||||||
|
|
||||||
|
1. 作为**智能体工具**,模型可以直接调用。
|
||||||
|
2. 作为**记忆源**,[自动拉取](../obsidian-wiki/auto-fetch.zh-CN.md)每二十分钟将其同步到[记忆树](../obsidian-wiki/memory-tree.zh-CN.md)。
|
||||||
|
3. 作为**个人化信号**,你在各服务上的活动为你的偏好模型提供数据。
|
||||||
|
4. 作为**触发器源**,实时事件(新邮件、新 charge、入站 DM)流入[触发器](triggers.zh-CN.md)流水线,可以自动触发智能体操作。
|
||||||
|
|
||||||
|
## 目录中的部分服务
|
||||||
|
|
||||||
|
目录涵盖生产力、商业、社交、消息和 Google 类目。不完全示例:
|
||||||
|
|
||||||
|
| 类别 | 示例 |
|
||||||
|
| ----------------------- | ---------------------------------------------------- |
|
||||||
|
| **邮件与日历** | Gmail、Outlook、Google Calendar、Apple Calendar |
|
||||||
|
| **文档与存储** | Google Docs、Google Drive、Notion、Dropbox、Airtable |
|
||||||
|
| **代码与开发** | GitHub、Linear、Jira、Figma |
|
||||||
|
| **通讯** | Slack、Discord、Microsoft Teams、Telegram、WhatsApp |
|
||||||
|
| **CRM 与销售** | Salesforce、HubSpot |
|
||||||
|
| **商业与支付** | Stripe、Shopify |
|
||||||
|
| **项目管理** | Asana、Trello |
|
||||||
|
| **社交** | Twitter / X、Spotify、YouTube |
|
||||||
|
|
||||||
|
## 原生 vs 代理
|
||||||
|
|
||||||
|
部分服务有**原生 provider**。Rust 模块知道如何直接将服务摄入记忆树(例如 Gmail 的原生摄入路径)。其他仅暴露为**代理工具**:智能体可以调用,但没有自动摄入。新的原生 provider 随着功能落地陆续添加。
|
||||||
|
|
||||||
|
## 连接如何工作
|
||||||
|
|
||||||
|
点击任意集成的**连接**。浏览器窗口打开进行 OAuth。登录后,连接变为活跃状态,OpenHuman 在下一个 20 分钟 tick 开始同步。
|
||||||
|
|
||||||
|
每个集成显示其当前状态:
|
||||||
|
|
||||||
|
* **未连接**。集成尚未设置。
|
||||||
|
* **已连接**。集成活跃并正在同步。
|
||||||
|
* **管理**。活跃集成,可重新配置或断开。
|
||||||
|
|
||||||
|
你可以随时从 Skills 标签页撤销任何连接。
|
||||||
|
|
||||||
|
## 消息渠道
|
||||||
|
|
||||||
|
三个集成是特殊的。OpenHuman 用它们*回复*你,而不只是读取:
|
||||||
|
|
||||||
|
* **Telegram**。主要消息渠道。双向:发送和接收消息、管理聊天、搜索历史、创建群组、代表你执行 80+ 操作。所有操作通过你自己加密的凭据运行。
|
||||||
|
* **Discord**。通过 Discord 发送和接收消息。连接你的账户以接收 OpenHuman 消息。
|
||||||
|
* **Web**。桌面应用内的浏览器聊天界面。消息完全保留在本地。
|
||||||
|
|
||||||
|
在**设置 → 自动化与渠道 → 消息渠道**中设置你的默认值。活跃路由状态显示当前使用的渠道。Telegram 提供两种凭据模式:通过 OpenHuman 连接(一键,加密)或提供你自己的凭据以获得最大控制权。
|
||||||
|
|
||||||
|
## 技能
|
||||||
|
|
||||||
|
除了第三方服务,OpenHuman 还有**技能**——运行在应用内的小型沙盒模块,获取外部数据、按计划运行、转换信息、响应事件。每个技能都强制执行资源限制。技能从 Skills 标签页安装,与其他所有内容一样集成到同一个记忆树。
|
||||||
|
|
||||||
|
## 原生语音和工具
|
||||||
|
|
||||||
|
有两个功能作为原生功能搭载,而非集成,因为它们对桌面体验是基础性的:
|
||||||
|
|
||||||
|
* [**语音**](../native-tools/voice.zh-CN.md)。语音转文字输入、文字转语音输出,加上实时 Google Meet 智能体——加入会议、转录到记忆树、在通话中说话。
|
||||||
|
* [**原生工具**](../native-tools/README.zh-CN.md)。内置网络搜索、网络抓取,以及完整的文件系统/git/lint/test/grep 编码工具集,智能体开箱即用。
|
||||||
|
|
||||||
|
## 隐私边界
|
||||||
|
|
||||||
|
OpenHuman core 从不直接调用任何第三方 API。所有请求都通过 OpenHuman 后端,该后端处理 OAuth token 和速率限制。你的 token 永不以明文形式存储在电脑磁盘上,智能体只看到工具调用的*结果*,而不是凭据。
|
||||||
|
|
||||||
|
如果你选择直连 Composio 模式,该边界会改变:你本地的 core 使用你自己的 Composio API 密钥,你负责 Composio 账户、速率限制、计费关系,以及触发器投递所需的任何 webhook 端点。
|
||||||
|
|
||||||
|
完整边界见[隐私与安全](../privacy-and-security.zh-CN.md)。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [触发器](triggers.zh-CN.md),已连接集成的实时事件以及它们如何触发智能体操作。
|
||||||
|
* [从集成自动拉取](../obsidian-wiki/auto-fetch.zh-CN.md)
|
||||||
|
* [记忆树](../obsidian-wiki/memory-tree.zh-CN.md)
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
已连接集成(Gmail 新邮件、Notion 编辑、Stripe charge)的实时事件
|
||||||
|
作为触发器到达,被分类器分类,并可自动触发智能体操作。
|
||||||
|
icon: bolt
|
||||||
|
---
|
||||||
|
|
||||||
|
# 触发器
|
||||||
|
|
||||||
|
已连接的集成不仅仅是智能体可以按需读取的地方。它也是**实时事件源**。当有人给你发邮件、编辑 Notion 页面、在你的某个仓库打开 GitHub Issue、在 Stripe 上给你的卡收费、或在 Slack 上给你发 DM 时,OpenHuman 几乎实时接收该事件,并可以决定是否要对其采取行动。
|
||||||
|
|
||||||
|
本页关于这条流水线:触发器如何到达、如何分类、以及触发器如何无需你输入一个字就变成完整的智能体操作。
|
||||||
|
|
||||||
|
## 什么是触发器
|
||||||
|
|
||||||
|
触发器是你所连接集成发布的外部事件。常见形态:
|
||||||
|
|
||||||
|
| 集成 | 示例触发器 |
|
||||||
|
| --- | --- |
|
||||||
|
| **Gmail** | `GMAIL_NEW_GMAIL_MESSAGE`,收件箱中的新邮件 |
|
||||||
|
| **Slack** | `SLACK_NEW_MESSAGE`,你被提及的频道/DM 消息 |
|
||||||
|
| **Notion** | `NOTION_PAGE_UPDATED`,被跟踪的页面有变化 |
|
||||||
|
| **GitHub** | `GITHUB_ISSUE_OPENED`、`GITHUB_PULL_REQUEST_OPENED`,你的仓库上 |
|
||||||
|
| **Stripe** | `STRIPE_CHARGE_SUCCEEDED`,你账户上的一笔成功 charge |
|
||||||
|
| **日历** | `GOOGLE_CALENDAR_EVENT_CREATED`,你日历上的新事件 |
|
||||||
|
|
||||||
|
完整集合来自为[第三方集成](README.md)提供支持的 [Composio](https://composio.dev) 连接器层。当连接活跃时,相关的触发器订阅会自动接入。
|
||||||
|
|
||||||
|
### Gmail OAuth 作用域
|
||||||
|
|
||||||
|
Gmail 触发器订阅需要所连接 Google 账户的邮件读取权限。新鲜的 OpenHuman Gmail 授权请求 `https://www.googleapis.com/auth/gmail.readonly`,这样 `GMAIL_NEW_GMAIL_MESSAGE` 可以启用,原生 Gmail 同步路径可以读取新邮件元数据。
|
||||||
|
|
||||||
|
如果旧 Gmail 连接在此作用域被请求之前创建,请从设置中重新连接 Gmail 然后再启用 Gmail 触发器。
|
||||||
|
|
||||||
|
## 触发器从哪里来,从头到尾
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌────────────────────┐
|
||||||
|
│ third-party API │ Gmail / Slack / Notion / GitHub / ...
|
||||||
|
└─────────┬──────────┘
|
||||||
|
│ webhook
|
||||||
|
▼
|
||||||
|
┌────────────────────┐
|
||||||
|
│ OpenHuman backend │ HMAC 验证 webhook,规范 payload
|
||||||
|
└─────────┬──────────┘
|
||||||
|
│ Socket.IO 事件("composio:trigger")
|
||||||
|
▼
|
||||||
|
┌────────────────────┐
|
||||||
|
│ Rust core │ 在进程内事件总线上发布 DomainEvent::ComposioTriggerReceived
|
||||||
|
│(你的笔记本)│
|
||||||
|
└─────────┬──────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────┐
|
||||||
|
│ Trigger Triage │ 分类:drop / acknowledge / react / escalate
|
||||||
|
└─────────┬──────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────┐
|
||||||
|
│ 以下之一: │
|
||||||
|
│ - nothing │ ← drop
|
||||||
|
│ - memory note │ ← acknowledge
|
||||||
|
│ - Trigger Reactor │ ← react(1-2 个工具调用)
|
||||||
|
│ - Orchestrator │ ← escalate(完整多步规划)
|
||||||
|
└────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
Webhook 永远不会被原始地到达你的机器。后端持有 OAuth token 并直接从第三方接收 webhook。它进行 HMAC 验证、规范 payload,并通过已认证的 socket 将其转发给你的 Rust core。你的笔记本在总线上看到一个干净的、经过验证的 `ComposioTriggerReceived` 事件,没有别的。
|
||||||
|
|
||||||
|
## 分类步骤
|
||||||
|
|
||||||
|
在任何操作运行之前,每个触发器都经过 [`trigger_triage`](https://github.com/tinyhumansai/openhuman/tree/main/src/openhuman/agent/agents/trigger_triage) 智能体。它的唯一工作是决定系统其余部分应该做什么。
|
||||||
|
|
||||||
|
它精确选择四种操作之一:
|
||||||
|
|
||||||
|
| 操作 | 发生什么 | 何时使用 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| **`drop`** | 什么也不做。触发器被静默记录并丢弃。 | 垃圾邮件、重复、不相关的噪音。默认用于你不在乎的东西。 |
|
||||||
|
| **`acknowledge`** | 持久化一条短期记忆笔记,不运行智能体。 | 值得记住的被动通知("档案中创建了一个新页面")。 |
|
||||||
|
| **`react`** | 使用一到两个工具调用运行 [`trigger_reactor`](https://github.com/tinyhumansai/openhuman/tree/main/src/openhuman/agent/agents/trigger_reactor) 智能体。 | 一个小的、单步的副作用:存储一条记忆条目、发布快速确认、将线程标记为已读。 |
|
||||||
|
| **`escalate`** | 全权交给带规划能力的 **orchestrator** 智能体。 | 需要推理、多步、或多技能的任何东西:起草回复、更新多个 Notion 页面、决定如何分类入站 issue。 |
|
||||||
|
|
||||||
|
分类智能体拥有与智能体其余部分相同的记忆和工作区上下文。它可以判断触发器是否与你现在正在做的事情相关、涉及哪些人、以及是否是你之前要求 OpenHuman 采取行动的那类事情。
|
||||||
|
|
||||||
|
## 触发器何时变成智能体操作
|
||||||
|
|
||||||
|
这就是区分"OpenHuman 有 Gmail 集成"和"OpenHuman 在值班你的收件箱"的部分:
|
||||||
|
|
||||||
|
- **`react`** 是廉价路径。Trigger Reactor 是一个有严格预算的窄专家,只有几个工具调用。它非常适合:写一条简短的记忆笔记说"看到 Stripe 新增一笔 $84 charge,客户 X,商户 Y"、静默将同一自动提醒标记为已处理因为你本周已经分类过两次、或存储用户以后可能想查找的事件的结构化记录。
|
||||||
|
|
||||||
|
- **`escalate`** 是重型路径。当分类智能体决定触发器需要真正的工作时,它将自包含的任务描述交给 Orchestrator。orchestrator 可以访问你完整的技能表面、工具、记忆和[潜意识循环](../subconscious.md)输出。从那里它可能:
|
||||||
|
- 起草一封重要邮件的回复并排队等待你批准。
|
||||||
|
- 为入站 issue 拉取相关的 Notion / Linear / Drive 上下文并写一条结构化评论。
|
||||||
|
- 基于单个入站事件更新三个已连接系统("这个客户的计划在 Stripe 变了,更新 HubSpot,在 #revenue 发帖,并在他们的 Notion 文件中添加一条笔记")。
|
||||||
|
- 判断触发器意味着一个会议刚刚被预定并为该通话预加载[会议智能体](../mascot/meeting-agents.md)。
|
||||||
|
|
||||||
|
两种情况下操作都在你的机器上运行,针对你的本地记忆树,使用与智能体其余部分相同的模型路由和工具表面。
|
||||||
|
|
||||||
|
## 为什么要一个分类步骤
|
||||||
|
|
||||||
|
跳过分类器并将每个触发器直接管道到 orchestrator 很有诱惑力。这是一个坏主意,有两个原因:
|
||||||
|
|
||||||
|
1. **大多数触发器是噪音。** 一个已连接的 Gmail 账户每小时触发数十个触发器,其中绝大多数是用户不在乎的。在每个上运行 orchestrator 会消耗预算并产生持续的后台活动流。
|
||||||
|
2. **不同的触发器值得不同的上限。** 一个自动 Stripe 收据和个人 Slack DM 不应该花相同的 token 数来处理。分类让廉价路径保持廉价,并将 orchestrator 保留给值得它的东西。
|
||||||
|
|
||||||
|
分类在快速模型层运行(参见[自动模型路由](../model-routing/README.md)),所以分类本身在亚秒级完成。
|
||||||
|
|
||||||
|
## 配置和退出
|
||||||
|
|
||||||
|
- **默认开启。** 一旦集成被连接,其触发器自动进入流水线。
|
||||||
|
- **退出。** 分类路径由 `OPENHUMAN_TRIGGER_TRIAGE_DISABLED` 环境变量控制。设为 `1` / `true` / `yes` 关闭智能体分类并退回到仅被动日志记录。集成本身保持连接;只有自动操作行为被抑制。
|
||||||
|
- **每触发器设置。** 触发器设置(哪些集成和事件类型应该被评估)在**设置**下管理;底层 RPC 方法是 `update_composio_trigger_settings` / `get_composio_trigger_settings`。
|
||||||
|
- **审计日志。** 每个触发器,无论决策如何,都被写入触发器历史,这样你可以看到什么到达了、分类器决定了什么、以及(如果有的话)运行了什么。决策和升级也作为进程内总线上的 `TriggerEvaluated` / `TriggerEscalated` 事件发布,这意味着核心内部的任何东西都可以订阅它们。
|
||||||
|
|
||||||
|
## 隐私边界
|
||||||
|
|
||||||
|
触发器遵循与产品其余部分相同的边界(参见[隐私与安全](../privacy-and-security.md)):
|
||||||
|
|
||||||
|
- 第三方 token 位于后端,永不在你的笔记本上。
|
||||||
|
- Webhook 在到达你的机器之前由后端进行 HMAC 验证。
|
||||||
|
- 触发器 payload 由你的本地 core 处理;分类和任何反应在你机器上运行,针对你的本地记忆树。
|
||||||
|
- `acknowledge` / `react` / `escalate` 路径写入的记忆笔记存储在你本地 SQLite 记忆树和 Markdown 存储库中,与任何其他来源相同。
|
||||||
|
|
||||||
|
## 开发者实现指针
|
||||||
|
|
||||||
|
- 分类智能体:`src/openhuman/agent/agents/trigger_triage/`
|
||||||
|
- Reactor 智能体:`src/openhuman/agent/agents/trigger_reactor/`
|
||||||
|
- Composio 总线订阅器:`src/openhuman/composio/bus.rs`(`ComposioTriggerSubscriber`)
|
||||||
|
- 触发器历史持久化:`src/openhuman/composio/trigger_history.rs`
|
||||||
|
- 领域事件:`DomainEvent::ComposioTriggerReceived`、`DomainEvent::TriggerEscalated` 在 `src/core/event_bus/events.rs` 中
|
||||||
|
- 触发器设置 RPC:`src/openhuman/config/` 中的 `update_composio_trigger_settings` / `get_composio_trigger_settings`
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [第三方集成](README.md),触发器来源的服务目录。
|
||||||
|
* [从集成自动拉取](../obsidian-wiki/auto-fetch.md),轮询对应部分,定期将源数据摄入记忆树。
|
||||||
|
* [潜意识循环](../subconscious.md),使用触发器上下文和记忆提前规划的背景循环。
|
||||||
|
* [会议智能体](../mascot/meeting-agents.md),升级触发器可以落地的地方之一(日历事件有 Meet 链接)。
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
OpenHuman 的屏幕之脸——一个桌面吉祥物,能说话、能反应、
|
||||||
|
能加入你的会议、能在你不看的时候在后台思考。
|
||||||
|
icon: face-smile
|
||||||
|
---
|
||||||
|
|
||||||
|
# 吉祥物
|
||||||
|
|
||||||
|
OpenHuman 有一张脸。吉祥物是一个生活在你桌面上的动画角色,作为智能体的可见表面——它在说什么、它在思考什么、它何时空闲、何时忙碌、何时有话要告诉你。
|
||||||
|
|
||||||
|
它不是装饰性镀层。吉祥物接入智能体同一套组件:语音、记忆、[潜意识循环](../subconscious.zh-CN.md)和 [Google Meet 集成](../native-tools/voice.zh-CN.md)。智能体说话时,吉祥物就是说话的那个;智能体思考时,吉祥物就是思考的那个。
|
||||||
|
|
||||||
|
## 它做什么
|
||||||
|
|
||||||
|
### 它说话,并与自己的声音口型同步
|
||||||
|
|
||||||
|
智能体回复时,音频通过托管 TTS 模型生成并流式传输到你的扬声器。同时,吉祥物驱动一个 viseme 贴图与音频对齐,这样它的嘴型与说出的词语相匹配。没有单独的"说话头像"视频,你听到的同一音频流驱动着动画。
|
||||||
|
|
||||||
|
吉祥物所依赖的语音转文字、文字转语音、会议管道见[原生语音](../native-tools/voice.zh-CN.md)。
|
||||||
|
|
||||||
|
### 它加入你的会议,作为真实参与者
|
||||||
|
|
||||||
|
吉祥物是 OpenHuman 的旗舰语音集成。它可以作为真实参与者加入 Google Meet 会议:它听到每个人、将笔记记入你的[记忆树](../obsidian-wiki/memory-tree.zh-CN.md)、当它有话要说时在通话中说话,并将其自己的动画脸作为摄像头画面管道输送到会议中。
|
||||||
|
|
||||||
|
这是头条用例,有专门页面,见[会议智能体](meeting-agents.zh-CN.md)。
|
||||||
|
|
||||||
|
### 它移动并对周围环境做出反应
|
||||||
|
|
||||||
|
吉祥物有情绪状态(空闲、思考、倾听、说话、惊讶、做梦),它根据智能体的行为在状态间转换。当你开始打字时它切换到倾听姿势。当模型在推理时它显示出来。当工具调用返回值得注意的内容时它做出反应。当你停止交互一段时间后,它进入空闲状态。
|
||||||
|
|
||||||
|
它应该让人感觉是活的,而非轨道动画。
|
||||||
|
|
||||||
|
### 它记得你
|
||||||
|
|
||||||
|
吉祥物是拥有[记忆树](../obsidian-wiki/memory-tree.zh-CN.md)的智能体的可见部分。它记得你们聊过什么、你生活中的人是谁、你盘子上有什么、已决定了什么、什么还悬而未决,跨越你连接的所有来源。当它早上问候你时,它不是从零开始。
|
||||||
|
|
||||||
|
这种记忆使性格在数周和数月间保持一致。今天和你说话的吉祥物知道上周二和你说话的吉祥物知道的东西。
|
||||||
|
|
||||||
|
### 它在后台思考——潜意识
|
||||||
|
|
||||||
|
即使你已经停止打字,吉祥物也在继续思考。[潜意识循环](../subconscious.zh-CN.md)是一个后台 tick:
|
||||||
|
|
||||||
|
* 加载你的待办任务和背景目标。
|
||||||
|
* 读取你工作区和最近记忆的当前状态。
|
||||||
|
* 决定对每项做什么(自主执行、保留、或升级给你审批)。
|
||||||
|
* 将结果写入你可以审计的活动日志。
|
||||||
|
|
||||||
|
所以当你回到桌前,吉祥物可能已经起草了邮件、刷新了仪表板、或排队了它需要问你的问题。屏幕上的那张脸就是做了工作的那张。
|
||||||
|
|
||||||
|
### 它做梦
|
||||||
|
|
||||||
|
当你离开得足够久,吉祥物进入做梦状态。做梦是智能体的离线整合过程,将一天的块凝练为更长期限的摘要、刷新已升温实体的主题树、浮现不符合任何单一来源的模式。吉祥物在做梦时动画不同,这样你可以一眼看出:它不是空闲,它在处理。
|
||||||
|
|
||||||
|
当你回来时,做梦已经折叠到记忆树中。吉祥物醒来时比睡前更聪明。
|
||||||
|
|
||||||
|
## 为什么要有一个吉祥物?
|
||||||
|
|
||||||
|
大多数助手只是一个闪烁的文本输入。对工具来说这没问题。对于要整天陪伴你、对你生活有持久记忆、代表你执行操作的东西来说,这还不够。
|
||||||
|
|
||||||
|
吉祥物的存在是因为:
|
||||||
|
|
||||||
|
* **存在胜过面板。** 你可以扫一眼的脸在一帧中告诉你智能体是忙碌、空闲、做梦还是在试图引起你注意。
|
||||||
|
* **它让语音通话感觉像对话。** 一个与自己的语音口型同步的动画角色的摄像头画面,与黑色方块的机器人声音是截然不同的体验。
|
||||||
|
* **性格是一个 UX 表面。** 屏幕上始终如一的角色比无脸的 API 更值得信任、更容易交谈、更容易原谅错误。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [会议智能体](meeting-agents.zh-CN.md),吉祥物在 Google Meet 中:倾听、说话、动画、使用工具。
|
||||||
|
* [原生语音](../native-tools/voice.zh-CN.md),吉祥物所依赖的 STT / TTS 管道。
|
||||||
|
* [记忆树](../obsidian-wiki/memory-tree.zh-CN.md),吉祥物记住什么以及如何记住。
|
||||||
|
* [潜意识循环](../subconscious.zh-CN.md),你离开时它在思考什么。
|
||||||
|
* [Chromium Embedded Framework](../../developing/cef.md),摄像头进入 Meet 的管道(开发者参考)。
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
吉祥物作为真实参与者加入会议:倾听、记笔记、在通话中说话、
|
||||||
|
将动画脸管道到摄像头网格,并在会议中间使用工具。不只是笔记工具。
|
||||||
|
icon: video
|
||||||
|
---
|
||||||
|
|
||||||
|
# 会议智能体
|
||||||
|
|
||||||
|
吉祥物的旗舰集成是**会议智能体**:你在桌面上对话的同一角色可以代表你加入 Google Meet,坐在参与者网格中作为动画脸,听到房间里的每个人,用自己的声音在通话中说话,并在会议进行时使用工具。
|
||||||
|
|
||||||
|
它不是笔记工具。笔记工具安静地坐着产生转录。会议智能体参与——它回答问题、实时查找、在与同一个人之前的会议中记住事情,并在你(或它)决定有用的内容要补充时做出贡献。
|
||||||
|
|
||||||
|
## 它在通话中实际做什么
|
||||||
|
|
||||||
|
### 1. 作为真实参与者加入
|
||||||
|
|
||||||
|
吉祥物通过嵌入式 webview 加入会议,与一个人从浏览器加入的方式相同。网格中有一个名字、一张脸和一个瓦片。其他参与者像看到任何其他与会者一样看到和听到它——没有日历 bot、没有拨入号码、没有"此会议正被……录制"横幅。
|
||||||
|
|
||||||
|
在底层,会议大脑位于 `src/openhuman/meet_agent/brain.rs`,webview 端是 OpenHuman 用于其他嵌入式 provider 的相同 CEF 子窗口。
|
||||||
|
|
||||||
|
### 2. 它倾听房间里的每个人
|
||||||
|
|
||||||
|
会议的入站音频被捕获并实时推送通过流式语音转文字。转录按说话者分离,经过与桌面听写相同的幻觉过滤和后处理,并在会议展开时折叠到[记忆树](../obsidian-wiki/memory-tree.zh-CN.md)中——在正确的人、正确的主题、正确的项目下,带有吉祥物以后可以使用的反向链接。
|
||||||
|
|
||||||
|
因为转录正在实时结构化,吉祥物可以在会议仍在进行时回答关于_这个_会议(或与同一个人任何之前的会议)的问题。
|
||||||
|
|
||||||
|
### 3. 它互动——回答、提问、跟进
|
||||||
|
|
||||||
|
智能体没有静音。当你是指向它("Ghosty,你能拉出上个季度的数字吗?"),或者当它决定有用的内容要补充时,它使用项目正常 LLM 堆栈实时生成回复并在会议中说话。
|
||||||
|
|
||||||
|
对话轮次通过快速模型层路由(参见[自动模型路由](../model-routing/README.zh-CN.md)),这样延迟感觉像在和一个正在倾听的人说话,而不是等待聊天机器人。
|
||||||
|
|
||||||
|
### 4. 它说话——自己的 TTS 音频播放回通话
|
||||||
|
|
||||||
|
回复由项目 TTS 堆栈生成并直接作为出站麦克风 feed 流式传输到会议中。它不是通过你的本地扬声器播放并被你的麦克风重新捕获——它直接作为智能体的音频注入,所以它干净地到达其他每个人,不会通过你的房间回声。
|
||||||
|
|
||||||
|
### 5. 它动画——吉祥物的脸就是摄像头 feed
|
||||||
|
|
||||||
|
吉祥物的画布被管道到 Meet 通话作为出站摄像头流(commit `b6d05cb4` 引入的工作,Mascot 帧流水线在 `f5dce783` 中进一步打磨)。当智能体在说话时,吉祥物在摄像头瓦片上说话——嘴型与所有其他人听到的同一 TTS 音频口型同步。当它在倾听时,它显示倾听姿势。当它在说话前推理时,你看到思考姿势。
|
||||||
|
|
||||||
|
其他参与者在网格中看不到黑色瓦片或静态头像。他们看到一个与正在说的话实时反应的动画角色,这使得通话感觉像与活着的东西对话,而不是声音从无处传来。
|
||||||
|
|
||||||
|
### 6. 它在会议中间使用工具——这是笔记工具做不到的部分
|
||||||
|
|
||||||
|
这就是转录 bot 和会议_智能体_之间的区别。
|
||||||
|
|
||||||
|
当通话发生时,吉祥物可以访问它在桌面上相同的工具表面:
|
||||||
|
|
||||||
|
- [**记忆树**](../obsidian-wiki/memory-tree.zh-CN.md)——召回之前的会议、决策、开放线程、谁上次说了什么、承诺了什么。
|
||||||
|
- [**从集成自动拉取**](../obsidian-wiki/auto-fetch.zh-CN.md)和[**第三方集成**](../integrations/README.zh-CN.md)——从 Slack 拉取线程、一封邮件、一个 Linear ticket、一个 Notion 文档、一个日历条目、一个 Drive 文件。
|
||||||
|
- [**原生工具**](../native-tools/README.zh-CN.md)——搜索网络、抓取页面、运行快速代码/数据查询,全部不离开通话。
|
||||||
|
- [**潜意识循环**](../subconscious.zh-CN.md)输出——任何它在后台一直在工作的东西都随手可得。
|
||||||
|
|
||||||
|
所以当通话中有人问"等等,我们不是上个月决定放弃 Q3 发布的吗?",吉祥物不只是转录问题。它回答它——用实际的决策、做出它的会议、以及谁同意了。
|
||||||
|
|
||||||
|
这将它从_笔记工具_移到_房间里信息最丰富的参与者_。
|
||||||
|
|
||||||
|
## 为什么它感觉是活的
|
||||||
|
|
||||||
|
只转录的会议智能体是工具。参与的会议智能体是一种存在。Meet 集成刻意构建为让吉祥物感觉像一个真正的与会者,而不是录音设备:
|
||||||
|
|
||||||
|
- 它在摄像头网格上有**一张脸**,会口型同步和反应,不是黑色方块或标志。
|
||||||
|
- 它有**自己的声音**,播放到通话中,而不是你的扬声器。
|
||||||
|
- 它有**持久记忆**房间里的、项目、之前的决策——所以它可以被命名并上下文回答。
|
||||||
|
- 它有**工具**,所以它可以行动于所说的话,而不只是记录。
|
||||||
|
- 它在会议之间运行**潜意识循环**——所以当它加入你的下一个通话时,它已经做完了在上一个会议中承诺的功课。
|
||||||
|
|
||||||
|
实际结果是,参与者不再把它当作 bot 开始对待,而是开始把它当作一个恰好非常快速查找东西的同事。
|
||||||
|
|
||||||
|
## 设置、控制、隐私
|
||||||
|
|
||||||
|
- **加入通话。** 你可以从桌面 app 给吉祥物一个 Google Meet 链接;它将打开嵌入式 Meet webview,用配置的显示名称加入,并将其摄像头瓦片切换到吉祥物画布。
|
||||||
|
- **麦克风和摄像头控制。** 智能体的麦克风是 TTS 注入流,不是你真正的麦克风。智能体的摄像头是吉祥物帧生成器,不是你真正的网络摄像头。你可以随时从 app 中将智能体的麦克风静音,就像在 Meet 中静音自己一样。
|
||||||
|
- **转录和记忆。** 实时转录以与任何其他来源相同的方式落在[记忆树](../obsidian-wiki/memory-tree.zh-CN.md)中——在通话中的人、项目和出现的主题下。它们是本地优先的,遵循项目的[隐私与安全](../privacy-and-security.zh-CN.md)规则。
|
||||||
|
- **无秘密录制。** 智能体在网格中作为正常参与者出现;通话中的每个人都可以看到它,并在它说话时看到。
|
||||||
|
|
||||||
|
## 开发者实现指针
|
||||||
|
|
||||||
|
好奇这是如何连接的:
|
||||||
|
|
||||||
|
- 大脑 - `src/openhuman/meet_agent/brain.rs`(LLM 轮次、说话/不说话决定、工具调用)。
|
||||||
|
- 语音管道 - `src/openhuman/voice/`(STT in、TTS out、幻觉过滤、后处理)。参见[原生语音](../native-tools/voice.zh-CN.md)。
|
||||||
|
- 作为出站摄像头的吉祥物画布 - `app/src/features/meet/MascotFrameProducer.tsx` 和 Tauri 端 `mascot_native_window.rs` 窗口。
|
||||||
|
- 嵌入式 Meet webview - 参见 [Chromium Embedded Framework](../../developing/cef.md)。Meet 子 webview **零注入 JavaScript** 发货;所有 host 端通过 CDP 原生运行。
|
||||||
|
- 要阅读的上下文的重要 commit - `0bc74575`(实时记笔记)、`f1203479`(真实 LLM 轮次 + 调优 TTS)、`b6d05cb4`(吉祥物画布作为出站摄像头)、`f5dce783`(吉祥物帧流水线 + 屏外会议窗口)。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
- [吉祥物](./)——屏幕上的角色本身,会议之外。
|
||||||
|
- [原生语音](../native-tools/voice.zh-CN.md)——会议智能体所依赖的 STT / TTS。
|
||||||
|
- [记忆树](../obsidian-wiki/memory-tree.zh-CN.md)——转录和决策落地的地方。
|
||||||
|
- [原生工具](../native-tools/README.zh-CN.md)——吉祥物在通话中可以伸手拿什么。
|
||||||
|
- [自动模型路由](../model-routing/README.zh-CN.md)——对话轮次为什么感觉低延迟。
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
一个订阅,多个模型。任务通过 hint 前缀选择模型:
|
||||||
|
推理发给强模型,快速路径发给快模型,视觉发给视觉模型。
|
||||||
|
icon: route
|
||||||
|
---
|
||||||
|
|
||||||
|
# 自动模型路由
|
||||||
|
|
||||||
|
智能体的不同部分需要不同的模型。长推理需要前沿模型。快速的"修这个拼写错误"需要又快又便宜的模型。视觉需要视觉模型。OpenHuman 通过内置**路由 provider**处理这一切,所以你永远不需要考虑它。
|
||||||
|
|
||||||
|
## 请求如何被路由
|
||||||
|
|
||||||
|
任何聊天调用上的 model 参数可以取两种形式:
|
||||||
|
|
||||||
|
- **具体模型名**。例如 `anthropic/claude-sonnet-4`。路由到带该精确模型的默认 provider。
|
||||||
|
- **Hint 前缀**。例如 `hint:reasoning`。在路由表中查找 hint 并解析为 `(provider, model)` 对。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/openhuman/providers/router.rs
|
||||||
|
fn resolve(&self, model: &str) -> (usize, String) {
|
||||||
|
if let Some(hint) = model.strip_prefix("hint:") {
|
||||||
|
if let Some((idx, resolved_model)) = self.routes.get(hint) {
|
||||||
|
return (*idx, resolved_model.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(self.default_index, model.to_string())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
路由器包装了多个预创建的 providers(Anthropic、OpenAI、Google、Groq 等),每次请求选择正确的一个。Hint 可以在运行时重新映射而无需重启 core。
|
||||||
|
|
||||||
|
## 常见 hint
|
||||||
|
|
||||||
|
| Hint | 典型目标 | 使用场景 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `hint:reasoning` | 强推理模型 | 多步规划、数学、重度代码轮次 |
|
||||||
|
| `hint:fast` | 快速/便宜模型 | UI 助手、自动补全、小型分类调用 |
|
||||||
|
| `hint:vision` | 有视觉能力的模型 | 截图、图像附件、OCR |
|
||||||
|
| `hint:summarize` | 擅长压缩的模型 | 记忆树摘要构建器 |
|
||||||
|
| `hint:code` | 代码调优的模型 | 原生编码器轮次 |
|
||||||
|
|
||||||
|
精确映射可配置;默认值提供每个 provider 的合理路由。
|
||||||
|
|
||||||
|
## 一个订阅
|
||||||
|
|
||||||
|
路由在单一 OpenHuman 订阅背后发生。你不需要分别为 Anthropic、OpenAI、Google 等持有单独的 API 密钥,后端经纪访问,路由器为每个任务选择正确的一个。这就是 README 中"一个订阅,多个 provider"的承诺,具体化了。
|
||||||
|
|
||||||
|
## 覆盖路由
|
||||||
|
|
||||||
|
- **全局**。配置 TOML(`src/openhuman/config/schema/types.rs` 中的 `Config` 结构体)可以在启动时提供自定义路由表。
|
||||||
|
- **每次调用**。传递具体模型名(无 `hint:` 前缀),路由器回退到带该精确模型的默认 provider。
|
||||||
|
- **对于技能**。技能可以在其 manifest 中固定一个 hint 或模型。
|
||||||
|
|
||||||
|
## 为什么这不是简单的"模型切换器"
|
||||||
|
|
||||||
|
路由不是 UI 下拉菜单。智能体循环本身根据它要做什么发出 hint。你不选择模型;*任务*选择。这就是"多模型"和"智能路由"的区别。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
- [智能 Token 压缩](../token-compression.zh-CN.md)。什么使大型推理调用负担得起。
|
||||||
|
- [原生工具](../native-tools/README.zh-CN.md)。不同的工具调用暗示不同的路由。
|
||||||
|
- [本地 AI(可选)](local-ai.zh-CN.md)。轻量聊天 hint 可以在设备上运行。
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
可选、自愿开启的本地 AI,通过 Ollama 或 LM Studio 提供。
|
||||||
|
为记忆嵌入向量、摘要树构建和后台推理循环提供端侧支持。聊天/视觉/语音走云端。
|
||||||
|
icon: microchip
|
||||||
|
---
|
||||||
|
|
||||||
|
# 本地 AI(可选)
|
||||||
|
|
||||||
|
OpenHuman 可以为以下工作负载在你机器上运行本地模型:当本地保留数据最为重要时:**记忆嵌入向量、摘要树构建和后台推理循环**。它是**自愿开启**的,默认**关闭**。
|
||||||
|
|
||||||
|
这是一个刻意的范围界定。之前的设计尝试将聊天、视觉、STT 和 TTS 全部放在 Gemma 3 的设备上,结果是对硬件较敏感的资源占用,与产品其余部分所需的东西冲突。如今,本地最有价值的东西(循环、低延迟、隐私敏感的内存工作)走本地;最有价值于前沿模型的东西(默认聊天、推理、视觉)走云端。
|
||||||
|
|
||||||
|
## 开启后什么在本地运行
|
||||||
|
|
||||||
|
| 工作负载 | 默认模型 | 实现 |
|
||||||
|
| ------------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| **记忆嵌入向量** | `all-minilm:latest` | `src/openhuman/embeddings/ollama.rs`——用于[记忆树](../obsidian-wiki/memory-tree.zh-CN.md)向量搜索。 |
|
||||||
|
| **摘要树构建** | `gemma3:1b-it-qat`(可配置) | `src/openhuman/tree_summarizer/ops.rs`——记忆树的源/主题/全局摘要构建器。 |
|
||||||
|
| **心跳循环** | 小型聊天模型 | `src/openhuman/heartbeat/`——周期性后台反思。 |
|
||||||
|
| **学习 / 反思** | 小型聊天模型 | `src/openhuman/learning/reflection.rs`——巩固所学内容的通过。 |
|
||||||
|
| **潜意识** | 小型聊天模型 | `src/openhuman/subconscious/executor.rs`——后台评估循环。 |
|
||||||
|
|
||||||
|
每个都是**按功能开启的 opt-in flag**。开启本地 AI 不会静默将所有内容路由到它,你选择工作负载。
|
||||||
|
|
||||||
|
## 什么留在云端
|
||||||
|
|
||||||
|
| 工作负载 | 为什么走云端 |
|
||||||
|
| ------------------ | --------------------------------------------------------------------------------------------------- |
|
||||||
|
| **聊天(默认)** | 前沿推理质量。通过[模型路由器](README.zh-CN.md)在单一订阅下路由。 |
|
||||||
|
| **视觉** | 同上。 |
|
||||||
|
| **STT** | 后端代理转录(`src/openhuman/voice/cloud_transcribe.rs`)。 |
|
||||||
|
| **TTS** | 底层托管[文字转语音](../native-tools/voice.zh-CN.md)(`reply_speech.rs`)。 |
|
||||||
|
| **网络搜索** | 后端代理(你的机器上没有 API key)。 |
|
||||||
|
|
||||||
|
对于**轻量级或中等聊天 hint**(`hint:reaction`、`hint:classify`、`hint:format`、`hint:sentiment`、`hint:summarize`、`hint:medium`、`hint:tool_lite`),当本地 AI 开启且 Ollama 可达时,[路由器](README.zh-CN.md)会优先使用本地 provider。重型 hint(`hint:reasoning`、`hint:agentic`、`hint:coding`)走云端。
|
||||||
|
|
||||||
|
## 工作原理
|
||||||
|
|
||||||
|
在底层,OpenHuman 支持两种本地 provider 路径:
|
||||||
|
|
||||||
|
* [Ollama](https://ollama.com),用于捆绑模型生命周期、嵌入向量和现有模型资产流。
|
||||||
|
* [LM Studio](https://lmstudio.ai),通过其本地 OpenAI 兼容服务器用于聊天风格本地推理。
|
||||||
|
|
||||||
|
对于 Ollama,OpenHuman 在可能的情况下与其 OpenAI 兼容的 `/v1` 端点对话。这意味着:
|
||||||
|
|
||||||
|
* `OpenAiCompatibleProvider`(`src/openhuman/providers/compatible.rs`)与 Ollama 的包装方式与与远程 OpenAI 风格 provider 完全相同。没有特殊案例代码路径。
|
||||||
|
* Provider 路由器在启动时创建一个_健康门控_的本地 provider。如果 Ollama 不可达,请求透明地回退到远程 provider,没有破碎状态。
|
||||||
|
* 模型按需由 Ollama 拉取并缓存在其自己的存储中。OpenHuman 自己不附带权重。
|
||||||
|
|
||||||
|
对于 LM Studio,设置 `local_ai.provider = "lm_studio"` 并确保 LM Studio 本地服务器正在运行。OpenHuman 默认为 `http://localhost:1234/v1`,探测 `GET /v1/models`,并将聊天请求发送到 `POST /v1/chat/completions`。你可以用 `local_ai.base_url`、`OPENHUMAN_LM_STUDIO_BASE_URL` 或 `LM_STUDIO_BASE_URL` 覆盖端点。
|
||||||
|
|
||||||
|
## 选择加入
|
||||||
|
|
||||||
|
本地 AI 由 core 配置中的两个 flag 门控(`src/openhuman/config/schema/local_ai.rs`):
|
||||||
|
|
||||||
|
| Flag | 默认 | 含义 |
|
||||||
|
| ------------------------------------ | ------- | ------------------------------------------------------------------- |
|
||||||
|
| `local_ai.runtime_enabled` | `false` | 主开关。`false` ⇒ 根本不创建本地 provider。 |
|
||||||
|
| `local_ai.opt_in_confirmed` | `false` | 明确的 opt-in 标记。除非你重新 opt-in,否则 Bootstrap 强制为 `false`。 |
|
||||||
|
| `local_ai.provider` | `ollama` | 本地 provider:`ollama` 或 `lm_studio`。 |
|
||||||
|
| `local_ai.base_url` | 未设置 | 可选的 provider URL。LM Studio 默认为 `http://localhost:1234/v1`。 |
|
||||||
|
| `local_ai.usage.embeddings` | `false` | 使用本地进行记忆嵌入向量。 |
|
||||||
|
| `local_ai.usage.heartbeat` | `false` | 使用本地进行心跳循环。 |
|
||||||
|
| `local_ai.usage.learning_reflection` | `false` | 使用本地进行学习通过。 |
|
||||||
|
| `local_ai.usage.subconscious` | `false` | 使用本地进行潜意识循环。 |
|
||||||
|
|
||||||
|
在桌面 app 中,**设置 → AI 与技能 → 本地 AI** 暴露预设,选择一个("仅嵌入向量"、"记忆 + 反思"、"全部本地"),正确的 flag 组合会为你设置。状态(Ollama 可达性、模型可用性、每个子系统启用)通过 `openhuman.local_ai_status` 实时暴露。
|
||||||
|
|
||||||
|
## 何时开启
|
||||||
|
|
||||||
|
如果以下任一为真,开启本地 AI 是值得的:
|
||||||
|
|
||||||
|
* 你摄入大量邮件 / 聊天并希望**嵌入向量永不离开机器**。
|
||||||
|
* 你希望**摘要树构建**离线工作。
|
||||||
|
* 你对后台反思("潜意识")循环隐私敏感。
|
||||||
|
|
||||||
|
如果你的连接源很少,云端路径更快,隐私收益很小,则**不值得**开启。也有硬件成本:Ollama 和一个小型 Gemma 模型需要几 GB 的 RAM 并拉取几 GB 的权重。
|
||||||
|
|
||||||
|
## 你需要什么
|
||||||
|
|
||||||
|
* 安装并运行本地的 [**Ollama**](https://ollama.com),或启用本地服务器的 [**LM Studio**](https://lmstudio.ai)。
|
||||||
|
* 模型有足够的磁盘(`gemma3:1b-it-qat` \~700 MB,`all-minilm:latest` \~23 MB)。
|
||||||
|
* 有足够的 RAM 保持模型驻留(建议 8 GB+,理想 16 GB+)。
|
||||||
|
|
||||||
|
OpenHuman 处理其余:生命周期(`src/openhuman/local_ai/service/`)、API 客户端(`ollama_api.rs`、`lm_studio_api.rs`)、健康检查,以及当本地 provider 消失时优雅地回退到远程。
|
||||||
|
|
||||||
|
### LM Studio 故障排除
|
||||||
|
|
||||||
|
* 确认 LM Studio 本地服务器已启用并在 `http://localhost:1234/v1` 可达。
|
||||||
|
* 在调用 OpenHuman 之前在 LM Studio 中加载所选模型。当配置的 `local_ai.chat_model_id` 不在 `/v1/models` 中时,诊断报告 `load_lm_studio_model`。
|
||||||
|
* 如果 LM Studio 使用不同端口,设置 `local_ai.base_url` 或 `OPENHUMAN_LM_STUDIO_BASE_URL`。
|
||||||
|
* LM Studio 模型下载在 LM Studio 内部管理。OpenHuman 不会从本地资产下载控制中拉取 LM Studio 模型。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [记忆树](../obsidian-wiki/memory-tree.zh-CN.md)。本地嵌入向量 + 摘要 powering 什么。
|
||||||
|
* [自动模型路由](README.zh-CN.md)。轻量聊天 hint 如何优先使用本地 provider。
|
||||||
|
* [隐私与安全](../privacy-and-security.zh-CN.md)。当你 opt-in 时什么移至端侧。
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
OpenHuman 智能体开箱即用的完整工具集——研究、编码、
|
||||||
|
控制你的机器、安排任务、回复你,以及调用 118+ 第三方服务。
|
||||||
|
icon: toolbox
|
||||||
|
---
|
||||||
|
|
||||||
|
# 原生工具
|
||||||
|
|
||||||
|
OpenHuman 的智能体并非空载交付。智能体背后的每个模型在安装瞬间就有一套精选工具可用——无需插件市场、无需接入 API 密钥、无需注册 MCP 服务器。整个工具带都在盒子里。
|
||||||
|
|
||||||
|
本页是索引。每个子页面覆盖一个工具族。
|
||||||
|
|
||||||
|
## 为什么原生提供这些工具
|
||||||
|
|
||||||
|
纯插件模式意味着工具跑在不同进程里,通过 RPC 交互,各自维护认证和打包逻辑。这对于开放式扩展性没问题,但对于每个智能体都需要的**核心**工具(读文件、搜索网页、编辑代码、设提醒、加入会议),以内置方式提供意味着:
|
||||||
|
|
||||||
|
* 一致的错误处理。
|
||||||
|
* 零安装门槛。
|
||||||
|
* 所有输出自动经过[智能 Token 压缩](../token-compression.zh-CN.md)。
|
||||||
|
* 可预测的安全边界——文件系统工具遵守工作区作用域,网络工具通过 OpenHuman 代理。
|
||||||
|
|
||||||
|
## 工具带
|
||||||
|
|
||||||
|
| 类别 | 包含内容 |
|
||||||
|
| ------ | -------------- |
|
||||||
|
| [网络搜索](web-search.zh-CN.md) | 无需自带 API key 搜索实时网页。 |
|
||||||
|
| [网页抓取](web-scraper.zh-CN.md) | 从任意 URL 拉取干净文本——文章、文档、README。 |
|
||||||
|
| [编码器](coder.zh-CN.md) | 读/写/编辑/补丁文件,glob,grep,git,lint,test。 |
|
||||||
|
| [浏览器与计算机控制](browser-and-computer.zh-CN.md) | 打开 URL、截图、点击、输入、移动鼠标。 |
|
||||||
|
| [定时任务与调度](cron.zh-CN.md) | 循环任务、一次性提醒、定时智能体运行。 |
|
||||||
|
| [语音](voice.zh-CN.md) | 语音转文字输入、文字转语音输出、实时 Google Meet 智能体。 |
|
||||||
|
| [记忆工具](memory-tools.zh-CN.md) | 在[记忆树](../obsidian-wiki/memory-tree.zh-CN.md)中召回、存储、遗忘和搜索。 |
|
||||||
|
| [第三方集成](../integrations/README.zh-CN.md) | 智能体视角中的 [118+ 已连接服务](../integrations/README.zh-CN.md)。 |
|
||||||
|
| [智能体协作](agent-coordination.zh-CN.md) | 生成子智能体、委托给技能、规划、询问用户。 |
|
||||||
|
| [系统与工具](system-and-utilities.zh-CN.md) | Shell、node、SQL、当前时间、推送通知、LSP。 |
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [智能 Token 压缩](../token-compression.zh-CN.md) —— 保持工具输出成本有界的机制。
|
||||||
|
* [第三方集成](../integrations/README.zh-CN.md) —— 118+ 目录的面向用户介绍和 OAuth 流程。
|
||||||
|
* [隐私与安全](../privacy-and-security.zh-CN.md) —— 每个工具运行所在的安全边界。
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
description: 智能体用来规划、委托和求助的工具。
|
||||||
|
icon: sitemap
|
||||||
|
---
|
||||||
|
|
||||||
|
# 智能体协作
|
||||||
|
|
||||||
|
除了做工作,智能体还有用于*组织*工作的工具——规划多步任务、委托给专家、生成子智能体,以及当某些东西真正模糊时暂停询问用户。
|
||||||
|
|
||||||
|
## 系列中的工具
|
||||||
|
|
||||||
|
| 工具 | 功能 |
|
||||||
|
| ----------------------- | --------------------------------------------------------------------------------------------- |
|
||||||
|
| `todo_write` | 在长任务中维护结构化 TODO 列表。随着工作进展标记完成。 |
|
||||||
|
| `spawn_subagent` | 为独立子任务启动具有自己上下文窗口的新智能体。 |
|
||||||
|
| `spawn_worker_thread` | 不需要阻塞主对话的后台工作。 |
|
||||||
|
| `delegate` | 将任务交给专家(例如具有不同提示/工具/权限的原型)。 |
|
||||||
|
| `archetype_delegation` | 路由到命名原型——coder、researcher、planner 等。 |
|
||||||
|
| `skill_delegation` | 交接给工作区中安装的[技能](../integrations/README.zh-CN.md#skills)。 |
|
||||||
|
| `ask_clarification` | 暂停并向用户提出精确问题,而不是猜测。 |
|
||||||
|
| `plan_exit` | 退出规划阶段并开始执行。 |
|
||||||
|
| `check_onboarding_status` / `complete_onboarding` | 根据用户是否完成入门进行门控。 |
|
||||||
|
|
||||||
|
## 为什么这些是工具,不是隐式行为
|
||||||
|
|
||||||
|
长任务在智能体试图将所有东西保存在一个头脑中时会崩溃。通过 TODO 和子智能体拆分工作意味着:
|
||||||
|
|
||||||
|
* 每个子智能体获得干净的上下文——更少 token、更少干扰。
|
||||||
|
* 主线程保持高级别进度视图。
|
||||||
|
* 一个分支中的失败不会污染其余。
|
||||||
|
|
||||||
|
询问澄清也是一个工具,是刻意的:这使得"我应该问用户"成为一个*可见的*决定,智能体可以被引导,而不是紧急出现的行为。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [编码器](coder.zh-CN.md)——coder-archetype 子智能体通常使用什么。
|
||||||
|
* [潜意识循环](../subconscious.zh-CN.md)——始终开启的后台智能体线程。
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
description: 原生打开 URL、截图、点击、输入、移动鼠标。
|
||||||
|
icon: display
|
||||||
|
---
|
||||||
|
|
||||||
|
# 浏览器与计算机控制
|
||||||
|
|
||||||
|
当智能体需要像人一样*使用*你的机器时——打开页面、截图、点击按钮、输入短语——这些工具就是它做这些事的方式。
|
||||||
|
|
||||||
|
## 浏览器
|
||||||
|
|
||||||
|
* **打开**一个 URL,进入智能体可以回读的嵌入式 webview。
|
||||||
|
* **截图**当前页面。
|
||||||
|
* **检查**图像输出和元数据,以便智能体描述它看到的内容。
|
||||||
|
|
||||||
|
浏览器界面通过 CEF(Chromium Embedded Framework)运行,并包含一个安全层,限制页面能做什么。参见 [Chromium Embedded Framework](../../developing/cef.md) 了解平台详情。
|
||||||
|
|
||||||
|
## 计算机(鼠标 + 键盘)
|
||||||
|
|
||||||
|
* **鼠标**——移动、点击、拖拽。
|
||||||
|
* **键盘**——输入文本、发送快捷键。
|
||||||
|
* **类人路径**——移动和点击遵循类人轨迹,而非瞬移,因此不会触发简单的机器人检测。
|
||||||
|
|
||||||
|
## 适用于
|
||||||
|
|
||||||
|
* 驱动没有 API 或没有[原生集成](../integrations/README.md)的网站。
|
||||||
|
* 单次截图不够的多步骤 UI 流程。
|
||||||
|
* 在聊天中自动化本地应用。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [网页抓取](web-scraper.zh-CN.md) —— 当你只需要文章而非整个页面时。
|
||||||
|
* [Chromium Embedded Framework](../../developing/cef.md) —— 运行时浏览器层。
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
description: 一个完整的工具集,用于处理真实代码库——读、写、编辑、搜索、git、lint、test。
|
||||||
|
icon: code
|
||||||
|
---
|
||||||
|
|
||||||
|
# 编码器
|
||||||
|
|
||||||
|
编码器系列使 OpenHuman 成为可行的编码伙伴,而不是一个*假装*了解代码库的聊天窗口。
|
||||||
|
|
||||||
|
## 系列中的工具
|
||||||
|
|
||||||
|
| 工具 | 功能 |
|
||||||
|
| ---------------- | ----------------------------------------------------------------- |
|
||||||
|
| `file_read` | 读文件(带行号,像 `cat -n`)。 |
|
||||||
|
| `file_write` | 写一个新文件。 |
|
||||||
|
| `edit_file` | 定向编辑——严格唯一性检查的匹配替换。 |
|
||||||
|
| `apply_patch` | 应用统一 diff。 |
|
||||||
|
| `glob_search` | 按 glob 模式查找文件。 |
|
||||||
|
| `grep` | 跨树 ripgrep 风格搜索。 |
|
||||||
|
| `list_files` | 遍历目录树。 |
|
||||||
|
| `read_diff` | 两个文件或版本之间的 diff。 |
|
||||||
|
| `git_operations` | Status、diff、log、blame、branch、commit。 |
|
||||||
|
| `run_linter` | 运行项目的 linter。 |
|
||||||
|
| `run_tests` | 运行项目的 test 命令。 |
|
||||||
|
| `csv_export` | 将查询结果导出为 CSV。 |
|
||||||
|
|
||||||
|
## 为什么这些是原生的,而非纯 shell
|
||||||
|
|
||||||
|
Shell 工具加 `cat`/`sed`/`awk` 技术上可以完成所有这些。原生工具存在是因为:
|
||||||
|
|
||||||
|
* 编辑通过唯一性检查,所以智能体不会意外覆盖错误的行。
|
||||||
|
* 读取返回智能体可以在后续中引用的行号。
|
||||||
|
* Git 操作将输出解析为结构化数据,而不是让智能体刮擦 porcelain。
|
||||||
|
* Lint 和 test 运行连接到项目的实际命令,而非通用猜测。
|
||||||
|
|
||||||
|
## 工作区作用域
|
||||||
|
|
||||||
|
文件系统工具遵守工作区边界——智能体未经明确许可不能在其外部读写。边界与应用的其余部分用于 `OPENHUMAN_WORKSPACE` 的相同。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [系统与工具](system-and-utilities.zh-CN.md) —— `shell`、`node_exec`、`npm_exec` 用于开发循环的其余部分。
|
||||||
|
* [智能体协作](agent-coordination.zh-CN.md) —— `todo_write`、`spawn_subagent` 用于更大的重构。
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
description: 循环任务、一次性提醒和定时智能体运行——一等公民。
|
||||||
|
icon: clock
|
||||||
|
---
|
||||||
|
|
||||||
|
# 定时任务与调度
|
||||||
|
|
||||||
|
调度是一等公民能力,而非权宜之计。智能体可以设置循环任务("每个工作日早上 9 点,总结我的收件箱")、一次性提醒("三小时后提醒我这件事")以及按 cron 时间表运行的任意智能体任务。
|
||||||
|
|
||||||
|
## 系列中的工具
|
||||||
|
|
||||||
|
| 工具 | 功能 |
|
||||||
|
| ------------- | ------------------------------------------------------------------ |
|
||||||
|
| `cron_add` | 创建新计划任务——cron 表达式 + 智能体提示。 |
|
||||||
|
| `cron_list` | 列出现有任务及其下次运行时间。 |
|
||||||
|
| `cron_update` | 编辑现有任务——更改时间表、提示或启用状态。 |
|
||||||
|
| `cron_remove` | 删除任务。 |
|
||||||
|
| `cron_run` | 立即运行一次任务,无论其时间表如何。 |
|
||||||
|
| `cron_runs` | 检查最近运行历史——何时、多久、产生了什么。 |
|
||||||
|
|
||||||
|
[系统与工具](system-and-utilities.zh-CN.md)中还有一个一次性 `schedule` 工具,用于"在时间 T 做一次"而不需要循环条目的情况。
|
||||||
|
|
||||||
|
## 适用于
|
||||||
|
|
||||||
|
* 按你选择的消息渠道发送的每日/每周摘要。
|
||||||
|
* 轮询没有推送事件的慢速集成。
|
||||||
|
* 智能体自己拥有的提醒("周四提醒我跟进 Alice")。
|
||||||
|
* 循环研究——"每周一,检查这个话题有什么新内容,给我写个简报"。
|
||||||
|
|
||||||
|
## 如何与其余部分关联
|
||||||
|
|
||||||
|
每次 cron 运行都是一次正常的智能体调用,所以它可以使用任何其他工具——搜索网页、查询[记忆树](../obsidian-wiki/memory-tree.zh-CN.md)、调用[第三方集成](../integrations/README.zh-CN.md)、发消息。运行历史被记录,这样你可以看到每个 tick 产生了什么。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [系统与工具](system-and-utilities.zh-CN.md) —— 一次性 `schedule` 工具。
|
||||||
|
* [智能体协作](agent-coordination.zh-CN.md) —— 向子智能体扇出的任务。
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
description: 智能体对 118+ 已连接第三方服务的视图。
|
||||||
|
icon: plug
|
||||||
|
---
|
||||||
|
|
||||||
|
# 第三方集成
|
||||||
|
|
||||||
|
OpenHuman 的智能体可以通过单一代理工具接口调用 [118+ 第三方服务](../integrations/README.zh-CN.md)——Gmail、Notion、GitHub、Slack、Stripe、日历,以及长长的尾部的服务。
|
||||||
|
|
||||||
|
## 它在智能体看来如何
|
||||||
|
|
||||||
|
一旦你通过 OAuth 连接了服务,其操作就变为可调用工具。智能体不需要知道工具是与 Gmail 还是与本地文件对话——它只调用工具,代理用你的 token 通过 OpenHuman 后端路由请求,结果像任何其他工具输出一样返回。
|
||||||
|
|
||||||
|
一些变为可用的例子:
|
||||||
|
|
||||||
|
* "在 Slack 上向 #engineering 发送消息。"
|
||||||
|
* "在 openhuman 仓库中创建一个 issue。"
|
||||||
|
* "我日历上明天有什么?"
|
||||||
|
* "拉取过去 20 笔超过 $1000 的 Stripe charge。"
|
||||||
|
|
||||||
|
## 原生 vs 代理
|
||||||
|
|
||||||
|
部分服务有**原生 provider**——Rust 模块知道如何直接将服务摄入[记忆树](../obsidian-wiki/memory-tree.zh-CN.md)(例如 Gmail 的原生摄入路径)。其他仅暴露为**代理工具**:智能体可以调用,但没有自动摄入。新的原生 provider 随着功能落地陆续添加。
|
||||||
|
|
||||||
|
## 隐私边界
|
||||||
|
|
||||||
|
OpenHuman core 从不直接调用任何第三方 API。所有请求都通过 OpenHuman 后端,该后端处理 OAuth token 和速率限制。你的 token 永不以明文形式存储在你机器的磁盘上,智能体只看到工具调用的*结果*,而不是凭据。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [第三方集成(目录)](../integrations/README.zh-CN.md)——面向用户的介绍、OAuth 流程和连接管理。
|
||||||
|
* [自动拉取](../obsidian-wiki/auto-fetch.zh-CN.md)——已连接服务如何流入记忆树。
|
||||||
|
* [隐私与安全](../privacy-and-security.zh-CN.md)——完整边界。
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
description: 智能体如何在对话期间读取、写入和搜索自己的长期记忆。
|
||||||
|
icon: brain
|
||||||
|
---
|
||||||
|
|
||||||
|
# 记忆工具
|
||||||
|
|
||||||
|
[记忆树](../obsidian-wiki/memory-tree.zh-CN.md) 是 OpenHuman 的知识库。记忆工具是智能体在对话期间如何与其对话的。
|
||||||
|
|
||||||
|
## 系列中的工具
|
||||||
|
|
||||||
|
| 工具 | 功能 |
|
||||||
|
| -------- | ----------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `recall` | 按查询搜索记忆树——源作用域、主题作用域或全局。返回带来源的块。 |
|
||||||
|
| `store` | 写入智能体认为值得保留的新记忆(事实、偏好、一段上下文)。 |
|
||||||
|
| `forget` | 按 ID 删除记忆——当某些东西出错、过时或用户明确要求忘记时使用。 |
|
||||||
|
|
||||||
|
还有一个树感知的检索表面(深入主题、获取一天的全局摘要)——智能体根据问题选择正确的一个。
|
||||||
|
|
||||||
|
## 为什么这些是工具,不是隐式上下文
|
||||||
|
|
||||||
|
记忆树太大了,无法倾倒到每个对话中。工具让模型*询问*——"我对 Alice 知道什么?","昨天发生了什么?","提醒我上周 Stripe webhook 说了什么"——检索层只返回相关块,并附带你 Obsidian 存储库中源文件的来源追溯。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [记忆树](../obsidian-wiki/memory-tree.zh-CN.md)——这些工具从什么读取和写入什么。
|
||||||
|
* [自动拉取](../obsidian-wiki/auto-fetch.zh-CN.md)——树如何首先被填充。
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
description: Shell、node、SQL、当前时间、推送通知——完善工具带的小工具。
|
||||||
|
icon: gear
|
||||||
|
---
|
||||||
|
|
||||||
|
# 系统与工具
|
||||||
|
|
||||||
|
兜底系列。智能体伸手拿来完成任务的小巧、锋利工具。
|
||||||
|
|
||||||
|
## 系列中的工具
|
||||||
|
|
||||||
|
| 工具 | 功能 |
|
||||||
|
| ------------------- | ----------------------------------------------------------------------------- |
|
||||||
|
| `shell` | 运行 shell 命令。有界输出,捕获退出码。 |
|
||||||
|
| `node_exec` | 运行 Node.js 片段——用于临时脚本。 |
|
||||||
|
| `npm_exec` | 运行 `npm`/`pnpm`/`yarn` 脚本。 |
|
||||||
|
| `current_time` | 获取任意时区的当前时间,带格式化选项。 |
|
||||||
|
| `schedule` | 一次性"在时间 T 做这个"——循环任务见 [Cron](cron.zh-CN.md)。 |
|
||||||
|
| `pushover` | 向你的设备发送推送通知。 |
|
||||||
|
| `insert_sql_record` | 向智能体的结构化工作区 SQL 存储追加一行。 |
|
||||||
|
| `lsp` | 查询语言服务器(定义、引用、诊断)。 |
|
||||||
|
| `workspace_state` | 检查当前工作区——打开的文件、最近的编辑、环境。 |
|
||||||
|
| `proxy_config` | 读取或更改出站请求的代理配置。 |
|
||||||
|
| `tool_stats` | 自我反思——本会话中使用了哪些工具以及频率。 |
|
||||||
|
|
||||||
|
## 适用于
|
||||||
|
|
||||||
|
* 不适合更丰富工具家族的工组流部分。
|
||||||
|
* "就跑这个命令,告诉我它打印了什么"。
|
||||||
|
* 时间感知行为("用户现在几点?")而不是将时区假设烘焙到提示中。
|
||||||
|
* 让智能体在完成长时间运行的任务后*通知你*。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [编码器](coder.zh-CN.md) —— 对于文件系统重的工作,优先使用专用工具而非 `shell`。
|
||||||
|
* [定时任务与调度](cron.zh-CN.md) —— 对于任何循环性的任务。
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
原生语音——语音转文字输入、文字转语音输出、吉祥物口型同步,
|
||||||
|
以及一个实时 Google Meet 智能体,能听会说。
|
||||||
|
icon: microphone
|
||||||
|
---
|
||||||
|
|
||||||
|
# 语音
|
||||||
|
|
||||||
|
OpenHuman 在你需要时是语音优先的。STT、TTS 和实时 Google Meet 智能体是核心的一部分,而非第三方插件。
|
||||||
|
|
||||||
|
## 语音转文字
|
||||||
|
|
||||||
|
* **热键**——按键说话和切换模式。
|
||||||
|
* **音频捕获**——跨平台麦克风捕获,带语音活动检测。
|
||||||
|
* **流式转录**——你说话时词语即时出现。
|
||||||
|
* **幻觉过滤器**——剥离已知人工产物("感谢观看"、静默诱导短语)。
|
||||||
|
* **后处理**——标点、大写、听写清理。
|
||||||
|
|
||||||
|
听写可以替换你桌面上活动的文本输入,或直接发送到与智能体的聊天中。
|
||||||
|
|
||||||
|
## 文字转语音
|
||||||
|
|
||||||
|
回复语音通过托管 TTS 模型路由。智能体的回复可以用你选择的嗓音说出来,带自然的时机和韵律。语音选择可按用户配置,吉祥物头像通过 viseme 贴图与音频流口型同步。
|
||||||
|
|
||||||
|
## 实时 Google Meet 智能体
|
||||||
|
|
||||||
|
OpenHuman 的旗舰语音集成:
|
||||||
|
|
||||||
|
* 通过嵌入式 webview 加入 Google Meet。
|
||||||
|
* 实时流式输出音频到 STT,转录通话中的每个人,并在会议进行时将结构化笔记写入[记忆树](../obsidian-wiki/memory-tree.zh-CN.md)。
|
||||||
|
* 当你让它说话(或它觉得有需要补充的有用内容时),它通过 TTS 模型生成音频并**作为出站摄像头/麦克风流播放回会议**,这样其他参与者真的能听到它。
|
||||||
|
|
||||||
|
## 隐私
|
||||||
|
|
||||||
|
* 音频捕获是本地的。流式 STT 通过 OpenHuman 后端;除实时转录外不保留任何录音。
|
||||||
|
* TTS 音频流式传输后丢弃——不存储。
|
||||||
|
* 会议转录内容会像其他来源一样落入你的本地记忆树中。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [记忆树](../obsidian-wiki/memory-tree.zh-CN.md) —— Meet 转录和笔记存放的地方。
|
||||||
|
* [自动模型路由](../model-routing/) —— Meet 的大脑使用 `hint:fast` 实现低延迟对话轮次。
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
description: 一个专门的"获取并阅读"工具,返回干净的文本而非原始 HTML。
|
||||||
|
icon: globe
|
||||||
|
---
|
||||||
|
|
||||||
|
# 网页抓取
|
||||||
|
|
||||||
|
一个专门构建的获取工具,区别于通用的 `http_request` / `curl`。它的存在是因为智能体不需要原始 HTML——它需要的是*文章*。
|
||||||
|
|
||||||
|
## 功能
|
||||||
|
|
||||||
|
* 获取一个 URL。
|
||||||
|
* 剥离 Boilerplate(导航、广告、页脚、脚本)。
|
||||||
|
* 返回智能体可以推理的干净文本。
|
||||||
|
|
||||||
|
## 护栏
|
||||||
|
|
||||||
|
* 响应上限 1 MB——大页面被截断,而非静默丢弃。
|
||||||
|
* 20 秒超时——慢速服务器不会阻塞对话。
|
||||||
|
* 遵守与其他网络工具相同的代理和 URL 防护规则。
|
||||||
|
|
||||||
|
## 适用于
|
||||||
|
|
||||||
|
* 阅读文章、博客文章、文档页面、GitHub README,去除噪音。
|
||||||
|
* 跟进[网络搜索](web-search.zh-CN.md)的结果。
|
||||||
|
* 按需摘要单个页面。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [网络搜索](web-search.zh-CN.md) —— 找到要输入抓取器的 URL。
|
||||||
|
* [智能 Token 压缩](../token-compression.zh-CN.md) —— 在长页面到达模型之前对其进行修剪。
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
description: 智能体可直接调用的原生搜索工具——无需 API key。
|
||||||
|
icon: magnifying-glass
|
||||||
|
---
|
||||||
|
|
||||||
|
# 网络搜索
|
||||||
|
|
||||||
|
智能体可以自行搜索实时网页。由服务器端代理(Parallel)支持,所以你无需携带搜索 API key,该工具返回标题、摘要片段和 URL,供后续跟进。
|
||||||
|
|
||||||
|
## 适用于
|
||||||
|
|
||||||
|
* 研究——"X 的最新动态是什么"。
|
||||||
|
* 引用追踪——"为我找到 Y 的三个来源"。
|
||||||
|
* 回答前的事实核查——如果智能体不够自信,会快速搜索。
|
||||||
|
|
||||||
|
## 与通用 HTTP 的区别
|
||||||
|
|
||||||
|
一个纯粹的 `http_request` 工具可以获取 URL 但无法*找到* URL。网络搜索是发现层:它为智能体挑选正确的 URL,然后交给[网页抓取](web-scraper.zh-CN.md)进行实际阅读。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [网页抓取](web-scraper.zh-CN.md) —— 获取并清理特定 URL。
|
||||||
|
* [智能 Token 压缩](../token-compression.zh-CN.md) —— 搜索摘要片段在进入模型之前被压缩。
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
每个记忆块也作为 Markdown 文件存在于与你 Obsidian 兼容的存储库中,
|
||||||
|
你可以打开和编辑。灵感来自 Karpathy 的 obsidian-wiki 工作流。
|
||||||
|
icon: book-open
|
||||||
|
---
|
||||||
|
|
||||||
|
# Obsidian 风格的记忆
|
||||||
|
|
||||||
|
<figure><img src="../../.gitbook/assets/image (1).png" alt=""><figcaption><p>OpenHuman 记忆在 Obsidian 中的预览。来自各种来源(GMail、Slack、Whatsapp 等)的数据被组织成一棵记忆树。</p></figcaption></figure>
|
||||||
|
|
||||||
|
OpenHuman 的记忆不是一个黑箱。智能体在其上推理的相同块作为普通的 `.md` 文件写入你工作区内的存储库中。你可以在 [Obsidian](https://obsidian.md) 中打开它,浏览、编辑、手动链接笔记,智能体都会看到你的改动。
|
||||||
|
|
||||||
|
设计直接灵感来自 [Andrej Karpathy 的 obsidian-wiki 工作流](https://x.com/karpathy/status/2039805659525644595):一个个人 wiki,你生活中每个有趣的事物最终都成为一个可链接的笔记。
|
||||||
|
|
||||||
|
## 存储库在哪里
|
||||||
|
|
||||||
|
```text
|
||||||
|
<workspace>/
|
||||||
|
└── wiki/
|
||||||
|
├── summaries/ # 自动生成的源 / 主题 / 全局摘要
|
||||||
|
├── notes/ # 你的手写笔记(自由格式)
|
||||||
|
└── … # 每个已连接工具包的文件夹
|
||||||
|
```
|
||||||
|
|
||||||
|
`summaries/` 文件夹按层级布局:全局树按日期,源树按源,主题树按实体。每个文件的前置元数据携带来源(源 id、时间范围、作用域),以便智能体可以将任何声明追溯到产生它的块。
|
||||||
|
|
||||||
|
## 打开存储库
|
||||||
|
|
||||||
|
在桌面 app 中,**记忆**标签页有一个**"在 Obsidian 中查看存储库"**按钮。它使用 `obsidian://open?path=...` 深度链接,所以你需要已安装 Obsidian。
|
||||||
|
|
||||||
|
你也可以在任何编辑器中打开该文件夹,它其实就是 Markdown。文件之间的链接使用标准的 `[[wiki-link]]` 语法,因此 Obsidian 的图谱视图、反向链接和标签浏览器开箱即用。
|
||||||
|
|
||||||
|
## 手动编辑笔记
|
||||||
|
|
||||||
|
`wiki/notes/` 中的任何内容都会被纳入摄取范围。处理 Gmail 和 Slack 的相同流水线会获取你的手写笔记,对它们进行分块、评分,并与其他所有内容一起折叠到主题树和全局树中。
|
||||||
|
|
||||||
|
这意味着你可以:
|
||||||
|
|
||||||
|
* 将会议笔记放入 `wiki/notes/2026-05-08-board-call.md`,智能体明天就会知道背景。
|
||||||
|
* 按项目、人物、股票代码维护一个文件,主题树将你的手动笔记视为另一个数据源。
|
||||||
|
* 批量导入现有 Obsidian 存储库:将 `.md` 文件放入并触发摄入。
|
||||||
|
|
||||||
|
## 为什么这很重要
|
||||||
|
|
||||||
|
你无法信任你无法读取的记忆。大多数"AI 记忆"系统将状态隐藏在不透明的嵌入中;OpenHuman 的存储库则相反,智能体的记忆**确确实实**就是一个你拥有的 Markdown 文件夹。如果智能体弄错了什么,你可以找到文件,修复它,下一次检索就是正确的。
|
||||||
|
|
||||||
|
这也是最干净的导出方式:即使明天不再使用 OpenHuman,你仍然保留一个完整的个人 wiki。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [记忆树](memory-tree.zh-CN.md)。产生存储库的流水线。
|
||||||
|
* [从集成自动拉取](auto-fetch.zh-CN.md)。存储库如何自行增长。
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
可选的 `Memory` trait 后端,委托给本地运行的 agentmemory REST 服务器,
|
||||||
|
适用于在 Claude Code、Cursor、Codex、OpenCode 和 OpenHuman 间
|
||||||
|
自托管 agentmemory 的用户。
|
||||||
|
icon: database
|
||||||
|
---
|
||||||
|
|
||||||
|
# agentmemory 后端
|
||||||
|
|
||||||
|
OpenHuman 默认的 `Memory` trait 后端是 `sqlite`——即 [记忆树](memory-tree.zh-CN.md) 中记录的统一存储。对于已经在本地运行 [agentmemory](https://github.com/rohitg00/agentmemory) 的用户——通常是因为他们希望在 Claude Code、Cursor、Codex、OpenCode 和 OpenHuman 之间共享单一持久化存储——OpenHuman 暴露了一个可选后端,将每个 trait 调用代理到 agentmemory 的 REST 层面。
|
||||||
|
|
||||||
|
选择 `backend = "agentmemory"` 会跳过 OpenHuman 的 SQLite + 嵌入器路径。agentmemory 拥有存储、嵌入和检索层。OpenHuman 成为一个精简的 REST 客户端。
|
||||||
|
|
||||||
|
## 何时使用
|
||||||
|
|
||||||
|
在以下情况下使用 agentmemory 后端:
|
||||||
|
|
||||||
|
- 你已经为一个或多个编码智能体运行 `npx -y @agentmemory/agentmemory`,并希望 OpenHuman 共享相同的持久化存储。
|
||||||
|
- 你希望混合 BM25 + 向量 + 图检索,而无需在 OpenHuman 端配置单独的嵌入器。
|
||||||
|
- 你偏好 agentmemory 的生命周期(整合、保留评分、自动遗忘、图提取)而不是 OpenHuman 的统一存储。
|
||||||
|
|
||||||
|
在以下情况下保持默认的 `sqlite` 后端:
|
||||||
|
|
||||||
|
- 你想要完全自包含的单进程操作,无外部守护进程依赖。
|
||||||
|
- 你依赖 OpenHuman 特定的记忆树功能(分块、密封、摘要树),这些功能在 SQLite 存储之上运行。记忆树流水线不受 trait 后端影响——它在主机的文档存储上操作,正交——但 agentmemory 后端在你已经在其他智能体上标准化使用 agentmemory 时最有价值。
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
1. **安装 + 启动 agentmemory**(一个终端):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx -y @agentmemory/agentmemory
|
||||||
|
```
|
||||||
|
|
||||||
|
默认为 `http://localhost:3111`(REST)+ `ws://localhost:49134`(引擎)。首次启动在 `~/.agentmemory/.hmac` 生成 HMAC 密钥并打印一次。
|
||||||
|
|
||||||
|
2. **在 `config.toml` 中将 OpenHuman 指向它**:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[memory]
|
||||||
|
backend = "agentmemory"
|
||||||
|
# 以下为默认值——仅在覆盖时设置。
|
||||||
|
# agentmemory_url = "http://localhost:3111"
|
||||||
|
# agentmemory_secret = "" # HMAC bearer token,可选
|
||||||
|
# agentmemory_timeout_ms = 5000
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **重启 OpenHuman**。Factory 会跳过 SQLite 路径并记录 `[memory::factory] using agentmemory backend at <url>`。
|
||||||
|
|
||||||
|
就这样。现有的 OpenHuman 调用点(`store`、`recall`、`get`、`list`、`forget`、`namespace_summaries`、`count`、`health_check`)保持不变。
|
||||||
|
|
||||||
|
## 配置 keys
|
||||||
|
|
||||||
|
| 字段 | 默认值 | 用途 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `agentmemory_url` | `http://localhost:3111` | agentmemory REST 服务器的基础 URL |
|
||||||
|
| `agentmemory_secret` | 无 | 可选的 HMAC bearer token。作为 `Authorization: Bearer <secret>` 发送 |
|
||||||
|
| `agentmemory_timeout_ms` | `5000` | 每个请求的 reqwest 超时 |
|
||||||
|
|
||||||
|
当 `backend == "agentmemory"` 时,以下现有 `MemoryConfig` 字段被**忽略**——agentmemory 通过 `~/.agentmemory/.env` 管理自己的嵌入堆栈:
|
||||||
|
|
||||||
|
- `embedding_provider`
|
||||||
|
- `embedding_model`
|
||||||
|
- `embedding_dimensions`
|
||||||
|
- `sqlite_open_timeout_secs`
|
||||||
|
|
||||||
|
在此路径上设置它们是空操作。本地 AI Ollama 健康检查也不在此路径上运行——agentmemory 的守护进程管理自己的嵌入器生命周期。
|
||||||
|
|
||||||
|
## 字段映射
|
||||||
|
|
||||||
|
OpenHuman 的 `MemoryEntry` ↔ agentmemory 传输行:
|
||||||
|
|
||||||
|
| OpenHuman 字段 | agentmemory 字段 | 备注 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `namespace` | `project` | 空时默认为 `"default"` |
|
||||||
|
| `key` | `title` | |
|
||||||
|
| `content` | `content` | |
|
||||||
|
| `id` | `id` | agentmemory 生成的(`mem_<rand>`) |
|
||||||
|
| `category: Core` | `type: "fact"` | |
|
||||||
|
| `category: Daily` | `type: "conversation"` | |
|
||||||
|
| `category: Conversation` | `type: "conversation"` | |
|
||||||
|
| `category: Custom(s)` | `type: "fact"` + `concepts: [s]` | 自定义标签滚入 concepts 数组以保持可查询性 |
|
||||||
|
| `session_id` | `sessionIds: [...]` | OpenHuman 暴露单个 id;agentmemory 持久化一个数组 |
|
||||||
|
| `timestamp` | `updatedAt`(RFC3339) | 如果 `updatedAt` 缺失则回退到 `createdAt` |
|
||||||
|
| `score`(仅召回命中) | smart-search `score` | 在 `recall` 响应中填充,`get` / `list` 时为 `None` |
|
||||||
|
|
||||||
|
agentmemory 携带额外字段——`concepts`(自动提取)、`files`(路径标签)、`strength`(保留评分)、`version`、`supersedes`(生命周期链)——此后端保留为默认值。它们是 agentmemory 生命周期层的内部字段,不需要通过 OpenHuman 的 trait 进行往返。
|
||||||
|
|
||||||
|
## Trait 方法 → 端点
|
||||||
|
|
||||||
|
| `Memory` 方法 | agentmemory REST | 备注 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `store` | `POST /agentmemory/remember` | `{project, title, content, type, concepts, sessionIds}` |
|
||||||
|
| `recall` | `POST /agentmemory/smart-search` | 混合 BM25 + 向量 + 图 |
|
||||||
|
| `get` | `POST /agentmemory/smart-search` | + 客户端精确 title 过滤 |
|
||||||
|
| `list` | `GET /agentmemory/memories?latest=true&project=<ns>` | |
|
||||||
|
| `forget` | `get(ns, key)` → `POST /agentmemory/forget` | 两步:先解析 id 再 forget |
|
||||||
|
| `namespace_summaries` | `GET /agentmemory/projects` | 返回 `[{name, count, lastUpdated}]` |
|
||||||
|
| `count` | `GET /agentmemory/health` | 读取 `memories` 字段 |
|
||||||
|
| `health_check` | `GET /agentmemory/livez` | |
|
||||||
|
|
||||||
|
`RecallOpts.category`、`RecallOpts.session_id` 和 `RecallOpts.min_score` 作为**客户端过滤**应用于 smart-search 响应。agentmemory 的 REST 面今天不将它们作为服务器端过滤器暴露。对于非常大的召回窗口(limit > 100),建议发出更严格的查询字符串以减少服务器端工作,而不是依赖客户端后过滤。
|
||||||
|
|
||||||
|
## 安全性
|
||||||
|
|
||||||
|
当 `agentmemory_secret` 被设置时,客户端遵守 agentmemory 的 v0.9.12 明文 Bearer 守卫约定:
|
||||||
|
|
||||||
|
- **环回主机**(`localhost`、`127.0.0.1`、`::1`)上的 `http://` —— 允许。本地开发路径。
|
||||||
|
- **`https://`** 到任何主机 —— 允许。
|
||||||
|
- **到非环回主机的明文 HTTP** —— 在构造时发出一次性 stderr 警告。Bearer 在线路上是可观察的。
|
||||||
|
- **`AGENTMEMORY_REQUIRE_HTTPS=1`**(进程环境,ASCII 大小写不敏感,匹配 `1` 或 `true`)—— 将警告升级为构造时的硬性拒绝。后端启动失败而不是静默泄露 bearer。
|
||||||
|
|
||||||
|
生产部署应设置 `AGENTMEMORY_REQUIRE_HTTPS=1`,这样配置错误的 TLS 终结器会明显报错,而不是静默泄露。
|
||||||
|
|
||||||
|
明文 bearer guard 镜像了 agentmemory [PR #315](https://github.com/rohitg00/agentmemory/pull/315) 中的集成插件 guard,因此在 Hermes / OpenClaw / pi 上看到过相同警告的操作员会在 OpenHuman 上认出它。
|
||||||
|
|
||||||
|
## 故障模式
|
||||||
|
|
||||||
|
| 故障 | 后端行为 |
|
||||||
|
| --- | --- |
|
||||||
|
| 启动时守护进程不可达 | `from_config` 成功(URL 解析),但首次调用时 `health_check()` 返回 false。Trait 方法向上冒泡 `reqwest` 传输错误 |
|
||||||
|
| 网络超时 | 按 trait 约定返回 `anyhow::Error`;浮出到调用者 |
|
||||||
|
| 4xx / 5xx 响应 | 带状态 + body 片段的 `anyhow::Error` |
|
||||||
|
| Bearer 通过明文非环回(无环境变量) | 一次性 stderr 警告,请求继续 |
|
||||||
|
| Bearer 通过明文非环回 + `AGENTMEMORY_REQUIRE_HTTPS=1` | 构造时硬性拒绝 |
|
||||||
|
| 空的 `agentmemory_url` | 构造时硬性拒绝并提示留空以使用默认值 |
|
||||||
|
| 无效的 URL 语法 | 构造时硬性拒绝并附带解析器错误 |
|
||||||
|
|
||||||
|
**不会自动回退到 SQLite。** 如果守护进程在启动时未运行,后端会明显抛出传输错误。操作员在 `config.toml` 中切回 `backend = "sqlite"` 以恢复。理由:静默的 SQLite 回退会隐藏配置错误的守护进程——"私密、简单、可预测"胜过"神奇容忍"。
|
||||||
|
|
||||||
|
## 性能说明
|
||||||
|
|
||||||
|
后端是一个精简的 REST 代理——每个 trait 调用增加一个 HTTP 往返。实际影响:
|
||||||
|
|
||||||
|
- `store` 和 `forget` 是单 RTT。
|
||||||
|
- `recall`、`get`、`list` 是单 RTT。
|
||||||
|
- 对未知 key 的 `forget` 是两个 RTT(隐式 `get` 查找 + 一个空操作确认)。调用者可以通过检查先前 `list` 的返回值来短路这个。
|
||||||
|
- agentmemory 的 REST 默认是 `127.0.0.1` —— 同主机延迟低于一毫秒。通过 HTTPS 终结的管理部署,预期每个 RTT 约 10–30ms。
|
||||||
|
- 默认每请求超时为 5 秒。如果在 iii 引擎冷启动时看到间歇性超时,增加 `agentmemory_timeout_ms`;agentmemory 长时间空闲后的第一次请求延迟可达 3–5 秒,取决于持久化状态。
|
||||||
|
|
||||||
|
## 迁移:从 SQLite 到 agentmemory
|
||||||
|
|
||||||
|
目前没有原地迁移。建议路径:
|
||||||
|
|
||||||
|
1. 通过 OpenHuman 现有的导出 RPC(或直接 SQL)从 SQLite 存储导出你现有的记忆。
|
||||||
|
2. 遍历导出,将每一行 POST 到 `/agentmemory/remember`,使用相同的 `project` + `title` + `content`。agentmemory 将分配新 id;OpenHuman 端在首次 `list` 时获取它们。
|
||||||
|
3. 设置 `backend = "agentmemory"` 并重启。
|
||||||
|
|
||||||
|
专门的批量导入路径作为后续跟进。
|
||||||
|
|
||||||
|
## 实现参考
|
||||||
|
|
||||||
|
仓库内文件:
|
||||||
|
|
||||||
|
- [`store/agentmemory/mod.rs`](https://github.com/tinyhumansai/openhuman/tree/main/src/openhuman/memory/store/agentmemory/mod.rs) —— 模块表面
|
||||||
|
- [`store/agentmemory/backend.rs`](https://github.com/tinyhumansai/openhuman/tree/main/src/openhuman/memory/store/agentmemory/backend.rs) —— `impl Memory for AgentMemoryBackend`
|
||||||
|
- [`store/agentmemory/client.rs`](https://github.com/tinyhumansai/openhuman/tree/main/src/openhuman/memory/store/agentmemory/client.rs) —— reqwest 包装器 + 明文 bearer guard
|
||||||
|
- [`store/agentmemory/mapping.rs`](https://github.com/tinyhumansai/openhuman/tree/main/src/openhuman/memory/store/agentmemory/mapping.rs) —— `MemoryEntry` ↔ agentmemory JSON
|
||||||
|
- [`tests/agentmemory_backend.rs`](https://github.com/tinyhumansai/openhuman/tree/main/tests/agentmemory_backend.rs) —— 12 个 axum-mock 集成测试
|
||||||
|
|
||||||
|
相关的上游:
|
||||||
|
|
||||||
|
- agentmemory 仓库 —— <https://github.com/rohitg00/agentmemory>
|
||||||
|
- agentmemory REST 约定 —— `~/.agentmemory/.env` keys + 端点列表在 agentmemory README 中
|
||||||
|
- v0.9.12 明文 bearer guard —— agentmemory PR #315
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
每隔二十分钟,OpenHuman 遍历每个活跃集成,将新数据整合进你的记忆树。
|
||||||
|
无需提示词,无需编写轮询循环。
|
||||||
|
icon: arrows-rotate
|
||||||
|
---
|
||||||
|
|
||||||
|
# 自动拉取集成
|
||||||
|
|
||||||
|
大多数"AI 助手"是被动的:你提问,它们思考,它们回答。OpenHuman 则相反。它持续从你的技术栈中拉取数据,所以当你问"昨晚我的收件箱收到了什么?"时,答案已经在[记忆树](memory-tree.zh-CN.md)里了。
|
||||||
|
|
||||||
|
## 工作原理
|
||||||
|
|
||||||
|
一个单一的周期性调度器每二十分钟触发一次。每次触发时,它遍历每个活跃的[集成](../integrations/README.zh-CN.md),查找匹配的原生 provider,如果该连接的距上次同步的时间足够长,就调用 `provider.sync(ctx, SyncReason::Periodic)`。
|
||||||
|
|
||||||
|
```text
|
||||||
|
每 20 分钟
|
||||||
|
|
|
||||||
|
v
|
||||||
|
遍历每个活跃连接(Gmail、Notion、GitHub……)
|
||||||
|
|
|
||||||
|
+--> 检查 sync_state(toolkit, connection_id)
|
||||||
|
| - 上次同步时间戳
|
||||||
|
| - 每日预算
|
||||||
|
| - 去重集合
|
||||||
|
| - 游标
|
||||||
|
|
|
||||||
|
+--> 如果间隔已过 -> provider.sync()
|
||||||
|
|
|
||||||
|
+--> 成功 -> record_sync_success(ts)
|
||||||
|
```
|
||||||
|
|
||||||
|
这里有几个关键点:
|
||||||
|
|
||||||
|
* **一个全局触发,而不是每个连接一个任务。** 每个用户的连接数很少;一个 20 分钟的触发周期足够了,而且 bookkeeping 很简单。
|
||||||
|
* **状态按 `(toolkit, connection_id)` 划分。** 每个连接有自己的游标、上次同步时间戳、去重集合和每日预算。重启时从中重建;即使重启后错过了一次周期性同步也无害,因为下一个触发周期会重新拾取。
|
||||||
|
* **原生同步与事件驱动路径共享。** 当 webhook 或 `on_connection_created` 事件触发非周期性同步时,它们在同一个 sync_state 上盖戳,所以调度器不会冗余地重新触发。
|
||||||
|
* **错误被记录并静默处理。** 调度器绝不能在其循环中 panic,否则周期性同步会在进程剩余生命周期内静默停止。
|
||||||
|
|
||||||
|
## 什么进入记忆树
|
||||||
|
|
||||||
|
每个 provider 负责定义自己的摄入逻辑。例如 Gmail provider 获取一页新消息,运行邮件规范化器,通过相同的手动 UI 摄入路径传输结果,块进入 SQLite,摘要 bucket 被填充,任何被触及的实体都会将主题树标记为脏。
|
||||||
|
|
||||||
|
其他 providers(GitHub、Slack、Notion……)遵循相同的形状:从游标后获取新项目 → 规范化 → 摄入到[记忆树](memory-tree.zh-CN.md)。
|
||||||
|
|
||||||
|
## 为什么是 20 分钟触发周期
|
||||||
|
|
||||||
|
最初设计每 60 秒运行一次。当连接了多个 provider 时,这意味着持续不断的 HTTP 获取和数据库写入,在笔记本上明显繁忙。二十分钟用一点延迟换取明显更少的前台负载。每个 provider 的 `sync_interval_secs` 仍然限制实际同步之间的**最小**延迟;全局触发周期只放宽上限。
|
||||||
|
|
||||||
|
## 调优和可见性
|
||||||
|
|
||||||
|
* **每个 provider 的间隔。** 每个原生 provider 声明自己的 `sync_interval_secs`,所以高流量工具包(Gmail)可以比低流量工具包(Stripe)更频繁地同步。
|
||||||
|
* **每日预算。** 每个连接有每日请求预算,以保持 API 成本和速率限制合理。
|
||||||
|
* **日志。** 同步活动以 debug 级别记录在 core 日志中。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [第三方集成](../integrations/README.zh-CN.md)。自动拉取运行的连接器层。
|
||||||
|
* [记忆树](memory-tree.zh-CN.md)。一切最终到达的地方。
|
||||||
|
* [智能 Token 压缩](../token-compression.zh-CN.md)。使"获取一切"保持低成本的原因。
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
OpenHuman 的本地优先存储库。从工具中摄入数据,规范化为 Markdown,
|
||||||
|
分块,评分,并折叠为层级化的摘要树。
|
||||||
|
icon: tree
|
||||||
|
---
|
||||||
|
|
||||||
|
# 记忆树
|
||||||
|
|
||||||
|
<figure><img src="../../.gitbook/assets/image.png" alt=""><figcaption><p>记忆树。所有文档的高度压缩视图。</p></figcaption></figure>
|
||||||
|
|
||||||
|
记忆树是 OpenHuman 的存储库。它不是一个披着"记忆"外衣的向量数据库,而是一个确定性的、bucket-sealed(桶密封)处理流水线,将你一天中杂乱的数据流——聊天、邮件、文档、集成同步结果——转化为你机器上结构化的、可查询的、带摘要支撑的 Markdown。
|
||||||
|
|
||||||
|
## 它做什么
|
||||||
|
|
||||||
|
每个连接的源都走同样的流水线:
|
||||||
|
|
||||||
|
```text
|
||||||
|
源适配器(聊天 / 邮件 / 文档)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
规范化 规范化的 Markdown + 来源元数据
|
||||||
|
|
|
||||||
|
v
|
||||||
|
分块器 确定性的 ID,≤3k token 的有界片段
|
||||||
|
|
|
||||||
|
v
|
||||||
|
内容存储 原子 .md 文件(正文 + 标签)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
存储 持久化(块、评分、摘要、任务、热度)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
评分 信号 + 向量 + 实体提取
|
||||||
|
|
|
||||||
|
v
|
||||||
|
源 / 主题 / 全局树 按作用域的摘要树
|
||||||
|
|
|
||||||
|
v
|
||||||
|
检索 搜索 / 深入 / 主题 / 全局 / 获取
|
||||||
|
```
|
||||||
|
|
||||||
|
热路径(规范化 → 分块 → 快速评分 → 持久化 → 入队后续工作)很快。重型工作——向量生成、实体提取、密封摘要 bucket、每日摘要——在后台 workers 中运行,UI 永远不会阻塞。
|
||||||
|
|
||||||
|
如果你开启了[本地 AI](../model-routing/local-ai.md),嵌入向量和摘要树的构建可以在**设备上通过 Ollama** 运行;否则它们像其他模型调用一样通过 OpenHuman 后端处理。
|
||||||
|
|
||||||
|
## 三棵树,三个作用域
|
||||||
|
|
||||||
|
* **源树**,每个源一个滚动缓冲区(L0),填满后密封为 L1 → L2 → …。每个 Gmail 标签、每个 Slack 频道、每个上传的文档各一棵。
|
||||||
|
* **主题树**,按实体懒加载的摘要,由**热度**驱动。某个实体(人、项目、股票代码、仓库)出现得越频繁,其主题树就越积极地被构建和刷新。
|
||||||
|
* **全局树**,一个跨当天摄入的所有内容的每日全局摘要。
|
||||||
|
|
||||||
|
检索可以针对任何作用域:搜索单个源,深入某个主题,或拉取全局摘要。
|
||||||
|
|
||||||
|
## 它在磁盘上的位置
|
||||||
|
|
||||||
|
位于你的工作区内(默认 `~/.openhuman`,或 `OPENHUMAN_WORKSPACE` 指向的路径):
|
||||||
|
|
||||||
|
| 路径 | 内容 |
|
||||||
|
| ------------------------- | ---------------------------------------------- |
|
||||||
|
| `memory_tree/chunks.db` | 块、评分、摘要、实体索引、任务、热度 |
|
||||||
|
| `wiki/` | Markdown 存储库 —— 见 [Obsidian Wiki](./README.zh-CN.md) |
|
||||||
|
|
||||||
|
一切都是本地的。除非你明确发送包含原始数据的聊天消息,否则你的原始数据不会离开你的机器。
|
||||||
|
|
||||||
|
## 为什么是树,而不是向量存储
|
||||||
|
|
||||||
|
向量存储回答"与这个查询相似的是什么?"记忆需要回答更多:
|
||||||
|
|
||||||
|
* **今天发生了什么?**(全局摘要)
|
||||||
|
* **这个人的最新情况是什么?**(主题树,热度驱动)
|
||||||
|
* **上周二下午 3 点 Stripe webhook 说了什么?**(源树 + 来源追溯)
|
||||||
|
|
||||||
|
树给你压缩**和**导航。嵌入向量仍然存在于内部,所以语义搜索继续工作,但上面的结构才是让记忆感觉像大脑而不是一堆碎片的原因。
|
||||||
|
|
||||||
|
## 流水线如何工作?
|
||||||
|
|
||||||
|
用户看到的功能很简单:连接一个源,智能体就获得了对其的持久记忆。实现这一功能的流水线横跨一条 HTTP 触发的摄入路径、一个持久化的任务队列、一组后台 workers、三个独立的摘要树,以及一个每日 UTC 调度器。
|
||||||
|
|
||||||
|
### 1. 摄入
|
||||||
|
|
||||||
|
新的聊天 / 邮件 / 文档到达。热路径将其规范化为 Markdown,用确定性 ID 分块,运行廉价的快速评分,在单个事务中持久化所有内容,将每个块标记为 `pending_extraction`,并为 workers 入队后续工作。
|
||||||
|
|
||||||
|
这里有三个重要属性:
|
||||||
|
|
||||||
|
* **确定性的。** 块 ID 是内容寻址的,所以对相同输入重新运行摄入永远不会产生重复。
|
||||||
|
* **快速的。** 这条路径中没有 LLM 调用——只有廉价的启发式方法。
|
||||||
|
* **写入有界。** 所有操作在一个事务中完成,所以部分摄入不会留下悬空的行。
|
||||||
|
|
||||||
|
### 2. 队列
|
||||||
|
|
||||||
|
后续工作进入持久化的任务队列(与块在同一个磁盘存储中)。每个任务携带一种类型、一个 payload、一个去重 key、重试记录和一个调度窗口。类型如下:
|
||||||
|
|
||||||
|
| 类型 | 功能 |
|
||||||
|
| --------------- | -------------------------------------------------------------------------------------- |
|
||||||
|
| `extract_chunk` | 深度评分 + 实体提取。决定 `admitted` 还是 `dropped`。 |
|
||||||
|
| `append_buffer` | 将一个 admitted 的叶子添加到源的(或主题的)树的 L0 缓冲区。可能触发密封。 |
|
||||||
|
| `seal` | 将 L0 缓冲区压缩为 L1 摘要;如果父缓冲区已满,则向上级联。 |
|
||||||
|
| `topic_route` | 将叶子路由到每个实体的主题树,由热度检查控制。 |
|
||||||
|
| `digest_daily` | 构建全局每日摘要节点。 |
|
||||||
|
| `flush_stale` | 强制密封停留太久的缓冲区。 |
|
||||||
|
|
||||||
|
### 3. Workers
|
||||||
|
|
||||||
|
一个小型的后台 workers 池(默认 3 个)从队列中取出任务并运行。池被摄入路径立即唤醒,有一个短轮询后备方案,所以错过的唤醒不会搁置工作。共享信号量限制并发 LLM 调用,这样新源的突发不会意外地扇出到数十个并发嵌入向量。
|
||||||
|
|
||||||
|
启动时,任何 worker 租约已过期的任务(因为崩溃或 kill)会被返还到队列。崩溃不会丢失已 admitted 但尚未密封的工作。
|
||||||
|
|
||||||
|
### 4. 树状态
|
||||||
|
|
||||||
|
三棵独立的树从同一个叶子流构建。
|
||||||
|
|
||||||
|
* **源树** —— 每个源一个。新叶子进入 L0 缓冲区;当缓冲区填满(或 stale-flush 触发),一个 `seal` 写入 L1 摘要,级联继续向上。
|
||||||
|
* **主题树** —— 每个高热度实体一个。路由器检查实体是否足够热以值得拥有自己的树,如果是,则追加到其缓冲区。
|
||||||
|
* **全局树** —— 一棵树,每天增长一个节点,随着天数累积向上行走。
|
||||||
|
|
||||||
|
### 5. 调度器
|
||||||
|
|
||||||
|
调度器循环独立于摄入路径运行。每天 00:00 UTC 它为昨天入队一个全局每日摘要,并为今天入队一个 stale-flush。调度器**不自己运行**摘要器——一切通过队列,所以重试、去重和 stale-lock 恢复保持集中。
|
||||||
|
|
||||||
|
### 6. 叶子生命周期
|
||||||
|
|
||||||
|
每个块经历一个小型状态机:
|
||||||
|
|
||||||
|
```text
|
||||||
|
pending_extraction --> admitted --> buffered --> sealed
|
||||||
|
\
|
||||||
|
--> dropped
|
||||||
|
```
|
||||||
|
|
||||||
|
* 提取根据深度评分决定 `admitted` 还是 `dropped`。
|
||||||
|
* Admitted 的叶子移入缓冲区(`buffered`)。
|
||||||
|
* 当缓冲区密封时,里面的每个叶子被标记为 `sealed`。
|
||||||
|
* `dropped` 的叶子停在这里。它们的块行保留用于来源追溯,但没有缓冲区或摘要引用它们。
|
||||||
|
|
||||||
|
这就是为什么检索可以显示来源追溯而无需重新运行流水线:块行及其终端生命周期状态就够了。
|
||||||
|
|
||||||
|
## 触发摄入
|
||||||
|
|
||||||
|
* **自动的** —— 每个活跃的集成每 20 分钟自动拉取一次;见 [自动拉取](auto-fetch.zh-CN.md)。
|
||||||
|
* **手动的** —— 桌面 app 的"记忆"标签页暴露了每个源的"运行摄入"触发器。
|
||||||
|
* **RPC** —— `openhuman.memory_tree_ingest`,用于高级工作流。
|
||||||
|
|
||||||
|
## 在桌面 app 中 —— 智能标签页
|
||||||
|
|
||||||
|
从底部导航栏打开。
|
||||||
|
|
||||||
|
**系统状态。** 页面顶部显示当前状态(空闲、摄入中、摘要中)和一个**运行摄入**按钮,用于手动触发对任何连接源的同步。
|
||||||
|
|
||||||
|
**记忆指标:**
|
||||||
|
|
||||||
|
| 指标 | 显示内容 |
|
||||||
|
| ---------------------- | ------------------------------------------------------------------------------------------ |
|
||||||
|
| **存储** | `<workspace>/memory_tree/chunks.db` 和 Obsidian 存储库总大小。 |
|
||||||
|
| **源** | 已摄入的不同源数量(每个 Gmail 标签、Slack 频道、文档等各算一个)。 |
|
||||||
|
| **块** | 存储中 ≤3k token 的块总数。 |
|
||||||
|
| **主题** | 目前已实例化的主题树数量(从"热"实体构建的每个实体摘要)。 |
|
||||||
|
| **最早 / 最新记忆** | 最旧和最新块的时间戳。 |
|
||||||
|
|
||||||
|
**记忆图谱。** 一个实体及其关系的力导向可视化,从实体索引绘制。图谱随着自动拉取获取更多数据而增长——早期稀疏,几天内变得密集。
|
||||||
|
|
||||||
|
**Obsidian 存储库。** 一个**"在 Obsidian 中查看存储库"**按钮通过 `obsidian://open?path=...` 深度链接直接打开 `<workspace>/wiki/`。你也可以在任何文件浏览器中打开该文件夹。
|
||||||
|
|
||||||
|
**摄入活动。** 一个显示摄入事件随时间分布的热力图,类似于 GitHub 的贡献图。可用于发现自动拉取空闲的时期(例如连接中断导致同步停止)。
|
||||||
|
|
||||||
|
**搜索与检索。** 记忆树上的搜索栏。支持源作用域、主题作用域或全局查询,任何结果都可以链接回底层块文件(在你的 Obsidian 存储库中)以获取完整来源追溯。
|
||||||
|
|
||||||
|
**路由。** 智能标签页还显示智能体每个任务使用的模型——见[自动模型路由](../model-routing/README.zh-CN.md)。
|
||||||
|
|
||||||
|
## 交换后端
|
||||||
|
|
||||||
|
记忆树流水线(分块 → 评分 → 密封 → 摘要)是默认的。在多个智能体间自托管 [agentmemory](https://github.com/rohitg00/agentmemory) 且希望 OpenHuman 共享相同持久化存储的操作员可以通过 `MemoryConfig.backend = "agentmemory"` 选择外部后端——参见 [agentmemory 后端](agentmemory-backend.zh-CN.md) 了解配置 keys、字段映射、端点表、安全措施和故障模式。
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
OpenHuman 以什么形式交付(原生 React + Tauri v2 桌面应用,Rust core)、
|
||||||
|
支持的平台,以及当前范围内的功能。
|
||||||
|
icon: layer-plus
|
||||||
|
---
|
||||||
|
|
||||||
|
# 平台与可用性
|
||||||
|
|
||||||
|
OpenHuman 是一个原生桌面应用,不是浏览器扩展,也不是 Electron 包装器。基于 **React + Tauri v2** 构建,搭载 **Rust core**,它体积小、启动快、不干扰你的工作流。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 支持的平台
|
||||||
|
|
||||||
|
| 平台 | 架构 | 分发方式 |
|
||||||
|
| ---------- | ---------------------- | -------------------------- |
|
||||||
|
| **macOS** | Intel、Apple Silicon | `.dmg` 安装包、Homebrew |
|
||||||
|
| **Windows**| x64、ARM64 | `.msi` 安装包 |
|
||||||
|
| **Linux** | x64 | AppImage、`.deb` |
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 为什么是原生应用
|
||||||
|
|
||||||
|
OpenHuman 作为原生应用构建而非 Web 包装器,有三个原因:
|
||||||
|
|
||||||
|
**体积小。** 只有典型通信工具的几分之一。不到一秒启动,内存占用极少。
|
||||||
|
|
||||||
|
**启动快。** 无需初始化浏览器引擎。立即就绪接受请求。
|
||||||
|
|
||||||
|
**操作系统级安全。** 凭据保存在你平台的安全密钥链中:macOS Keychain、Windows Credential Manager、Linux Secret Service。敏感数据永不放在浏览器存储或明文文件中。本地记忆树的 SQLite 数据库位于你的工作区文件夹中,由你拥有。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 架构概览
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌──────────────────────────────────────────────────┐
|
||||||
|
│ Tauri shell - windowing, OS integration │
|
||||||
|
└──────────────────────────────────────────────────┘
|
||||||
|
│ JSON-RPC ↕
|
||||||
|
┌──────────────────────────────────────────────────┐
|
||||||
|
│ Rust core(进程内 `openhuman` core)│
|
||||||
|
│ • Memory Tree, integrations, auto-fetch │
|
||||||
|
│ • Model router, TokenJuice, native tools │
|
||||||
|
│ • Voice (STT in, TTS out, Meet agent) │
|
||||||
|
└──────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌──────────────────────────────────────────────────┐
|
||||||
|
│ React frontend - screens, navigation │
|
||||||
|
└──────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
Shell 是载体(负责窗口化、进程生命周期、IPC)。所有产品逻辑都在 Rust core 中。React 前端通过 JSON-RPC 与 core 通信。参见[架构](../developing/architecture/)获取完整图景。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 实时通信
|
||||||
|
|
||||||
|
桌面应用与 OpenHuman 后端保持持久连接。响应在生成时流式输出;输出渐进出现,而非等待后的最终结果。如果网络断开,应用会自动重连,使用渐进退避。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 离线行为
|
||||||
|
|
||||||
|
你的本地状态保存在设备上。偏好设置、设置和连接的源配置在离线时仍然可用。本地记忆树完全可访问,你可以浏览 [Obsidian 存储库](obsidian-wiki/),在无网络连接的情况下阅读你现有的笔记。
|
||||||
|
|
||||||
|
自动拉取和实时 LLM 调用需要网络连接。网络恢复时,下一个 20 分钟触发周期会从上次停止的地方继续。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 自动更新
|
||||||
|
|
||||||
|
桌面 shell 通过 Tauri 的更新插件自动更新,针对 GitHub Releases 上发布的一份清单。进程内 OpenHuman core 打包在同一 bundle 中,所以 shell 更新会同时升级两者。
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
---
|
||||||
|
icon: shield
|
||||||
|
---
|
||||||
|
|
||||||
|
# 隐私与安全
|
||||||
|
|
||||||
|
OpenHuman 的设计使得**你生活的记忆活在你的机器上**。本地 SQLite 记忆树、Markdown Obsidian 存储库、你的音频缓冲区,所有这些都在你的控制之下。OpenHuman 后端处理必须经纪的事(LLM 调用、OAuth token、搜索代理),别无其他。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 隐私设计
|
||||||
|
|
||||||
|
**记忆树是本地的。** SQLite 数据库(`<workspace>/memory_tree/chunks.db`)和 Markdown 存储库(`<workspace>/wiki/`)位于你的机器上。智能体在本地读取;你的原始源数据没有任何内容存在于 OpenHuman 后端。
|
||||||
|
|
||||||
|
**集成 token 由后端持有,不在你的笔记本上。** OAuth token 永不以明文形式写入磁盘。OpenHuman 后端经纪每个集成请求,core 从不直接与任何第三方 API 通信。
|
||||||
|
|
||||||
|
**操作系统级凭据存储。** 敏感 token 存储在你平台的安全密钥链中:macOS Keychain、Windows Credential Manager、Linux Secret Service。
|
||||||
|
|
||||||
|
**不使用你的数据训练。** 你的对话、记忆树和个人信息永不用于训练 AI 模型或改进系统。
|
||||||
|
|
||||||
|
**可选**[本地 AI](model-routing/local-ai.zh-CN.md)**。** 如果你想让嵌入向量和摘要树构建保留在你的机器上,可以选择加入。心跳/学习/潜意识循环同样可以移至端侧。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 保留在你机器上的内容
|
||||||
|
|
||||||
|
| | |
|
||||||
|
| ------------------------------- | --------------------------------------------------------------- |
|
||||||
|
| **记忆树 SQLite 数据库** | 本地 - `<workspace>/memory_tree/chunks.db`。 |
|
||||||
|
| **Obsidian Markdown 存储库** | 本地 - `<workspace>/wiki/`。你可以阅读、编辑、复制、删除。 |
|
||||||
|
| **音频捕获缓冲区** | 本地。STT 后丢弃。 |
|
||||||
|
| **本地模型状态** | 本地。 |
|
||||||
|
|
||||||
|
## OpenHuman 后端处理的内容
|
||||||
|
|
||||||
|
| | |
|
||||||
|
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| **LLM 调用** | 通过一个订阅由后端代理,然后按[模型路由器](model-routing/)转发至底层提供商(Anthropic / OpenAI / Google 等)。 |
|
||||||
|
| **网络搜索代理** | 原生[网络搜索工具](native-tools/web-search.zh-CN.md)调用后端代理,这样你无需携带搜索 API key。 |
|
||||||
|
| **集成 OAuth 和工具代理** | [118+ 集成](integrations/README.zh-CN.md)的 token 存储和限速请求经纪。 |
|
||||||
|
| **TTS 流媒体** | 托管[文字转语音](native-tools/voice.zh-CN.md)音频流。音频生成后丢弃——不保留。 |
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 权限和访问控制
|
||||||
|
|
||||||
|
OpenHuman 仅在你完成 OAuth 流程后才访问集成。每个连接有自己的作用域;你可以随时从 Skills 标签页撤销它们。
|
||||||
|
|
||||||
|
[自动拉取](obsidian-wiki/auto-fetch.zh-CN.md)确实在连接活跃时持续运行,这正是它的意义所在。但它受以下约束:
|
||||||
|
|
||||||
|
* 你授予该集成的 **OAuth 作用域**。
|
||||||
|
* 每个 provider 的**同步间隔**(例如 Gmail 默认每 15 分钟)。
|
||||||
|
* 每个连接的**每日预算**,限制 API 使用。
|
||||||
|
|
||||||
|
如果你撤销一个连接,下一个 tick 停止同步;已在你本地记忆树中的块保留在那里,因为它们是你的。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 为什么本地记忆是隐私的
|
||||||
|
|
||||||
|
大多数 AI 助手面临权衡:更多上下文意味着更多原始数据发送到云端。记忆树消除了这一权衡。
|
||||||
|
|
||||||
|
因为规范化、分块、评分和摘要树都在**你本地 Rust core 内部**运行,你的原始源数据永不离开你的机器。LLM 看到的唯一东西是智能体在当前轮次从你本地记忆树中检索的内容,而该检索由你的提示管理,而非后台上传。
|
||||||
|
|
||||||
|
压缩和本地性共同构成隐私架构。
|
||||||
|
|
||||||
|
<figure><img src="../.gitbook/assets/V17 — Privacy Shield@2x.png" alt=""><figcaption></figcaption></figure>
|
||||||
|
|
||||||
|
## 安全性
|
||||||
|
|
||||||
|
**传输加密。** 应用与 OpenHuman 后端之间的所有通信使用 TLS。没有数据以明文传输。
|
||||||
|
|
||||||
|
**沙盒技能。** 每个技能在自己的隔离执行环境中运行,强制执行内存和资源限制。技能无法访问彼此的数据、主机系统的文件系统或你的凭据。
|
||||||
|
|
||||||
|
**工作区作用域工具。** 原生[文件系统工具](native-tools/coder.zh-CN.md)在用户打开的工作区内操作;它们没有对磁盘其余部分的ambient访问权限。
|
||||||
|
|
||||||
|
**短生命周期 token。** 应用与后端之间的认证 token 是有时间限制的。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 信任与风险智能
|
||||||
|
|
||||||
|
OpenHuman 包含一个智能层,旨在帮助你推理已连接来源的可信度、信息质量和潜在风险。
|
||||||
|
|
||||||
|
**诈骗和冒充信号。** 与诈骗、冒充或协调滥用相关的行为模式可以浮现为警告。信号来自模式,而非来自共享个人消息内容。
|
||||||
|
|
||||||
|
**上下文动态信任。** 信任是上下文相关的,一个领域的可信度不会自动转移到另一个。OpenHuman 通过聚合数据和历史准确性而非静态分数来呈现信任。
|
||||||
|
|
||||||
|
**建议性,而非执行性。** 信任和风险输出是为你判断提供信息的建议性信号。OpenHuman 不会封禁用户、删除消息或执行审核决策。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 共享环境
|
||||||
|
|
||||||
|
在团队或社区环境中,隐私仍以用户为中心。每个用户的已连接源都作用域到其账户;管理员无法通过后门访问其他用户的记忆树。
|
||||||
|
|
||||||
|
社区级智能从聚合和匿名化的信号中推导,绝不从直接访问个人消息内容获取。
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
后台循环,评估用户/系统任务相对于工作区的状态,
|
||||||
|
并决定做什么。
|
||||||
|
icon: loader
|
||||||
|
---
|
||||||
|
|
||||||
|
# 潜意识循环
|
||||||
|
|
||||||
|
一个后台任务评估和执行系统。在每个周期 tick 上,它加载用户定义和系统任务列表,读取你工作区的当前状态,决定对每项做什么,然后要么自主行动,要么升级给你审批。
|
||||||
|
|
||||||
|
把它想象成智能体的空闲线程:你停止打字后仍在继续思考的部分。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 一个 tick 如何工作
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Heartbeat │
|
||||||
|
│ (tick 之间睡眠几分钟) │
|
||||||
|
└──────────────────────┬──────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Subconscious Engine │
|
||||||
|
│ │
|
||||||
|
│ 1. 加载到期任务 │
|
||||||
|
│ 2. 将每项标记为进行中 │
|
||||||
|
│ 3. 构建情况报告(记忆 + 工作区) │
|
||||||
|
│ 4. 用本地模型评估每个任务 │
|
||||||
|
│ 5. 执行决定(act / noop / escalate) │
|
||||||
|
│ 6. 将结果写回活动日志 │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌───────────┼───────────┐
|
||||||
|
▼ ▼ ▼
|
||||||
|
noop act escalate
|
||||||
|
(skip) (execute) (deeper agent)
|
||||||
|
```
|
||||||
|
|
||||||
|
每个 tick 是独立的。如果一个 tick 在下一个开始时仍在运行(慢速模型调用、网络抖动),新的 tick 接管,旧的在进行中的条目被标记为已取消。Tick 永远不会堆叠。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 任务类型
|
||||||
|
|
||||||
|
### 系统任务
|
||||||
|
|
||||||
|
引擎启动时自动播种。不能删除,只能禁用。默认覆盖你希望任何助手监视的事情:
|
||||||
|
|
||||||
|
* 检查已连接技能的错误或断开
|
||||||
|
* 审查新记忆更新中的可操作项目
|
||||||
|
* 监控系统健康(本地模型、记忆、连接)
|
||||||
|
|
||||||
|
你可以通过在 workspace 的 `HEARTBEAT.md` 文件中列出额外的系统任务来扩展,每行一个任务。
|
||||||
|
|
||||||
|
### 用户任务
|
||||||
|
|
||||||
|
你从 UI 手动添加的任何内容。切换开/关、编辑、删除。例如:
|
||||||
|
|
||||||
|
* "检查紧急邮件"(只读)
|
||||||
|
* "发送每日摘要到 Slack"(写意图)
|
||||||
|
* "总结 Notion 更新"(只读)
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 决策
|
||||||
|
|
||||||
|
对于每个到期任务,本地模型返回三个决策之一:
|
||||||
|
|
||||||
|
| 决策 | 含义 |
|
||||||
|
| -------- | --------------------------------------------------- |
|
||||||
|
| Skip | 现在没什么相关的 |
|
||||||
|
| Act | 发现了相关的东西,执行任务 |
|
||||||
|
| Escalate | 需要更深入的推理,交给云端智能体 |
|
||||||
|
|
||||||
|
决定如何执行取决于任务是否有**写意图**(它要求智能体执行一个操作)还是**只读**(它要求智能体查看和报告):
|
||||||
|
|
||||||
|
```text
|
||||||
|
Decision: Skip
|
||||||
|
→ 记录"没什么新东西",调度下一次运行
|
||||||
|
|
||||||
|
Decision: Act
|
||||||
|
→ 在本地模型上执行(读或写)
|
||||||
|
|
||||||
|
Decision: Escalate
|
||||||
|
├─ 写意图任务
|
||||||
|
│ → 用完整权限运行云端智能体
|
||||||
|
│ → 不需要批准(你明确要求了该操作)
|
||||||
|
│
|
||||||
|
└─ 只读任务
|
||||||
|
→ 用仅分析模式运行云端智能体
|
||||||
|
→ 如果智能体浮出未经请求的推荐操作
|
||||||
|
│ → 为你审批创建升级卡片
|
||||||
|
│ → 批准后 → 用完整权限重新运行
|
||||||
|
└─ 否则 → 记录结果,完成
|
||||||
|
```
|
||||||
|
|
||||||
|
每个任务评估都带着彩色点和简短状态落在活动日志中:
|
||||||
|
|
||||||
|
| 状态 | 颜色 | 文本 |
|
||||||
|
| ----------------- | -------------- | ---------------------- |
|
||||||
|
| 进行中 | 蓝色(脉冲) | "评估中…" |
|
||||||
|
| 已行动 | 绿色 | 结果文本 |
|
||||||
|
| 已跳过 | 灰色 | "没什么新东西" |
|
||||||
|
| 等待批准 | 琥珀色 | "等待批准" |
|
||||||
|
| 失败 | 珊瑚色 | 错误消息 |
|
||||||
|
| 已取消 | 灰色 | "已取消" |
|
||||||
|
| 已忽略 | 灰色 | "已跳过" |
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 两个模型,一个循环
|
||||||
|
|
||||||
|
| 阶段 | 运行位置 | 为什么 |
|
||||||
|
| -------------------------------------- | ----------------------- | -------------------------------------------- |
|
||||||
|
| 每个任务评估(每个 tick) | 本地模型(Ollama) | 免费,无速率限制,适合端侧 |
|
||||||
|
| 仅文本执行(摘要、检查) | 本地模型 | 相同 |
|
||||||
|
| 工具使用执行(发送、发布…) | 云端智能体 | 工具、更大上下文、速率限制重试 |
|
||||||
|
| 升级读取的分析模式 | 云端智能体(只读) | 本地模型 defer 时更深入的推理 |
|
||||||
|
|
||||||
|
这种分割保持了循环便宜:只有当任务真正需要时你才为云端调用付费。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 审批门
|
||||||
|
|
||||||
|
只有当智能体想要采取**你没有明确要求的写操作**时才需要审批。
|
||||||
|
|
||||||
|
| 任务意图 | 智能体想要写 | 需要审批? |
|
||||||
|
| ------------------------------ | -------------------- | -------------------------- |
|
||||||
|
| "发送摘要到 Slack"(写) | 是 | 否,你要求的 |
|
||||||
|
| "检查紧急邮件"(读) | 否 | 否,只读结果 |
|
||||||
|
| "检查紧急邮件"(读) | 是(转发它们) | **是**,未经请求的写 |
|
||||||
|
|
||||||
|
审批流程:
|
||||||
|
|
||||||
|
1. 云端智能体以仅分析模式运行。
|
||||||
|
2. 它浮出一个推荐,例如 _"将 3 封紧急邮件转发到 #team-alerts。"_
|
||||||
|
3. 升级卡片出现在 UI 的**需要审批**下。
|
||||||
|
4. **继续**用完整权限重新运行。
|
||||||
|
5. **跳过**什么都不做。
|
||||||
|
|
||||||
|
与技能相关的升级(断开的集成、过期的 OAuth、缺失的范围)显示一个**在技能中修复**按钮,直接带你到技能页面而不是。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 失败处理
|
||||||
|
|
||||||
|
失败计数器跟踪连续 tick 全评估步骤失败(本地模型宕机、网络断开)。任何成功 tick 将其重置为零,并在 UI 状态栏中以珊瑚色显示(当非零时)。
|
||||||
|
|
||||||
|
每任务失败不会触发此计数器,tick 本身仍被认为成功。
|
||||||
|
|
||||||
|
如果一个 tick 失败或被取消,引擎不会推进其"上次看到"时间戳,所以下一次成功 tick 覆盖相同的窗口。你工作区中的任何内容都不会被跳过。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 配置
|
||||||
|
|
||||||
|
循环可在桌面 app 中配置:
|
||||||
|
|
||||||
|
* **启用 / 禁用。** 打开或关闭整个后台循环。
|
||||||
|
* **Tick 间隔。** tick 触发的频率。默认为 5 分钟;这也是最小值。
|
||||||
|
* **推理。** 本地模型是否在每个 tick 评估任务。如果你想仅通过手动**立即运行**按钮运行,则禁用。
|
||||||
|
* **上下文预算。** 情况报告一次可以传入多少工作区。默认值是合理的;为更丰富的上下文调高,为更紧密的成本调低。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 在 UI 中
|
||||||
|
|
||||||
|
位于**智能 → 潜意识**。
|
||||||
|
|
||||||
|
* **状态栏。** 任务数、总 tick 数、上次 tick 时间、失败计数器(如果有)。
|
||||||
|
* **进行中的任务。** 系统任务(只读,带"默认"badge)和你自己的任务(切换 + 删除)。
|
||||||
|
* **需要审批。** 待处理升级的琥珀色卡片。每张有标题、描述和优先级。按钮:**继续**、**在技能中修复**(当相关时)、或**跳过**。
|
||||||
|
* **活动日志。** 每个任务评估的按时间顺序的 feed,彩色点 + 结果。当任何内容进行中时自动刷新。
|
||||||
|
* **立即运行。** 手动触发一个 tick。立即返回;UI 轮询结果。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [记忆树](obsidian-wiki/memory-tree.zh-CN.md),情况报告从中读取。
|
||||||
|
* [从集成自动拉取](obsidian-wiki/auto-fetch.zh-CN.md),tick 之间工作区如何保持新鲜。
|
||||||
|
* [本地 AI(可选)](model-routing/local-ai.zh-CN.md),为评估提供支持的端侧模型。
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
TokenJuice - 一层规则叠加,在工具输出进入 LLM 上下文之前将其压缩。
|
||||||
|
处理成千上万封邮件依然成本低廉。
|
||||||
|
icon: file-zipper
|
||||||
|
---
|
||||||
|
|
||||||
|
# 智能 Token 压缩
|
||||||
|
|
||||||
|
LLM Token 价格不菲,而冗长的工具输出是消耗大多数 Token 的地方。繁忙仓库里的 `git status`、一次 `cargo build` 日志、一个 600 条消息的邮件串,或者针对真实集群的 `docker ps -a`,这些都可能把上下文窗口撑得很大,却几乎不带多少有效信息。
|
||||||
|
|
||||||
|
OpenHuman 搭载 **TokenJuice**,这是 [vincentkoc/tokenjuice](https://github.com/vincentkoc/tokenjuice) 的移植版本,直接集成到工具执行路径中。在任何工具结果到达模型之前,TokenJuice 会将输出通过一层规则叠加进行处理,去除噪音、保留信号。
|
||||||
|
|
||||||
|
## 三层规则叠加
|
||||||
|
|
||||||
|
规则是 JSON,按以下顺序合并,后面的层级覆盖前面的:
|
||||||
|
|
||||||
|
<table><thead><tr><th width="134.41796875">层级</th><th>路径</th><th>用途</th></tr></thead><tbody><tr><td><strong>内置</strong></td><td>随二进制文件发布</td><td>为 git、npm、cargo、docker、kubectl、ls 等提供的合理默认值</td></tr><tr><td><strong>用户</strong></td><td><code>~/.config/tokenjuice/rules/</code></td><td>你的个人覆盖,应用于所有项目</td></tr><tr><td><strong>项目</strong></td><td><code>.tokenjuice/rules/</code></td><td>仓库特定的覆盖,纳入版本控制,与团队共享</td></tr></tbody></table>
|
||||||
|
|
||||||
|
每条规则命名一个工具/命令模式和一个压缩策略(截断、行去重、折叠空白、删除匹配的正则表达式、摘要分段等)。新规则就是 JSON 文件,无需重新编译。
|
||||||
|
|
||||||
|
## 为什么这和记忆有关
|
||||||
|
|
||||||
|
TokenJuice 是使[自动拉取](obsidian-wiki/auto-fetch.zh-CN.md)在经济上可行的原因。当 Gmail provider 同步一页 200 条消息时,TokenJuice 在每个规范化的邮件进入构建摘要的模型**之前**就将其压缩。GitHub diff、Slack 频道转储以及其他任何高流量来源同理。
|
||||||
|
|
||||||
|
具体来说:通过前沿模型摄入你最近六个月的邮件费用从数百美元降到个位数美元。
|
||||||
|
|
||||||
|
## 它在流水线中的位置
|
||||||
|
|
||||||
|
```text
|
||||||
|
工具调用结果
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
TokenJuice(分类 → 匹配规则 → 压缩)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
LLM 上下文
|
||||||
|
```
|
||||||
|
|
||||||
|
实现:`src/openhuman/tokenjuice/`(`classify.rs`、`reduce.rs`、`rules/compiler.rs`、`tool_integration.rs`)。
|
||||||
|
|
||||||
|
## 检查和覆盖
|
||||||
|
|
||||||
|
* 在 `~/.config/tokenjuice/rules/` 中放入一个 JSON 文件来全局添加或覆写规则。
|
||||||
|
* 在仓库内的 `.tokenjuice/rules/` 中放入一个来做同样的项目级设置。
|
||||||
|
* 使用 `RUST_LOG=openhuman_core::openhuman::tokenjuice=debug` 启动 core,可以查看匹配了什么以及多少输出被裁剪了。
|
||||||
|
|
||||||
|
## 另见
|
||||||
|
|
||||||
|
* [原生工具](native-tools/README.zh-CN.md)。大多数重型工具输出都经过 TokenJuice。
|
||||||
|
* [记忆树](obsidian-wiki/memory-tree.zh-CN.md)。压缩输出的下游消费者。
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
---
|
||||||
|
description: >-
|
||||||
|
安装 OpenHuman,完成应用内入门引导(登录、连接 Gmail、
|
||||||
|
选择 AI 运行方式),然后对你的记忆树发出第一个请求。
|
||||||
|
icon: play
|
||||||
|
---
|
||||||
|
|
||||||
|
# 快速入门
|
||||||
|
|
||||||
|
本文将引导你完成安装 OpenHuman、完成应用内入门引导,以及发出第一个请求。
|
||||||
|
|
||||||
|
OpenHuman 遵循 GNU GPL3 开源许可证,代码库位于 [github.com/tinyhumansai/openhuman](https://github.com/tinyhumansai/openhuman)。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 系统要求
|
||||||
|
|
||||||
|
OpenHuman 支持 **macOS、Windows 和 Linux** 桌面端。建议 4 GB 以上内存;如果要摄入超大型邮箱或仓库,或在同一台机器上运行[本地模型](../features/model-routing/local-ai.zh-CN.md),建议 16 GB 以上。
|
||||||
|
|
||||||
|
### 权限
|
||||||
|
|
||||||
|
首次启动 OpenHuman 时,操作系统会提示授予应用所需的权限(macOS 上的 Accessibility、语音热键的 Input Monitoring,以及计划使用[会议智能体](../features/mascot/meeting-agents.zh-CN.md)时的相机/麦克风)。你随时可以在 **设置 → 自动化与渠道** 中查看和调整这些权限。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 1. 下载并安装
|
||||||
|
|
||||||
|
从 [https://tinyhumans.ai/openhuman](https://tinyhumans.ai/openhuman) 或通过你平台的软件包管理器获取 OpenHuman 桌面应用。安装后打开应用。
|
||||||
|
|
||||||
|
## 2. 登录
|
||||||
|
|
||||||
|
第一个屏幕是**"登录!让我们开始吧"**。提供多种登录方式,包括社交登录。如果你要将应用指向自定义 core RPC URL(自建后端的情况),还有一个**高级**面板;大多数用户可以忽略它。
|
||||||
|
|
||||||
|
{% hint style="info" %}
|
||||||
|
**无永久锁定。** 登录不会授予 OpenHuman 对任何内容的持续访问权。所有第三方访问都需要在以下步骤中每个集成单独进行明确的 OAuth 批准。
|
||||||
|
{% endhint %}
|
||||||
|
|
||||||
|
## 3. 发出你的第一个请求
|
||||||
|
|
||||||
|
一旦 Gmail 完成摄入(首次自动拉取会在二十分钟内触发),可以尝试以下提示:
|
||||||
|
|
||||||
|
**简报**
|
||||||
|
|
||||||
|
* "过去 12 小时我需要了解什么?"
|
||||||
|
* "有什么在等着我?"
|
||||||
|
|
||||||
|
**跨源查询**
|
||||||
|
|
||||||
|
* "总结我今天错过了什么。"
|
||||||
|
* "这周有哪些关键决策?"
|
||||||
|
* "从我最近的对话中提取行动项。"
|
||||||
|
* "Sarah 在邮件和聊天中对这个项目说了什么?"
|
||||||
|
|
||||||
|
OpenHuman 自动为每个任务选择合适的模型。参见[自动模型路由](../features/model-routing/)。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 4. 打开 Obsidian 存储库
|
||||||
|
|
||||||
|
"记忆"标签页有一个**"在 Obsidian 中查看存储库"**按钮。点击它可以在 [Obsidian](https://obsidian.md) 中打开 `<workspace>/wiki/`。你可以浏览智能体的摘要、放入你自己的笔记,甚至构建手动链接——智能体会在下一次摄入时获取你的编辑。参见 [Obsidian 风格的记忆](../features/obsidian-wiki/)。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## 5. 让吉祥物做更多
|
||||||
|
|
||||||
|
现在智能体有了记忆和一个模型,产品的其余部分就是给它更多发挥空间:
|
||||||
|
|
||||||
|
* [**会议智能体**](../features/mascot/meeting-agents.zh-CN.md) —— 放入一个 Google Meet 链接,吉祥物作为真实参与者加入:它倾听、将笔记记入记忆树、在通话中说话,并实时使用工具。
|
||||||
|
* [**从集成自动拉取**](../features/obsidian-wiki/auto-fetch.zh-CN.md) —— 从**设置**中连接更多源;每二十分钟调度器将新数据拉入你的树。
|
||||||
|
* [**原生语音**](../features/native-tools/voice.zh-CN.md) —— 按键说话输入和 TTS 回复,这样你可以和 OpenHuman 对话而不是打字。
|
||||||
|
* [**潜意识循环**](../features/subconscious.zh-CN.md) —— 让你离开时吉祥物继续处理待办任务。
|
||||||
|
|
||||||
|
## 加入社区
|
||||||
|
|
||||||
|
OpenHuman 处于早期测试阶段。在这个阶段,反馈和贡献能带来真正的改变。
|
||||||
|
|
||||||
|
* **GitHub:** [github.com/tinyhumansai/openhuman](https://github.com/tinyhumansai/openhuman)
|
||||||
|
* **Discord:** [discord.tinyhumans.ai](https://discord.tinyhumans.ai)
|
||||||
Executable
+92
@@ -0,0 +1,92 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# i18n-doc-scan.sh - OpenHuman GitBook 中文文档问题扫描
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== OpenHuman i18n 文档扫描 ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. 未本地化的内部链接
|
||||||
|
echo "【1/5】检查未本地化的 .md 链接..."
|
||||||
|
UNLOCALIZED=$(find gitbooks -name "*.zh-CN.md" -exec grep -l '\.md)' {} \; 2>/dev/null | while read f; do
|
||||||
|
grep '\.md)' "$f" 2>/dev/null | grep -v '\.zh-CN\.md)' | sed "s|^|$f:|" || true
|
||||||
|
done)
|
||||||
|
if [[ -n "$UNLOCALIZED" ]]; then
|
||||||
|
COUNT=$(echo "$UNLOCALIZED" | grep -c ':' || echo 0)
|
||||||
|
echo "❌ 发现未本地化链接(共 $COUNT 处):"
|
||||||
|
echo "$UNLOCALIZED" | head -30
|
||||||
|
else
|
||||||
|
echo "✅ 无未本地化链接"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. MD040 - 代码块缺少语言标识(查找孤立的 ``` 行)
|
||||||
|
echo "【2/5】检查代码块语言标识(MD040)..."
|
||||||
|
NO_LANG=$(find gitbooks -name "*.zh-CN.md" -exec sh -c '
|
||||||
|
for f; do
|
||||||
|
line_num=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
line_num=$((line_num + 1))
|
||||||
|
if [[ "$line" == "\`\`\`" ]]; then
|
||||||
|
# 检查前一行是否也是 ``` 或空(是代码块开始)
|
||||||
|
# 简单判断:当前行是 ``` 且下一行不是以 ``` 开头(结尾没有语言标识)
|
||||||
|
prev_line=$(sed "$((line_num - 1))q;d" "$f" 2>/dev/null || echo "")
|
||||||
|
next_line=$(sed "$((line_num + 1))q;d" "$f" 2>/dev/null || echo "")
|
||||||
|
if [[ ! "$line" =~ ^\`\`\`[a-zA-Z] ]]; then
|
||||||
|
echo "$f:$line_num: $line"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "$f"
|
||||||
|
done
|
||||||
|
' sh {} + 2>/dev/null || true)
|
||||||
|
if [[ -n "$NO_LANG" && ${#NO_LANG} -gt 10 ]]; then
|
||||||
|
echo "❌ 发现裸代码块:"
|
||||||
|
echo "$NO_LANG" | head -20
|
||||||
|
else
|
||||||
|
echo "✅ 所有代码块均有语言标识"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. http:// 外部链接
|
||||||
|
echo "【3/5】检查 http:// 外部链接..."
|
||||||
|
HTTP_FILES=$(find gitbooks -name "*.zh-CN.md" -exec grep -l 'http://' {} \; 2>/dev/null || true)
|
||||||
|
if [[ -n "$HTTP_FILES" ]]; then
|
||||||
|
echo "❌ 发现 http:// 链接:"
|
||||||
|
find gitbooks -name "*.zh-CN.md" -exec grep -n 'http://' {} \; 2>/dev/null | head -10
|
||||||
|
else
|
||||||
|
echo "✅ 无 http:// 链接"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 4. sidecar 术语
|
||||||
|
echo "【4/5】检查 sidecar 术语..."
|
||||||
|
SIDECAR_FILES=$(find gitbooks -name "*.zh-CN.md" -exec grep -l -i 'sidecar' {} \; 2>/dev/null || true)
|
||||||
|
if [[ -n "$SIDECAR_FILES" ]]; then
|
||||||
|
echo "❌ 发现 sidecar 提及:"
|
||||||
|
find gitbooks -name "*.zh-CN.md" -exec grep -n -i 'sidecar' {} \; 2>/dev/null | head -10
|
||||||
|
else
|
||||||
|
echo "✅ 无 sidecar 术语"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 5. 末尾空行检查
|
||||||
|
echo "【5/5】检查文件末尾空行..."
|
||||||
|
MISSING_TRAILING=$(find gitbooks -name "*.zh-CN.md" -exec sh -c '
|
||||||
|
for f; do
|
||||||
|
if [[ -s "$f" ]]; then
|
||||||
|
last=$(tail -c1 "$f" 2>/dev/null | xxd -p | tr -d " ")
|
||||||
|
if [[ "$last" != "0a" ]]; then
|
||||||
|
echo "$f"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
' sh {} + 2>/dev/null || true)
|
||||||
|
if [[ -n "$MISSING_TRAILING" ]]; then
|
||||||
|
echo "❌ 文件缺少末尾空行(共 $(echo "$MISSING_TRAILING" | wc -l) 个):"
|
||||||
|
echo "$MISSING_TRAILING" | head -10
|
||||||
|
else
|
||||||
|
echo "✅ 所有文件末尾有空行"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== 扫描完成 ==="
|
||||||
Reference in New Issue
Block a user