법령해석 BMT
모델이 법령 위임 사슬을 타고 공무원처럼 답했는지 채점하는 도구.
회사 업무로 시작한 프로젝트다. 회사·발주처·사내 모델과 서버, 민원 원문, 채점 기준표 문구, 사내 측정 점수는 전부 비공개다. 여기 남기는 건 평가를 어떻게 설계했고 어디서 틀렸는지, 그리고 회사에 넘긴 뒤 개인 쪽에서 이어 가는 엔진의 구조뿐이다.
법령해석 BMT는?
모델에게 민원 질의를 주고, 모델이 법령 위임 사슬(법 → 시행령 → 시행규칙 → 고시·별표)을 도구로 타고 내려가 공무원식 회신을 쓰는지 채점하는 평가 도구다. 대상 모델을 법령 조회 MCP 서버에 물려 실행하고, 도구 호출 기록과 최종 답변을 정답지에 대고 형식·내용·층 세 축으로 따로 채점한다.
회사에서 2026년 9월 중순부터 10월 초까지 만들어 회사에 넘겼고, 지금은 개인 쪽 로컬 엔진(saegim-bench)으로 옮겨 이어 간다. 채점기는 새김 Eval의 eval_core를 사본 없이 그대로 쓴다. 이름이 비슷한 한국어 LLM 벤치마크와는 다른 프로젝트다. 그쪽은 정답지 대조형 학술 벤치이고, 이쪽은 도구를 타는 경로와 회신 형식을 잰다.
왜 만들었나
처음엔 관찰 실험이었다. 법률 조문에서 시행규칙, 고시까지 내려가는 사슬을 모델이 따라가는지 보려고, 답을 아는 사람이 대화에 끼면 결과가 오염되니 별도 세션에 질문만 던지고 같은 질문을 세 번 독립으로 돌렸다.
그런데 요약본에 쓰인 핵심 용어의 출처를 로그로 되짚어 보니 검색 결과가 아니라 모델의 사전 지식이었다. 조문 번호도 먼저 추측하고 나중에 확인하는 순서였다. 답이 맞아 보여도 도구를 탔는지는 기록을 봐야 안다. 여기서 "답변만 채점하지 않고 호출 기록까지 채점한다"는 방향이 섰다.
그리고 사흘 뒤 목적을 한 번 고쳤다. 조사 문서를 다시 읽으니 작은 모델이 사슬을 못 타는 문제만 주 목적으로 잡혀 있었고, 더 근본적인 문제가 빠져 있었다. 공무원이 쓴 정답을 LLM 심판이 표현 차이만으로 오답 처리한다는 것이다. 공무원은 "의무가 발생합니다"라고 쓰고 모델은 "조건에 따라 해당될 수 있습니다"라고 쓰는데, 결론 라벨을 맞춰 보면 같은 결론이 틀린 답이 된다.
그래서 목표를 **「공무원처럼 답했는가」**로 다시 세웠다. 근거 조문을 밝혔는지, 단서를 반영했는지, 질문마다 답했는지, 확인할 곳을 적었는지 같은 형식 축을 평가의 본체로 올리고, 결론은 라벨이 아니라 실질이 같은지(결론 동치)로 본다. 사슬 추적은 그중 한 축이 됐다.
구조
실행 틀은 셋이다. OpenAI 호환 모델은 엔진의 도구 루프로, Claude 는 Claude Code CLI 로, 그리고 현업 검색 파이프라인을 물리는 자리가 하나 더 있다. 결과 표에 어느 틀로 돌았는지를 반드시 드러낸다. 틀이 다르면 점수 차이가 모델 탓인지 틀 탓인지 가를 수 없기 때문이다.
심판은 판정만, 점수는 코드
채점 설계의 뼈대는 심판에게 점수를 맡기지 않는 것이다.
3점 척도에 점수별 서술문을 붙인 이유는 간단하다. 서술문 없는 3단 척도에서 심판이 가운데를 자의로 고르는 것은 이미 알려진 실패 원인이다. 그래서 기본은 이진이고, 부분 점수가 필요하면 항목을 쪼갠다. 근거 조문 명시라면 결론마다, 질문 대응이라면 질문마다 따로 이진 판정하고 그 비율을 항목값으로 쓴다.
해당 없음과 라벨 없음은 같은 칸에 담지 않는다. 쟁점이 없어 언급하지 않은 것과, 정답지에 기대값이 없어 채점을 못 한 것은 다른 사실이다. 판정 상태를 「판정 / 해당없음 / 라벨없음 / 무효」 네 갈래로 못 박았다.
관문
근거 없는 인용, 출처 오기, 틀린 단정은 점수에 섞지 않고 관문으로 뺐다. 점수가 높아도 없는 조문을 인용했으면 회신으로 쓸 수 없다. 섞으면 이 결함이 다른 항목의 점수에 묻힌다.
형식, 내용, 층은 따로 싣는다. 합치면 형식이 좋고 내용이 틀린 답과, 내용이 맞고 형식이 엉성한 답이 같은 점수로 보인다. 판정 순서도 그렇게 짰다. 관문을 어기면 바로 탈락이고 총점을 아예 내지 않는다. 참고용 총점도 안 보인다. 보이면 결국 점수로 읽히기 때문이다.
심판 한 표가 기권하면 관문 판정이 동수가 되고, 동수를 위반으로 치면 모델 전체가 탈락했다. 반대로 통과로 치면 검사하지 않은 것을 통과시킨다. 그래서 판정 못 한 관문이 있으면 결과를 보류로 낸다. 기권을 0 으로 바꿔 적지 않는다.
무효 문항을 전부 평균에서 빼면 역설이 생긴다. 어려운 문항일수록 턴 초과·시간 초과로 무효가 되고, 그걸 빼면 점수가 오른다. 턴·시간 초과나 너무 짧은 답처럼 모델 탓인 무효는 0점으로 세고, 호출 실패 같은 서버 탓만 평균에서 뺐다.
과단정은 한 번 갈랐다. 처음엔 하나의 관문이었는데 너무 엄격해서, 결론이 맞아도 근거를 덜 열었다는 이유로 전체가 떨어졌다. 회신이나 조문 원문과 어긋나는 틀린 단정만 관문으로 두고, 확인하지 않은 단정은 감점으로 내렸다. 조문보다 약하게 말한 것은 깎지 않고, 의무를 재량으로 바꿔 쓴 것은 깎는다.
심판에게 무엇을 주나
심판 오판의 원인은 대개 심판이 아니라 심판에게 준 재료였다.
| 오판 | 원인 | 바꾼 것 |
|---|---|---|
| 답변에 없는 내용을 일치로 판정 | 근거 확인 수단이 없음 | 답변에서 그대로 따온 문장을 근거로 받고, 채점기가 답변과 글자로 대조 |
| 맞는 인용을 출처 오기로 탈락 | 조문 이름만 보고 기억으로 판정 | 모델이 실제로 받은 조문 원문을 같이 넘김 |
| 「근거를 안 열었다」고 탈락 | 도구 응답이 제목만 넘어가 있었음 | 열어 본 조문 이름 목록 대신 원문을 주고, 채점기가 줄인 생략과 도구가 자른 생략을 구분 |
| 조문의 대우 명제를 반대 주장으로 읽음 | 기준에 경계가 없음 | 대우 명제, 다른 쪽 면 서술, 일부 누락은 출처 오기가 아니라고 기준에 적음 |
심판의 기억은 근거로 쓰지 않는다. 회신과, 모델이 실제로 열어 본 원문만 본다.
층 도달, 위임 사슬을 어떻게 셀까
층 축은 정답지에 적어 둔 층(법, 시행령, 고시, 별표 등)에 모델이 닿았는지를 본다. 이 축의 규칙은 세 번 바뀌었다.
첫째, 분모. 처음에는 정답지에 적은 모든 층을 다 타야 통과였는데, 기준 모델조차 늘 실패로 나왔다. 정답지에 사슬 밖 층이 섞여 있었기 때문이다. 위임 사슬에 든 층만 통과 기준으로 보고, 도달 비율을 점수로 바꿨다.
둘째, 순서. 한때 층을 순서대로 내려갔는지도 점수에 넣었다. 되돌렸다. 조문에서 별표로 곧장 가거나 별표를 보고 조문으로 되짚는 것도 정당한 경로라 순서를 벌점으로 매기면 오탐이 난다. 실측에서도 순서 판정은 어느 모델이든 같은 값이 나와 구분력이 없었다. 공개 에이전트 벤치마크들도 경로 강제를 보상에서 빼거나 꺼 둔다. 역행 횟수는 진단으로만 남긴다.
셋째, 사슬 표시를 없앴다. 사슬에 든 층만 세는 방식은 다른 구멍을 냈다. 회신의 핵심 답이 부칙에서 나오는데, 그 부칙이 사슬 밖으로 표시돼 있어서 부칙을 안 짚어도 만점이 되는 문항이 있었다. 같은 축의 위임 깊이는 적은 층 전부를 보고 있어 두 항목의 기준도 갈려 있었다. 사슬 표시 체크를 두 번 번복한 끝에 없애고, 정답지에 적은 층은 전부 짚어야 할 곳으로 통일했다.
그러자 정답지 AI 초안이 회신이 언급한 조문을 전부 층으로 뽑아 층이 몇 배로 불어났다. 문제를 채점 규칙에서 정답지 쪽으로 옮긴 셈이라, 정답지에 들어갈 층의 기준을 하나로 세웠다.
이 조문을 안 열었다면 회신의 결론을 쓸 수 있었나.
같은 조문이라도 문항마다 본론인지 곁가지인지가 다르니, 질문이 그 조문을 묻는지로 가른다.
위임 깊이에서도 하나 걸렸다. 기준 문서는 「닿은 층 중 가장 깊은 단계」인데 코드는 「첫 층부터 연속으로 닿은 개수」를 세고 있었다. 지난 실행 기록에 두 규칙을 다 적용해 값이 실제로 갈리는 것을 확인한 뒤 코드를 문서에 맞췄다.
작은 모델이 사슬 끝에 못 가던 이유
작은 모델이 사슬의 마지막 층(고시·별표)에 못 닿는 현상이 계속 나왔다. 처음엔 모델 성능 문제로 봤는데, 계산해 보니 산수 문제였다. 고시 전문을 통째로 가져오는 조회 하나의 응답이 작은 모델의 컨텍스트 창보다 컸다. 그 층은 닿는 것 자체가 불가능했다.
창을 먹는 건 도구 응답만이 아니었다. 도구 정의와 시스템 프롬프트도 상당한 몫을 차지해서, 규칙을 넣어 행동을 고칠수록 창이 줄어드는 구조였다. 템플릿이 실제로 허용하는 도구만 주는 걸러내기를 넣었다.
자르기에는 원칙을 하나 박았다. 도구 응답은 도구 서버에서 자르지 않는다. 채점은 원문으로 하고, 모델에게 건넬 때만 자른다. 이걸 지키고 나서야 하나가 드러났다. 작은 모델이 별표 층에 닿았다고 본 판을 다시 보니, 잘린 응답 구간 안에 실제 근거 문구가 없었다. 큰 모델이 사슬을 끝까지 탔다고 쓴 요약도 틀렸다. 고시 표가 고유번호순이라 판정을 가르는 행이 뒤쪽에 있었고, 응답 절단이 그 앞에서 일어나 큰 모델도 그 행을 본 적이 없었다.
답은 도구 구성을 나누는 것이었다. 법령 조회 서버에서는 검색과 본문 두 도구만 쓰고, 고시와 별표는 목차를 먼저 주고 조 단위·표 행 단위로 꺼내 주는 별도 서버로 옮겼다. 창 초과는 이걸로 풀렸다.
| 도구 하나로 전문 조회 | 도구 구성 분리 | |
|---|---|---|
| 고시 | 전문을 통째로 받는다 | 목차를 먼저 받고 필요한 조만 꺼낸다 |
| 별표 | 표 전체를 받는다 | 행 단위로 꺼낸다 |
| 작은 모델 | 응답 하나가 창보다 커서 자르거나 실행이 끝난다 | 창 초과가 풀리고 요점대조와 층 도달이 함께 올랐다 |
그 뒤로 해 본 시도들(새 프롬프트 템플릿, 표 구간을 정리해 주는 보조 도구, 답 양식을 채우게 하는 해석 강제)은 셋 다 반복 측정의 흔들림 폭을 넘지 못했다. 효과가 확인된 것은 도구 분리 하나다.
남은 격차는 조문을 못 찾아서가 아니라 찾은 조문을 민원 사실에 대입하는 자리에서 났다. 같은 규칙에서 반복해 틀린다. 의무 주체를 넓게 잡고, 수량 구간을 헷갈리고, 비교해야 할 수치를 다른 수치로 바꿔 비교한다. 로그를 따라가 보면 위임 문구를 보고도 하위 고시나 다른 법까지 찾아가야 할 때를 판단하지 못한다. 프롬프트로는 효과가 없어서 하네스 코드로 다루기로 했다.
고시 별표의 일반기준에 「어떤 경우에는 다른 별표의 값을 적용한다」는 안내가 있는데, 모델이 그 안내를 따라 내려간 적이 없었다. 모델에게 맡기는 것을 접고, 안내가 가리킨 별표의 같은 행을 도구가 같이 준다. 다만 어느 값이 최종인지는 도구가 판정하지 않는다. 도구가 결론을 쓰면 평가하는 것이 모델이 아니라 도구가 된다.
모델이 도구를 엉뚱한 서버로 부르는 일도 있었다. 이건 템플릿을 고치지 않고 하네스에서 흡수했다. 템플릿은 시험 대상이라서다. 교정 안내는 모델이 받는 응답에만 붙이고 저장하는 원문에는 넣지 않는다.
측정이 측정이 아니었던 자리
이 프로젝트에서 가장 많이 배운 곳이다. 점수가 나오는데 그 점수가 재고 있는 것이 모델이 아니었던 경우들이다.
| 걸린 것 | 무엇이 틀어졌나 |
|---|---|
| CLI 가 MCP 연결을 기다리지 않고 첫 턴 시작 | Claude 대상이 도구 없이 기억으로 답했다 |
| 고른 템플릿이 첫 메시지에 안 실림 | 템플릿 비교가 비교가 아니었다 |
| 분석 모델이 import 누락으로 늘 건너뜀 | 분석이 안 돈 것을 아무도 몰랐다 |
| 정답지 초안을 평가받는 모델이 만들고 있었음 | 기본값이 목록 첫 모델(비용 없는 모델)을 고르는 정책 때문. 초안 모델을 설정으로 따로 고정 |
| 측정이 휴지통으로 옮긴 옛 정답지로 돎 | 채점기 회귀 시험도 같이 조용히 건너뛰어졌다 |
| 형식 항목이 실험 템플릿을 재고 있었음 | 템플릿이 시킨 문구 때문에 모든 실행이 같은 항목에서 실패 |
요점대조가 성립하지 않았다
핵심 지표인 요점대조의 결함은 도구 전체를 읽기 전용으로 점검하다 나왔다. 설계 문서 대비 구현, 코드와 화면, 채점 잣대 셋으로 갈라 읽었다.
심판에게 정답지 요점을 주고 답변이 각 요점을 충족했는지 묻는데, 심판이 요점 이름을 표마다 자유롭게 썼다. 집계가 이름 문자열로 묶다 보니 정답지 요점이 몇 배로 불어났고, 단위마다 한두 표로 확정돼 다수결이 성립하지 않았다. 더 나쁜 건 심판이 빠뜨린 요점은 분모에서도 빠져 점수가 올라간다는 것이었다. 회신과 반대로 쓴 답이 "언급은 했다"로 부분 점수를 받기도 했다.
모든 실행에 같은 결함이 걸려 있어서 조건 사이의 방향은 남지만, 절대값과 차이의 크기는 믿을 수 없었다. 고친 방식은 이렇다.
- 정답지가 단위를 준 항목(요점, 질문, 단서)은 심판이 번호로 답하고 번호로 묶는다
- 표에서 빠진 번호는 기권이 아니라 미충족이다. 분모는 정답지 단위 수로 고정한다
- 답에서 단위를 나누는 항목은 이름으로 묶지 않는다. 표마다 비율을 내고 그 중앙값을 쓴다. 한 표가 유난히 잘게 쪼개도 한 표로 그친다
한 번 재서는 아무것도 말할 수 없다
같은 조건을 세 번씩 반복해 처음 재 봤더니, 한 문항의 점수가 바닥에서 만점까지 흔들렸다. 1회 측정으로는 작은 차이를 개선이라고 말할 수 없다. 이 뒤로 조건 비교는 3회 이상 반복으로 문서에 박았다. 반복 실행은 독립 표본이 아니라 한 문항의 묶음이라 오차 막대 대신 값을 하나씩 다 보인다.
정답지
정답지는 분모를 정한다. 정답지가 틀리면 모든 모델이 같은 방향으로 틀리게 채점되고, 그 오류는 점수 비교로는 절대 안 보인다.
- 사람이 안 본 것은 안 봤다고 표시한다. AI 가 채운 빈 칸에 검토 완료 표시가 붙어 있던 적이 있다. 지금은 AI 초안과 AI 교차 검토를 거친 것도 「확인 필요」로 남는다. 다만 사람 확인은 실행을 막는 관문이 아니라 진행 표시로만 쓴다
- 질문에 매단다. 공무원 회신이 질문마다 답하고 단서를 다는 구조라, 정답지도 요점·단서·해당 여부를 질문에 매다는 형태로 바꿨다. 질문 목록은 채점 대상과 다른 모델이 초안을 뽑고 사람이 검수해 한 번 고정한다. 실행마다 다시 뽑으면 분모가 흔들린다
- 원천 파일을 AI 에 통째로 읽히지 않는다. 비용이 들고, 원문을 지어낼 수 있고, 가리기 전의 개인정보가 나간다. 알려진 형식은 코드가 읽고 AI 는 문항 경계만 짚는다
- 세트 단위, 서버 작업. 폴더에 평평하게 쌓던 정답지를 세트 단위로 묶었다. AI 초안은 브라우저 탭에 매여 화면을 떠나면 멈췄는데, 서버 작업으로 옮겨 끝까지 돌게 했다
- 판 번호. 실행마다 쓴 정답지의 해시를 남기고, 채점 기준표에는 판 번호를 붙인다. 판이 다른 실행끼리는 「기준이 달라 비교 안 함」으로 보인다
회사에 넘기고 이어 가기
회사 쪽 도구는 인수인계용 단독 저장소로 떼어 넘겼다. 그 뒤 엔진을 새김 모노레포의 projects/saegim-bench로 옮겨 독립 프로젝트로 이어 간다. 동기화는 하지 않는다. 두 쪽은 여기서 갈라진다.
옮기면서 지킨 것은 회사 자료를 하나도 들이지 않는 것이다. 채점 기준표, 정답지, 프롬프트 템플릿, 실행 로그는 환경변수로 저장소 밖을 가리킨다. 저장소 안에는 기본 경로도 두지 않는다. 기본 경로가 있으면 언젠가 누군가 그 자리에 사본을 놓는다.
자료가 없는 것이 정상 상태라서, 앱은 그대로 뜨고 법령 BMT 만 「준비 안 됨」과 사유를 달고 선다. 시험도 그에 맞췄다. 기본은 지어낸 기준표로 돌고, 진짜 회사 자료에 기대야만 뜻이 있는 시험만 따로 표식을 달아 자료가 없으면 건너뛴다. 2026-10-06 기준 846개 통과, 34개 건너뜀이다. 회사 자료 없이 실행부터 결과 조회까지 끝까지 돌려 보는 시연용 BMT(지어낸 문항 세 개, 가짜 조회 도구)도 따로 있다.
구조는 계층으로 나눴다. 인터페이스, 응용, BMT 종류, 공용 부품, 포트, 도메인, 어댑터. 의존은 안쪽으로만 가고, import 경계를 시험이 검사한다. 새 BMT 는 폴더 하나와 등록 목록 한 줄로 붙는다. 법령해석은 첫 BMT 일 뿐이다.
Claude 대상과 심판은 이 맥에 로그인한 Claude Code CLI(구독)로 돈다. 구독 토큰을 파일, 환경변수, 이미지에 따로 두지 않으므로 뒷단은 컨테이너에 못 넣는다. 다른 사람이 접속해 내 구독으로 실행하게 하면 안 되니 127.0.0.1 에만 바인드한다. 컨테이너에는 법령 조회 서버만 올리고, 법제처 키도 그 안에만 둔다.
화면은 옮기지 않았다. 새김 웍스의 평가 화면이 이 로컬 엔진을 부르도록 갈아 끼웠다.
지금 상태와 남은 것
- 축별 과락선은 임시값이다. 합격선은 사람과 심판의 항목별 일치율을 잰 뒤 정하기로 했고, 그 일치율은 아직 없다
- 층 도달은 조문 이름 완전 일치로 판정해서 한 글자 차이로도 떨어진다. 찾을 문구로 판정하는 보강은 이번 범위 밖이다
- 근거 없는 인용은 계산이 아니라 심판이 판정한다. 계산 판정은 남은 과제다
- 현업 검색 파이프라인을 물리는 답변 경로는 자리만 있고 실제 API 로는 검증 전이다
- 웍스의 정답지 화면은 아직 사용자 검증 전이다
회고
모델을 재는 도구를 만들면서, 가장 많이 고친 건 모델이 아니라 재는 쪽이었다. 목적이 어긋나 있었고, 층 분모가 틀렸고, 심판에게 줄 재료가 모자랐고, 요점대조는 성립하지 않았고, 한 번 잰 결과는 흔들림에 묻혀 있었다. 점수가 나온다는 것과 그 점수가 무엇을 재는지 아는 것은 다른 일이었다.
그래서 이 도구의 기본값은 모르면 보류다. 판정 못 한 관문은 통과가 아니고, 기권은 0 이 아니고, 합격선이 없으면 숫자를 지어내지 않는다.