"""冲突严重程度分级纯函数。 依据: - 高(high):相似度 >= HIGH_CONFLICT_THRESHOLD → 制度文件核心条款直接冲突 - 中(medium):相似度 >= MEDIUM_CONFLICT_THRESHOLD → 程序/用词层歧义 - 低(low):其它(如命名相似但实质无关) """ from __future__ import annotations from typing import Tuple def classify_conflict_severity( similarity: float, thresholds: Tuple[float, float] = (0.85, 0.92), ) -> str: """根据条款相似度返回冲突等级。 thresholds = (medium_min, high_min),须 0 <= medium_min <= high_min <= 1。 返回:'high' / 'medium' / 'low'。 """ medium_min, high_min = thresholds if similarity >= high_min: return "high" if similarity >= medium_min: return "medium" return "low" def normalize_policy_text(s: str) -> str: """规范化制度文本:去空白 + 中文/英文标点统一。 用于语义比对前的预处理,确保章节编号差异不干扰相似度计算。 转换规则: - 全角空格 → 半角空格 - 全角 ASCII(数字 0-9 / 字母 A-Z a-z / 常见标点)→ 半角 - 合并连续空白为单空格 """ if s is None: return "" # 全角 ASCII 标点 → 半角(覆盖冒号/逗号/句号/分号/问号/感叹号/括号/方括号/引号) full_to_half_punct = { ",": ",", "。": ".", ":": ":", ";": ";", "?": "?", "!": "!", "(": "(", ")": ")", "【": "[", "】": "]", "『": "'", "』": "'", "「": "'", "」": "'", } out_chars = [] for ch in str(s): code = ord(ch) # 全角空格 if ch == " ": out_chars.append(" ") continue # 已映射的标点 if ch in full_to_half_punct: out_chars.append(full_to_half_punct[ch]) continue # 全角数字 0xFF10-0xFF19 → 0x30-0x39 if 0xFF10 <= code <= 0xFF19: out_chars.append(chr(code - 0xFEE0)) continue # 全角字母 0xFF21-0xFF3A / 0xFF41-0xFF5A → 半角 if 0xFF21 <= code <= 0xFF3A: out_chars.append(chr(code - 0xFEE0)) continue if 0xFF41 <= code <= 0xFF5A: out_chars.append(chr(code - 0xFEE0)) continue out_chars.append(ch) text = "".join(out_chars) # 合并连续空白为单空格 return " ".join(text.split()) def parse_policy_draft_id(s: str) -> str: """解析送审稿 ID:去空白 + 校验非空。 占位骨架的轻量校验,业务层后续接入更严格规则。 """ if s is None: raise ValueError("policy_draft_id 不能为空") s = str(s).strip() if not s: raise ValueError("policy_draft_id 不能为空") return s