42 lines
1.9 KiB
Python
42 lines
1.9 KiB
Python
"""LLM 结构化输出的校验和安全护栏。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pam_deploy_graph.constants import ALLOWED_ACTIONS
|
|
from pam_deploy_graph.models import LlmDeployPlan, LlmIntentResult, LlmModeDecision
|
|
|
|
VALID_INTENTS = {"deploy", "show_usage", "preview", "query_node_ips", "rollback"}
|
|
VALID_EXECUTION_MODES = {"fixed_runtime", "agentic_skill"}
|
|
VALID_RISK_LEVELS = {"low", "medium", "high"}
|
|
FORBIDDEN_TEXT = ("bash ", "powershell ", "deploy.sh", "deploy.ps1", "CLIENT_SECRET=")
|
|
|
|
|
|
def validate_intent_result(result: LlmIntentResult) -> None:
|
|
"""校验意图识别结果是否合法。"""
|
|
if result.intent not in VALID_INTENTS:
|
|
raise ValueError(f"非法意图: {result.intent}")
|
|
if not 0 <= result.confidence <= 1:
|
|
raise ValueError("意图置信度必须在 0 到 1 之间")
|
|
|
|
|
|
def validate_deploy_plan(plan: LlmDeployPlan) -> None:
|
|
"""校验部署计划中的 action 和文本安全性。"""
|
|
invalid = [action for action in plan.planned_actions if action not in ALLOWED_ACTIONS]
|
|
if invalid:
|
|
raise ValueError(f"计划包含非法 action: {', '.join(invalid)}")
|
|
combined_text = "\n".join([plan.summary, *plan.risk_notes])
|
|
lowered = combined_text.lower()
|
|
forbidden = [item for item in FORBIDDEN_TEXT if item.lower() in lowered]
|
|
if forbidden:
|
|
raise ValueError(f"计划包含禁止出现的可执行文本: {', '.join(forbidden)}")
|
|
|
|
|
|
def validate_mode_decision(result: LlmModeDecision, allowed_modes: list[str] | None = None) -> None:
|
|
"""校验模式决策结果是否合法。"""
|
|
if result.mode not in VALID_EXECUTION_MODES:
|
|
raise ValueError(f"非法执行模式: {result.mode}")
|
|
if result.risk_level not in VALID_RISK_LEVELS:
|
|
raise ValueError(f"非法风险等级: {result.risk_level}")
|
|
if allowed_modes and result.mode not in allowed_modes:
|
|
raise ValueError(f"模式 {result.mode} 不在允许集合内")
|