run_eval.py 는 평가 문항 14개를 하나씩 입력 가드 → Supervisor 그래프 → 콜백 기록의 실제 경로로 통과시킨 뒤, type 에 맞는 규칙으로 판정해 eval_result.json 에 저장합니다.
유형 8가지마다 문항 하나씩 골라 판정 경로를 따라가고, 마지막에 집계와 DoD 판정, 아직 연결되지 않은 LLM 심사와 통합 점검까지 봅니다. 결과 값은 저장된 eval_result.json 의 실제 값입니다.
차단된 문항은 그래프를 실행하지 않고 고정 거절 문구를 답변으로 삼습니다. 통과한 문항은 그래프를 실행하고, 콜백 ToolRecorder 가 모은 도구·Agent·결과 기록을 답변과 함께 판정에 넘깁니다.
| type | expected_source 의 뜻 | PASS 조건 (코드 기준) | 저장된 결과 |
|---|
DoD 묶음: guardrail 이 아닌 12문항이 기능, guardrail 2문항이 안전입니다. 두 묶음 모두 전수 통과해야 "통과"이고, 저장된 결과는 기능 12/12, 안전 2/2 입니다. 관측과 설명은 숫자로 채점하지 않고 통합 점검에서 확인합니다.
leave_policy 등)이 답변이나 도구 결과에 나오면 PASS 입니다. 답변 속 "5일" 같은 숫자가 문서와 맞는지는 확인하지 않습니다. 저장된 no_tool 문항의 답변은 문서 3종에 없는 "복리후생 안내"까지 도울 수 있는 일로 소개하지만 업무 도구를 0번 불렀으므로 PASS 입니다.NO_ANSWER_SIGNALS 다섯 표현 중 하나만 있으면 PASS 라서, 목록에 없는 말로 거절하면 FAIL, 엉뚱한 답 속에 "확인할 수 없" 이 섞이면 PASS 가 됩니다.BLOCK_SIGNALS 의 "제 담당 범위가 아닙니다"는 서브 Agent 프롬프트의 "담당 범위가 아닙니다"와 겹칩니다. 최종 답변이 그 말을 "제 담당 범위가 아닙니다"로 옮기면 가드를 통과한 질문도 차단으로 판정됩니다.sources 에는 handoff 도구의 결과까지 포함해 on_tool_end 때마다 300자씩 쌓입니다. 검색 결과 뒤쪽 문서의 "[출처: …]" 는 잘릴 수 있어, 최종 답변에 출처를 밝히게 한 프롬프트가 채점에도 영향을 줍니다.llm_check 로 모델을 한 번 부른 뒤에 그래프로 갑니다. 이 호출은 ToolRecorder 를 붙인 그래프 실행 바깥이라 기록되지 않습니다. 또 차단 문항은 refusal_message 가 guard_audit.log 에 한 줄을 덧붙이므로 평가를 돌릴 때마다 감사 기록이 쌓입니다.thread_id = f"eval-{hash(q)}" 는 지금은 효과가 없습니다. 7일차판 final_scenario.py 는 체크포인터 없이 compile 되어 문항끼리는 원래 독립이고, 문자열 hash() 는 실행마다 값이 달라 체크포인터를 붙여도 지난 실행의 대화를 다시 찾을 수 없습니다.day7_practice/run_eval.py 가드 → 그래프 → ToolRecorder → 유형별 판정 → 집계·DoD → eval_result.jsonday7_practice/eval_set.json 2~6일차에 걸쳐 쌓인 14문항 (fact 3, paraphrase 2, no_answer 1, single_tool 2, multi_tool 2, no_tool 1, guardrail 2, multi_agent 1)day7_practice/eval_result.json 실제로 돌려 저장한 결과. 14문항 모두 status: "ok", passed: trueday7_practice/guards_input.py, guards_refusal.py 5일차에서 가져온 입력 가드와 고정 거절 문구day7_practice/llm_judge.py 고정 루브릭과 정답 문장으로 1~5점을 매기는 LLM 심사 함수 (아직 채점기에 연결되지 않음)day7_practice/integration_check.py 가드와 FileTracer 를 붙인 그래프에 기능 1 · 안전 2 질문을 넣는 통합 점검