from __future__ import annotations import re from app.core.constants import ACTION_TYPE_DEPLOY class IntentService: ENV_MAPPING = { "测试环境": "test", "测试": "test", "test": "test", "预发环境": "staging", "预发": "staging", "staging": "staging", "生产环境": "prod", "生产": "prod", "prod": "prod", } def parse(self, input_text: str) -> tuple[dict[str, str | None], list[str]]: parsed_intent: dict[str, str | None] = { "action_type": ACTION_TYPE_DEPLOY if self._is_deploy(input_text) else None, "app_code": self._extract_app_code(input_text), "env": self._extract_env(input_text), "version": self._extract_version(input_text), } missing_slots = [ slot_name for slot_name, value in parsed_intent.items() if slot_name in {"action_type", "app_code", "env", "version"} and not value ] return parsed_intent, missing_slots def _is_deploy(self, input_text: str) -> bool: lowered = input_text.lower() return "部署" in input_text or "deploy" in lowered def _extract_app_code(self, input_text: str) -> str | None: patterns = [ r"把\s*([A-Za-z0-9_-]+)", r"deploy\s+([A-Za-z0-9_-]+)", r"\b([A-Za-z0-9_-]+-service)\b", ] for pattern in patterns: match = re.search(pattern, input_text, re.IGNORECASE) if match: return match.group(1) return None def _extract_env(self, input_text: str) -> str | None: lowered = input_text.lower() for key, value in self.ENV_MAPPING.items(): if key.lower() in lowered: return value return None def _extract_version(self, input_text: str) -> str | None: match = re.search(r"\b\d+\.\d+\.\d+(?:[-._A-Za-z0-9]+)?\b", input_text) return match.group(0) if match else None