From f024733781b4be86b159506c39b1675ac6188aff Mon Sep 17 00:00:00 2001 From: ymq Date: Mon, 17 Aug 2026 13:31:05 +0800 Subject: [PATCH] =?UTF-8?q?feat(llm):=20set=5Fagent=5Fmodel=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E4=B8=AA=E4=BA=BA=E9=80=89=E6=8B=A9+=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E4=B8=8B=E6=8B=89=E8=BF=94=E5=9B=9Eselected=E6=A0=87?= =?UTF-8?q?=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wwwroot/api/cockpit_model_options.dspy | 11 ++++++++ wwwroot/api/set_agent_model.dspy | 38 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 wwwroot/api/set_agent_model.dspy diff --git a/wwwroot/api/cockpit_model_options.dspy b/wwwroot/api/cockpit_model_options.dspy index 22bfc9b..2488045 100644 --- a/wwwroot/api/cockpit_model_options.dspy +++ b/wwwroot/api/cockpit_model_options.dspy @@ -1,8 +1,10 @@ # cockpit_model_options.dspy - Returns active models with capabilities for dropdown # Used by cockpit model selector # org_id 多租户隔离:非系统级机构只看到本机构的模型(不含系统级兜底) +# 返回每项带 selected 标记,标识个人之前选择的默认模型(default_llm_id) dbname = get_module_dbname('pipeline-sdlc') +uid = await get_user() org_id = (await get_userorgid()) or '' async with DBPools().sqlorContext(dbname) as sor: @@ -14,6 +16,14 @@ async with DBPools().sqlorContext(dbname) as sor: sql += " ORDER BY name" recs = await sor.sqlExe(sql, params) + # 个人之前选择的默认模型 + current_llm_id = '' + if uid: + _s = await sor.sqlExe( + "SELECT default_llm_id FROM pipeline_agent_settings WHERE user_id=${u}$", {"u": uid}) + if _s: + current_llm_id = getattr(_s[0], 'default_llm_id', '') or '' + rows = [] for r in recs: rows.append({ @@ -22,6 +32,7 @@ for r in recs: 'provider': r.provider, 'model_id': r.model_id, 'capabilities': r.capabilities or 'text', + 'selected': r.id == current_llm_id, }) return rows diff --git a/wwwroot/api/set_agent_model.dspy b/wwwroot/api/set_agent_model.dspy new file mode 100644 index 0000000..fafc33e --- /dev/null +++ b/wwwroot/api/set_agent_model.dspy @@ -0,0 +1,38 @@ +# set_agent_model.dspy - 保存个人选择的默认模型 +# 机构人员在本机构 llm 池选模型,持久化到 pipeline_agent_settings.default_llm_id +# 下次进入会话,缺省模型 = 个人之前选择的模型 + +dbname = get_module_dbname('pipeline-sdlc') +uid = await get_user() +llm_id = (params_kw or {}).get('llm_id', '') + +if not uid: + return json.dumps({"success": False, "error": "请先登录"}, ensure_ascii=False) +if not llm_id: + return json.dumps({"success": False, "error": "缺少 llm_id"}, ensure_ascii=False) + +org_id = await get_userorgid() or '0' + +async with DBPools().sqlorContext(dbname) as sor: + # 校验 llm_id 属于本机构(严格本机构隔离;超管 org_id='0' 不过滤) + sql = "SELECT id FROM llm WHERE id=${id}$ AND status='active'" + params = {"id": llm_id} + if org_id and org_id != '0': + sql += " AND org_id=${org}$" + params['org'] = org_id + recs = await sor.sqlExe(sql, params) + if not recs: + return json.dumps({"success": False, "error": "模型不存在或不属于本机构"}, ensure_ascii=False) + + # upsert 到 pipeline_agent_settings(user_id 唯一键) + await sor.sqlExe( + "UPDATE pipeline_agent_settings SET default_llm_id=${lid}$ WHERE user_id=${uid}$", + {"lid": llm_id, "uid": uid}) + exists = await sor.sqlExe( + "SELECT 1 FROM pipeline_agent_settings WHERE user_id=${uid}$", {"uid": uid}) + if not exists: + await sor.C('pipeline_agent_settings', { + 'id': getID(), 'user_id': uid, 'default_llm_id': llm_id, + }) + + return json.dumps({"success": True, "llm_id": llm_id}, ensure_ascii=False)