Files
yawan-workbench/docs/系统整体架构与功能检查文档.md

408 lines
34 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.
# 私域 Agent 内容生产工作台:系统整体架构与功能检查文档
> 文档用途:给产品、运营、测试和维护人员逐项核对当前系统。内容依据 `/server/app`、`/web/src` 和启动脚本整理,描述的是代码已经实现或明确配置的行为;“待确认”项需要在实际环境中验收。本文不包含管理员密码、API 密钥等敏感信息。
>
> 代码位置:`server/app/main.py`(FastAPI 路由)、`server/app/models.py`(SQLModel 数据模型)、`server/app/agents`(Agent Runtime)、`server/app/rag`(知识库检索)、`web/src`(React 前端)。
## 1. 系统边界和运行拓扑
系统是一个单组织、本地持久化、可通过公网隧道访问的内容生产工作台。浏览器只访问 React 单页应用;前端通过 `/api` 调用 FastAPI;FastAPI 使用 SQLite 保存业务状态,知识库源文件和产物保存在数据目录,向量索引由 RAG 子系统维护。微信 iLink 连接由独立 Node sidecar 持有账号凭据,主 API 只保存哈希和引用。
```mermaid
flowchart LR
U[浏览器用户] -->|HTTPS / HashRouter| W[React 工作台]
W -->|/api + 会话令牌| A[FastAPI main.py]
A --> DB[(SQLite workspace.db)]
A --> FS[(data/ kb artifacts ocr models)]
A --> R[RAG pipeline]
R --> V[(向量/全文索引)]
A --> RT[Agent Runtime]
RT --> LLM[Provider / 模型]
A --> Q[持久任务队列]
A --> I[进度 SSE / 轮询]
I --> W
S[wechat_ilink_sidecar.mjs] -->|本机 127.0.0.1:8765| A
S --> WX[官方 iLink 微信协议]
CF[cloudflared / ngrok] --> A
```
### 1.1 进程与端口
| 进程 | 作用 | 默认地址/端口 | 主要数据/日志 |
|---|---|---|---|
| FastAPI + Uvicorn | 认证、业务 API、任务调度和后台线程 | 开发 `8011`;生产 `8010` | `/tmp/yawan-uvicorn.log`;生产 `server/data` |
| React/Vite | 开发预览;生产构建后的静态文件由现有部署方式提供 | 开发通常 `5173` | `web/dist` |
| 微信 iLink sidecar | 多账号扫码、收发微信消息、状态回调 | `127.0.0.1:8765` | `/tmp/yawan-wechat-sidecar.log`;按账号隔离的 storage |
| cloudflared/ngrok | 把生产 API/前端暴露到公网 | 隧道地址 | `/tmp/yawan-cloudflared.log`、`/tmp/yawan-ngrok.log` |
### 1.2 环境与存储
- `YAWAN_ENV=dev` 使用 `server/data-dev`;默认或 `prod` 使用 `server/data`。
- `YAWAN_DATA_DIR` 可指定绝对路径,把 `workspace.db`、`kb/`、`artifacts/`、`ocr/`、`models/`、`chroma/` 等整体迁移到外接硬盘。
- `YAWAN_CORS_ORIGINS` 控制允许的前端来源;生产默认包含 `https://agent.pducv.cn`。
- `DB_PATH`、`KB_DIR`、`ARTIFACTS_DIR`、`OCR_DIR`、`MODELS_DIR` 在 `server/app/config.py` 根据环境动态创建。
- 启动时 `init_db()` 建表、执行兼容迁移、恢复未完成的知识片段预留、对账物理文件与索引,并将空质检报告标记为需复检。
## 2. 用户端功能地图
侧栏由 `web/src/shell.tsx` 的 `navFor()` 根据权限生成;隐藏侧栏只是第一层保护,`AppRouter.tsx` 的 `FeatureGate` 和后端中间件还会再次校验。训练营导图已经作为内容任务入口的兼容路由保留;技能库和记忆库作为 Agent 与技能页签;标签作为知识库页签。
| 功能栏 | 页面/路由 | 主要能力 | 主要权限 |
|---|---|---|---|
| 总览 | `/admin/overview` | 状态、自检、快捷入口、通知 | `read` |
| 内容任务 | `/admin/tasks`、`/admin/tasks/:id` | 建任务、导图拆解、逐段生成、质检、组合和交付 | `feature:tasks`、`tasks:*` |
| 运行记录 | `/admin/runs` | 运行状态、事件、工具审批、失败恢复 | `feature:runs`、`runs:read` |
| 操作日志 | `/admin/audit-logs` | 用户动作审计 | `feature:audit`、`audit:read` |
| Agent 与技能 | `/admin/agents`,`?tab=skills|memories` | Agent、技能、记忆、模型工具、数字人身份配置 | `feature:agents`、`agents:*` |
| 数字人 | `/admin/digital-humans` | 文档蒸馏、测试、反馈、版本、授权、微信 Bot | `feature:digital-humans`、`digital_humans:read` |
| 画布编排 | `/admin/flows` | 节点、边、波次、总监模式、授权 | `feature:flows`、`flows:read` |
| 知识库 | `/admin/knowledge` | 建库、上传、去重、分类、预览、检索、消费记录 | `feature:knowledge`、`kb:*` |
| 模型管理 | `/admin/settings/providers` | Provider、模型目录、默认模型、连接测试 | `feature:models`、`providers:*` |
| 用量分析 | `/admin/settings/usage` | 用量事件、余额、点数发放、配额 | `feature:usage`、`usage:read`、`billing:manage` |
| 系统日志 | `/admin/system-logs` | HTTP/应用/任务错误和 Trace | `feature:system-logs`、`system_logs:read` |
| 访问控制 | `/admin/settings/access` | 成员、角色、资源授权、全局发布、版本审核 | `feature:access`、`roles/users/audit:manage` |
| 功能开关 | `/admin/settings/flags` | 读取和修改应用功能开关 | `feature:flags`、`flags:read` |
| 运营看板 | `/admin/ops` | 指标、告警、备份、死信队列 | `feature:ops`、`ops:*` |
| 操作手册 | `/admin/manual` | 面向普通用户的使用说明 | 登录后可见 |
## 3. 认证、组织和权限模型
### 3.1 登录链路
1. `GET /api/auth/status` 检查是否需要首次初始化。
2. 首次使用 `POST /api/auth/bootstrap` 创建管理员;之后使用 `POST /api/auth/login`。
3. 服务端生成不透明会话令牌,数据库只保存 SHA-256 哈希(`AuthSession`),默认有效期 12 小时。
4. 浏览器把令牌放入 API 请求的 `Authorization` 头;退出调用 `POST /api/auth/logout` 撤销会话。
5. `GET /api/auth/me` 返回当前用户、角色、组织和权限,前端据此渲染页面。
### 3.2 内置角色
- **管理员 admin**:`*` 全部权限,仍受组织边界约束。
- **编辑 editor**:内容任务、Agent/画布、知识库、数字人查看、运行和日志等日常生产权限。
- **审查 reviewer**:查看和审查任务、知识库、记忆,不含配置和生产写入权限。
- **只读 viewer**:只能查看被允许的知识库内容。
角色存储在 `AppUser.role`,可维护的角色集合存储在 `RoleDefinition.permissions`。权限目录按“内容生产、资产与知识、数据与洞察、系统管理”等抽屉分组,仅改变展示方式,不改变已保存 key。
### 3.3 访问判定顺序
1. HTTP 中间件确认 `/api` 请求已认证;微信回调为特例,必须在接口内用账号密钥校验。
2. `required_permission()` 校验方法和路径所需操作权限。
3. `feature_permissions()` 校验功能栏权限。
4. 资源访问函数(`require_kb`、`require_skill`、`require_canvas`、`require_memory` 等)校验组织、所有者、可见性和成员授权。
5. 组织 ID:`0` 表示全局资源;正整数表示租户。数据库迁移会添加索引和触发器,阻止非法组织值落库。
### 3.4 可见性和授权
资源具有 `private/shared/global` 三种可见性。所有者可以管理自己的资源;共享资源通过 `*Grant` 表按 `read/use/manage/export` 授权;全局资源对普通用户只允许查看和使用,不能导出或修改全局本体。普通用户对全局资源的修改/删除写入 `ResourceRevision`,管理员审核后才合并。`ResourceFork` 记录个人副本与全局源的版本基线。
## 4. 数据模型和绑定关系
### 4.1 核心实体
| 实体 | 表 | 关键字段/职责 |
|---|---|---|
| 组织 | `Organization` | 租户名称、slug、启用状态 |
| 用户/角色/会话 | `AppUser`、`RoleDefinition`、`AuthSession` | 本地账号、PBKDF2 密码摘要、RBAC、可撤销登录 |
| Agent | `Agent` | 角色类型、标签、知识库 ID/分类、融合 Agent、模型、工具、规则、数字人、发布快照 |
| 技能 | `AgentSkill`、`AgentSkillBinding`、`AgentSkillGrant` | 技能指令、版本、挂载 Agent、成员授权 |
| 数字人 | `DigitalHuman`、`DigitalHumanGrant` | 十一维人格档案、蒸馏元数据、版本、来源文件和授权 |
| 微信账号 | `WeChatBotAccount` | 所有者、组织、Agent、状态、二维码、凭据哈希/引用 |
| 画布 | `Canvas`、`CanvasGrant` | 节点 Agent、边、总监 Agent/模式、授权 |
| 知识库 | `KnowledgeBase` | 源目录、索引状态、文件/片段计数、分段策略、所有权 |
| 分类/文件 | `KnowledgeCategory`、`KnowledgeFile` | 无限层级分类、AI 推荐分类、文件哈希和 revision |
| 消费记录 | `KnowledgeUsage` | Agent+知识库+片段唯一锁、引用、状态、禁用标记 |
| 任务/内容段 | `Campaign`、`Segment` | 导图原文、画布快照、段级 Agent、状态、锚点、引用、历史版本 |
| 质检/产物 | `QCReport`、`Artifact` | 结构/内容/风格/跨稿质检,组合成稿和下载预览 |
| 运行 | `CampaignRun`、`RunEvent`、`AgentSession`、`TaskQueueItem` | 可恢复执行、进度事件、工具调用会话、租约/重试/死信 |
| AI 用量 | `LLMCall`、`UsageEvent`、`PointAccount`、`PointTransaction`、`UsageQuota` | 调用追踪、不可变计量、余额流水和配额 |
| 日志/通知/记忆 | `AuditLog`、`SystemLog`、`Notification`、`PendingMemory`、`Memory` | 用户动作、系统故障、待读提醒、Agent 长期记忆 |
| 版本提案 | `ResourceRevision`、`ResourceFork` | 全局资源个人修改、删除提案及冲突基线 |
### 4.2 绑定关系(当前代码语义)
```mermaid
erDiagram
APP_USER ||--o{ AGENT : owns
APP_USER ||--o{ KNOWLEDGE_BASE : owns
APP_USER ||--o{ DIGITAL_HUMAN : owns
AGENT }o--o{ AGENT_SKILL : mounts
AGENT }o--o{ KNOWLEDGE_BASE : reads
AGENT }o--o{ AGENT : fusion
AGENT }o--|| DIGITAL_HUMAN : identity
CANVAS }o--o{ AGENT : nodes
CAMPAIGN }o--|| CANVAS : snapshot
CAMPAIGN ||--o{ SEGMENT : contains
SEGMENT }o--|| AGENT : assigned
SEGMENT }o--o{ KNOWLEDGE_BASE : consumes
AGENT ||--o{ MEMORY : accumulates
CAMPAIGN_RUN ||--o{ RUN_EVENT : emits
CAMPAIGN_RUN ||--o{ AGENT_SESSION : resumes
LLM_CALL ||--o| USAGE_EVENT : measured
```
- **Agent→知识库**:`Agent.kb_ids` 和 `kb_category_ids` 保存挂接及分类范围;任务创建时运行快照冻结,生成时不读取后来新增的未授权库。
- **Agent→技能**:`AgentSkillBinding` 多对多;任务快照记录技能指令。
- **Agent→数字人**:`Agent.digital_human_id` 绑定身份;运行时数字人人格优先于 Agent 的 `persona_json`。
- **Agent→记忆**:`Memory.agent_id` 归属 Agent;记忆候选按用户、组织、画布范围过滤并冻结到运行快照。
- **画布→Agent/知识/记忆**:画布节点保存 Agent;画布授权只连带允许依赖资源的读/用,不放大编辑、删除、导出权限。
- **内容任务→画布**:`Campaign.canvas_snapshot` 是创建时快照,之后修改画布不会改变历史任务。
- **知识库消费隔离**:`KnowledgeUsage` 唯一约束为 `(agent_id,kb_id,chunk_id)`,不同 Agent 的消费互不锁定;`banned=true` 的片段永久排除检索。
- **微信账号→Agent**:一个 `WeChatBotAccount.agent_id` 绑定一个 Agent;sidecar 收到消息时把账号 ID、Agent ID、会话 ID 一并回传,后端再次校验所有权和授权。
## 5. Agent 与技能工作区
### 5.1 Agent 配置
可创建、编辑、停用、发布和删除非内置 Agent。职责类型代码为 `production`、`training_map`、`qc`、`service`、`coordinator`、`composer`。生产 Agent 可配置内容标签和融合 Agent;知识库可以限定到分类;模型可跟随全局默认或指定 Provider/目录模型;`allowed_tools` 控制 Runtime 工具。
发布接口 `POST /api/agents/{id}/publish` 调用快照冻结逻辑,将规则、模型、技能、知识边界和记忆候选固化到 `runtime_snapshot`。任务创建又会把该快照复制到 `Segment.runtime_snapshot`,保证生成中途修改配置不会改变本次任务。
### 5.2 技能和记忆
技能支持 Markdown 导入(`POST /api/skills/import`)、版本和 Agent 多选挂载;技能自身可以按成员授权。记忆分为 L1 规则、L2 纠错、L3 偏好、L4 成功等层级,先进入 `PendingMemory`,审批后写入 `Memory`。Runtime 在模型真正调用前记录注入记忆的次数,避免恢复会话重复计量。
### 5.3 删除与绑定检查(现状和验收点)
当前删除接口会先检查引用关系:被画布节点、融合 Agent、历史任务或其他资源引用的 Agent/技能/知识库/记忆/数字人可能被拒绝删除,前端会提示先解绑。产品要求“弹出一键解绑所有后再删除”时,验收应确保:
- 明确列出将解除的绑定(Agent、技能、画布节点、知识库分类、数字人、记忆、微信账号等)。
- 一键操作在同一事务或可恢复事务中完成;失败不得留下半解绑状态。
- 历史任务的快照、日志、质检和账单保留,不因删除配置而丢失。
- 全局资源的普通用户操作仍只能建立个人 `ResourceRevision`,不能直接解绑全局本体。
- 删除微信账号先停止 sidecar 实例、清理二维码和凭据引用,再删除数据库记录。
## 6. 数字人蒸馏和微信 iLink
### 6.1 蒸馏流程
1. `POST /api/digital-humans/distill` 上传或选择文档,服务端抽取代表性样本。
2. `_dh_distill()` 生成 `persona` 与 `persona_meta`,记录来源文件、覆盖范围和不确定性,状态为 `testing` 或 `distilling`。
3. `POST /api/digital-humans/{id}/test-write` 进行人工试写;`/redistill` 根据反馈提升版本号。
4. 补充素材通过 `/redistill` 上传并生成待测试新版本;微信对话不会自动写入数字人人格。
5. 创建数字人时自动生成同名默认 Agent 并绑定;后续可继续创建多个 Agent 绑定同一数字人,运行时把人格档案合并进系统提示。
### 6.2 iLink 账号流程
- 前端数字人页调用 `POST /api/wechat/bot/accounts/connect`,后端生成账号级密钥(只保存哈希)并转发到 `YAWAN_WECHAT_ADAPTER_URL`。
- sidecar 使用 `@wechatbot/wechatbot`、Node 22 和每账号独立 storage 目录;登录回调把 `pending_qr`、`connected`、`error`、`disconnected` 和二维码状态回传 API。
- 微信消息签名为 HMAC-SHA256,后端验证时间戳、账号密钥、账号状态、Agent 绑定、组织和所有者;会话按账号/用户/Agent 隔离。
- 删除调用 `DELETE /api/wechat/bot/accounts/{id}`,sidecar 停止对应 Bot 并回调断开。
- 生产环境需要 `.env.production` 中的 `YAWAN_WECHAT_ADAPTER_URL=http://127.0.0.1:8765`,并由 `守护隧道.sh` 检查 8765 端口自动拉起。
## 7. 知识库、索引和检索
### 7.1 导入链路
支持 `.doc/.docx/.srt/.md/.txt/.json/.jsonl/.pdf` 以及音视频转写后索引。大文件走 `uploads/init`、分片上传、`uploads/{id}/finish`;目录导入走 `import-folder`。文件落盘后计算 `content_hash`,同内容文件跳过,重复片段在索引阶段去重。`KnowledgeFile.revision` 在同名内容变化时递增。
```text
上传/分片 → 文件哈希和去重 → 文本解析或媒体转写 → 分段
→ Embedding → 向量/全文索引 → 后台预热 → ready
```
`index_status`:`empty`、`indexing`、`ready`、`needs_reindex`、`error`。启动对账会比较磁盘文件、文件表和向量计数;不会因为对账自动重建大库。
### 7.2 分类和预览
`KnowledgeCategory` 为无限层级树;文件同时保存人工分类 `category_id` 和 AI 建议 `ai_category_id`、置信度、理由。`POST /api/kbs/{kid}/classify` 批量推荐,`.../classification/confirm` 人工确认。知识库页签提供文件、分类、检索测试、消费记录和设置;文件查看走预览接口,管理员可查看全部消费记录,普通用户只返回自己有权看到的记录。
### 7.3 检索模式
- **full**:选定知识库/分类的全部已索引资料分批阅读/检索,时间和用量较高。
- **quick**:按查询相关性召回,适合快速生成。
- **reuse**:复用已阅读缓存,减少重复解析和模型调用。
RAG 管道包含查询校验、Embedding、召回、去重、消费锁和后处理,并记录阶段耗时和缓存命中率;`/api/kbs/{kid}/search` 和 `/api/kbs/search` 提供检索测试。知识片段消费状态为 `reserved`、`consumed`、`available`,进程启动会归还中断留下的 `reserved`。
## 8. 内容任务和训练营导图
### 8.1 创建和拆解
`POST /api/campaigns` 创建任务并保存导图文本、所选画布快照、知识库范围和 Agent;`POST /api/campaigns/{cid}/parse` 调用 coordinator 将导图拆为 `Segment`。每段包含节点、标题、时间范围、标签、指定 Agent、知识分类限制和运行快照。拆解失败可由 `POST /api/campaigns/{cid}/reparse` 重新拆解。
训练营导图 API 位于 `server/app/training_map.py`,核心输入包括主题、至少一个知识库、可选分类、天数和 Agent。严格模型校验:天数连续、节点标题和叶子内容去重、每个叶子必须有证据来源;导图节点只保留框架短语,详细正文在内容任务生成。导图建议支持整套方案、单天、单日导图和全部导图修改,生成阶段支持进度事件。
全库评估采用分层摘要:原始片段按库分批阅读并递归归并;同一组织、用户、主题、知识库/分类范围及模型签名下,完全相同批次会写入 `training-corpus/summary-cache.sqlite`,后续草稿或重试可增量复用,缓存使用 WAL、忙等待和单批次文件锁避免并发重复调用。通用全文预读仍使用按知识库隔离的 `training-knowledge` 清单;两类缓存均不写入 `KnowledgeUsage` 消费账本。
### 8.2 连续生成和跳过
任务运行使用 `CampaignRun`、`Segment.status` 和锚点卡:上游段产出 `anchor_card`,下游只接收摘要和最后确认段结尾,避免重复全文。跳过段会被记录为 `skipped`,后续段不能假设用户已经学会该前置知识,需要补足最小前提。段状态包括 `pending/running/qc/human_review/approved/rework/failed/skipped`。
逐段操作接口:
- `POST /api/campaigns/{cid}/segments/{sid}`:新增段。
- `PUT /api/campaigns/{cid}/segments/{sid}`:修改 Agent、分类或正文。
- `DELETE /api/campaigns/{cid}/segments/{sid}`:删除段。
- `POST /api/segments/{sid}/review`:通过、打回或跳过。
- `POST /api/segments/{sid}/fix`:提交修改意见并重新生成。
- `POST /api/campaigns/{cid}/run-step`:运行下一步。
- `POST /api/campaigns/{cid}/run`:启动完整流水线;支持暂停、取消、恢复。
### 8.3 质检、组合和交付
质检门包括 `structure`、`content`、`style`、`cross`;报告存放在 `QCReport`,空检查列表在启动迁移时自动标记 FAIL。全部段通过后 `POST /api/campaigns/{cid}/compose` 生成 `Artifact`,支持预览和下载。运行期间每次模型调用都关联 `trace_id`、Agent、段、Provider、模型和用量事件。
## 9. Agent Runtime、工具和 AI 调用
Runtime 的系统工具:`knowledge_search`、`read_upstream_anchors`、`read_agent_memory`、`request_handoff`;联网工具 `web_search`、`web_collect` 默认关闭,启用后需人工审批。每个 `AgentSession` 保存消息、工具状态、轮次、阶段和结果,可从检查点恢复;每个运行共享 240 轮模型预算,耗尽即停止并写入事件。
每次调用的记录路径:
```text
AgentSession → RuntimeContext → LLMCall → UsageEvent → PointTransaction(如结算)
↘ RunEvent / Trace / SystemLog
```
模型选择:Agent 可指定 `model_provider_id/model_catalog_id/model_name`,否则跟随 `/api/settings/model-default`。Provider 通过 `/api/providers` 管理,支持连接测试、发现模型、刷新目录和删除;密钥来自配置或本地密钥存储,错误响应经过脱敏处理。
## 10. 日志、追踪、通知和用量
### 10.1 日志
- **AuditLog 操作日志**:记录用户、动作、资源、结果;不记录请求正文、令牌和密钥。典型动作包括登录、建库、上传、建 Agent、改权限、生成任务等。
- **SystemLog 系统日志**:记录 HTTP 失败、应用错误、任务失败、RAG/队列异常和 Trace;错误处理中间件会把具体 `detail` 写入日志。级别支持 `INFO/WARNING/ERROR`,前端可按来源、状态和时间查看。
- **RunEvent/LLMCall**:运行级工具调用、Agent、模型、重试、耗时和失败原因;用于运行记录和 Trace 详情。
接口:`/api/audit-logs`、`/api/system-logs`、`/api/llm_calls`、`/api/traces`、`/api/traces/{trace_id}`。
### 10.2 通知和进度
`Notification` 记录失败、待审查、记忆待确认等提醒;`GET /api/notifications`、`POST /api/notifications/{id}/read`、`POST /api/notifications/read-all` 支持单条和一键已读。生成进度由 `/api/events/progress`(SSE)和 `/api/events/progress-poll`(轮询)提供,前端 `ProgressToast` 显示 AI 工作阶段。
### 10.3 用量和点数
`UsageEvent` 是追加式计量账本,服务类型包括 `llm/embedding/ocr/storage/export/rerank`,具备幂等键、价格版本、输入输出数量和金额分。`PointAccount` 保存余额,`PointTransaction` 保存充值/扣费/调整流水,`UsageQuota` 保存每日/月度 token、金额、存储和并发限制。用户端 `/api/me/usage`、`/api/points/me` 只返回本人;管理员端 `/api/admin/usage/*` 和 `/api/admin/points/*` 可按用户/组织汇总和发放。
## 11. 任务队列、可靠性和恢复
`TaskQueueItem` 提供幂等 `task_key`、租约、重试退避和死信状态。`CampaignRun` 的 `checkpoint`、`pause_requested`、`cancel_requested` 支持服务重启后恢复。后台线程负责运行任务、索引、预热和告警;进程启动会回收未完成的知识消费预留和历史异常质检。
运营接口包括:
- `GET /api/ops/dashboard`:健康指标。
- `POST /api/ops/alerts/sweep`:扫描告警。
- `POST /api/ops/dead-letter/{task_id}/requeue`:死信重放。
- `GET/POST /api/ops/backup`、`POST /api/ops/backup/drill`:备份和恢复演练。
- `GET /api/system/status`、`GET /api/health`:API、RAG、队列等状态检查。
## 12. 管理员资源发布和版本审核
管理员资源页按 Agent、技能、知识库、画布、数字人、记忆分别查看授权。对应接口提供成员 grant、撤销、发布全局和导出。普通用户编辑全局资源时,后端创建 `ResourceRevision(operation=update/delete)` 和必要的 `ResourceFork`;管理员通过 `/api/admin/resource-revisions/{id}/approve` 或 `reject` 审核。审核批准后才改变全局资源版本,个人删除只隐藏自己的视图,不影响其他用户。
## 13. API 分组速查
### 认证与管理
`/auth/status`、`/auth/bootstrap`、`/auth/login`、`/auth/logout`、`/auth/me`、`/auth/users`、`/auth/roles`;管理员资源授权集中在 `/admin/{agents,skills,knowledge-bases,canvases,digital-humans,memories}`。
### Agent、技能、数字人和画布
`/agents`、`/agents/{id}/publish`、`/agents/{id}/fork`、`/skills`、`/skills/import`、`/skills/{id}/agents`、`/digital-humans/*`、`/canvases`、`/canvases/{id}/fork`。
### 知识库和上传
`/kbs`、`/kbs/{id}`、`/kbs/{id}/categories`、`/kbs/{id}/files/*`、`/kbs/{id}/classify`、`/kbs/{id}/search`、`/kbs/search`、`/uploads/init`、`/uploads/{id}/chunk/{index}`、`/uploads/{id}/finish`、`/kbs/{id}/import`、`/kbs/{id}/rebuild`。
### 任务与运行
`/campaigns`、`/campaigns/{id}/parse`、`/campaigns/{id}/reparse`、`/campaigns/{id}/segments/*`、`/campaigns/{id}/run`、`/runs/{id}`、`/agent-sessions/{id}`、`/segments/{id}/review`、`/segments/{id}/fix`、`/campaigns/{id}/compose`、`/artifacts/{id}/preview`。
### 微信
`/wechat/bot/accounts`(列表、连接、更新、绑定 Agent、删除)、`/wechat/bot/accounts/{id}/callback`(sidecar 状态回调)、`/wechat/bot/reply`(签名消息转发)。
## 14. 从用户角度的标准操作链
1. 登录后在“模型管理”确认可用 Provider 和默认模型。
2. 在“知识库”建库,上传文件/目录,等待索引状态为“就绪”;必要时执行去重、分类和预览。
3. 在“Agent 与技能”创建 Agent,选择职责、挂接知识库/分类、技能、模型和数字人,保存并发布。
4. 在“画布编排”用节点和连线编排 Agent;检查每个节点是否有唯一 Agent 和有效知识范围。
5. 在“内容任务”粘贴训练营导图/框架,选择画布和知识范围,创建任务并拆解;若失败使用“重新拆解”。
6. 查看每个内容段的 Agent、知识引用和锚点;可更换 Agent、修改分类、生成、质检、通过/打回/跳过。
7. 全部段通过后组合成稿,在预览页面复核并下载交付。
8. 需要微信服务时,在“数字人 → 微信 Bot 连接”选择已配置 Agent,生成二维码,扫码后确认状态为“已连接”。
9. 在“运行记录、操作日志、系统日志、用量分析”核对执行、错误、模型调用和余额。
## 15. 逐项验收清单
### 账号与权限
- [ ] 非管理员直接访问无权限路由显示明确中文提示,API 返回 403/404 且不泄露资源存在性。
- [ ] 普通用户看不到未授权 Agent、知识库、技能、数字人、记忆和画布。
- [ ] 全局资源个人修改/删除生成个人版本提案,不影响其他用户。
- [ ] 账号删除是永久删除;停用只改变 `enabled`,两者按钮和审计动作不同。
- [ ] 删除有关联资源时可查看依赖,并验证一键解绑事务、历史快照和日志保留。
### 知识库
- [ ] 首次打开知识库不会显示旧库残留或短暂的“不存在”;详情加载有明确状态。
- [ ] 同内容文件和完全重复片段被跳过,导入结果显示跳过数量。
- [ ] 子分类有文件时父分类计数同步;分类树可展开/收起。
- [ ] 普通用户消费记录只包含自己可用的 Agent/片段;管理员可按用户筛选。
- [ ] 预览按钮返回正确文件标题和正文;大文件不阻塞列表首屏。
- [ ] full/quick/reuse 三种检索模式显示估算耗时、进度和失败原因。
### AI 生成与任务
- [ ] 导图先输出框架文本,确认后才能进入内容任务;节点标题/叶子内容无重复。
- [ ] 导图每天按前置关系递进;跳过内容段后,后续段能看到桥接提示。
- [ ] 内容段显示当前 Agent、模型、知识分类和引用来源。
- [ ] 拆解失败、生成失败、AI 修改、图片/OCR/预读均有进度条、重试入口和日志。
- [ ] 质检四道门均产生可追踪报告;空报告自动判为需复检。
- [ ] 运行暂停、取消、恢复后不会重复扣费或重复消费片段。
### 微信 iLink
- [ ] 选择 Agent 后二维码出现;扫码成功后二维码隐藏且列表显示“已连接”。
- [ ] 已连接账号仍显示删除按钮;删除后 sidecar 实例停止、状态回调断开、刷新不复现。
- [ ] 多账号使用不同 storage 目录和账号密钥;账号 A 无法调用账号 B 的 Agent/会话。
- [ ] 绑定 Agent 变更实时同步 sidecar;失效/过期/错误状态能回传并允许重新扫码。
### 可靠性与部署
- [ ] 生产只使用 `data/`(或明确的 `YAWAN_DATA_DIR`),开发只使用 `data-dev/`。
- [ ] 后端、sidecar、隧道守护进程均可单独重启;502/1033 时日志能定位是 API、隧道还是 sidecar。
- [ ] 启动后未完成运行、片段预留和索引状态能正确恢复或标记。
- [ ] 生产构建通过 `npm run build`,前端动态模块版本与静态资源缓存一致。
## 16. 当前限制和风险边界
- SQLite + NullPool 适合单机/中小规模;多实例横向扩展前需要共享数据库、对象存储和队列,不能直接把本地文件目录挂到多个实例。
- iLink sidecar 依赖 Node.js 22 和 `@wechatbot/wechatbot`;官方适配器不可用时只会显示配置/连接错误,不能在浏览器端直接完成协议登录。
- 本地向量和全文索引路径由 `server/app/rag` 管理;若切换 Qdrant 等外部服务,需要同步配置、迁移和故障回退策略,当前代码仍保留本地存储能力。
- AI 输出受模型可用性、点数余额、Runtime 轮次预算和知识索引状态影响;任何“全库阅读”都可能显著增加时间和用量。
- 日志会对密钥、令牌和请求正文脱敏;若需要排查具体模型错误,应使用 Trace ID、Provider 状态和服务端原始日志,而不是把密钥写入前端提示。
## 16.1 性能基线与运行维护
- SQLite 连接统一启用 WAL、`busy_timeout=30000`、`synchronous=NORMAL` 和外键约束,并建立日志、知识库文件/分类/消费、授权、运行事件、队列等复合索引。
- 知识片段消费预留、确认和释放使用批量查询/`executemany`,减少逐片段 SQL 往返和写锁竞争。
- RAG 检索记录校验、Embedding、召回、后处理和总耗时,并保留缓存命中率;缓存键包含知识库版本、范围、模型和检索参数。
- 管理员可调用 `GET /api/ops/performance` 查看最近 512 次 API 的 P50/P95/P99、慢接口、状态分布及 RAG 阶段指标。该指标为进程内基线,重启后重新采样。
- 启动阶段只做必要初始化;知识库文件对账和全文索引预热由后台维护线程执行,避免大库扫描阻塞首屏和健康检查。
- 生产守护脚本使用单实例锁,避免重复守护进程同时启动后端,降低内存争抢和 SQLite 写锁风险。
- 普通 INFO/DEBUG/WARNING 系统日志与 AI 观测日志进入有界批量队列(最多 1000 条、每批 100 条、最长 1 秒刷盘);ERROR、关键审计、计量账本和任务状态仍同步写入。队列丢弃/失败计数可通过性能指标追踪,进程优雅退出会先刷盘。
- 性能指标现在通过匿名指标信封从 RAG 子进程回传 API 进程,包含 SQL 次数、SQL 耗时、锁错误、RAG 各阶段耗时和错误样本,避免把查询正文、令牌或原始路径写入指标。
- 当前任务队列仍是旁路记录,内容生成/导图/上传依赖进程内线程和内存进度总线;外部 Worker 尚未启用。直接启用会造成重复执行和 SSE 进度丢失,必须先完成原子租约认领、持久化进度游标及唯一执行模式切换。
- 2026-09-13 基线(本机冷启动、37 段产品信息库):首次检索约 3.37 秒,其中 Embedding 约 2.93 秒、召回约 0.41 秒;相同查询命中缓存约 6 毫秒。该样本不能代表 9.8 万段以上大库,需在空闲、内容生成和索引运行中分别采样 P50/P95/P99。
- Worker 审计结论:`TaskQueueItem.lease_next` 当前不是原子认领,且内容任务入队后仍由内存线程直接执行;上传、拆解、导图和 SSE 也依赖进程内状态。因此暂不启用内容生成外部 Worker,下一安全阶段仅考虑可幂等的 FTS 预热;迁移前需先完成原子租约、唯一执行模式、持久化进度游标和幂等验收。
- 2026-09-13 Embedding 诊断已细分为模型加载、Tokenizer、Encode 推理、向量后处理/序列化、进程启动和 IPC 残差,并记录来源、数量、模型版本、维度、PID、缓存命中及 Worker 是否复用。管理员性能接口会聚合这些阶段的 P50/P95;`embedding_count` 可识别 quick 检索误做批量向量化。
- 查询向量 LRU 与检索候选池缓存已分离:向量缓存只依赖规范化 query、模型/版本和策略(模型版本代表向量维度契约);候选池缓存包含知识库/分类文件范围、权限签名、索引版本、检索模式和 top-k。知识库版本变化只影响候选池,避免无关地清空查询向量。
- 2026-09-13 热态未命中采样(单库产品信息,15 条不同 query):首条冷启动约 4.17 秒,其中模型加载约 3.06 秒;模型常驻后总耗时 P50 约 15.93ms、P95 约 25.84ms,Embedding P95 约 16.70ms,Encode P95 约 16.59ms,召回 P95 约 4.30ms,`embedding_count=1` 且 15 条均未命中查询缓存。六库联合采样(约 15 万段)首条冷启动约 7.48 秒,热态未命中约 0.66~0.78 秒,主要耗时在多库召回而非 Embedding。
- 查询缓存复测确认:同 query、同 top-k 第二次命中候选池约 17ms;改变 top-k 后候选池重新计算约 45ms,但查询向量缓存命中、Embedding 耗时约 0ms。缓存键已修复首次维度从未知切换到 512 导致的伪未命中问题。
- 2026-09-13 六库召回稳定性优化:召回线程池改为进程内固定 4 个 Worker,避免每次请求创建线程并限制高并发时的磁盘争用;只读 FTS 索引使用带 inode/版本校验的共享连接、页缓存和 mmap,索引原子替换后自动重连。新增 `fts_connection_reused` 指标,用于区分连接复用与索引自身耗时。
- 2026-09-13 六库热态未命中复测(生产 6 库):Embedding 已常驻后约 14~129ms,召回约 0.64~0.91 秒;瓶颈集中在心法、情欲内容的大型 FTS 索引(约 461MB/862MB)和对应向量 I/O,模型加载不再是稳态瓶颈。后续优先做大库索引体积与查询词规模优化,暂不切换模型或向量数据库。
- 2026-09-13 向量查询进一步优化:移除检索热路径上的 `collection.count()`。该调用在外置盘冷读时,108135 段库约 1.7 秒,而实际向量查询约 20ms;Chroma/Qdrant 对空集合均直接返回空结果,因此无需先 count。检索指标现在只记录 collection、filter、vector 三段真实 I/O。
- 2026-09-13 空闲态 10 条不同 query 只读采样:P50 约 556ms,P95 约 1.25s;首条冷启动约 6.43s,后续 Embedding 约 6~345ms。4 路并发只读采样全部完成,未再出现 `database is locked`;高并发仍受单个常驻 RAG Worker 的队列容量限制,继续保持单 Worker 以控制内存峰值。
- 2026-09-13 稳定性修复:Embedding 用量事件改为独立短事务提交,计量写入失败只记录告警,不再让知识库检索失败;避免内容任务并发时主业务事务与用量写入互相持有 SQLite 写锁。
- 计量短事务设置 500ms 忙等待上限;数据库暂时繁忙时只丢弃本次非关键计量并保留检索结果,避免用户看到 30 秒级假性超时。
## 17. 检查记录模板
| 检查日期 | 环境(dev/prod) | 页面/API | 操作步骤 | 预期 | 实际 | Trace/截图 | 结论 |
|---|---|---|---|---|---|---|---|
| | | | | | | | |
维护此文档时,应以代码中的模型字段、路由和权限 key 为准;新增功能同时补充“功能地图、数据模型、API、权限、验收清单”五个位置。