feat: model-onboarding技能——模型上线流程(配置→测试→上线)
- 治理链全貌+表角色+策略即开关机制 - 无apikey场景: 配置可全部完成,测试须先补key - 测试判据四项: 调用成功/流水status=ok/charge与四价吻合/账号余额扣cost - 同协议模型快速复用通道(模板按协议×能力去重)
This commit is contained in:
parent
e11aa7fd61
commit
94de38b22f
@ -0,0 +1,170 @@
|
||||
---
|
||||
name: model-onboarding
|
||||
description: 模型上线流程:配置→测试→上线三步。新供应商无apikey场景、同协议模型快速复用配置、测试必查调用成功+记账。内部agent上线模型必读。
|
||||
capability: model_onboarding
|
||||
tools: [fetch_model_doc, extract_llm_api_spec, apply_llm_config, platform_llm_status]
|
||||
---
|
||||
|
||||
# 模型上线流程(配置 → 测试 → 上线)
|
||||
|
||||
新模型接入治理链的标准流程。**核心约束:新供应商没有 apikey 时,配置步骤全部可完成
|
||||
(不需要 key),测试步骤必须先补 apikey 才能执行。**
|
||||
|
||||
## 治理链全貌(运行时实际机制)
|
||||
|
||||
```
|
||||
调用方 → llm_bridge.llm_call_msgs
|
||||
→ govern_resolve 门禁链:
|
||||
① 用户限流 → ② 机构限流 → ⑤ 模型链(主→备容错)
|
||||
→ ⑥ 候选选择(端点偏好过滤 → 限流冷却避让 → 余额加权)
|
||||
→ ③④ 预授权(按估算冻结机构池+个人额度)
|
||||
→ 实际调用 (api_base + api_key 进程内, OpenAI 兼容 /chat/completions)
|
||||
→ govern_settle 结算:多退少补 + 账号余额扣 cost + 写 llm_usage 流水
|
||||
```
|
||||
|
||||
**治理开关 = 策略即开关**:机构有 active 的 `llm_org_policy` 才走治理链;
|
||||
无策略 → `__LEGACY__` 走旧 `llm` 表。上线新模型给某机构用,必须配该机构的策略。
|
||||
|
||||
## 涉及的表(pipeline 库)
|
||||
|
||||
| 表 | 角色 | 关键约束 |
|
||||
|---|---|---|
|
||||
| llm_vendor | 供应商 + 端点目录 | endpoints JSON: [{base_url, region, timeout}],全球端点配一次 |
|
||||
| llm_api_profile | 适配模板 | **按协议×能力去重**,同 (protocol, capability) 复用,勿重复建 |
|
||||
| llm_model | 模型目录 | vendor_model_id + profile_id + ppid + 四价(元/千token) |
|
||||
| llm_account | 供应商账号 | api_key(AES) + endpoint_ids(选用端点下标) + balance(成本侧钱包) |
|
||||
| llm_org_policy | 机构策略 | 主模型 + 备链 + 端点偏好;**有它才启用治理** |
|
||||
| llm_org_quota / llm_user_quota | 机构池/个人额度 | 余额+限流,预授权从这里冻结 |
|
||||
| llm_usage | 双维度流水 | charge(售价侧,扣机构池) + cost(成本侧,扣账号余额),测试必查 |
|
||||
|
||||
> uapi/upapp/upappkey 是 sage 旧机制,产线平台模型治理一律走上面的表。
|
||||
|
||||
## 步骤一:配置(无需 apikey,全部可完成)
|
||||
|
||||
1. **抓文档**:`fetch_model_doc` 抓 API 文档 + 定价页
|
||||
2. **提取规格**:`extract_llm_api_spec` → 端点/协议/模型清单/定价
|
||||
3. **落库**:`apply_llm_config`(幂等):
|
||||
- 供应商:按名复用,端点去重合并
|
||||
- 模板:按 (协议×能力) 复用——**已有同协议同能力的 active 模板直接引用,不新建**
|
||||
- 模型:按 (vendor, vendor_model_id) 幂等,四价只来自文档原文
|
||||
- 定价只来自文档;未列价 → 0 + 描述标注「需人工补录」
|
||||
4. **定价项目**(可选,机构计费需要):建 `pricing_program`(pricing_belong=provider)
|
||||
并把 id 回填到 `llm_model.ppid`
|
||||
5. 把配置摘要给用户确认
|
||||
|
||||
**此时状态**:模型已在目录,但因无账号,候选选择会报
|
||||
「供应商下无启用账号」——预期行为,不是错误。
|
||||
|
||||
## 步骤二:测试(先补 apikey,必查调用成功 + 记账)
|
||||
|
||||
**前置(向用户要)**:
|
||||
1. 供应商 **apikey**(由用户在模型治理页录入 `llm_account`,AES 加密存储;
|
||||
**改 key 须重启服务**——key 有进程内缓存)
|
||||
2. 账号**充值**(`recharge_account`,成本侧钱包;余额为 0 也能被选中但建议充值,
|
||||
余额参与加权选择)
|
||||
3. 账号**选用端点**(endpoint_ids,不选端点则候选为空)
|
||||
|
||||
**测试脚本模板**(测试机 /d/pipeline/pipeline-app 下执行):
|
||||
|
||||
```python
|
||||
import asyncio, sys, json
|
||||
sys.path.insert(0, ".")
|
||||
from sqlor.dbpools import DBPools
|
||||
from appPublic.jsonConfig import getConfig
|
||||
db = DBPools(); cfg = getConfig(".", {"workdir": "."})
|
||||
if cfg and cfg.databases: db.databases = cfg.databases
|
||||
|
||||
MODEL = "<新模型注册名>"; ORG = "<测试机构id>"
|
||||
|
||||
async def m():
|
||||
# 记录测试前余额(先取模型→供应商,避免子查询多行)
|
||||
async with db.sqlorContext("pipeline") as sor:
|
||||
rs = await sor.sqlExe("SELECT vendor_id FROM llm_model WHERE name=${n}$ LIMIT 1", {"n": MODEL})
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
if not rs:
|
||||
print("MODEL_MISSING: llm_model 无此注册名"); return
|
||||
vid = getattr(rs[0], "vendor_id", "")
|
||||
rs = await sor.sqlExe("SELECT id, balance FROM llm_account WHERE status='active' "
|
||||
"AND vendor_id=${v}$ LIMIT 5", {"v": vid})
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
before = {getattr(r,'id',''): float(getattr(r,'balance',0)) for r in (rs or [])}
|
||||
# ① 真实调用(走完整治理链:限流→模型链→候选→预授权→调用→结算)
|
||||
from pipeline_service.llm_bridge import llm_call_msgs
|
||||
out = await llm_call_msgs(
|
||||
[{"role": "user", "content": "ping"}],
|
||||
model=MODEL, org_id=ORG, user_id="onboarding-test")
|
||||
print("CALL_OK:", str(out)[:100])
|
||||
# ② 记账检查(必须做)
|
||||
async with db.sqlorContext("pipeline") as sor:
|
||||
rs = await sor.sqlExe(
|
||||
"SELECT id, req_tokens, resp_tokens, charge, cost, status, note FROM llm_usage "
|
||||
"WHERE model_id=(SELECT id FROM llm_model WHERE name=${n}$ LIMIT 1) "
|
||||
"ORDER BY created_at DESC LIMIT 1", {"n": MODEL})
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
if not rs:
|
||||
print("USAGE_MISSING: 无流水——治理链未生效或结算失败,必须排查")
|
||||
else:
|
||||
u = rs[0]
|
||||
print("USAGE|status=%s req=%s resp=%s charge=%s cost=%s note=%s" % (
|
||||
getattr(u,'status',''), getattr(u,'req_tokens',''),
|
||||
getattr(u,'resp_tokens',''), getattr(u,'charge',''),
|
||||
getattr(u,'cost',''), str(getattr(u,'note',''))[:60]))
|
||||
rs = await sor.sqlExe("SELECT id, balance FROM llm_account WHERE status='active' "
|
||||
"AND vendor_id=${v}$ LIMIT 5", {"v": vid})
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
for r in (rs or []):
|
||||
aid = getattr(r,'id','')
|
||||
print("BALANCE|%s: %s -> %s" % (aid, before.get(aid), float(getattr(r,'balance',0))))
|
||||
|
||||
asyncio.run(m())
|
||||
```
|
||||
|
||||
**测试通过判据(四项缺一不可)**:
|
||||
- [ ] `CALL_OK`:模型真实返回内容(不是报错/空)
|
||||
- [ ] `llm_usage` 有新流水且 `status=ok`(status=failed 即未通过)
|
||||
- [ ] `charge = req_tokens/1000×price_input + resp_tokens/1000×price_output`(售价侧金额与四价吻合,核对 llm_model 定价)
|
||||
- [ ] 账号 `balance` 减少 ≈ `cost`(成本侧扣减生效)
|
||||
|
||||
任一项不通过:**禁止进入上线步骤**,先查根因(见故障对照表)。
|
||||
测试完成后,清理或标注测试产生的流水与额度消耗。
|
||||
|
||||
## 步骤三:上线(机构策略 = 开关)
|
||||
|
||||
1. 为目标机构配置 `llm_org_policy`:主模型 = 新模型,备链 = 既有模型(容错),
|
||||
端点偏好(any/prefer/must × domestic/international)
|
||||
2. 确认机构额度池 `llm_org_quota` 有余额(否则预授权失败)
|
||||
3. **重启服务**(策略与 key 均有进程内缓存:`_govern_cache`、key 缓存)
|
||||
4. 复测一次:该机构真实调用新模型 + 记账四项复查
|
||||
5. 回报:模型已上线,主备链与端点偏好说明
|
||||
|
||||
## 同协议模型快速配置(复用通道)
|
||||
|
||||
同供应商追加模型、或不同供应商但协议相同(如又一个 OpenAI 兼容端点):
|
||||
|
||||
1. **模板零新建**:(protocol, capability) 已有 active `llm_api_profile` → 新模型
|
||||
`profile_id` 直接引用,`apply_llm_config` 内部已自动按 (协议×能力) 去重复用
|
||||
2. **端点零重建**:同供应商直接追加模型;新供应商但同协议 → 新建供应商记录,
|
||||
端点目录填自己的,模板仍复用
|
||||
3. **批量注册**:多个模型一次 `apply_llm_config`(spec.models 数组),
|
||||
每个模型只需 `vendor_model_id + capability + 四价`
|
||||
4. **同价模型**:文档里同价的模型逐一照录价格(禁止省略成"同上"推导);
|
||||
文档未列价的模型 → 0 + 标注,单独列出让用户补
|
||||
|
||||
## 故障对照表(govern_resolve 真实报错 → 根因)
|
||||
|
||||
| 报错关键词 | 根因 | 处置 |
|
||||
|---|---|---|
|
||||
| 机构未配置模型容错策略 | 该机构无 active llm_org_policy | 上线步骤未做(预期)或忘配策略 |
|
||||
| 未绑定供应商 | llm_model.vendor_id 空 | 配置步骤漏了 |
|
||||
| 端点目录为空 | llm_vendor.endpoints 空 | 补端点 |
|
||||
| 供应商下无启用账号 | 无 active llm_account | apikey 未录入(配置阶段预期) |
|
||||
| 所有账号都未选用端点 | account.endpoint_ids 空 | 账号要选端点 |
|
||||
| 端点偏好为「仅…」但没有 | must 偏好无匹配区域端点 | 配该区域端点或改偏好,**不跨端点降级** |
|
||||
| 主/备模型全部不可用 | 候选全败(余额/冷却/限流) | 看最后原因;429 = 触发冷却,稍后重试 |
|
||||
|
||||
## 硬规则
|
||||
|
||||
- 定价只来自文档原文(参见 auto-api-pricing-config 技能);缓存价/折扣价未列不配
|
||||
- apikey 只在 `llm_account`(AES),**不写进技能/日志/回报文本**
|
||||
- 改 apikey、改策略后必须重启(进程内缓存)
|
||||
- 测试不过不上线;测试必查调用成功 + 记账四项,缺流水即失败
|
||||
Loading…
x
Reference in New Issue
Block a user