Files

905 lines
50 KiB
Markdown
Raw Permalink Normal View History

# 雅文内容创造工作台 · v6 用户端、管理端与云化设计
> 文档日期:2026-08-27
> 文档状态:v6 设计 + v6.1 提示模板实现同步
> 关联文档:[设计文档 v5](./设计文档v5-系统设计.md)
> 核心逻辑:[核心逻辑设计文档 v6](./核心逻辑设计文档v6.md)
> 从零落地:[核心逻辑设计文档 v6:从 0 到 1](./核心逻辑设计文档v6-从0到1.md)
> 本文只修改设计文档,不代表本轮已经修改源码
## 0. 这次要解决什么
当前 v5 已经具备本地 Agent Runtime、知识库、任务编排、认证、Trace 和 KB3 稳定索引。本 v6 设计在此基础上增加六个企业化能力:
1. 面向普通用户的用户端,以及面向运营人员的管理端。
2. 按用户统计 AI 调用量、Token、Embedding、OCR 和存储量,并形成可审计的计费账单。
3. 所有源文件、向量快照、产物和导出包迁移到云对象存储。
4. 增加全局知识库、私有知识库和管理员授权共享机制。
5. 模型连接、模型发现和模型费率全部收敛到管理端,用户端只选择已开放模型。
6. 记忆库复用知识库的私有、共享、全局、授权、撤销、导出和审计逻辑。
本版本的关键原则是:**所有权与使用权分离、全局资源与私有资源隔离、计费以真实调用账本为准、管理端可见但不能绕过审计**。
## 1. 产品形态
### 1.1 用户端
普通用户只看到自己的工作空间,以及管理员授权给他的资源:
- 我的任务:创建任务、运行 Agent、查看进度、审查内容和下载成稿。
- 我的 Agent:创建和维护自己的生产 Agent、技能绑定和规则。
- 我的知识库:上传、分类、预览、检索和删除自己的私有素材。
- 全局知识库:读取管理员开放的公共资料;不能删除和修改原文。
- 共享知识库:管理员明确授予当前用户后才显示。
- 记忆库:管理自己的记忆,以及管理员授予的共享/全局记忆。
- 模型选择:只能从管理端已接入并开放的模型目录中选择,不能添加 Provider、API Key 或模型。
- 用量与账单:查看本月 AI 用量、余额/额度、调用明细和导出记录。
- 我的记忆:只管理自己的私有记忆,不能读取其他用户未授权的记忆。
### 1.2 管理端
管理员使用独立的管理端导航,不与用户端混在同一组页面里:
- 用户与组织:账号、状态、角色、所属组织和配额。
- 全局知识库:创建和维护所有用户可用的公共知识。
- 知识库总览:查看全部用户私有知识库的元数据、容量、索引状态和归属。
- 授权中心:把某个私有知识库授权给指定用户,或开放给全部用户。
- 记忆库总览:查看全部用户记忆、来源 Agent、可见性、使用者和版本。
- 模型目录:接入 Provider、维护模型列表、费率、能力、启用状态和用户可见范围。
- AI 用量与计费:按用户、Provider、模型、时间和任务查看用量与费用。
- 云存储与导出:导出数据库、知识库文件、向量索引、Trace 和账单。
- 安全审计:查看登录、权限变更、知识库授权、导出和计费调整记录。
管理端可以“看见”用户私有知识库的元数据和内容预览,但所有查看、下载、导出行为都要写入审计日志;默认不改变文件归属和内容。
## 2. 总体架构变化
```mermaid
flowchart LR
U[普通用户端] --> G[统一 API 网关]
A[管理端] --> G
G --> IAM[身份、组织与 RBAC]
G --> TENANT[租户与资源授权]
G --> ORCH[Agent Runtime / 任务编排]
G --> BILL[用量计量与计费]
G --> KB[RAG 知识库服务]
G --> EXP[导出任务服务]
IAM --> DB[(关系数据库)]
TENANT --> DB
BILL --> DB
ORCH --> DB
KB --> META[知识库元数据]
KB --> OBJ[云对象存储]
KB --> VEC[云向量存储或本地加速索引]
EXP --> OBJ
ORCH --> LLM[模型 Provider]
ORCH --> BILL
A --> AUDIT[审计日志]
U --> AUDIT
```
### 2.1 资源边界
每个请求先解析出三个边界:
| 边界 | 作用 |
| --- | --- |
| `organization_id` | 组织或租户隔离,决定用户属于哪个企业空间 |
| `owner_user_id` | 私有资源的所有者,决定默认可见范围 |
| `visibility` | `private`、`shared`、`global` 三种知识库可见性 |
管理员权限是跨用户的管理权限,不会把私有知识库自动变成公共知识库。只有执行“授权共享”或“设为全局”操作后,资源的使用范围才改变。
## 3. 用户、组织与角色设计
### 3.1 账号层级
```text
Organization
└── UserAccount
├── UserRoleBinding
├── UsageQuota
├── BillingAccount
├── KnowledgeBase(私有)
├── Agent
└── Memory
```
同一个用户只能在当前组织范围内使用组织资源。未来需要跨组织时,使用组织成员关系授权,不直接复用另一组织的用户 ID。
### 3.2 角色
| 角色 | 用户端能力 | 管理端能力 |
| --- | --- | --- |
| `user` | 使用自己的 Agent、私有库、获授权的共享库和全局库 | 无 |
| `reviewer` | 额外执行内容审查、查看审查 Trace | 无用户管理能力 |
| `operator` | 使用用户端全部功能 | 查看用户、处理导出、处理索引和授权申请 |
| `admin` | 使用全部用户端功能 | 用户、知识库、权限、计费、云存储和审计全管理 |
| `owner` | 组织内全部功能 | 当前组织最高权限,不跨组织 |
管理员接口和用户接口使用不同的权限前缀:
```text
user:read 用户读取自己的资源
user:write 用户修改自己的资源
admin:users 管理用户与角色
admin:kb 管理所有知识库和授权
admin:memory 管理所有记忆和授权
admin:models 管理 Provider、模型目录和模型授权
admin:billing 查看和调整计费规则
admin:export 创建和下载全量导出
admin:audit 查看审计日志
```
### 3.3 模型配置权限边界
模型连接属于管理端资源,用户端只消费“可用模型目录”,不接触 Provider 凭据:
| 操作 | 用户端 | 管理端 |
| --- | --- | --- |
| 新增/修改/删除 Provider | 禁止 | 允许 |
| 填写或查看 API Key | 禁止 | 允许,界面只显示脱敏摘要 |
| 从 Provider 发现模型 | 禁止 | 允许 |
| 启用/停用模型 | 禁止 | 允许 |
| 修改模型费率和能力标签 | 禁止 | 允许 |
| 给 Agent 选择模型 | 允许,在可用目录内选择 | 允许全部模型 |
| 直接输入任意模型名称 | 禁止 | 可作为受控维护动作 |
用户创建或编辑 Agent 时,模型字段只能引用 `ModelCatalog` 中状态为 `enabled` 且对当前组织可见的记录。用户端不显示 Provider 管理入口,也不接受 `base_url`、`api_key` 或任意自定义模型名。管理员停用模型后,历史任务继续使用已冻结的运行快照,新任务不能再选择该模型。
## 4. 知识库可见性与授权模型
### 4.1 三类知识库
| 类型 | 创建者 | 默认使用者 | 修改者 |
| --- | --- | --- | --- |
| 私有知识库 `private` | 普通用户或管理员代建 | 仅所有者 | 所有者;管理员可代维护 |
| 共享知识库 `shared` | 普通用户或管理员 | 被授权用户列表 | 所有者和管理员 |
| 全局知识库 `global` | 管理员 | 当前组织全部用户 | 管理员 |
用户自己上传的知识库默认是 `private`。管理员可以执行两种授权动作:
1. 授权给指定用户:保持私有归属不变,增加可使用者。
2. 开放给全部用户:将可见性改为 `global`,所有用户可以检索,但只有管理员可以修改原文。
取消授权只影响后续检索,不删除原文件、不改变历史任务的引用快照。
### 4.2 访问判定顺序
```mermaid
flowchart TD
R[收到知识库读取请求] --> S{账号已启用?}
S -- 否 --> X[返回 401/403]
S -- 是 --> M{管理员管理动作?}
M -- 是 --> L[允许管理范围内读取并记录审计]
M -- 否 --> O{当前用户是所有者?}
O -- 是 --> L2[允许读写私有库]
O -- 否 --> G{visibility = global?}
G -- 是 --> L3[允许只读检索]
G -- 否 --> P{存在有效授权记录?}
P -- 是 --> L4[允许按授权范围读取]
P -- 否 --> D[拒绝访问]
```
检索服务必须在数据库层先得到“允许查询的知识库 ID 列表”,再调用向量搜索;不能先搜索全库后在结果层过滤。
### 4.3 授权记录
建议新增 `KnowledgeBaseGrant`:
| 字段 | 含义 |
| --- | --- |
| `id` | 授权记录 ID |
| `kb_id` | 知识库 ID |
| `grantee_user_id` | 被授权用户;全员开放时为空 |
| `grantee_organization_id` | 被授权组织 |
| `permission` | `read`、`use`、`manage` |
| `status` | `active`、`revoked`、`expired` |
| `granted_by` | 执行授权的管理员 |
| `expires_at` | 可选到期时间 |
| `created_at`、`revoked_at` | 生命周期时间 |
`use` 允许 Agent 检索并消费 chunk,`read` 只允许人工浏览,`manage` 允许分类、重建和文件维护。普通用户不能给自己追加授权,也不能把私有库开放给全部用户。
### 4.4 记忆库与画布组合授权
记忆库保留知识库的所有权和可见性字段,但运行时授权根改为 Agent 画布。用户创建的 Agent 记忆默认是 `private`;管理员授权某个画布后,画布节点 Agent 的知识库和确认记忆一起获得查看/运行范围,不再要求为同一流程重复授权记忆。
| 记忆范围 | 默认可见者 | 用户端行为 | 管理端行为 |
| --- | --- | --- | --- |
| 私有记忆 `private` | 所有者及其 Agent | 查看、编辑、删除、绑定自己的 Agent | 可查看、导出、代维护,所有行为审计 |
| 共享记忆 `shared` | 画布授权用户 | 读取并在授权画布中使用 | 通过画布授权、撤销、修改可使用者 |
| 全局记忆 `global` | 当前组织全部用户 | 只读使用,不修改原文 | 创建、编辑、版本管理和下架 |
记忆的访问判定顺序为:管理员管理动作 → 所有者 → 全局 → 有效画布授权 → 兼容的历史 `MemoryGrant` → 拒绝。用户端的记忆检索必须先得到允许访问的记忆 ID 集合,再注入 Agent Runtime,不能先读取全量记忆后在前端过滤。
画布授权使用 `read`、`use`、`manage`、`export` 四种权限;画布对依赖知识和记忆的继承只覆盖查看和使用,不放大编辑、删除、导出权限。旧 `MemoryGrant` 仅用于迁移兼容,管理端新界面不再创建单独记忆授权。撤销画布授权只影响后续运行;已经创建的任务仍保留其运行快照和引用来源。
建议新增 `MemoryGrant`,字段结构与 `KnowledgeBaseGrant` 一致,并在 `Memory` 增加:
```text
owner_user_id
organization_id
visibility: private | shared | global
source_agent_id
version
```
管理员查看或导出其他用户记忆时必须写入 `AccessAudit`,用户不能通过修改 Agent ID 绕过记忆归属校验。
## 5. 模型目录与选择
### 5.1 管理端模型目录
Provider 的 API Key、Base URL 和模型发现全部由管理端维护。管理端将发现结果规范化为 `ModelCatalog`,用户只看到安全的展示字段:
| 字段 | 说明 |
| --- | --- |
| `id` | 稳定的模型目录 ID |
| `provider_id` | 所属 Provider |
| `model_name` | Provider 上的真实模型名 |
| `display_name` | 用户端展示名 |
| `capabilities` | 文本、工具调用、视觉、长上下文等能力 |
| `enabled` | 是否允许新任务选择 |
| `visibility` | `global`、组织范围或管理员专用 |
| `pricing_version` | 当前计费费率版本 |
管理员添加 Provider 后,可以点击“发现模型”获取列表,再逐个启用或停用。发现失败只影响目录刷新,不暴露 API Key 和 Provider 错误细节给普通用户。
### 5.2 用户端模型选择
用户端 Agent 表单只请求:
```text
GET /api/models/available
```
返回当前用户所在组织可用的模型目录。用户选择的是目录 ID,不是 Provider 地址或自由文本;保存 Agent 时服务端再次校验目录状态和组织可见性。
模型目录变更不覆盖历史任务快照:
1. 任务创建时保存 Provider、模型名、能力和费率版本。
2. 管理员停用模型后,旧 Run 可以继续恢复或审计。
3. 新建任务和重跑任务只能选择当前启用模型。
4. 账单使用快照中的费率版本,不按当前目录价格回算历史费用。
### 5.3 模型相关审计
以下管理动作写入审计:Provider 新增/删除、API Key 替换、模型启停、费率变更、组织可见范围变更。用户只能看到自己的模型选择记录和调用账单,不能看到其他 Provider 的密钥、内部地址和组织费率策略。
### 5.4 多用户并发治理
多个用户同时使用同一个模型不会共享错上下文,原因是每次调用都绑定完整的归属键:
```text
organization_id + user_id + campaign_id + run_id + trace_id + span_id
```
运行时不把消息历史放在 Provider 或全局内存中;每个 Agent Session 独立保存自己的消息、工具状态和配置快照。模型请求发送前由服务端按当前 Session 组装消息,返回后再按同一 `run_id/trace_id` 写入调用账本。
并发控制分为四层:
| 层级 | 控制内容 | 目的 |
| --- | --- | --- |
| 用户级 | 并发 Run 数、Token 日/月额度 | 防止单个用户占满资源 |
| 组织级 | 总并发、总 Token、预算上限 | 防止一个组织影响其他组织 |
| 模型级 | Provider QPS、并发连接、超时和重试 | 遵守模型服务限制 |
| 任务级 | 同一 Campaign 只允许一个活跃 Run | 防止重复计费和结果覆盖 |
请求进入后先经过配额检查,再进入带组织和模型键的队列。队列状态、限流等待、重试和失败都会写入 Trace;因此“等待”不会被误认为“模型混乱”。
模型目录必须使用版本化和软停用:
1. 同一个 Provider 的模型名称变化时创建新的目录版本,不覆盖旧记录。
2. 管理员停用只禁止新任务,不删除历史目录和账单费率。
3. Provider 临时故障时只影响绑定该 Provider 的队列,其他模型继续运行。
4. 用量账本使用调用发起用户归属,不使用最后一个修改 Agent 的用户归属。
因此,多个用户可以同时选择同一模型;他们的上下文、权限、配额、Trace 和账单分别隔离。真正需要避免的是“共享消息历史、按名称动态解析模型、无用户归属的用量记录”,这些在本设计中全部禁止。
### 5.5 成人内容能力兼容性测试
用户所说的“破限”在系统中落地为**管理员可执行、可回归、可审计的成人内容能力兼容性测试**。测试记录模型在指定内容类型上的真实表现,不把测试结果伪装成模型能力,也不把某个 Provider 的策略状态传播给其他 Provider。
测试分为四个维度:
| 维度 | 测试内容 | 结果示例 |
| --- | --- | --- |
| 成人内容生成 | 合规的成人向文本、角色设定和情节续写样例 | `supported`、`provider_blocked`、`partial` |
| 中文表达 | 大白话、段落样式、连续口语和上下文衔接 | `pass`、`format_mismatch` |
| Agent 结构 | 锚点卡、工具调用、JSON 结构和多轮恢复 | `pass`、`schema_failed` |
| 稳定性 | 超时、限流、空输出、长度和重复调用 | `stable`、`timeout`、`rate_limited` |
测试套件使用版本号和固定样例集,例如 `adult-content-compat-v1`。样例内容存放在管理员控制的测试集内,测试结果只保存哈希、分类、状态、模型版本、Provider、Token、耗时和 Trace,不把测试样例全文写入普通用户日志。
管理端可以单个测试、批量测试或按计划回归:
1. 选择一个或多个已接入模型。
2. 选择测试套件和生成参数,冻结测试输入、温度、最大输出长度和超时。
3. 并行调用模型,记录每个样例的状态、输出哈希和断言结果。
4. 计算通过率、成人内容兼容等级、稳定性和平均费用。
5. 更新 `ModelCatalog` 的能力状态;只有达到管理员设定阈值的模型才显示为“可用于成人内容”。
6. 测试结束后生成 Trace 和报告,支持与上一个模型版本做回归对比。
Provider 侧的内容策略仍然会影响结果;出现 `provider_blocked` 时,目录应标记为“该 Provider 当前不支持此能力”,而不是把模型标记为已兼容。系统通过管理员选择其他已接入模型或调整路由来满足业务要求,测试结果不覆盖 Provider 的服务策略。
模型目录增加以下字段:
```text
content_capability: general | adult_supported | adult_partial | adult_unavailable
capability_test_version
capability_tested_at
capability_score
capability_status
```
生产任务在创建时声明内容能力需求。运行时只从满足需求且对当前组织可见的目录中选择;任务开始后把能力结果和费率一起写入快照。管理员更新测试结果不会改变已运行任务,后续新任务和重跑任务使用最新目录状态。
这种设计避免了多用户场景下的三个混乱来源:用户自己上传“解除限制”提示词、模型名称相同但 Provider 不同、模型更新后旧任务被新能力覆盖。
### 5.6 公开资料检索结论与采用方式
2026-08-26 对 Linux.do `/latest` 及其公开主题进行检索。`/latest` 本身只是主题索引页,没有一套可直接复现的模型能力规范;相关主题中的用户反馈显示,同一个模型在不同 Provider、中转层、账号和版本下表现可能不同,外置审查和版本更新也会让之前的测试结果失效。这些属于社区观察,作为线索而不是生产结论:
- [关于破限/破甲的疑问](https://linux.do/t/topic/2512323):讨论了模型本体偏好与模型前置拦截层的差异。
- [破限词仓库没了,谁还有备份的](https://linux.do/t/topic/2504365):反映提示词仓库和测试结果存在时效性,且不同接入方式结果不同。
- [更新了破限工具的 ZCode 版本](https://linux.do/t/topic/2524019):提到成人向创作在不同模型上的结果差异,并指出本地部署模型更容易保持可控测试环境。
- [关于成人内容模型的公开讨论](https://linux.do/t/topic/1680571):显示社区通常按模型和接入渠道分别试用,而不是假设存在一个适用于全部 Provider 的固定方案。
系统据此采用以下工程结论:
1. 不把“破限成功”作为永久能力,而是把它记录为“某 Provider + 某模型版本 + 某测试套件”的一次测试结果。
2. 同一个目录模型至少测试直连 Provider 和实际中转/网关两条路径,区分模型行为与前置审查层行为。
3. 每次模型版本、Provider 路由、系统提示词或外置审查配置变化,都触发 `adult-content-compat` 回归;旧结果保留,新结果生成新版本。
4. 失败结果必须区分 `provider_blocked`、`gateway_blocked`、`model_refused`、`timeout`、`format_failed`,不能用一个“破限失败”状态掩盖根因。
5. 只有管理员可以查看原始测试输出和发布能力标签;用户端只看到已发布的能力等级和最后测试时间。
测试实现可采用 Promptfoo 的 Provider × Test Case × Assertion 矩阵,也可用 Garak 的 Probe/Detector 机制做回归探测;两者都应在工作台内部保存输入哈希、断言、通过率和 Trace,而不是直接把第三方工具输出当作生产路由结论。
## 6. 云存储设计
### 6.1 存储职责
云对象存储保存大文件和可导出产物,关系数据库只保存元数据、权限、哈希和生命周期状态。
| 数据 | 存储位置 | 数据库记录 |
| --- | --- | --- |
| 原始上传文件 | 对象存储 | `CloudObject` + `KnowledgeFile` |
| 解析后的文本快照 | 对象存储 | 文件哈希和版本 |
| 向量索引快照 | 对象存储或托管向量库 | 索引版本和校验值 |
| Markdown/DOCX 成稿 | 对象存储 | `Artifact` 的对象键和哈希 |
| Trace 导出包 | 对象存储 | `ExportJob` |
| 账单导出 | 对象存储 | `BillingExport` |
### 6.2 对象键规范
对象键不使用用户原始文件名作为唯一标识,避免重名覆盖:
```text
org/{organization_id}/users/{user_id}/kb/{kb_id}/files/{sha256}-{safe_name}
org/{organization_id}/users/{user_id}/kb/{kb_id}/index/{index_version}.json
org/{organization_id}/campaigns/{campaign_id}/artifacts/{artifact_id}.docx
org/{organization_id}/exports/{export_job_id}/{part_name}
```
写入流程:上传临时对象 → 计算 SHA-256 → 写入数据库元数据 → 原子切换当前版本 → 删除过期临时对象。数据库提交失败时不把对象标记为当前版本;对象清理任务按状态和保留期回收孤儿文件。
### 6.3 下载与导出
- 用户下载自己的文件或有权访问的全局/共享文件。
- 管理员导出全部或指定用户数据,但必须选择范围、原因和保留期。
- API 返回短时效签名地址,不把云存储长期密钥下发到浏览器。
- 导出任务异步执行,页面显示排队、打包、上传、完成和失败状态。
- 导出包包含 `manifest.json`,列出文件、哈希、归属、分类、权限和创建时间。
## 7. AI 使用量计费
### 7.1 计量对象
每一次 AI 行为都生成一条不可变用量事件:
| 计量项 | 来源 | 计费单位 |
| --- | --- | --- |
| LLM 输入 | `LLMCall.prompt_tokens` | 百万 Token |
| LLM 输出 | `LLMCall.completion_tokens` | 百万 Token |
| Embedding | RAG 导入和查询 | 千 Token 或向量次数 |
| OCR | 导图图片 OCR | 页数/图片数 |
| 重排 | 可选 Rerank Provider | 次数或 Token |
| 云存储 | 对象存储统计 | GB·月 |
| 导出 | 导出任务 | GB 或次数 |
每条计量事件携带 `user_id`、`organization_id`、`campaign_id`、`run_id`、`trace_id`、Provider、模型、数量、费率版本和幂等键。管理员修改费率不会回写历史事件。
### 7.2 费用公式
```text
llm_fee = prompt_tokens / 1,000,000 * prompt_rate
+ completion_tokens / 1,000,000 * completion_rate
embedding_fee = embedding_tokens / 1,000 * embedding_rate
ocr_fee = image_count * ocr_rate
storage_fee = gb_month * storage_rate
total_fee = llm_fee + embedding_fee + ocr_fee + storage_fee + export_fee
```
最终金额按费率版本保存,不从当前 Provider 配置实时反算。内部计费精度使用整数最小货币单位,界面再格式化为元。
### 7.3 用量账本
建议新增:
- `UsageEvent`:单次 AI 行为原始计量,追加写入,不允许普通用户修改。
- `UsageRate`:Provider/模型/服务类型的费率和生效时间。
- `BillingAccount`:用户或组织余额、额度、冻结和状态。
- `UsageSettlement`:按日/月汇总的结算结果。
- `BillingAdjustment`:管理员手工调账,必须填写原因并关联审计事件。
- `UsageQuota`:日/月 Token、存储、并发和导出限制。
### 7.4 计费时序
```mermaid
sequenceDiagram
participant User as 用户
participant Runtime as Agent Runtime
participant LLM as Provider
participant Meter as 用量计量
participant Bill as 账单服务
participant Admin as 管理端
User->>Runtime: 发起任务
Runtime->>LLM: 模型请求
LLM-->>Runtime: 输出与 Token 统计
Runtime->>Meter: 写入不可变 UsageEvent
Meter->>Bill: 按费率计算预估费用
Bill-->>User: 更新用量与额度
Admin->>Bill: 查询、导出或调整账单
Bill-->>Admin: 汇总、明细和审计记录
```
在 Provider 没有返回 Token 时,系统可以使用本地 tokenizer 做“估算”标记,但不能把估算值伪装成计费确认值。账单中区分 `measured`、`estimated`、`settled` 三种状态。
### 7.5 超额策略
用户达到配额后按组织策略处理:
- `warn`:继续执行,仅提示超额。
- `soft_limit`:允许当前任务完成,禁止新任务排队。
- `hard_limit`:暂停新的 LLM、Embedding 和 OCR 请求。
已经进入运行中的任务根据 Run 策略完成或取消,取消动作必须写入 Trace 和账单状态。
## 8. 数据模型扩展
### 8.1 账号与组织
建议在现有 `AppUser` 之上增加:
| 表 | 关键字段 | 说明 |
| --- | --- | --- |
| `Organization` | `id`、`name`、`status`、`plan_id` | 企业或个人工作区 |
| `UserAccount` | `user_id`、`organization_id`、`status` | 用户与组织关系 |
| `UserRoleBinding` | `user_id`、`role`、`scope` | 角色和作用域 |
| `BillingPlan` | `id`、`name`、`quota`、`rates` | 套餐和配额 |
| `UsageQuota` | `user_id`、`period`、`limits`、`used` | 用户用量限制 |
### 8.2 知识库与云对象
建议扩展现有 `KnowledgeBase`:
```text
owner_user_id
organization_id
visibility: private | shared | global
storage_provider
storage_prefix
index_version
source_bytes
retention_policy
```
新增:
| 表 | 作用 |
| --- | --- |
| `KnowledgeBaseGrant` | 用户/组织授权关系 |
| `CloudObject` | 对象键、版本、哈希、大小、存储类和删除状态 |
| `ExportJob` | 导出范围、发起人、进度、对象键和过期时间 |
| `AccessAudit` | 查看、下载、授权、撤销和导出行为 |
### 8.3 模型目录与记忆库
新增模型目录表 `ModelCatalog`,由管理端维护,用户端只引用目录 ID:
| 表 | 关键字段 | 说明 |
| --- | --- | --- |
| `ModelCatalog` | `provider_id`、`model_name`、`capabilities`、`enabled`、`visibility`、`pricing_version` | 管理端接入并开放给用户选择的模型 |
| `ModelOrganizationGrant` | `model_id`、`organization_id`、`status` | 可选的组织级模型授权 |
| `ModelCapabilityTest` | `model_id`、`suite_version`、`status`、`score`、`trace_id` | 管理端模型能力兼容性测试结果 |
| `ModelCapabilityCase` | `test_id`、`case_hash`、`dimension`、`assertions`、`result` | 单个测试样例的可审计断言结果 |
| `MemoryGrant` | `memory_id`、`grantee_user_id`、`permission`、`status` | 记忆库共享/全局授权 |
现有 `Memory` 增加 `owner_user_id`、`organization_id`、`visibility`、`source_agent_id` 和 `version`。用户端只能维护自己的私有记忆;共享和全局记忆由授权判定服务控制,规则与 `KnowledgeBaseGrant` 相同。
### 8.4 任务与账单关联
现有 `LLMCall` 已经有 `run_id`、`campaign_id`、`agent_id`、`trace_id`、Token 和耗时字段。v6 只需补充:
```text
organization_id
user_id
usage_event_id
billing_status
```
这样一次账单可以回溯到模型调用、Agent、内容段、任务和最终产物。
## 9. 用户端页面设计
### 9.1 首页总览
首屏显示四个指标:
- 本月已用 Token / 剩余额度。
- 本月预估费用 / 已结算费用。
- 私有知识库数量和存储占用。
- 当前运行任务和待审查数量。
顶部显示当前组织和账号,不显示其他用户的名称、用量或私有资源。
### 9.2 知识库页面
页面分为三个 Tab:
1. 我的知识库:上传、分类、预览、重建、删除。
2. 已授权知识库:只显示管理员授予当前用户的库。
3. 全局知识库:只读浏览和检索,显示来源与版本。
每个知识库卡片显示:可见性、所有者、授权状态、文件数、分块数、索引状态、容量和最近更新时间。用户不能在列表中看到未授权私有库。
### 9.3 用量与账单页面
提供时间筛选、任务筛选、模型筛选和导出按钮:
- 用量趋势:输入 Token、输出 Token、Embedding、OCR、存储。
- 调用明细:时间、Agent、模型、Trace、数量、状态、费用。
- 配额状态:当前值、上限、预警线。
- 账单导出:生成当前用户可见范围的 CSV/JSON 包。
### 9.4 模型与记忆页面
- 模型选择器只展示 `/api/models/available` 返回的启用模型;不显示 Provider API Key、Base URL 和发现按钮。
- 用户不能新增、编辑或删除模型,也不能输入任意模型名称;表单保存时服务端再次校验目录 ID。
- 用户在模型卡片上只看到管理员确认的能力标签,例如“支持成人内容”“部分支持”或“当前不可用”,不能自行修改该标签。
- 记忆库页面分为“我的记忆”“已授权记忆”“全局记忆”三个范围,支持查看、确认、停用和删除当前用户有权限管理的条目。
- 共享/全局记忆显示所有者、版本、来源 Agent 和授权状态,但用户不能修改原文。
## 10. 管理端页面设计
### 10.1 用户与组织
管理员可以:
- 创建、停用、重置和删除用户。
- 设置角色、组织、套餐、配额和并发限制。
- 查看用户最近登录、任务数、知识库数量和本月用量摘要。
- 强制撤销用户全部 Session。
### 10.2 知识库总览与授权中心
管理端表格显示:
```text
知识库名称 | 所有者 | 类型 | 文件数 | 容量 | 索引状态 | 使用者数 | 最近访问 | 操作
```
操作包括:查看、导出、分类维护、重建索引、授权指定用户、开放全局、撤销授权。任何“开放全局”操作都要二次确认,并记录变更前后的可见性。
### 10.3 记忆库总览与授权中心
管理员可以按用户、Agent、组织、可见性和状态查看全部记忆,并执行:
- 查看、预览和导出用户私有记忆。
- 授权指定用户使用某条记忆或某组记忆。
- 将记忆发布为组织全局记忆,或恢复为私有/共享状态。
- 修改版本、停用过期记忆、撤销授权和恢复授权。
管理员的查看、下载、导出和授权动作都写入 `AccessAudit`;撤销授权只影响新建任务,历史任务继续保留运行快照。
### 10.4 模型目录管理
管理员在模型目录页面完成 Provider 和模型生命周期管理:
1. 新增 Provider 并安全保存 API Key。
2. 调用 Provider 的模型发现接口。
3. 逐个启用/停用模型,设置能力标签和费率版本。
4. 按组织开放模型;用户端只读显示可用目录。
5. 查看模型调用量、错误率、Token 和费用。
6. 运行成人内容能力兼容性测试,查看版本间的通过率、拒绝率、超时率和成本变化。
7. 仅在测试结果达到阈值后,发布或下架模型的“支持成人内容”能力标签。
### 10.5 计费管理
管理员可以设置 Provider/模型费率、套餐配额、预警阈值和超额策略;可以按用户、组织、任务和 Trace 查询费用,并对异常账单执行带原因的调账。
计费页面区分:
- 原始用量。
- 费率版本。
- 预估金额。
- 已结算金额。
- 管理员调整金额。
## 11. API 设计
### 11.1 用户端 API
```text
GET /api/me/usage
GET /api/me/billing
GET /api/me/exports
POST /api/me/exports
GET /api/models/available
GET /api/kbs?scope=mine|granted|global
GET /api/kbs/{id}/access
POST /api/kbs/{id}/import
GET /api/kbs/{id}/search
GET /api/kbs/{id}/files/{filename}
GET /api/memories?scope=mine|granted|global
POST /api/memories/{id}/decide
PUT /api/memories/{id}
DELETE /api/memories/{id}
```
接口返回结果必须经过当前用户可见范围过滤;`scope=mine` 不能返回管理员代建但归属其他用户的私有库。
`GET /api/models/available` 是用户端唯一的模型目录入口,只返回管理员已启用且当前组织可见的模型。用户端不开放 Provider CRUD、模型发现、费率修改和 API Key 相关接口。
### 11.2 管理端 API
```text
GET /api/admin/organizations
GET /api/admin/users
POST /api/admin/users/{id}/revoke-sessions
PUT /api/admin/users/{id}/quota
GET /api/admin/knowledge-bases
POST /api/admin/knowledge-bases/{id}/grants
DELETE /api/admin/knowledge-bases/{id}/grants/{grant_id}
POST /api/admin/knowledge-bases/{id}/publish-global
POST /api/admin/knowledge-bases/{id}/export
GET /api/admin/memories
POST /api/admin/memories/{id}/publish-global
GET /api/admin/canvases
POST /api/admin/canvases/{id}/grants
DELETE /api/admin/canvases/{id}/grants/{grant_id}
POST /api/admin/canvases/{id}/publish-global
GET /api/admin/knowledge-bases/{id}/export
GET /api/admin/canvases/{id}/export
GET /api/admin/memories/{id}/export
GET /api/admin/model-providers
POST /api/admin/model-providers
PUT /api/admin/model-providers/{id}
DELETE /api/admin/model-providers/{id}
POST /api/admin/model-providers/{id}/discover
GET /api/admin/models
PUT /api/admin/models/{id}
POST /api/admin/models/{id}/organization-grants
POST /api/admin/models/{id}/capability-tests
GET /api/admin/models/{id}/capability-tests
POST /api/admin/models/{id}/capability-tests/{test_id}/publish
GET /api/admin/usage
GET /api/admin/billing/settlements
POST /api/admin/billing/adjustments
GET /api/admin/audit
```
管理端模型接口和画布授权接口只允许管理员权限;记忆的用户使用范围由 `CanvasGrant` 继承计算。普通用户即使知道管理端路径,也只能得到 `403`,不会得到 Provider 配置或其他用户的管理数据。
能力测试接口只接受管理端预置的测试套件 ID,拒绝由普通用户或前端传入任意“破限提示词”。测试执行和发布结果写入 Trace、`ModelCapabilityTest` 与审计日志。
### 11.3 响应和错误
| 状态码 | 场景 |
| --- | --- |
| `401` | 未登录或 Session 过期 |
| `403` | 已登录但没有用户/管理端权限,或没有知识库授权 |
| `404` | 资源不存在,或为了防止枚举而隐藏未授权资源 |
| `409` | 重复授权、重复结算或并发修改冲突 |
| `422` | 计费、导出或存储参数不合法 |
| `429` | 用户或组织达到并发/调用限额 |
| `503` | 云存储、Embedding 或 Provider 暂时不可用 |
## 12. 数据安全与审计
### 12.1 最小权限
- 用户检索只在“所有者 + 有效授权 + 全局库”集合中执行。
- 管理员查看私有库内容需要 `admin:kb`,下载/导出还需要 `admin:export`。
- 用户端只能读取自己可用的 `ModelCatalog`,模型 Provider 和费率只对 `admin:models` 开放。
- 用户记忆只在“所有者 + 有效画布授权 + 全局记忆”集合中注入 Agent Runtime;旧 `MemoryGrant` 仅作为迁移兼容。
- 计费明细按用户和组织隔离;普通用户不能查看其他用户 Token 或费用。
- 记忆、任务、Trace 和产物沿用同一所有者/组织边界。
### 12.2 审计事件
以下操作必须记录操作者、目标对象、前后值、IP/客户端、Trace 和结果:
- 登录、退出、Session 撤销和角色变更。
- 查看、下载、导出用户私有知识库。
- 查看、下载、导出用户私有记忆。
- 授权、撤销授权、开放全局和恢复私有。
- Provider/API Key 替换、模型启停、模型组织授权和费率版本变更。
- 成人内容能力测试的发起、样例套件版本、结果发布、能力标签变更和回归差异。
- 修改 Provider 费率、配额、套餐和手工调账。
- 删除文件、删除知识库和索引回滚。
### 12.3 删除与保留
用户删除私有知识库时进入回收站,不立即物理删除;默认保留 30 天,管理员可以在审计确认后提前清理。全局知识库删除需要管理员二次确认,并保留历史任务引用的内容哈希和快照。
## 13. 从 v5 迁移到 v6
### 13.1 兼容策略
1. 现有 `AppUser` 迁移为第一个 `Organization` 下的管理员账号。
2. 现有 `KnowledgeBase` 默认归属该组织和管理员,历史库先标记为 `private`。
3. 现有 `Memory`、Agent、Campaign、Segment、Trace 和 Artifact 追加 `organization_id/user_id`,历史数据使用迁移时的拥有者补齐;历史记忆默认为 `private`。
4. 现有 Provider 和模型列表迁移为管理端 `ModelCatalog`,历史 Agent 的模型引用转换为目录 ID;用户端不继承 Provider 写入权限。
5. 本地源文件先上传到对象存储,校验哈希一致后再切换读取路径。
6. KB3 的 2,717 个分块和 512 维向量先作为一个 index version 上传,不重新计算 Embedding。
7. 迁移完成前保留本地 SQLite、原始文件和 `vector_fallback` 目录,验证通过后再进入清理周期。
### 13.2 迁移验收
迁移必须逐项验证:
- 用户只能看到自己的私有库和已授权库。
- 用户只能选择管理端已开放的模型,不能创建 Provider、修改 API Key 或输入任意模型名。
- 用户只能看到自己的私有记忆和已授权/全局记忆,记忆授权撤销后新任务立即失效。
- 管理员可以查看和导出所有库,但操作有审计记录。
- KB3 重启后仍为 `ready/2717`,引用和 chunk ID 不变化。
- 一次 LLM 调用可以从账单回溯到 `LLMCall`、Run、Trace 和用户。
- 对象哈希、数据库哈希和导出 manifest 一致。
- 撤销授权后,新任务检索不到该库,历史任务仍能查看已有引用快照。
## 14. 实施阶段建议
### 阶段 P1:边界和云对象
- 新增组织、用户归属、资源所有者和可见性字段。
- 将现有 Provider/模型整理成管理端 `ModelCatalog`,先确定用户端只读选择边界。
- 建立 `adult-content-compat-v1` 等版本化能力测试套件,先校验模型目录再向用户端发布能力标签。
- 建立对象存储适配层、对象键规范和上传/下载生命周期。
- 先迁移原始文件和最终产物,不改变 Agent 业务流程。
### 阶段 P2:全局库与授权
- 增加 `KnowledgeBaseGrant` 和授权判定服务。
- 增加 `MemoryGrant`,让记忆库和知识库使用同一套私有/共享/全局判定。
- 用户端拆分“我的/已授权/全局”三个知识库范围。
- 用户端拆分“我的/已授权/全局”三个记忆范围。
- 管理端增加知识库和记忆库总览、授权和导出入口。
### 阶段 P3:用量计量与账单
- 将 `LLMCall`、Embedding、OCR 和存储事件统一写入 `UsageEvent`。
- 增加费率版本、配额、预警、结算和调账。
- 管理端完成按用户、组织、模型和 Trace 的账单查询。
### 阶段 P4:迁移与压测
- 迁移当前数据并执行权限矩阵测试。
- 测试对象存储断点续传、重复上传、孤儿文件清理和导出恢复。
- 测试并发 Agent、额度耗尽、授权撤销和管理员审计。
## 15. 设计完成标准
当以下条件全部满足,v6 设计可以进入实现验收:
- 用户端和管理端导航、权限和 API 边界清晰分离。
- 用户端没有 Provider CRUD、模型发现、API Key 和费率修改入口,只能选择管理员开放的模型目录。
- 成人内容模型能力由管理端版本化测试结果发布;用户端只读查看能力标签,不能自行“破限”或改写测试结论。
- 私有、共享、全局三种知识库访问规则可以通过数据库授权记录解释。
- 记忆库沿用同样的私有、共享、全局、授权、撤销和审计规则。
- 管理员能查看、预览、导出每个用户私有知识库,同时所有行为可审计。
- 管理员能查看、预览、导出每个用户私有记忆,并能授权给指定用户或全部用户。
- AI 用量可以按用户和组织精确归集到 Trace,费率变更不影响历史账单。
- 云存储对象有哈希、版本、生命周期和导出 manifest。
- 重启、索引失败、云存储暂时不可用和配额超限都有明确状态,不产生假成功。
- v5 的 Agent Runtime、QC、组合、记忆和 KB3 既有行为保持兼容。
## 16. v6.1 提示模板与结构化输出(已实现)
根据《提示工程实战指南》的工程化原则,Agent 配置增加独立的 `AgentPromptTemplate`。模板字段为角色提示、任务模板、约束列表、上下文示例、输出 Schema、表达风格和版本状态。它与 Agent 规则分离,避免规则、任务数据和示例互相污染。
运行时固定使用“角色 → 任务 → 风格 → Agent 规则 → 约束 → 示例 → 技能/记忆/锚点/知识 → Runtime 硬规则 → 输出协议”的分层提示。用户模板只负责组织输入,知识来源边界、Agent 级消费锁、工具审批、取消、QC 和人工审查由 Runtime 保持最高优先级。
新建任务时保存模板完整快照并记录版本。模板更新自动递增版本;历史任务继续使用旧快照。输出协议以锚点卡 JSON 为当前生产 Schema,运行器在产物写入前执行 `required` 和字段类型校验,失败结果释放知识片段并进入重做或人工处理。
管理端入口:`GET/POST /api/prompt-templates`、`GET/PUT/DELETE /api/prompt-templates/{id}`;Agent 管理中的 `prompt_template_id` 只允许引用启用模板。内置模板允许停用,已绑定模板需要解除关系后再删除。
## 17. v6.2 模型目录边界(已实现)
Provider 仅负责连接信息和模型发现,用户可选项由独立 `ModelCatalog` 管理。Provider 模型清单发生变化时,系统自动同步目录并停用消失的历史项;目录项保留能力状态、费率版本和启用状态,供管理员后续测试发布。
用户端只能调用 `GET /api/models/available` 获取启用目录,Agent 保存目录 ID 并由服务端再次校验 Provider、模型名称和启用状态。Provider 列表、模型发现、模型连通性测试、目录能力和费率修改均收敛到管理权限,历史任务仍使用其冻结的 Provider/模型快照。
## 18. v6.3 资源边界与授权实现(P1,已完成)
服务端已新增 `Organization` 和统一资源范围字段 `organization_id / owner_user_id / visibility`,覆盖 Agent、画布、任务、知识库、待确认记忆、记忆和成稿。普通用户创建的资源自动绑定当前用户并默认为私有;全局发布与共享范围由管理员控制。
知识库和记忆库分别使用 `KnowledgeBaseGrant`、`MemoryGrant` 保存用户授权,权限分为 `read / use / manage / export`。`use` 自动包含读取,`manage` 包含全部操作,`export` 只用于导出与读取。用户列表、详情、上传、分类、索引、检索、记忆确认/删除、任务运行、Trace 和成稿下载均在服务端检查组织、所有者、可见性和有效授权;撤销授权只影响后续请求,不破坏历史任务快照。
管理端已提供知识库和记忆库的总览、指定用户授权、撤销授权和发布全局接口。Provider、模型目录、知识/记忆授权均由 `/api/admin/*` RBAC 保护,用户端不获得配置写权限。成稿、待确认记忆和运行链路创建时继承所属任务的范围字段,避免关联资源出现跨用户泄漏。
本阶段迁移是幂等的:已有 SQLite、原始文件、向量索引和成稿保留,新增列与授权表在启动时补齐。资源隔离、授权分级、模型目录、Agent Runtime 和前端构建均已完成自动化回归验证。
## 19. 用量计量与账单实现(v6.4,已完成)
系统已使用追加式 `UsageEvent` 作为唯一用量账本,覆盖 LLM、Embedding 和 OCR。每条事件包含 `user_id`、`organization_id`、`campaign_id`、`run_id`、`segment_id`、`trace_id`、Agent、Provider、模型、服务类型、单位、数量、输入/输出 Token、费率、费率版本、金额(人民币分)、状态和唯一幂等键。`LLMCall` 通过 `usage_event_id` 回链事件,并记录 `billing_status`。
计费流程为:
```text
请求进入
→ 解析发起用户和组织
→ 读取 ModelCatalog 当前费率快照
→ Provider 返回真实 Token(或本地估算)
→ 追加 UsageEvent
→ LLMCall/Trace 回链
→ 周期汇总与配额检查
```
建库、重建索引和知识检索都记录 Embedding 事件,导图 OCR 记录一次图像事件。Provider 未提供 Token 时标记 `estimated`;`measured`、`estimated`、`settled`、`void` 在界面和汇总中分开统计。费率后续调整只影响新事件,历史金额保持费率版本快照。
用户端新增 `/api/usage/summary`、`/api/usage/events` 和“用量与账单”入口;管理员新增 `/api/admin/usage/summary`、`/api/admin/usage/events`、`/api/admin/quotas` 及配额新增/删除接口,可按用户、模型、服务类型和日/月周期筛选。管理员代运行任务时,`CampaignRun.user_id` 保存实际发起账号,LLM 账单优先继承该字段,防止多人共用模型造成串账。
`UsageQuota` 支持 Token、金额、存储、并发限制与 `warn / soft_limit / hard_limit` 策略。任务启动前做配额预检;未配置配额时不改变原有行为,达到软/硬限制时返回 429。事件幂等唯一索引、配额唯一索引及用户/组织/时间索引均通过启动迁移补齐,重复启动不会重复建表或重复计费。
## 20. 企业级双入口与 RBAC 收口(v6.5,已实现)
企业产品通常采用同一身份体系下的独立用户门户和管理控制台:用户进入 `/app`,管理员进入 `/admin`。两者共享登录会话、组织和审计链,但拥有不同的导航、页面职责和 API 权限。门户入口是账号角色的固定边界,管理员和普通用户都没有跳转到另一门户的入口。
本项目的入口职责如下:
| 入口 | 可见范围 | 典型动作 |
| --- | --- | --- |
| 用户工作台 `/app` | 全部业务页面,但数据限定为本人、已授权和全局资源 | 新建任务、管理自己的 Agent/画布/标签/技能/模板/知识库/记忆、选择已发布模型、查看账单 |
| 管理控制台 `/admin` | 全部业务页面 + 全组织资源与配置 | 成员/RBAC、Provider、模型目录、Agent、技能、标签、模板、授权、配额、审计 |
服务端中间件对 `/api/admin/*`、Provider、模型默认配置、模型发现和模型目录治理接口要求 `admin:manage` 或管理员配置权限;普通用户可以读取 `/api/models/available` 的已发布模型目录,但不接触连接凭据、费率治理、配额配置和能力发布。标签、技能、提示模板、Agent、画布、知识库和记忆库在用户端保留完整业务操作,并通过组织、所有者、可见性和 Grant 做行级过滤。用户用量接口只按当前会话用户查询,管理端账单接口只由管理员访问。前端路由守卫和服务端资源判定共同抵抗跨门户与越权请求。
账号响应新增 `portal` 和 `permissions` 字段。登录后服务端返回的 `portal` 决定唯一入口,前端将管理员定向 `/admin`、普通用户定向 `/app`;访问不匹配的入口只显示入口阻断页。该设计便于未来将 `/app` 与 `/admin` 拆为独立前端或独立域名,同时保留当前单体部署的平滑迁移路径。
### 20.1 画布作为组合授权根
`CanvasGrant` 授权对象是一个可运行 Agent 流程的组合边界。管理员给用户授予画布的 `read / use / manage / export` 权限后,画布中的 Agent、Agent 关联知识库以及该 Agent 的已确认记忆按同一范围参与查看和运行;系统不再要求为同一画布重复配置记忆授权。该继承仅允许查看和使用,不把知识库或记忆的编辑、删除、导出能力传递给用户。用户运行后产生的新记忆使用当前用户作为 owner,默认保存为私有;管理员可查看、导出并发布到全局。记忆库页面继续提供个人记忆管理,管理端保留全组织审计和全局发布能力。
### 20.2 角色管理补充(v6.6)
角色属于租户级 RBAC 配置。管理员可以在管理控制台创建中文角色、填写职责说明、选择权限、修改权限并删除自定义角色。内置角色仅允许调整权限;自定义角色仍被成员使用时,删除请求返回业务冲突,避免成员瞬间失去权限。服务端为自定义角色生成内部标识,前端和导出报告只展示中文角色名称与中文权限名称。
权限目录:查看内容、内容编辑、内容审查、运行追踪、配置查看、系统配置、成员管理、管理控制台。角色接口为 `GET/POST/PUT/DELETE /api/auth/roles`,成员创建和修改会校验角色是否存在,并继承当前管理员所属组织。
### 20.3 记忆库治理补充(v6.6)
记忆记录采用“待确认 → 已生效 → 可索引调用”的状态链。除原有 Agent、层级、正文、来源和可见性外,记录还保存标题、描述、隐私范围、标签、沉淀日期、索引状态、使用次数和最近使用时间。人工编辑后进入 `needs_reindex`,索引完成后才可进入 Agent 快照;运行时优先加载高使用频次且已建立索引的记忆,单 Agent 加载上限为 50 条。
该设计对齐记忆库文章的五层记忆、两级分类、元数据、总索引/子索引和人工确认原则。生产云化阶段还需增加对象存储中的索引文件、来源证据、版本链、冲突检测和过期任务,且所有读写均按租户和画布授权范围执行。
### 20.4 SaaS 生产门槛
当前本地版已具备租户字段、用户级账单、资源行级授权和独立 `/app`、`/admin` 入口;上线 SaaS 前必须将 SQLite、本地文件和本地向量回退替换为云数据库、对象存储和托管向量索引,并接入密钥托管、限流、组织邀请、平台管理员分层、审计留存和账单结算。详见《SaaS与记忆库全面审查报告》。
## 20.5 点数余额规则(v6.7)
用户 AI 使用额度改为点数余额,统一换算为 `10 点数 = 1 Token`。用户端只能查看自己的点数和用量账单;管理端可以按组织成员增加点数并查看余额。余额低于 10 点数时,服务端在模型请求前返回“点数余额不足”,不向 Provider 发起请求。
每次模型调用成功后,根据实际输入与输出 Token 扣除 `Token × 10` 点数;Provider 未提供 Token 时按 1 Token 最低计量,并在 `UsageEvent` 中保留估算状态。充值与扣点均写入不可变 `PointTransaction` 流水,充值使用管理员操作幂等键,扣点使用模型用量事件幂等键。余额、流水和账单都按用户与组织隔离,多用户同时调用同一个模型时互不串账。
`UsageQuota` 及其管理接口仅保留为旧版本数据兼容,不再作为页面入口和运行时限制。管理端页面不再提供“成员配额”编辑器,平台的 AI 可用性只由点数余额控制;`UsageEvent` 仍用于成本、费率快照、Trace 和审计,不用于给用户充值。