From e8a5511535883c55ff0052e904bed08c171d1cc4 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sat, 5 Sep 2026 21:41:42 +0800 Subject: [PATCH] =?UTF-8?q?fix(platform):=20apply=5Fllm=5Fconfig=E5=B9=82?= =?UTF-8?q?=E7=AD=89=E9=94=AE=E6=94=B9=E4=B8=BAname=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=94=AF=E4=B8=80=E9=94=AE(=E5=AE=9E=E6=B5=8B:=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E8=BF=81=E4=BE=9B=E5=BA=94=E5=95=86=E5=90=8E=E6=8C=89?= =?UTF-8?q?vendor=5Fid+vmid=E6=9F=A5=E4=B8=8D=E5=88=B0=E2=86=92INSERT?= =?UTF-8?q?=E6=92=9Euk=5Fllm=5Fmodel=5Fname=E5=B4=A9);=E4=BE=9B=E5=BA=94?= =?UTF-8?q?=E5=95=86=E5=BD=92=E5=B1=9E=E4=B8=8D=E4=B8=80=E8=87=B4=E4=B8=8D?= =?UTF-8?q?=E9=9D=99=E9=BB=98=E8=BF=81=E7=A7=BB,=E6=8A=A5vendor=5Fconflict?= =?UTF-8?q?s=E7=94=B1=E7=94=A8=E6=88=B7=E5=86=B3=E7=AD=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pipeline_platform/platform_ability.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/pipeline_platform/platform_ability.py b/pipeline_platform/platform_ability.py index 0414955..a2fdf0e 100644 --- a/pipeline_platform/platform_ability.py +++ b/pipeline_platform/platform_ability.py @@ -423,8 +423,8 @@ def _f(v, default=0.0): async def _h_apply_llm_config(sor, params, ctx): """按提取的规格写库:供应商(复用/新建)+ 适配模板 + 模型。 - 幂等:供应商按名称复用;模型按 (vendor, vendor_model_id) 复用—— - 已存在则更新,不重复创建。 + 幂等:供应商按名称复用;模型按 name/vendor_model_id 复用(name 全局唯一键)—— + 已存在则更新元数据;供应商归属不一致时不改挂、如实报 vendor_conflicts。 规格来源(2026-09-05 防编造改造): use_last_extract=true(推荐)→ 取本会话 extract 锚定的规格, @@ -557,9 +557,10 @@ async def _h_apply_llm_config(sor, params, ctx): "status": "active"}) profile_ids[cap] = pid - # 3. 模型:按 (vendor, vendor_model_id) 幂等 + # 3. 模型:按 name/vendor_model_id 幂等(name 全局唯一键) doc_url = (spec.get("doc_url") or "").strip() created, updated, skipped = [], [], [] + conflicts = [] # 供应商归属冲突(模型已挂别的供应商)——如实报告不静默迁移 for m in models: vmid = (m.get("vendor_model_id") or "").strip() if not vmid: @@ -582,12 +583,21 @@ async def _h_apply_llm_config(sor, params, ctx): if qid: query_ids.append(qid) query_ids_json = json.dumps(query_ids) if query_ids else "" + # 幂等键=name(uk_llm_model_name 全局唯一)。不能按 (vendor_id, vmid) 查: + # 模型换挂供应商后(如迁到阿里云百炼),旧查询找不到→INSERT→撞唯一键崩(实测)。 recs = await sor.sqlExe( - "SELECT id FROM llm_model WHERE vendor_id=${v}$ AND vendor_model_id=${m}$", - {"v": vendor_id, "m": vmid}) + "SELECT id, vendor_id FROM llm_model WHERE name=${m}$ OR vendor_model_id=${m}$", + {"m": vmid}) await sor.sqlExe("COMMIT", {}) if recs: mid = getattr(recs[0], "id", "") + cur_vendor = getattr(recs[0], "vendor_id", "") or "" + if cur_vendor and cur_vendor != vendor_id: + # 供应商归属不一致:治理决策,不静默迁移——只更新元数据并如实报告 + conflicts.append( + "%s: 模型已存在且挂供应商 id=%s,与本次规格供应商(%s)不一致——" + "未改供应商归属,仅更新描述/同步模式;如需迁移请明确指示" + % (vmid, cur_vendor, vendor_name)) await sor.sqlExe( "UPDATE llm_model SET description=${d}$, " "sync_mode=${sm}$, query_profile_ids=${q}$, updated_at=NOW() " @@ -615,6 +625,7 @@ async def _h_apply_llm_config(sor, params, ctx): return json.dumps({ "vendor": vendor_action, "profiles": profile_ids, "models_created": created, "models_updated": updated, "models_skipped": skipped, + "vendor_conflicts": conflicts, "runtime_note": rt_note, "media_audit": audit_note, }, ensure_ascii=False)