Code › tail-villain

관찰한 행동만 평가하기

부분 인터뷰 transcript를 전체 인터뷰처럼 채점하지 않도록 평가 범위와 근거 상태를 분리한 과정

tail-villain의 인터뷰 평가를 다시 돌려보다가 이상한 점수가 하나 나왔다. transcript에는 인터뷰어의 첫 질문만 있었는데, contextual follow-up 점수가 1점이었다.

처음에는 프롬프트가 follow-up을 너무 엄격하게 보고 있다고 생각했는데, transcript를 다시 보면 후보자의 답변이 없었다. 후보자가 답하지 않았으니 인터뷰어가 이어서 물어볼 기회도 없었다.

그런데 점수는 이미 실패라고 말하고 있었다.

이건 모델이 조금 냉정한 평가를 한 문제가 아니었다. 평가 시스템이 관찰되지 않은 행동을 낮은 품질로 바꿔버린 문제였다. 첫 질문만 있는 transcript에서 follow-up을 못 했다고 벌점을 주면, 그 점수는 인터뷰어 품질이 아니라 평가 설계의 허점을 보여준다.


점수 하나로 다 말할 수 없었다

이전 평가 구조에서는 각 항목을 숫자로 만드는 데 집중했다. 페르소나가 잘 유지됐는지, 질문이 구체적인지, follow-up이 맥락을 이어 갔는지, 깊게 파고들었는지 같은 항목을 judge에게 넘기고 1점에서 5점 사이로 받았다.

완료된 인터뷰라면 이 방식이 어느 정도 말이 된다. 후보자가 답하고 인터뷰어가 이어서 물으며 여러 턴이 오갔다면 품질을 평가할 재료가 있기 때문이다. 하지만 opening만 있는 transcript에서는 첫 질문만 평가할 수 있고, 아직 존재하지 않는 follow-up이나 반복 여부까지 같은 방식으로 채점할 수는 없다.

평가 항목은 세 가지 상태로 나눴다. 관찰된 행동은 scored로 두고 1점에서 5점으로 평가하며, 인터뷰 흐름상 필요한 항목이지만 아직 transcript가 부족하면 insufficient_evidence로 둔다. 현재 맥락 자체에 적용되지 않는 항목은 not_applicable이다.

이 구분은 작아 보이지만 의미가 컸다. insufficient_evidence는 아직 판단하지 않겠다는 뜻이고, not_applicable은 이 세션에서는 묻지 않겠다는 뜻이라서 둘 다 낮은 점수가 아니다. 특히 opening-only transcript에서 follow-up과 probing depth, non-repetition을 낮은 점수로 만들지 않는 것이 중요했다.

평가는 엄격해야 하지만, 엄격함이 없는 증거를 만들어내면 안 된다.


judge에게 모든 판단을 맡기지 않았다

처음에는 프롬프트를 고치면 해결될 것처럼 보였다. 후보자 답변이 없으면 follow-up을 평가하지 말라고 쓰고, 근거가 부족하면 낮은 점수를 주지 말라고 더 분명히 말하면 될 것 같았다.

하지만 LLM judge에게 적용 가능성까지 매번 판단하게 두면 같은 문제가 반복된다. transcript에 후보자 입력이 있는지, 그 답변이 실질적인 답변인지, 인터뷰어 턴이 몇 개인지, Goal이나 Background 같은 참고 문맥이 붙어 있는지는 백엔드에서 안정적으로 알 수 있는 사실이다.

그래서 eligibility를 백엔드 계약으로 옮겼다. 후보자 입력 뒤의 인터뷰어 턴이 없으면 contextual follow-up은 근거 부족이고, 후보자의 실질적인 답변이 없으면 probing depth도 근거 부족이다. 인터뷰어 턴이 두 개보다 적으면 반복 여부를 판단할 수 없고, 참고 문맥이 없으면 personalization과 evidence grounding은 적용하지 않는다.

judge에게는 이 계약을 통과한 항목만 응답 스키마로 넘겼고, 코드가 이미 결정한 항목에서는 applicable 같은 필드도 아예 빼버렸다. 모델이 나중에 사실상 같은 결정을 다시 뒤집지 못하게 한 것이다.

이 방식은 LLM을 덜 믿어서 만든 게 아니라, 오히려 모델이 잘해야 하는 일에 집중시키기 위해서였다. transcript 안의 발화가 전문적인지, 질문이 구체적인지, 답변을 제대로 따라갔는지는 모델이 평가할 수 있지만, 후보자 답변이 아예 있었는지 같은 상태 판단은 프로그램이 더 잘한다.


opening, 진행 중, 완료를 따로 봤다

부분 transcript의 가장 위험한 점은 숫자가 너무 그럴듯하다는 데 있다. 첫 질문이 아주 좋으면 평균 점수도 좋아 보일 수 있고, 반대로 아직 기회가 없던 항목 때문에 낮아 보일 수도 있다. 둘 다 전체 인터뷰 품질이라고 말하면 틀린 해석이 된다.

