from __future__ import annotations import re from typing import Tuple class OutputValidator: def validate(self, query: str, qtype: str, output: str) -> Tuple[bool, str]: s = (output or "").strip() if not s: return False, "empty" # “秒でそれっぽい”を弾く if len(s) < 260: return False, "too_short" # ガード文禁止 bad = [ "もう少し具体化", "精度が上がります", "情報が不足", "受理しました", "章タイトル", "Available routes" ] if any(x in s for x in bad): return False, "guard_phrase" # 章タイトル列挙っぽい(名詞だけ箇条書き)を弾く # 例: "- Finite Bond Dimension Bottleneck" みたいなのが連続 lines = [ln.strip() for ln in s.splitlines() if ln.strip().startswith("-")] if lines: title_like = 0 for ln in lines[:10]: # 動詞/因果記号が無い if not re.search(r"(=>|because|therefore|implies|bound|<|>|ため|したがって|ゆえに|上限|制約)", ln, re.IGNORECASE): title_like += 1 if title_like >= 6: return False, "headings_only" # advanced_physicsならキーワード最低限 if qtype == "advanced_physics": need = ["χ", "N", "Page", "QES", "RT", "complexity"] hit = sum(1 for w in need if w.lower() in s.lower()) if hit < 2: return False, "missing_phys_terms" return True, "ok"