feat(saju-lab): interpret/prompt + schema — 12항목 + 궁합 SYSTEM_PROMPT (8 tests)
This commit is contained in:
60
saju-lab/app/interpret/schema.py
Normal file
60
saju-lab/app/interpret/schema.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""사주 + 궁합 응답 JSON 검증."""
|
||||
|
||||
VALID_CONFIDENCE = {"high", "medium", "low"}
|
||||
SAJU_ITEM_KEYS = {
|
||||
"기질", "오행밸런스", "지지상호작용", "신살영향",
|
||||
"재물운", "직업적성", "애정운", "건강운",
|
||||
"현재대운", "올해세운", "인생황금기", "종합조언",
|
||||
}
|
||||
|
||||
|
||||
def validate_saju_interpretation(parsed: dict) -> tuple[bool, str]:
|
||||
if not isinstance(parsed, dict):
|
||||
return False, "응답이 dict가 아님"
|
||||
for k in ("items", "summary", "advice", "confidence"):
|
||||
if k not in parsed:
|
||||
return False, f"필수 필드 누락: {k}"
|
||||
if parsed.get("confidence") not in VALID_CONFIDENCE:
|
||||
return False, f"confidence 값 비정상: {parsed.get('confidence')}"
|
||||
|
||||
items = parsed["items"]
|
||||
if not isinstance(items, list):
|
||||
return False, "items가 list 아님"
|
||||
if len(items) != 12:
|
||||
return False, f"items는 12개 필요 (현재 {len(items)})"
|
||||
seen_keys = set()
|
||||
for i, it in enumerate(items):
|
||||
if not isinstance(it, dict):
|
||||
return False, f"items[{i}] dict 아님"
|
||||
for k in ("key", "title", "content", "evidence"):
|
||||
if k not in it:
|
||||
return False, f"items[{i}].{k} 누락"
|
||||
if it["key"] not in SAJU_ITEM_KEYS:
|
||||
return False, f"items[{i}].key 비정상: {it['key']}"
|
||||
if it["key"] in seen_keys:
|
||||
return False, f"items[{i}].key 중복: {it['key']}"
|
||||
seen_keys.add(it["key"])
|
||||
ev = it["evidence"]
|
||||
if not isinstance(ev, dict) or "saju_element" not in ev or "reasoning" not in ev:
|
||||
return False, f"items[{i}].evidence 형식 오류"
|
||||
if not ev.get("saju_element", "").strip() or not ev.get("reasoning", "").strip():
|
||||
return False, f"items[{i}].evidence 빈 문자열"
|
||||
return True, ""
|
||||
|
||||
|
||||
def validate_compat_interpretation(parsed: dict) -> tuple[bool, str]:
|
||||
if not isinstance(parsed, dict):
|
||||
return False, "응답이 dict가 아님"
|
||||
for k in ("summary", "strengths", "challenges", "advice", "confidence"):
|
||||
if k not in parsed:
|
||||
return False, f"필수 필드 누락: {k}"
|
||||
if parsed.get("confidence") not in VALID_CONFIDENCE:
|
||||
return False, f"confidence 값 비정상: {parsed.get('confidence')}"
|
||||
for k in ("strengths", "challenges"):
|
||||
v = parsed[k]
|
||||
if not isinstance(v, list) or not v:
|
||||
return False, f"{k}는 비어있지 않은 list 필요"
|
||||
for i, item in enumerate(v):
|
||||
if not isinstance(item, dict) or "title" not in item or "explanation" not in item or "evidence" not in item:
|
||||
return False, f"{k}[{i}] 형식 오류"
|
||||
return True, ""
|
||||
Reference in New Issue
Block a user