配额与成本 — 用量与支出上限
配额引擎覆盖三类:token 配额与存储配额(Phase 207)以及成本配额(Phase 216,对真金白银的数学采用 hold-and-settle)。配额是运维者在多用户安装中的用量上限工具;它约束每个*已配置配额*的用户 — 包括管理员 — 而未配置的配额 = 不限量(fail-open:对既有安装零行为改变)。
配额引擎覆盖三类:token 配额与存储配额(Phase 207)以及成本配额(Phase 216,对真金白银的数学采用 hold-and-settle)。配额是运维者在多用户安装中的用量上限工具;它约束每个已配置配额的用户 — 包括管理员 — 而未配置的配额 = 不限量(fail-open:对既有安装零行为改变)。
Community 功能(运维者工具)。来源:docs/QUOTAS.md(Phase 207 + 216)、docs/MODEL_COSTS.md、docs/API.md(Costs, quotas, and per-user model policy 一节)。来源行:FACT-CENSUS.mdF-QUOTA-1。
核心不变量
- 没有第二个计数器。 消耗(token/成本)的事实保留在既有的 ledger
WorkspaceTokenUsage里(packages/server/src/services/quotaService.ts)。QuotaBalance/QuotaHold/QuotaReset= 派生且锚定的状态,绝不是计数表。 - Reset = ledger 的锚。 一次 reset 会再写一条
QuotaReset(kind, at)来界定滚动窗口 — 用量/成本的历史绝不会被清除或归零。 - 服务层面的门槛,pre-turn — 不是 auth 中间件(该检查需要的是领域数据,不是请求的形态)。门槛在 orchestrator 的第一次 LLM 调用之前、上传路径的 ingestion 之前启动。
- 未配置的配额 fail-open。 什么都没配置时,解析链条终结于“不限量”(D-08)。
- 钱的数学 = Decimal→cents。 全部成本算术经
Prisma.Decimal并落为整数 cents — 绝不是 float(costQuotaService.ts,COST-01 学说)。
解析链(D-08)
| 层级 | 来源 | 说明 |
|---|---|---|
| 1 | 按用户的覆盖 | User.tokenQuotaLimit / User.storageQuotaGb / 按用户的成本行 — 经 PUT /api/quota/:userId(admin) |
| 2 | 安装的预设 | SystemConfig 键(下表)— DB > ENV > 默认 |
| 3 | 不限量 | 哨兵值 "0" / "" / unset = 未配置 → fail-open |
配置键(SystemConfig,经 Settings 可编辑)
| 键 | 默认 | 含义 |
|---|---|---|
QUOTA_TOKEN_DEFAULT | unset 哨兵 | 对每个没有覆盖的用户,安装的 token 上限 |
QUOTA_STORAGE_GB_DEFAULT | unset 哨兵 | 安装的存储上限(GB) |
QUOTA_COST_EUR_DEFAULT | unset 哨兵("0"/"" = 不限量) | 安装的成本上限 — EUR 十进制字符串 |
QUOTA_COST_FALLBACK_INPUT_CENTS_PER_1M | 内置的非零下限 | SC-4 的兜底费率,用于没有价格的模型 — input,每 1M tokens 的整数 cents |
QUOTA_COST_FALLBACK_OUTPUT_CENTS_PER_1M | 内置的非零下限 | SC-4 的兜底费率,用于没有价格的模型 — output |
SC-4 学说:没价格的模型绝不做成本配额的漏网之鱼 — 兜底费率以 warn-once(warnFallbackOnce)适用:没有价格的模型绝不可能被视为免费。
Token 配额(quotaService.ts)
resolveTokenQuota(userId)→{ limit, source }—limit: null= 不限量;source说是 D-08 的哪一层定的。- 滚动窗口从
(userId, kind: "token")的最后一条QuotaReset锚开始(从未重置则从纪元起);窗口内的用量从 ledgerWorkspaceTokenUsage累加。 - 超限抛出
QuotaError(status+payload)— payload 的quota字段是 frontend、widget 和连接器 handler 读取的契约。没有可绕过的中间件:门槛运行在服务路径内部。
成本配额(costQuotaService.ts,Phase 216)— hold-and-settle
两阶段的预留:
- Reserve(LLM 调用之前) —
reserveCostQuota(principal, estimateCents)跑一条交互事务:条件式updateMany,其谓词(spentCents + estimate <= limitCents)由 Postgres 以 row-lock 求值,N 个并发的门槛因此 SERIALIZ化,而不是都从旧的检查上滑过(SC-2)+ 同一事务里的QuotaHold插入。 - Settle(使用段上) —
settleCostHold关闭 hold 并退还estimate − actual。飞行中的超支(actual > estimate)= 接受的窗口 — 绝不杀正在进行的 stream。 - 静止时成立不变量:
settledSpent + Σ(开启的 lead) ≤ 上限。 - 每行的价格来源: 存在时用 Phase 203 的 FROZEN 快照;否则 SC-4 兜底费率(warn-once);非本位币的行同样计价(绝不默默免费、绝不排除)。
- Reset —
resetCostQuota写Quota(kind "cost")锚并从 ledger 累加 + 未决 hold 重建余额(D-02)。
存储配额
checkStorageQuota / resolveStorageQuota 强制按用户覆盖 storageQuotaGb、预设 QUOTA_STORAGE_GB_DEFAULT 或不限量。门槛在 upload 路径的 dispatch 到 collector 之前启动。
Widget 的 principal
匿名的 widget 访客不是用户 — resolveWidgetQuotaPrincipal 把 widget 流量绑到 widget 所属组织的 principal 上:widget 的消耗记在组织的配额链上,而不是按访客的身份。
门槛在哪里启动(消耗点)
| 表面 | 门槛 | 文件 |
|---|---|---|
| 聊天(JWT、widget 代理、连接器 — 同一个 orchestrator) | token + 成本门槛 pre-turn / pre-LLM | packages/server/src/agent/orchestrator.ts |
| 文档上传 | pre-ingest 的存储门槛 | packages/server/src/routes/uploads.ts、routes/documents.ts |
| 重置清扫 | 每小时的 token 配额重置(pg-boss cron:initQuotaResetScheduler) | services/quotaResetJob.ts |
| 自助式读取 | GET /api/quota/me、rollups、手动重置 | routes/quota.ts |
运维者的流程
- 安装默认值 — Settings UI →
QUOTA_*键(或PUT /api/system/settings)。 - 按用户的覆盖 —
PUT /api/quota/:userId(admin)或配额 UI。 - 按用户的定价 — COSTS 家族(Phase 209:
/api/users/:userId/pricing,自有供应商键位于/api/me/provider-keys)供给同一引擎。 - 随时手动重置:
POST /api/quota/:userId/reset;每小时清扫维持稳态。
模型定价(MODEL_COSTS)
配置:Settings → Providers → 选择供应商 → 模型的 pricing 操作 → 每 1M-token 的 input/output 成本(例如 1.50 与 6.00)+ 货币 → Save。公式:cost = tokens × rate,服务端在每次使用写入时计算,快照在运行时冻结(之后的费率改动绝不改写历史)。货币:USD、EUR、GBP、JPY、CNY、INR — 按货币合计,v1 不做换算。N/A = 价格未配置(云端模型 unset;UI 显示 "N/A" — 管理员需配置);$0.00 = 明确免费(本地/Ollama 模型在迁移时回填为 0;可覆盖)。v1 限制:货币之间不换算;只有主迭代的成本(tool/MCP/synthesis 子流水线不计);成本在 done 事件时可用(不在流中段)。
端点参考
完整表在 API reference → Costs, quotas, and per-user model policy。
另见
- Scaling — 多实例部署下配额的行为
本指南介绍配额与成本的操作面;工程深潜见孪生博文:
Provenance
| 章节 | 来源 |
|---|---|
| 不变量 / 解析链 / 键 | docs/QUOTAS.md(core invariants、D-08、键 — Phase 207/203)— F-QUOTA-1 |
| 成本配额 / hold-and-settle | docs/QUOTAS.md(§ Cost quotas — Phase 216)+ costQuotaService.ts |
| 模型定价 | docs/MODEL_COSTS.md(Phase 203/209/216) |
| 门槛处 | docs/QUOTAS.md(§ Where the gates fire) |
---
运维参考 — Simmetric Chat v0.28.1(文档更新于 2026-10-02,普查 SHA `aca5b8ff`)。