# pipeline-llm 模块设计规范 > 版本:1.0 | 日期:2026-09-01 | 状态:待实施 > 宿主:产线平台(pipeline-app,共享 `pipeline` 库) | 表前缀:`llm_` ## 1. 背景与目标 产线平台现有模型层是 `llm` 单表(name/provider/model_id/api_base/api_key/capabilities), 内嵌接入信息、单一 OpenAI-chat 调用形态、能力是标签不是契约。随着模型增多(非 t2t 能力、 多供应商、多账号),需要独立的模型治理模块。本模块解决五类问题: 1. **供给侧治理**:供应商协议/端点目录、账号(钱包)、模型注册、适配模板 2. **容量治理**:供应商限流 → 多账号轮转;多供应商 → 主备模型容错 3. **需求侧治理**:组织级模型容错策略、组织限额限流、个人限额限流 4. **计费**:双维度记账(成本侧记账号、消费侧记组织/个人),挂定价平台 `pricing_program.ppid` 5. **端点选择**:供应商全球端点配置一次,账号选用端点,客户按区域偏好(prefer/must) ## 2. 架构总览 ``` 供给侧(容量) 需求侧(治理) ───────────── ───────────── llm_vendor (协议+端点目录) llm_org_policy (组织容错策略) └─ llm_account (钱包+选端点) llm_org_quota (组织限额限流) └─ llm_model (模型注册) llm_user_quota (个人限额限流) └─ llm_api_profile (适配) ↓ llm_usage (用量流水,双维度) ``` **调用门禁链**(所有 LLM 调用收敛点 `llm_call`): ``` ① 个人限流窗口 → ② 组织限流窗口 → ③ 个人额度余额 → ④ 组织池余额 → ⑤ 组织容错策略选模型(主→备) → ⑥ 账号×端点候选池:区域偏好过滤 → 剩余额度加权轮转 + 冷却避让 → ⑦ 预授权(冻结预估用量)→ 调用 → ⑧ 结算(实际用量,双维度记账) 任何一级不过:快速失败 + 明确原因(不挂起、不静默) ``` ## 3. 数据表(8 张,全部 `llm_` 前缀,建在 `pipeline` 库) ### 3.1 llm_vendor — 供应商 | 字段 | 类型 | 说明 | |---|---|---| | id | str(32) PK | | | name | str(100) | 供应商名(如 阿里云百炼) | | protocol | str(20) | openai_compat / dashscope_async / custom | | endpoints | text(JSON) | 端点目录 `[{region, base_url, proxy, timeout, note}]` | | description | text | | | status | str(20) | active / disabled,默认 active | | org_id | str(32) | 0=系统级 | | created_at/updated_at | str(30) | | 端点目录挂在 vendor 下(全球端点配置一次),账号选用。`endpoints` JSON 元素: `region`(domestic/international/europe/...)、`base_url`、`proxy`(可选,国外端点走 SOCKS)、 `timeout`(秒,默认 60)、`note`。 ### 3.2 llm_account — 供应商账号(钱包) | 字段 | 类型 | 说明 | |---|---|---| | id | str(32) PK | | | vendor_id | str(32) | → llm_vendor.id | | name | str(100) | 账号名 | | api_key | str(500) | **AES 单层加密**(appPublic.aes.aes_encode_b64,password_key 做密钥,对称可解密)。⚠️ 不能用 RC4:rc4.password()/unpassword() 盐不对称,加密后永久不可解(2026-08 实测坑)。改 key 须重启进程(有缓存) | | endpoint_ids | text(JSON) | 选用的端点索引列表(对应 vendor.endpoints 下标),有序;空=不启用 | | balance | decimal(14,4) | 余额(充值-消耗),单位与定价币种一致 | | total_recharge | decimal(14,4) | 累计充值 | | status | str(20) | active / suspended / exhausted,默认 active | | org_id | str(32) | | | created_at/updated_at | str(30) | | 独立充值、独立记账。轮转限流时余额不足的账号直接跳过(不消耗)。 ### 3.3 llm_model — 模型注册(旧 `llm` 表的替代) | 字段 | 类型 | 说明 | |---|---|---| | id | str(32) PK | | | vendor_id | str(32) | → llm_vendor.id | | account_id | str(32) | 默认账号(可空,运行时轮转选) | | name | str(100) UNIQUE | 模型注册名(平台内唯一,调用方用此名) | | vendor_model_id | str(100) | 供应商侧模型名(各家命名不一) | | capability | str(20) | 能力类型,默认 t2t(见 §6 能力标准) | | sync_mode | str(10) | sync / async_task,默认 sync | | profile_id | str(32) | → llm_api_profile.id(适配模板) | | ppid | str(32) | → 定价平台 `pricing_program.id`(挂定价) | | default_params | text(JSON) | 默认参数(temperature/max_tokens 等) | | status | str(20) | active / disabled | | description | text | | | org_id | str(32) | | | created_at/updated_at | str(30) | | ### 3.4 llm_api_profile — 适配模板(协议×能力形态去重) | 字段 | 类型 | 说明 | |---|---|---| | id | str(32) PK | | | name | str(100) | 如 openai-chat、dashscope-image-async | | protocol | str(20) | 同 vendor.protocol | | capability | str(20) | 能力类型 | | request_template | text | Jinja2:参数 → 供应商请求体 | | response_template | text | Jinja2:供应商响应 → 统一结果(含 usage) | | param_schema | text(JSON) | bricks input_fields 格式(参数表单定义) | | status | str(20) | active / disabled | | created_at/updated_at | str(30) | | 模板按「协议×能力形态」开,不按模型开——同一端点 N 个模型共用一条,杜绝重复记录。 一期只内置 `openai-chat`(sync),非 chat 形态模型进来时再加对应 profile。 ### 3.5 llm_org_policy — 组织模型容错策略 | 字段 | 类型 | 说明 | |---|---|---| | id | str(32) PK | | | org_id | str(32) UNIQUE | 一组织一策略 | | primary_model_id | str(32) | → llm_model.id 主模型 | | backup_model_ids | text(JSON) | 备模型 id 列表(有序) | | endpoint_pref | str(20) | prefer_domestic / prefer_intl / must_domestic / must_intl / any,默认 any | | status | str(20) | active / disabled | | created_at/updated_at | str(30) | | 生效优先级:会话/项目选择 > 组织策略 > 平台默认(与现有 `sd_projects.default_model > pipeline_agent_settings.default_llm_id` 链兼容,组织策略插中间)。 must 模式:候选端点耗尽宁可报错冒泡,绝不跨端点。 ### 3.6 llm_org_quota — 组织限额限流 | 字段 | 类型 | 说明 | |---|---|---| | id | str(32) PK | | | org_id | str(32) UNIQUE | | | balance | decimal(14,4) | 组织池余额(充值-消耗) | | total_recharge | decimal(14,4) | 累计充值 | | rate_limit | int | 组织 QPM 上限(0=不限) | | status | str(20) | active / disabled | | created_at/updated_at | str(30) | | ### 3.7 llm_user_quota — 个人限额限流 | 字段 | 类型 | 说明 | |---|---|---| | id | str(32) PK | | | user_id | str(32) | | | org_id | str(32) | 所属组织(额度挂组织池) | | quota_limit | decimal(14,4) | 个人额度上限(0=不限) | | quota_used | decimal(14,4) | 个人已用 | | rate_limit | int | 个人 QPM 上限(0=不限) | | status | str(20) | active / disabled | | created_at/updated_at | str(30) | | 关系默认「共享池 + 个人上限」:组织充值一个池,个人上限防单人打爆池子。 个人额度耗尽不影响他人;组织池耗尽全员不可用(冒泡提醒充值)。 ### 3.8 llm_usage — 用量流水(双维度记账事实表) | 字段 | 类型 | 说明 | |---|---|---| | id | str(32) PK | | | org_id / user_id | str(32) | 消费侧维度 | | model_id / account_id | str(32) | 供给侧维度(model_id 空+source=recharge 时为充值记录) | | endpoint_region | str(20) | 实际走的端点区域 | | req_tokens / resp_tokens | int | 实际用量 | | cost | decimal(12,6) | 成本侧金额(账号扣减,按定价) | | charge | decimal(12,6) | 消费侧金额(组织池扣减,按产品定价) | | ppid | str(32) | 定价项目(冗余自模型,便于对账) | | task_ref | str(100) | 调用来源(任务/会话标识) | | status | str(20) | ok / failed / recharge(充值记录) | | note | str(200) | 失败原因/充值备注 | | created_at | str(30) | | 一次调用两条线:**成本侧** cost 记账号(供应商对账),**消费侧** charge 记组织池+个人 (客户计费)。充值是 balance 变动事件,记 `source=recharge` 行(model_id/account_id 空)。 ## 4. 核心机制 ### 4.1 选择链与轮转(gateway.py `llm_call`) ```python async def llm_call(prompt, model=None, org_id=None, user_id=None, task_ref='', **kw) ``` 1. 解析模型:调用方指定 model → 直接用;否则查组织策略主备链 2. 候选对构建:模型的账号池(account.status=active)× 账号选用端点 3. 区域偏好过滤:must_* 只留对应区域端点对;prefer_* 排序(匹配区域优先) 4. 加权轮转:按账号余额 + 端点窗口剩余配额加权;限流冷却中的对跳过 5. 调用 → 429 标记该(账号,端点)对冷却 → 换下一对;账号池耗尽 → 降备模型; 备模型也耗尽 → must 模式冒泡报错 / prefer 模式跨端点重试 6. 401/403 标记账号失效(不轮转);5xx 短暂重试(最多 2 次) ### 4.2 预授权-结算(防并发击穿余额) - 调用前:按 max_tokens 预估(默认 2000 token × 单价)Redis 原子冻结组织池+个人额度 - 调用后:按实际 token 多退少补,写双维度流水 - GeneratorExit/超时:结算兜底(按预估释放,写 failed 流水) ### 4.3 限流(Redis 滑动窗口) - key:`llm_rl:{user|org}:{id}:{minute}`,原子 INCR + EXPIRE - 超窗拒绝:返回明确错误(个人限流/组织限流),下窗口自动恢复,不涉及钱 - 供应商侧 429:(账号,端点)对冷却 60s,窗口内不再选它 ### 4.4 定价对接(ppid) - 模型挂 `pricing_program.id`(定价平台的定价项目) - 消费侧单价从定价平台读取(跨库:定价模块库),一期支持手动设置 `price_per_1k` 兜底(组织策略页配置),二期接定价平台实时价 - 成本侧单价:账号维度配置(供应商结算价),一期也走手动配置 ## 5. 功能点清单(共 18 项) | # | 功能点 | 表/文件 | 优先级 | |---|---|---|---| | F01 | 供应商管理(含端点目录配置) | llm_vendor + CRUD | P0 | | F02 | 账号管理(充值、余额、选端点) | llm_account + CRUD | P0 | | F03 | 模型注册(挂能力、挂定价、挂适配) | llm_model + CRUD | P0 | | F04 | 适配模板管理 | llm_api_profile + CRUD | P1(一期内置 openai-chat) | | F05 | 组织容错策略(主备模型+端点偏好) | llm_org_policy + CRUD | P0 | | F06 | 组织限额限流(充值、QPM) | llm_org_quota + CRUD | P0 | | F07 | 个人限额限流 | llm_user_quota + CRUD | P0 | | F08 | 调用门禁(①-④ 限流限额检查) | gateway.py | P0 | | F09 | 主备容错(策略选模型→备链) | gateway.py | P0 | | F10 | 账号×端点轮转(加权+冷却) | gateway.py | P0 | | F11 | 区域偏好过滤(prefer/must) | gateway.py | P0 | | F12 | 预授权-结算 | gateway.py | P0 | | F13 | 双维度记账流水 | llm_usage | P0 | | F14 | 充值操作(账号/组织池) | recharge dspy | P0 | | F15 | 用量查询(按组织/模型/账号/时间) | usage 列表页 | P1 | | F16 | 模型管理入口(主菜单) | index.ui 菜单项 | P0 | | F17 | 与现有调用链兼容(llm_bridge 切换) | llm_bridge.py 适配 | P0 | | F18 | 机构未配置冒泡提示 | gateway 错误路径 | P0 | ## 6. 能力类型标准(capabilities 取值,先行收敛) | 值 | 含义 | 同步性 | |---|---|---| | t2t | 文本对话/生成 | sync | | t2i | 文生图 | async_task | | i2t | 图生文(多模态理解) | sync | | t2v | 文生视频 | async_task | | embedding | 文本向量化 | sync | | mm-embedding | 多模态向量化 | sync | | rerank | 重排序 | sync | | mm-rerank | 多模态重排序 | sync | | tts | 语音合成 | sync | | asr | 语音识别 | sync | 新增能力类型走评审(改本文档 + init/data.json appcodes),禁止野生标签。 ## 7. 集成点 1. **宿主加载**:`pipeline_app.py` init() 加 `load_llm()`(try/except ImportError 兜底) 2. **菜单**:`wwwroot/index.ui` 主菜单加「模型管理」项 → `/llm`(TabPanel) 3. **RBAC**:`/llm/**` 注册到 superuser;静态资源 any;load_path.py 注册各路径 4. **i18n**:zh/en 双语文案(模块内文案走 appcodes + i18n msg.txt) 5. **建表**:mysql.ddl.sql(json2ddl 生成 + 手写补齐),存量库 ALTER 幂等 6. **兼容**:旧 `llm` 表保留,`llm_bridge.py` 优先查新表(按 name),无则回退旧表—— 现有调用零改动,迁移平滑 ## 8. 分期 - **一期(本次交付)**:全部 10 张表 + F01-F03/F05-F14/F16-F18 + F04 内置 openai-chat + F15 - **二期(触发:第一个非 t2t 模型)**:异步任务形态适配模板、任务轮询端点 - **三期(触发:定价平台实时价接入)**:成本/消费侧单价自动读取