#!/usr/bin/env python3
"""블라인드 pairwise LLM 저지 — 항목별로 A/B 순서를 랜덤화해 4개 기준 + 종합 판정.

저지 모델: gpt-5.6-luna (reasoning low). 자기편향 가능성은 리포트에 명시.
"""
import json, time, random, threading, queue
import requests

SP = "/private/tmp/claude-501/-Users-ymjung-Project-wordbit2/4ac326f2-ee60-44f4-ab5c-4b7aff5d25e6/scratchpad"
URL = "https://all-ai-proxy.brainup.workers.dev/v1/responses"
HEADERS = {
    "Content-Type": "application/json",
    "X-Proxy-Secret": "8e0851268439bdeb5338c17c2152fa0d38a559aceb85c0485e64481b95de653d",
    "X-Client-Key": "575f3f6bc071de763a61d755e828aefe10ca28bd07be474adbc9827c7a9fe46b",
    "X-App-Id": "net.wordbit.jpkr",
}

JUDGE_SYSTEM = """당신은 베트남어-한국어 언어교육 전문가이자 응답 품질 평가자다.
한국인 베트남어 왕초보 학습자용 단어 해설 두 개(A, B)를 비교 평가한다.
두 해설은 같은 단어에 대한 것이다. 어느 시스템이 생성했는지는 알 수 없다.

각 기준마다 "A", "B", "tie" 중 하나로 판정하라:
1. accuracy: 단어 뜻 설명과 베트남어 예문의 문법·어휘 정확성 (오류가 적은 쪽이 승)
2. pronunciation: 한글 발음 표기가 실제 베트남어 발음(성조 포함)에 가까운 정도
3. usefulness: 왕초보 학습자에게 실질 도움되는 정도 (예문 수준 적합성, 관련어휘 품질, 팁·문화정보의 사실성)
4. korean_fluency: 한국어 해설의 자연스러움

마지막으로 overall("A"/"B"/"tie")과 reason(한 문장, 한국어)을 제시하라.
반드시 아래 JSON만 출력하라. 다른 텍스트 금지:
{"accuracy":"A|B|tie","pronunciation":"A|B|tie","usefulness":"A|B|tie","korean_fluency":"A|B|tie","overall":"A|B|tie","reason":"..."}"""

def judge_one(pair):
    q = pair["question"]
    body = {
        "model": "gpt-5.6-luna",
        "input": [
            {"role": "developer", "content": [{"type": "input_text", "text": JUDGE_SYSTEM}]},
            {"role": "user", "content": [{"type": "input_text", "text":
                f"[입력 단어 데이터]\n{q}\n\n[해설 A]\n{pair['A_text']}\n\n[해설 B]\n{pair['B_text']}"}]},
        ],
        "stream": False,
        "max_output_tokens": 5000,
        "reasoning": {"effort": "low"},
        "executionMode": 5,
    }
    for attempt in range(3):
        try:
            r = requests.post(URL, headers=HEADERS, json=body, timeout=(15, 240))
            if r.status_code != 200:
                time.sleep(3); continue
            resp = r.json()
            texts = []
            for out in resp.get("output", []):
                if out.get("type") == "message":
                    for c in out.get("content", []):
                        if c.get("type") == "output_text":
                            texts.append(c.get("text", ""))
            raw = "".join(texts).strip()
            if raw.startswith("```"):
                raw = raw.strip("`").lstrip("json").strip()
            v = json.loads(raw)
            v["id"] = pair["id"]; v["content"] = pair["content"]
            v["A_model"] = pair["A_model"]; v["B_model"] = pair["B_model"]
            return v
        except Exception:
            time.sleep(3)
    return {"id": pair["id"], "content": pair["content"], "error": True,
            "A_model": pair["A_model"], "B_model": pair["B_model"]}

def worker(qq, out, lock):
    while True:
        try: pair = qq.get_nowait()
        except queue.Empty: return
        v = judge_one(pair)
        with lock:
            out.write(json.dumps(v, ensure_ascii=False) + "\n"); out.flush()
        qq.task_done()

def main():
    recs = [json.loads(l) for l in open(f"{SP}/results.jsonl")]
    ok = {}
    for r in recs:
        if r.get("ok"):
            ok.setdefault(r["id"], {})[r["model"]] = r
    rng = random.Random(7)
    pairs = []
    for iid, d in sorted(ok.items()):
        if "gpt-4.1-mini" in d and "gpt-5.6-luna" in d:
            a, b = ("gpt-4.1-mini", "gpt-5.6-luna") if rng.random() < 0.5 else ("gpt-5.6-luna", "gpt-4.1-mini")
            pairs.append({"id": iid, "content": d[a]["content"], "question": d[a]["question"],
                          "A_model": a, "B_model": b, "A_text": d[a]["text"], "B_text": d[b]["text"]})
    print("pairs to judge:", len(pairs))
    qq = queue.Queue()
    for p in pairs: qq.put(p)
    lock = threading.Lock()
    out = open(f"{SP}/judgments.jsonl", "w")
    ts = [threading.Thread(target=worker, args=(qq, out, lock), daemon=True) for _ in range(6)]
    for t in ts: t.start()
    for t in ts: t.join()
    out.close()

    # 집계 (A/B → 모델명 환산)
    js = [json.loads(l) for l in open(f"{SP}/judgments.jsonl")]
    crits = ["accuracy", "pronunciation", "usefulness", "korean_fluency", "overall"]
    tally = {c: {"gpt-4.1-mini": 0, "gpt-5.6-luna": 0, "tie": 0} for c in crits}
    errors = 0
    for j in js:
        if j.get("error"): errors += 1; continue
        for c in crits:
            v = j.get(c)
            if v == "A": tally[c][j["A_model"]] += 1
            elif v == "B": tally[c][j["B_model"]] += 1
            else: tally[c]["tie"] += 1
    print(json.dumps({"judged": len(js) - errors, "errors": errors, "tally": tally}, ensure_ascii=False, indent=1))
    json.dump(tally, open(f"{SP}/judge_tally.json", "w"), ensure_ascii=False, indent=1)

if __name__ == "__main__":
    main()
