I got Jev to zero mistakes. I'm still using Flash-Lite.
Jev의 실수를 0으로 줄였지만, 여전히 Flash-Lite를 씁니다
MLH는 코드 검사기와 LLM 판단기를 고르는 라우터에서 Jev와 Gemini Flash-Lite를 실제 데이터로 비교했습니다. Jev는 프롬프트를 고치자 위험한 오판을 줄였고, 두 모델을 조합하면 단독 Flash-Lite보다 비용을 낮추면서 각자의 장점을 살릴 수 있었습니다.
- 주제
AI 요약
Major League Hacking(MLH)은 AI 코딩 에이전트 평가 도구 benchspec에서 검사 항목마다 적절한 검증기를 선택하는 라우터를 운영합니다. 파일 존재 여부나 glob 개수처럼 코드로 빠르고 정확하게 확인할 수 있는 항목은 결정적 검사기로 처리하고, 내용의 의미를 읽어야 하는 항목은 LLM 판단기에 맡깁니다. 라우터가 코드 검증기로 처리할 수 있는 일을 LLM에 보내면 비용이 늘지만, 코드가 확인하지 못하는 항목을 검증했다고 판단하면 잘못된 결과가 통과합니다. 글쓴이는 비용보다 신뢰 손실이 더 큰 실수라며, 애매하면 판단기로 넘기는 편이 안전하다고 설명합니다.
실제 검사 항목으로 비교한 라우터
기존 라우터에는 Google의 Gemini Flash-Lite를 썼습니다. 글쓴이는 Flash-Lite가 빠르고 저렴하며 분류 작업에 적합하다고 봅니다. 자신의 AI Studio 사용량을 기준으로 월간 LLM 호출의 99%가 Flash-Lite였고, 입력은 길고 출력은 짧은 분류 작업이 주된 용도였습니다. 새로 주목받은 TypeSafe의 Jev는 텍스트와 선택지를 받아 확률을 반환하는 결정 모델입니다. 출력 생성 없이 분류에 집중하며, 입력 토큰 100만 개당 0.042달러, 출력 비용은 무료라고 소개합니다.
MLH는 라우터 호출 하나만 Jev로 바꾸고, 같은 검사 항목으로 두 모델을 수천 번 실행했습니다. Jev는 실제 검사 8개에서 위험한 오판을 세 번 냈습니다. 의미를 읽어야 하는 두 항목을 정규식 검사기로 보냈고, 저장소 전체에서 .DS_Store 파일을 찾아야 하는 항목은 루트의 한 경로만 확인하는 검사기로 보냈습니다. 반면 Flash-Lite는 위험한 오판을 내지 않았지만, 코드로 확인할 수 있는 항목까지 판단기로 넘기는 과잉 보수적 선택을 두 번 했습니다. 글쓴이는 이런 선택은 비용만 조금 늘릴 뿐 신뢰를 해치지는 않는다고 구분합니다.
검사기의 맹점을 묻는 프롬프트
Jev는 문장을 문자 그대로 따르는 경향이 있습니다. 원래 프롬프트는 항목이 기계적으로 검증 가능한지 물었고, 예시를 더하자 Jev는 패턴을 맞추듯 검사기를 선택해 위험한 오판이 늘었습니다. 글쓴이가 효과를 본 수정은 한 문장이었습니다. “이 검사기가 통과했다고 가정해 보세요. 그래도 검사항목이 거짓일 수 있나요?”
예를 들어 정규식이 source: 행을 찾더라도 그 행이 올바른 동작을 가리키는지 확인하지 못합니다. 루트 경로에 .DS_Store가 없는지 검사해도 하위 폴더에 파일이 남았는지는 알 수 없습니다. 이처럼 검사항목의 모양이 아니라 검사기가 놓치는 부분을 묻도록 기준을 바꿨습니다. 정규식은 특정 파일에서 패턴이 있는지만 확인하며, 일치한 텍스트의 의미나 지시 대상을 판단하지 못한다고 정의했습니다. 예시를 추가하는 방식은 오히려 나빴고, 검사기의 한계를 직접 확인하는 절차가 효과를 냈다고 설명합니다.
수정한 프롬프트를 적용하자 Jev는 처음 시험한 8개 항목과 보유한 검사 항목에서 위험한 오판과 잘못된 검사기 선택을 내지 않았습니다. 튜닝에 절반을 사용하고 나머지 절반에서 확인한 결과도 0건이었습니다. 다만 모델마다 같은 효과가 나타난 것은 아닙니다. 둘 다 보지 않은 새 검사 항목을 만들자 Jev와 Flash-Lite 모두 오판했습니다. Jev는 같은 항목에서 반복해 틀리는 맹점을 보였고, 수정된 프롬프트로 35번의 위험한 실행을 0으로 줄였습니다. Flash-Lite는 같은 항목을 반복 실행할 때 약 5번 중 한 번 틀리는 변동을 보였으며 프롬프트 수정만으로는 크게 달라지지 않았습니다. 글쓴이는 반복되는 맹점은 프롬프트를 고칠 문제지만, 실행마다 달라지는 변동은 반복 측정할 문제라고 구분합니다.
더 강한 모델과 두 단계 구성
같은 기본 프롬프트로 모델을 비교했을 때 Gemini 3.8 Flash와 Opus 5.5는 오판하지 않았고, Flash-Lite는 약 5번 중 한 번 틀렸습니다. 하지만 더 강한 모델도 프롬프트에 좌우됐습니다. Jev를 고친 문구는 두 모델을 과도하게 판단 보류 쪽으로 밀었고, Opus의 정답 선택은 절반 이상 줄었으며 3.8 Flash는 정답을 하나도 내지 않았습니다. 더 비싸고 느린 모델이 서툰 프롬프트의 영향을 가릴 수는 있어도, 프롬프트의 영향 자체를 없애지는 않는다는 설명입니다.
글쓴이는 Berkeley Function Calling Leaderboard(BFCL)의 일부 항목에서도 비교했습니다. 모델은 적절한 함수를 고르고 인자를 작성하거나, 맞는 함수가 없다고 판단해야 합니다. 표본에서 정답이 ‘맞는 함수 없음’이라고 한 일곱 항목을 확인한 결과, Flash-Lite의 선택이 실제 질문에 맞았습니다. 글쓴이는 이를 공개 벤치마크의 라벨 오류로 판단해 해당 항목을 제외하고 저장소에 목록을 남겼습니다.
BFCL에서 Jev는 가장 높은 확률의 함수를 곧바로 고르면 맞는 함수가 없는 항목 중 약 13분의 1에서 오판했습니다. Flash-Lite는 약 25분의 1이었습니다. Jev는 확률 기준을 0.8로 높이면 오판율을 1%로 낮출 수 있지만, 판단 보류는 두 배로 늘었습니다. Flash-Lite는 기준값 조정 기능이 없지만, 함수 인자를 10번 중 9번 넘게 완전히 맞게 작성했습니다.
그래서 글쓴이는 Jev가 함수 선택을 맡고 Flash-Lite가 인자를 작성하는 두 단계 구성을 시험했습니다. Jev의 출력에는 선택한 검사기와 확률이 있지만, 정규식에 필요한 파일 경로와 패턴 같은 인자는 없습니다. Flash-Lite를 한 번 더 호출해 그 정보를 채웁니다. 이 호출은 작성할 인자가 있는 항목에만 실행되며, 프롬프트도 한 단계 구성에 쓰는 프롬프트의 약 7분의 1 길이입니다. 전체 항목 중 Flash-Lite 호출이 필요한 비율은 40% 미만이었습니다. 측정 비용은 검사 1,000건당 Flash-Lite 단독 0.52달러에서 Jev와 Flash-Lite 조합 0.10달러로 줄었습니다. BFCL에서도 조합 비용은 Flash-Lite 한 번 호출하는 비용의 절반보다 낮았습니다. 대신 평균 약 0.25초의 왕복 시간이 더 들고, 오판 특성은 Flash-Lite가 아니라 Jev의 라우팅과 확률 기준을 따릅니다.
dev.to 반응
- @arhancanli — 맹점과 실행별 변동을 나눈 부분이 가장 중요해 보이며, 수치를 세는 단위도 달라져야 합니다. Jev의 위험한 실행 35건은 매번 같은 몇 개 항목에서 나온 것이므로, 정보를 담는 단위는 실행이 아니라 서로 다른 검사 항목입니다. 그러면 “35에서 0”은 검사 항목 수를 뜻하며, 아마 5개에서 0개일 수 있습니다. 보지 않은 고유 항목 N개에서 0건이 나와도 95% 신뢰수준에서 실제 비율은 대략 3/N까지 가능하니, 0 옆에 N도 표시하면 좋겠습니다. Flash-Lite에는 반복 실행 전체를 합친 비율보다, 반복 중 결과가 모두 일치하지 않는 항목의 비율을 보여주는 항목별 변동률이 더 적절합니다. BFCL 결과에서도 두 모델은 같은 항목을 평가했으므로, 오판율 1.1%와 4.3%는 독립된 두 비율이 아니라 짝지어진 비교입니다. 한 모델만 함수를 선택한 항목 수를 세고 McNemar 검정을 해야 합니다. 0.8 기준을 같은 표본을 보면서 골랐다면 1.1%는 낙관적인 수치입니다. 프롬프트 수정 실험처럼 절반에서 기준을 고르고 나머지 절반에서 보고하면 해결됩니다. 찾아낸 ‘맞는 함수 없음’ 항목 일곱 개도 좋은 부산물입니다. 라벨을 고친 결과 Flash-Lite의 96.9%도 바뀌나요, 아니면 오판 항목만 바뀌나요?
- @earlgreyhot1701d — AdaL 해커톤에서 이번 주 Jev를 쓰려던 참이라, 실제 질문을 하나 보내기도 전에 이 글을 읽고 질문 작성법을 바꿨습니다. 제 작업도 글의 라우터와 비슷합니다. README의 주장이 코드와 맞는지 확인합니다. Jev가 README의 각 문장에 라벨을 붙이고, 결정적 검증기가 사실 여부를 판단하며, Claude Haiku가 결과를 설명합니다. Jev가 결정하고 글쓰기 모델이 작성하는, 글에서 찾은 분업 방식과 같습니다. “검사항목의 모양이 아니라 검사기의 맹점을 설명하라”는 문장을 가져가겠습니다. 가장 큰 실패는 틀린 ‘모순’ 판정인데, 글에서 말한 잘못된 통과와 같습니다. 확신이 없으면 제 스캐너는 “판단할 수 없음”이라고 합니다. README에 글쓴이를 출처로 적었습니다. 홍보 대신 시험해 주셔서 감사합니다. 🚀
- @kanunilabs — 예시를 넣자 Jev의 성능이 나빠졌다는 점이 흥미롭습니다. 모델이 실제로 도구로 확인할 수 있는지를 따지기보다 패턴을 맞추기 시작하면 프롬프트 예시가 늘 도움이 되지는 않는다는 점을 보여줍니다. 훨씬 더 크고 다양한 검사 항목으로 시험할 필요가 있다고 생각합니다.
원문: dev.to / 번역·요약: Trawling