Repository navigation
Fix/#60 change interview score - #61
Conversation
kimwuju
left a comment
There was a problem hiding this comment.
competency-v1 채점 경로를 봤습니다. 매핑·근거 슬롯·등급 상한·집계, 전 직무(15개) solo/multi 시스템 프롬프트의 v4 기준 교체, strict 도구 스키마 제약, API 서버(#121) 콜백 수신 형식은 확인했고 문제를 찾지 못했습니다. 남은 문제 2건을 인라인으로 남깁니다.
| ] | ||
| breakdown = compute_breakdown(owned) | ||
| if owned and isinstance(owned[0], QuestionScore): | ||
| scores = summarize_competency_session([cast("QuestionScore", item) for item in owned], None, persona=True) |
There was a problem hiding this comment.
동기 문항만 맡은 면접관은 답을 잘해도 면접관 점수가 0점으로 나갑니다
MOTIVATION은 WEIGHTS에 없어서 종합 가중 평균에 들어가지 않고, summarize_session은 관측된 축이 없으면 total_score를 0으로 돌려줍니다. 세션 전체에는 기술 문항이 있어 괜찮지만, 면접관별 점수는 그 면접관이 맡은 문항만 넣기 때문에 문제가 됩니다.
N:1 HR 면접관은 권장 카테고리가 motivation·growth·collaboration이고 question_count가 1일 수 있어서, 동기 문항 하나만 받는 경우가 실제로 생깁니다. 이때 콜백은 score: 0, axes 전부 null, motivation.score: 100이 됩니다. 화면에는 "HR 면접관 0점"으로 보입니다. 미분류 문항에서 inferred_primary가 null로 온 경우도 같습니다.
재현: resolve_targets("motivation", "BACKEND", "HR") 문항 하나를 response 4, motivation 근거 4로 만들어 summarize_session([q], None, persona=True)를 부르면 total_score == 0, payload["motivation"]["score"] == 100입니다.
기존 코드는 "0점"과 "평가 대상 없음"을 구분하려고 담당 답변이 없는 면접관을 null로 보냈습니다. 같은 이유로, 가중 축이 하나도 관측되지 않은 면접관은 score를 null로 보내는 게 맞아 보입니다(scoreBreakdown은 남겨서 동기·응답 점수는 보이게).
| @@ -94,6 +99,11 @@ def parse_result(case: dict[str, Any], content_blocks: list[dict[str, Any]], too | |||
| expected = {question["id"] for question in case["questions"]} | |||
| if set(by_id) != expected or len(feedbacks) != len(expected): | |||
| raise ValueError("질문별 피드백 id 불일치") | |||
There was a problem hiding this comment.
competency-v1 평가 실행에서는 문항 누락 재시도가 일어나지 않아, 전환 기준의 실패율 비교가 v1에 불리하게 나옵니다
feedback_attempts.evaluate는 IncompleteGradingError일 때만 재시도합니다. axis-v4는 parse 전에 validate_legacy가 운영 파서를 먼저 돌려서, 문항이 빠지면 IncompleteGradingError가 나고 재시도됩니다. competency-v1은 그 단계가 없어서 여기 parse_result의 id 검사가 먼저 걸리고, ValueError("질문별 피드백 id 불일치")로 바로 실패합니다. 운영 parse_submission은 같은 응답에 IncompleteGradingError를 내고 한 번 더 부르므로, 평가 결과와 운영 동작이 다릅니다.
그래서 competency_gate의 "재시도 후 실패율 ≤ 기존 및 2%"는 v4는 재시도 후, v1은 재시도 없이 잰 값을 비교합니다. 운영 전환 판단이 이 값에 걸려 있어 결과가 틀리게 나옵니다.
competency-v1일 때는 이 id 검사보다 먼저 competency_run.parse_result(운영 parse_submission)를 돌리거나, 이 검사 실패를 IncompleteGradingError로 바꿔야 할 것 같습니다.
danjee2009
left a comment
There was a problem hiding this comment.
요청·응답 계약, competency-v1 채점/근거 검증, SOLO·MULTI 디스패치, 평가 도구와 테스트 변경을 검토했습니다. 확인된 실질적인 문제는 없습니다. GitHub의 behavior 및 checks 작업은 통과했습니다. 실제 LLM 반복 평가와 사람 평가 절차는 코드 리뷰에서 실행하지 않았으며, 문서에 적힌 대로 운영 전환 전 별도 검증이 필요합니다.
There was a problem hiding this comment.
코드 리뷰했습니다. 머지를 막을 버그는 찾지 못했습니다.
확인한 내용
docs/feedback-scoring-contract-v2.md와 구현이 일치합니다: 응답 등급별 주 역량 상한, 보조 역량은 등급 1 이상만 집계, 관측된 축만으로 가중 평균, 면접관 점수 null 조건, 답변이 1개면 consistency/reliability null, v4 문항 피드백에는 새 필드 미포함.category: 형식이 틀린 값은 422 대신 미분류로 처리하고, FOLLOW는 부모 카테고리를 이어받습니다. MULTI 질문 DTO도FeedbackQuestion을 상속하므로 category가 빠지지 않고 전달됩니다.- MULTI 질문 생성의 category enum(비기술 5종)은 비TECH 면접관 질문에만 적용됩니다. TECH 질문은
tech_questions로 따로 들어오므로 개발 카테고리 매핑이 그대로 유지됩니다. - 실패 콜백에는
result키가 없어서, debug 로그 분기의.get("result", {})체인에서 예외가 나지 않습니다. - API 서버의
ScoreBreakdownReader와reliabilityScore(nullable Integer)도 새 페이로드 모양을 받을 수 있습니다.
uv run pytest 결과 1535개 통과, 22개 건너뜀입니다.
No description provided.