From 0af4faff219b3148a19416d6f7ebdc4ef949f192 Mon Sep 17 00:00:00 2001 From: ymq Date: Sat, 22 Aug 2026 11:36:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20LLM=20=E6=9C=BA=E6=9E=84=E9=9A=94?= =?UTF-8?q?=E7=A6=BB=E2=80=94=E2=80=94=E6=9C=BA=E6=9E=84=E6=B2=A1=E9=85=8D?= =?UTF-8?q?=20llm=20=E6=97=B6=E8=A7=92=E8=89=B2/PM/QC=20=E5=86=92=E6=B3=A1?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E6=9A=82=E5=81=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _check_org_llm 检测机构 llm 配置(严格本机构隔离,不含系统级兜底) - role_agent_run/pm_review_run/qc_review_run 在 LLM 调用前检测,机构没配 llm 则 raise_problem(need_info) 冒泡问题暂停,等机构配置模型后恢复 --- pipeline_service/agent_loop.py | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/pipeline_service/agent_loop.py b/pipeline_service/agent_loop.py index d13f470..402c3ba 100644 --- a/pipeline_service/agent_loop.py +++ b/pipeline_service/agent_loop.py @@ -162,6 +162,23 @@ async def _resolve_llm_context(sor, project_id, role, model_name=None): return model_name, org_id +async def _check_org_llm(sor, org_id): + """检测机构是否配置了 LLM 模型(严格本机构隔离,不含系统级兜底)。 + + 返回 (missing: bool, available_names: list)。org_id 为空或 '0'(系统级)时不过滤, + 视为已配置(系统级模型对超管可用)。机构没配 llm 时角色/pm/qc 应冒泡问题暂停。 + """ + if not org_id or org_id == '0': + return False, [] + try: + recs = await sor.sqlExe( + "SELECT name FROM llm WHERE org_id=${org}$ AND status='active'", {"org": org_id}) + names = [getattr(r, "name", "") or "" for r in (recs or [])] + return (len(names) == 0), names + except Exception: + return False, [] + + def _get_db(): from sqlor.dbpools import DBPools db = DBPools() @@ -1158,6 +1175,19 @@ async def role_agent_run(project_id, role, agent_id=None, model_name=None): task_id = task.id title = getattr(task, "title", "") or "" params_str = getattr(task, "params", "{}") or "{}" + # 机构 llm 检测:机构没配 llm → 冒泡问题暂停(LLM 都调不了,不能硬跑) + llm_missing, _names = await _check_org_llm(sor, org_id) + if llm_missing: + from .communication import raise_problem + qid = await raise_problem( + "need_info", + f"机构(org_id={org_id})未配置 LLM 模型,角色 agent 无法调用模型。" + f"请在「模型管理」为该机构配置可用模型后重试。", + role, tenant_id=project_id, task_id=task_id, + first_handler_role="agent.main_agent", suspend_task=True, + ) + logger.warning(f"role_agent_run: org llm missing, task={task_id} org={org_id}") + return {"status": "need_info", "task_id": task_id, "question_id": qid} workspace_dir = await _get_workspace_dir(sor, project_id) try: @@ -1564,6 +1594,19 @@ async def pm_review_run(project_id, agent_id=None, model_name=None): task_id = task.id title = getattr(task, "title", "") or "" task_role = _normalize_role(getattr(task, "role", "") or "") + # 机构 llm 检测:机构没配 llm → 冒泡问题暂停 + llm_missing, _names = await _check_org_llm(sor, org_id) + if llm_missing: + from .communication import raise_problem + qid = await raise_problem( + "need_info", + f"机构(org_id={org_id})未配置 LLM 模型,PM 审核无法调用模型。" + f"请在「模型管理」为该机构配置可用模型后重试。", + "agent.pm", tenant_id=project_id, task_id=task_id, + first_handler_role="agent.main_agent", suspend_task=True, + ) + logger.warning(f"pm_review_run: org llm missing, task={task_id} org={org_id}") + return {"status": "need_info", "task_id": task_id, "question_id": qid} workspace_dir = await _get_workspace_dir(sor, project_id) try: @@ -1805,6 +1848,19 @@ async def qc_review_run(project_id, agent_id=None, model_name=None): task_id = task.id title = getattr(task, "title", "") or "" task_role = _normalize_role(getattr(task, "role", "") or "") + # 机构 llm 检测:机构没配 llm → 冒泡问题暂停 + llm_missing, _names = await _check_org_llm(sor, org_id) + if llm_missing: + from .communication import raise_problem + qid = await raise_problem( + "need_info", + f"机构(org_id={org_id})未配置 LLM 模型,QC 检查无法调用模型。" + f"请在「模型管理」为该机构配置可用模型后重试。", + "agent.qc", tenant_id=project_id, task_id=task_id, + first_handler_role="agent.main_agent", suspend_task=True, + ) + logger.warning(f"qc_review_run: org llm missing, task={task_id} org={org_id}") + return {"status": "need_info", "task_id": task_id, "question_id": qid} workspace_dir = await _get_workspace_dir(sor, project_id) try: