feat(govern): 能力降级规则i2i→t2i/r2v→t2v(2026-09-08用户定夺,与r2v→t2v同例)——selection加CAP_DEGRADE事实源+degrade_expand,models_catalog候选池含降级源模型,网关备链/owner容错链同能力铁律放行合法降级源,auto_select提示词补降级规则;单向降级反向永远非法
This commit is contained in:
parent
fba76a0cdc
commit
d086c4f7d2
@ -201,10 +201,18 @@ async def _model_chain(sor, org_id: str, model_name: str, purpose: str = ''):
|
||||
# sqlor IN 列表必须展开占位符(传 list 会崩)
|
||||
ph = ','.join('${b%d}$' % i for i in range(len(backups)))
|
||||
bparams = {'b%d' % i: b for i, b in enumerate(backups)}
|
||||
# 能力降级(2026-09-08):备链允许同能力或合法降级源能力
|
||||
# (t2i→i2i、t2v→r2v);跨能力(如 t2t)仍永远非法
|
||||
from .selection import CAP_DEGRADE_SOURCE
|
||||
_alt = CAP_DEGRADE_SOURCE.get(want_cap, '')
|
||||
if _alt:
|
||||
ph += ',${altcap}$'
|
||||
bparams['altcap'] = _alt
|
||||
bparams['cap'] = want_cap
|
||||
brecs = await sor.sqlExe(
|
||||
"SELECT id FROM llm_model WHERE status='active' AND id IN (%s) "
|
||||
"AND COALESCE(NULLIF(capability,''),'t2t')=${cap}$" % ph, bparams)
|
||||
_sql = ("SELECT id FROM llm_model WHERE status='active' AND id IN (%s) "
|
||||
"AND COALESCE(NULLIF(capability,''),'t2t') IN (${cap}$"
|
||||
+ (",${altcap}$" if _alt else "") + ")") % ph
|
||||
brecs = await sor.sqlExe(_sql, bparams)
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
for br in (brecs or []):
|
||||
bid = getattr(br, 'id', '')
|
||||
@ -542,10 +550,14 @@ async def govern_resolve(org_id: str, user_id: str = '', model_name: str = '',
|
||||
models0 = [m for m in models0 if _owner_allowed(m.get('org_id'), org_id)]
|
||||
# 同能力铁律(2026-09-07):显式指定模型时 owner 容错链也只许
|
||||
# 同能力替代——要图给文的静默回退在任何一层都不合法。
|
||||
# 能力降级(2026-09-08):合法降级源能力(t2i→i2i、t2v→r2v)除外。
|
||||
if model_name and models0:
|
||||
from .selection import CAP_DEGRADE_SOURCE
|
||||
_want = (models0[0].get('capability') or 't2t').strip().lower()
|
||||
_alt = CAP_DEGRADE_SOURCE.get(_want, '')
|
||||
models0 = [m for m in models0
|
||||
if (m.get('capability') or 't2t').strip().lower() == _want]
|
||||
if (m.get('capability') or 't2t').strip().lower()
|
||||
in (_want, _alt)]
|
||||
for m in models0:
|
||||
ok, cand = await _pick_candidate(sor, m, pref0)
|
||||
if ok and isinstance(cand, tuple):
|
||||
|
||||
@ -23,6 +23,26 @@ logger = logging.getLogger("pipeline_llm.selection")
|
||||
# 会话 agent 模型下拉只列这些;embedding/rerank/图视频生成等形态各有专属入口。
|
||||
CHAT_CAPS = ('t2t', 'i2t', 'm2t')
|
||||
|
||||
# 能力降级表(2026-09-08 用户定夺,与 r2v→t2v 同例):请求能力无可用模型时,
|
||||
# 允许降级用「超集能力」模型执行任务。方向 = 降级目标模型的输入契约覆盖
|
||||
# 请求能力:
|
||||
# i2i(图像→图像,接受文本提示+可选图)可执行 t2i(文本→图像)任务
|
||||
# r2v(参考媒体→视频,接受文本+参考媒体)可执行 t2v(文本→视频)任务
|
||||
# 单向降级:t2i 模型不能接 i2i(缺源图)、t2v 不能接 r2v——反向永远非法。
|
||||
CAP_DEGRADE = {'t2i': 'i2i', 't2v': 'r2v'}
|
||||
# 反向索引:降级源能力 → 请求能力(门禁契约换算用:i2i 模型无图输入时按 t2i 契约校验)
|
||||
CAP_DEGRADE_SOURCE = {v: k for k, v in CAP_DEGRADE.items()}
|
||||
|
||||
|
||||
def degrade_expand(caps):
|
||||
"""能力白名单 + 其合法降级源能力(候选池扩展用)。无映射时原样返回。"""
|
||||
out = [str(c).strip().lower() for c in (caps or ()) if str(c or '').strip()]
|
||||
for c in list(out):
|
||||
d = CAP_DEGRADE.get(c)
|
||||
if d and d not in out:
|
||||
out.append(d)
|
||||
return tuple(out)
|
||||
|
||||
|
||||
def _norm_caps(capabilities):
|
||||
"""capabilities 参数归一:'chat' 哨兵 → CHAT_CAPS;逗号串 → tuple;
|
||||
@ -178,6 +198,10 @@ async def models_catalog(org_id, capabilities=(), limit=50):
|
||||
"""
|
||||
db, dbname = _get_sor()
|
||||
caps = _norm_caps(capabilities)
|
||||
# 能力降级(2026-09-08):候选池含请求能力的合法降级源模型
|
||||
# (t2i→i2i、t2v→r2v),无可用 t2i 模型时 i2i 模型可承接文生图任务
|
||||
if caps:
|
||||
caps = degrade_expand(caps)
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
sql = ("SELECT m.id, m.name, m.vendor_model_id, m.capability, m.description, "
|
||||
"m.org_id, v.name AS vendor_name "
|
||||
@ -249,7 +273,10 @@ async def auto_select_model(org_id, user_input, user_id='', capabilities='chat')
|
||||
'(格式:模型名 [能力类型] 供应商:描述):\n%s\n\n'
|
||||
'能力类型含义:t2t=文本对话 i2t=图像理解 m2t=多媒体理解 t2i=文生图 '
|
||||
'i2v=图生视频 t2v=文生视频 r2v=参考生视频 tts=语音合成 asr=语音识别 '
|
||||
'embedding=向量化 rerank=重排序\n\n'
|
||||
'embedding=向量化 rerank=重排序\n'
|
||||
'能力降级规则:无 t2i 模型时 i2i(图生图)模型可承接文生图任务;'
|
||||
'无 t2v 模型时 r2v(参考生视频)模型可承接文生视频任务;'
|
||||
'反向(t2i 接图生图、t2v 接参考生视频)非法。\n\n'
|
||||
'用户任务:\n%s\n\n'
|
||||
'请根据任务的内容领域、语言、复杂度,从目录中选出最适合完成该任务的模型'
|
||||
'(只能选目录中的模型名,按适合度从高到低排序,最多 3 个)。'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user