
    i              	           d Z ddlZddlZddlZddlmZmZ dZdZde	de
fdZd	e
de	fd
Zd	e
de	de	fdZde	d	e
de
fdZ	 dd	e
de	de	de
fdZy)u=   Judge 모듈 - 체크리스트 기반 스킬 결과물 채점    N)call_claudeestimate_tokensu  
아래 체크리스트의 각 항목에 대해 결과물을 평가하세요.
각 항목에 PASS 또는 FAIL로 답하고, 짧은 이유를 달아주세요.

[체크리스트]
{checklist_items}

[스킬 결과물]
{skill_output}

JSON 형식으로 응답:
{{
  "items": [
    {{"id": "item_id", "result": "PASS", "reason": "..."}},
    ...
  ],
  "total_score": 0.8,
  "summary": "..."
}}
   checklist_pathreturnc                     t        | d      5 }t        j                  |      }ddd       j                  dg       }t	        |      t
        kD  rt        dt
         dt	        |       d      |S # 1 sw Y   NxY w)u   YAML 체크리스트를 로드하여 dict로 반환.

    필드: name, version, description, items (list of {id, question, weight}), scoring

    Raises:
        ValueError: items가 6개를 초과하는 경우
    zutf-8)encodingNitemsu!   체크리스트 항목은 최대 u   개여야 합니다. 현재 u   개.)openyaml	safe_loadgetlen_MAX_CHECKLIST_ITEMS
ValueError)r   fdatar
   s       K/home/jay/workspace/.worktrees/task-2116-dev1/scripts/autoresearch/judge.pyload_checklistr   !   s     
nw	/ '1^^A&' HHWb!E
5z((<=Q<RRrsvw|s}r~  C  D  E  	EK' 's   A11A:	checklistc           
          g }| j                  dg       D ]S  }|j                  dd      }|j                  dd      }|j                  dd      }|j                  d| d| d	| d
       U dj                  |      S )u   체크리스트를 프롬프트용 텍스트로 변환.

    각 항목을 "- [id] question (weight: X)" 형식으로 출력.
    r
   id questionweight      ?z- [z] z
 (weight: )
)r   appendjoin)r   linesitemitem_idr   r   s         r   format_checklist_for_promptr$   3   s    
 Egr* E((4$88J+(C(s7)2hZz&CD	E
 99U    skill_outputc                 F    t        |       }t        j                  ||      S )u   judge 프롬프트를 조립)checklist_itemsr&   )r$   JUDGE_PROMPT_TEMPLATEformat)r   r&   r(   s      r   build_judge_promptr+   A   s*    1)<O '''! (  r%   response_textc           
         t        j                  d|       }|st        d| dd       	 t        j                  |j                               }|j                  dg       }|j                  dd	      }|j                  dg       D ci c]!  }|d
   t        |j                  dd            # }}d}	d}
|D ]N  }|j                  d
d	      }|j                  dd      }|j                  |d      }|dk(  rdnd}|
||z  z  }
|	|z  }	P |	dkD  r|
|	z  nd}|||dS # t        j                  $ r}t        d| d| dd       |d}~ww xY wc c}w )u  LLM 응답을 파싱하여 채점 결과 반환.

    Returns:
        {
            "items": [{"id": str, "result": "PASS"|"FAIL", "reason": str}, ...],
            "total_score": float,  # 0.0~1.0
            "summary": str,
        }

    total_score는 가중평균으로 재계산 (LLM 답변 신뢰 대신 직접 계산)

    Raises:
        ValueError: JSON 파싱 실패 시
    z\{[\s\S]*\}u6   응답에서 JSON을 찾을 수 없습니다. 응답: N   u   JSON 파싱 실패: u
   . 응답: r
   summaryr   r   r   r   g        resultFAILPASS)r
   total_scorer/   )	researchr   jsonloadsgroupJSONDecodeErrorr   float)r,   r   
json_matchr   excr
   r/   r"   
weight_maptotal_weightweighted_scorer#   r0   r   scorer3   s                   r   parse_judge_responserA   J   s     >=9JQR_`dadReQhijjaZZ
 0 0 23 "-E88Ir*G \e[h[hiprt[u#vSWDJdhhx6M0N$N#vJ#vLN xxb)hhx0-'S%&.( 4@#3E.</3K " -  a/uJ}Tc?R>UVW]``a $ws   #D &EE*D??Emodelc                     t        | |      }t        ||d      }t        ||       }t        |      |d<   t        |      |d<   |S )u   LLM을 호출하여 채점 수행.

    Returns: parse_judge_response 결과 + {"input_tokens": int, "output_tokens": int}
    i   )promptrB   
max_tokensinput_tokensoutput_tokens)r+   r   rA   r   )r   r&   rB   rD   r,   r0   s         r   judge_outputrH   }   sM      	<8FvUtLM!-;F,V4F>-m<F?Mr%   )zclaude-haiku-4-5-20251001)__doc__r6   r4   r   autoresearch.claude_runnerr   r   r)   r   strdictr   r$   r+   rA   rH    r%   r   <module>rN      s    C  	  C *  3 4 $4 C $ c c 0 0 0 0l -  
	r%   