All notes

작은 모델이 이기는 자리

프론티어 모델은 데이터셋에 라벨을 한 번만 붙인다. 트래픽은 작은 모델이 계속 받아낸다. 진짜 어려운 7%를 누구한테 보낼지는 신뢰도 라우터가 정한다.

3 분 읽기서울과 나트랑에서 씁니다

"어떤 모델을 써야 하나"라는 질문은 대개 잘못 세운 질문이다. 분류에 가까운 일이라면 답은 모델 두 개와 임계값 하나다.

패턴: 라벨은 크게, 서빙은 작게

파이프라인이 대량으로 분류를 해야 할 때, 카테고리든 스팸이든 의도든 언어든, 항목마다 프론티어 모델을 부르지는 않는다. 데이터셋당 한 번만 부른다. 공들여 짠 루브릭으로 큰 모델이 과거 예시 3만 건에 라벨을 달게 하고, 그중 표본을 손으로 검수한 다음, 그 라벨을 우리 서버에서 도는 작은 모델로 증류한다. 프론티어 모델의 판단이 전기값만 내고 15ms에 서빙되는 무언가로 컴파일되는 셈이다.

어려운 꼬리는 라우터가 맡는다

const p = small.classify(x);            // ~15 ms, on-box, effectively free
if (p.confidence >= 0.92) return p.label;
return frontier.classify(x);            // ~1.5 s, the 7% that deserve it

우리 분포에서는 항목의 93%가 로컬에서 임계값을 넘고, 그 구간에서 프론티어 모델과의 일치율은 99%를 웃돈다. 애매한 7%만 비싼 두뇌로 넘어간다. 뒤섞은 비용은 모든 항목에 프론티어 모델을 부를 때의 100분의 1 수준으로 떨어지고, p50 지연은 초 단위에서 밀리초 단위로 내려간다. 분류기가 사용자 응답 경로 한복판에 앉아 있을 때는 이게 큰 차이를 만든다.

파인튜닝이 실제로 지는 지점

파인튜닝은 계속 다시 시험해 보지만 우리 일의 형태에서는 매번 프롬프팅에 진다. 문체, 형식, 정책 준수는 따뜻하게 데워진 프리픽스 캐시에 얹힌 few-shot 예시와 버전 관리되는 프롬프트로 다루는 편이 낫다. 수정은 몇 분이면 배포되고, 롤백은 몇 초면 되고, A/B도 깔끔하게 갈린다. 파인튜닝 모델은 반복 한 바퀴에 며칠이 걸리는 빌드 산출물이고, 베이스 모델이 좋아질 때마다 낡아 버리는데 요즘은 그게 자주 있는 일이다. 위의 증류 패턴은 파인튜닝이 값을 하는 예외인데, 그마저도 우리가 직접 호스팅하는 작은 오픈웨이트 모델로 증류하니 산출물은 우리 것으로 남는다.

드리프트 세금

증류한 모델은 얼어붙어 있지만 세상은 그렇지 않다. 그래서 라우터는 요청의 1%를 섀도 샘플로 떠서 프론티어 모델에도 끊임없이 함께 흘려보내고, 불일치가 임계값을 넘으면 우리에게 알림을 띄워 다시 라벨을 달고 다시 증류하게 한다. 작은 모델은 돌리기 싸고 그만큼 잊어버리기도 쉽다. "이건 지난봄에 자동화해 뒀지"가 "봄부터 조용히 오분류하고 있었네"로 썩어 가지 않게 붙잡아 주는 게 바로 이 섀도 샘플이다.