Files
freedak f7a720204a Update: 将子项目从 submodule 转为完整内容
- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用
- 添加所有子项目的完整源代码
- 保留原始 .git 为 .git.bak 备份
2026-07-04 19:20:46 +08:00

128 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 伙伴(Companions
NomiFun 的数字伙伴从「单个 nomi」升级为**多伙伴家庭**:你可以创建多个伙伴并同时使用、分别培养、自定义名称/形象/人格,每个伙伴可以使用自己的聊天模型、绑定自己的**专属知识库**(演进出金融/文学/coding/情感等专业伙伴);而所有伙伴**共享同一个记忆中枢**——采集与学习是一条全局链路,任何一个伙伴学到的东西全家都记得。记忆、伙伴、知识库都可以打包成 `.zip` 导出/导入,换机平滑迁移。
> 入口是侧边栏的 **桌面伙伴** 页(即 `/nomi` 路由);任意桌面伙伴窗口右键菜单的「打开聊天」也会深链到这里。
## 页面结构:伙伴切换条 + 双域 Tab
「桌面伙伴」页顶部是**伙伴切换条**:每个伙伴一张卡片(形象缩略图 + 名字 + 等级),加一个「新建伙伴」按钮。当前选中的伙伴驱动下面的**伙伴域** Tab;与伙伴无关的全局数据归**共享域** Tab:
| 域 | Tab | 内容 |
| --- | --- | --- |
| 伙伴域(随切换条变化) | 总览 | **桌面伙伴开关** + 该伙伴的等级 / XP / mood + 共享统计 |
| | 聊天 | 该伙伴自己的陪伴会话线程 |
| | 模型&知识 | 聊天模型选择 / **知识库绑定** |
| | 远程连接 | 该伙伴的 IM 机器人(按伙伴绑定,详见[渠道指南](./channels.zh.md) |
| | 设置 | 名称 / 形象 / 人格 / 勿扰 / 删除伙伴 |
| 共享域(全局唯一) | 记忆 · 数据采集 · 学习 · 建议 | 共享记忆中枢(所有伙伴同一份) |
| | 迁移 | 导出 / 导入迁移包(见下文) |
## 创建与管理多伙伴
1. 点伙伴条上的**新建伙伴**,起个名字、挑一个形象(mochi / ink / roux / pixel / bolt / boo 六款)即可。
2. **第一个伙伴自动成为默认伙伴**(卡片带「默认」徽标)。默认伙伴是渠道未显式绑定时的回退对象(见下文渠道一节)。
3. 在该伙伴的**设置** Tab 里可以随时改名(即时生效)、换形象、调人格(预设或自定义)、**为这个伙伴单独选聊天模型**、开关桌面伙伴窗口与勿扰时段。
4. **删除伙伴**会级联清理:它的陪伴会话、运行时状态(XP 等)、`('companion', companionId)` 知识库绑定一并移除;若删的是默认伙伴,默认资格自动顺延给下一个。删除允许删到零个(共享记忆中枢独立于伙伴存在,采集/学习照常运行)。
每个伙伴在磁盘上是一个目录:`{data_dir}/companion/companions/{companion_id}/config.json`,**目录即真相**——这也是伙伴包导出/导入的单位。
### 多个桌面伙伴同屏
每个开启了桌面伙伴开关的伙伴拥有自己的桌面窗口(透明、置顶、可拖动,窗口 label 为 `companion-{companionId}`)。多个可以同屏共处;建议同屏不超过 5 个(每个窗口是独立的 WebView 实例,开太多影响性能,UI 会提示但不硬限)。右键任意桌面伙伴窗口可直达它的聊天页。
## 共享记忆中枢
所有伙伴共用 `{data_dir}/companion/shared/` 下的同一套记忆设施:
- **采集**:单条链路订阅全局事件总线,按开关采集你的工作数据,写入 `shared/events/YYYYMMDD.jsonl`
- **学习**:单个学习器按设定间隔增量蒸馏事件为长期记忆,存入 `shared/memory.db`。学习链路使用**共享配置里的学习模型**(与每个伙伴的聊天模型相互独立,单链路单预算)。
- 任何一个伙伴聊天时保存的记忆、学习产出的记忆,**对全体伙伴可见**——换一个伙伴继续聊,它记得之前发生的一切。
### XP 与 mood 的归属规则
| 来源 | 归属 |
| --- | --- |
| 学习 run 产出(按处理事件数 + 新记忆数计分) | **所有伙伴**(家庭共同成长) |
| 建议被采纳(+20 | **所有伙伴** |
| 陪伴聊天轮次(+2) | 仅参与对话的那个伙伴 |
| 聊天中保存记忆(+5) | 仅该伙伴 |
**mood 是全局的**:由学习 run 产出、存共享状态,所有伙伴同一 mood(按伙伴分化的人格化 mood 留待后续版本)。
## 给伙伴绑定知识库
在伙伴的**模型&知识 Tab → 知识库**区域,用绑定控件为这个伙伴挂载一个或多个知识库(绑定关系为 `('companion', companionId)`)。生效范围:
- 该伙伴的**陪伴聊天**与它接待的**渠道会话**(会话上带 `extra.companionId`)都会挂载这个伙伴绑定的知识库——对话时可检索;不带 companionId 的普通会话维持原有的会话级绑定,二者**不合并**。
- **agent 看到什么**:库挂载到 `{workspace}/.nomi/knowledge/`,注入的上下文按库携带 描述 + AI 梗概 +「何时查阅」提示 + 按预算的目录(每库 20 条 / 全局 60 条,超出按目录聚合),外加一份显式检索协议——要求 agent 先查再答,而不是凭记忆作答。
- **回写(回血)**两种模式,简述如下:
- **staged(暂存)**——对话中产生的知识回写先落入知识库的 `_inbox/`(按会话隔离),由你在知识库页面审阅后入库;
- **direct(直写)**——跳过暂存直接写入知识库正文。
- **AI 自动生成**:知识库页面的「AI 生成」按钮(列表编辑 Modal 与详情页都有)调 `POST /api/knowledge/bases/{id}/autogen`,生成库的描述与 `README.md``.zip` 导入会自动补全空描述。需要已配置 AI Provider(否则返回 `409`)。
- **URL 知识源**:创建知识库时可给出最多 16 条 URL。*snapshot* 模式在创建时抓取并把每页转为 markdown 落入库的 `snapshots/`(超过 32 KB 的页面由 AI 压缩),并自动生成梗概——详情页可刷新快照;*live* 模式留给 agent 运行期实时抓取(无网络工具的引擎可调网关工具 `nomi_knowledge_fetch_url`)。仅接受公网 `http/https` URLSSRF 防护)。
- 伙伴也能**自己养库**Desktop Gateway 提供 7 个知识工具(列表 / 绑定 / 建库 / 写文件 / AI 生成 / 抓取 URL),且伙伴系统提示里内置了「知识沉淀技巧」——陪伴或渠道聊天中它可以不经吩咐就建库并把心得沉淀进去。注意 `nomi_knowledge_create_base``urls` 建库时,URL 抓取在**后台异步**执行——工具立即返回,agent 勿因快照尚未出现而重复建库;库描述(description)生成出来即代表抓取与梗概流水线已完成。
给不同的伙伴绑不同的库,就得到了「金融伙伴」「文学伙伴」「coding 伙伴」——人格、模型、知识三件套都按伙伴独立,记忆共享。
## 渠道绑定伙伴
每个 IM 平台(Telegram / Lark / 钉钉 / 微信)可以各绑一个伙伴来接待远程消息:打开该伙伴的 **Remote** tab`/nomi?companion=<id>&tab=remote`),在那里连接或改绑 bot。未绑定渠道行时仍会读取旧的平台级偏好 `assistant.{platform}.companionId` 作为兼容回退。未绑定时回退**默认伙伴**;切换绑定会重置该渠道的活跃会话(下一条消息由新伙伴接待);被绑定的伙伴若被删除,自动回退默认伙伴并同样重置会话。详见 [Channels 指南](./channels.zh.md)的「主 Agent 模式」一节。
> companionId 不授予任何权限(记忆本就共享):它只决定 persona / 模型 / 知识库挂载,与授予网关工具的 `desktopGateway` 标记性质不同。
## 导出 / 导入:换机迁移
共享域的**迁移** Tab 提供三种 `.zip` 迁移包(仅桌面版提供迁移 UI;路径用系统对话框选取):
| 包 | 内容 | 导入语义 |
| --- | --- | --- |
| **记忆包** | 全部长期记忆 + 学习历史 + mood;**可选**勾选包含原始事件数据 | 与本机记忆**合并去重**(保留原时间戳与来源) |
| **伙伴包** | 单个伙伴的人格 / 形象 / 设置 / XP + 它绑定的知识库**名称清单**(`knowledge_refs`) | 以新 id 创建新伙伴,名称冲突自动缀 "(2)";知识库引用**按名称**匹配本机已有库自动重建绑定,匹配不到的列出来提示你先导入对应知识库包再手动绑定 |
| **知识库包** | 知识库元数据 + md 文件树原样 | 新建知识库落地,名称冲突缀 "(2)" |
换机迁移步骤:
1. 旧机:导出**记忆包**(按需勾选事件数据)→ 逐个导出**伙伴包** → 逐库导出**知识库包**。
2. 新机:先导入**知识库包**(让伙伴包的绑定重建能按名匹配上)→ 导入**伙伴包** → 导入**记忆包**。
3. 检查每个伙伴的模型设置:模型配置原样随包带走,但若新机没有配置对应 provider,会显示未配置,需在设置里重选。
### 隐私边界
- `events/*.jsonl` 是**原始采集数据,包含你的工作内容原文**——默认**不**导出,只有显式勾选「包含原始事件数据」才会进记忆包。
- **聊天历史不随伙伴包迁移**:陪伴会话记录存在主数据库里,伙伴包只带人格与设置。聊天记录留在原机。
## 旧版数据自动迁移
从单伙伴版本升级后,首次启动会自动检测旧布局 `{data_dir}/companion/nomi/`:若存在且尚无 `companion/shared/`,自动迁移为共享记忆中枢 + 第一个伙伴(默认名 **"Nomi"**,继承原有 XP / 人格 / 形象 / 模型 / 桌面伙伴位置 / 陪伴会话线程)。迁移幂等可重入,完成后在旧目录写入 `.migrated` 标记并保留原目录(一个版本周期后清理)。无需任何手工操作。
## 手工走查清单
验证一套多伙伴部署是否健康,按序走一遍:
1. **建两个伙伴**:新建 A、B 两个伙伴,分别改名、换形象;确认第一个带「默认」徽标。
2. **各绑一库**:给 A 绑知识库 X、给 B 绑知识库 Y(伙伴模型&知识 Tab → 知识库)。
3. **各自检索**:分别在 A、B 的聊天里提问只在 X / Y 中存在的内容,确认 A 只命中 X、B 只命中 Y。
4. **共享记忆互通**:在 A 的聊天里让它记住一件事(保存记忆),切到 B 的聊天提问,确认 B 知道。
5. **导出导入 roundtrip**:导出记忆包 + A 的伙伴包 + 知识库 X 的包;(换机或清空后)按「知识库 → 伙伴 → 记忆」顺序导入,确认 A 重建后绑定自动恢复、记忆合并无重复。
6. **渠道切换伙伴**:在某个渠道平台把接待伙伴从 A 切到 B,确认活跃会话被重置、下一条远程消息由 B 的人格接待并挂 B 的知识库。
## 路由与 API
| 用途 | 位置 |
| --- | --- |
| 伙伴列表 / 创建 | `GET/POST /api/companion/companions` |
| 伙伴详情 / 修改 / 删除 | `GET/PATCH/DELETE /api/companion/companions/{companionId}` |
| 共享配置(采集 / 学习 / 默认伙伴) | `GET/PATCH /api/companion/config` |
| 每个伙伴的陪伴线程 | `GET /api/companion/companions/{companionId}/companion/threads``…/companion/active` |
| 导出记忆包 | `POST /api/companion/export/memory``{dest_path, include_events}` |
| 导出伙伴包 | `POST /api/companion/export/companions/{companionId}` |
| 导入记忆包 / 伙伴包 | `POST /api/companion/import`(按 manifest.kind 分发) |
| 导出 / 导入知识库包 | `POST /api/knowledge/bases/{id}/export``POST /api/knowledge/bases/import` |
| 渠道绑定伙伴 | `POST /api/channel/settings/companion` |
## 相关
- [Channels](./channels.zh.md) —— 渠道主 Agent 模式与每平台伙伴绑定。
- [数据与存储](../architecture/data-and-storage.zh.md) —— `companion/` 数据目录布局。