그래서 평가 범위를 opening, in_progress, complete로 저장했다. opening은 진단용이라서 첫 질문의 전문성이나 구체성은 볼 수 있지만, 전체 점수는 항상 null로 둔다. 시작 질문 하나가 좋았다고 해서 좋은 인터뷰가 끝났다고 말할 수는 없기 때문이다.

진행 중인 세션은 필요한 대화 항목이 관찰되기 시작하면 임시 점수를 낼 수 있지만, 아직 모든 항목이 준비되지 않았다면 전체 점수를 만들지 않는다. 완료된 세션은 필요한 항목이 모두 점수화됐을 때 final aggregate를 내고, 중대한 실패가 있으면 점수 상한도 둔다. 겉으로는 여러 항목이 괜찮아 보여도, 같은 질문을 반복하거나 명백히 잘못된 근거를 말하면 전체 품질을 높게 둘 수 없기 때문이다.

이렇게 나누고 나니 평가 결과를 읽는 방식도 바뀌었다. opening 평가는 첫 질문 디버깅 자료이고, 진행 중 평가는 현재까지의 provisional signal이며, 완료 평가는 세션 전체에 대한 결과다. 같은 judge가 만든 숫자라도 생명주기가 다르면 의미가 달라진다.


개인화와 grounding도 분리했다

이 작업의 배경에는 RAG도 있었지만, 이번 글의 중심은 검색 지표가 아니다. RAG가 Goal과 Background를 잘 가져오는지는 별도의 관측 문제이고, 인터뷰어가 그 정보를 어떻게 쓰는지는 평가 문제다.

personalization과 evidence grounding을 따로 둔 이유도 여기에 있다. personalization은 사용 가능한 사용자 맥락을 필요할 때 잘 활용했는지를 보는 항목이다. 예를 들어 사용자가 특정 회사 경험이나 프로젝트 배경을 제공했다면, 그 정보가 질문을 더 구체적으로 만드는 데 쓰였는지를 본다.

evidence grounding은 인터뷰어가 후보자에 대한 사실을 말했을 때 그 사실이 제공된 근거에 의해 뒷받침되는지를 본다. 관련 맥락을 쓰지 않은 것은 personalization 점수에 영향을 줄 수 있지만, 그 자체가 grounding 실패는 아니다. 반대로 근거에 없는 회사명이나 경험을 단정하면, 아무리 개인화된 것처럼 들려도 grounding 실패다.

백엔드는 employer나 project name처럼 신뢰도 높은 구조적 match가 있을 때 grounding을 점수화하도록 했다. 반면 backend, SaaS, target role 같은 넓은 단어는 deterministic match로 보지 않았다. 그런 단어는 주제나 일반 질문에도 자연스럽게 나올 수 있어서, 사용자 근거를 실제로 썼다는 증거로 삼기 어렵다.

이 구분 덕분에 N/A가 도피처가 되지 않았다. 근거 없는 candidate-specific claim이 있으면 grounding은 적용 불가가 아니라 점수화 대상이고, 낮게 평가되어야 한다.


평가도 transcript의 스냅샷을 가져야 했다

과거 평가를 다시 열 때도 비슷한 경계가 필요했다. 세션은 계속 진행될 수 있기 때문에 예전 평가 화면이 현재 전체 대화를 보여주면 평가의 근거가 바뀐 것처럼 보이고, opening만 보고 저장한 평가 옆에 나중에 추가된 답변과 follow-up이 붙어 있으면 점수가 왜 그렇게 나왔는지 설명할 수 없어진다.

그래서 평가 결과에 evaluated message count를 저장하고, rubric version, judge model, 평가 범위, 항목별 근거와 점수도 같이 남겼다. UI에서 과거 평가를 열면 현재 세션 전체가 아니라, 그 평가가 실행될 때 존재했던 message prefix만 보여준다.

이건 작은 기록 필드처럼 보이지만 평가를 믿기 위한 조건이었다. judge의 점수는 항상 어떤 transcript를 보고 나온 결과여야 하고, 그 transcript는 시간이 지나도 바뀌지 않아야 하기 때문에 세션이 이어지더라도 과거 점수의 근거는 과거의 경계에 묶어 두어야 한다.

같은 세션을 대상으로 targeted re-evaluation도 가능하게 만들어서, rubric을 고칠 때마다 새 인터뷰를 만들 필요가 없어졌다. 같은 transcript snapshot을 새 기준으로 다시 평가하면, 프롬프트나 eligibility 변경이 실제로 어떤 차이를 만드는지 더 직접적으로 볼 수 있다.

이번 작업 뒤에 남은 기준은 관찰한 행동만 평가한다는 단순한 것이었다. 아직 일어나지 않은 행동이나 적용되지 않는 항목을 낮은 점수로 바꾸지 않고, 숫자가 어떤 증거 위에 서 있는지 끝까지 잃어버리지 않는 쪽이 더 중요했다.