오늘 소개할 리포는 Yeachan-Heo/ifllm-learn 이다 (MIT, Python). 태그라인이 프로젝트 전체를 요약한다 — “Train the if. Not the essay.” LLM 에게 장문 생성을 시키는 대신, 라벨 붙은 예제로 ‘타입 있는 결정’을 로컬에서 학습시키는 작은 리서치 툴킷이다. 그리고 이 리포가 흥미로운 진짜 이유는 기능이 아니라 태도다: 실패한 실험을 지우지 않고 리포에 그대로 남겨 둔다.

무엇을 하는 물건인가

파이프라인은 한 줄로 요약된다:

prompt + question + choices  →  answer + scores
              labels         →  LoRA 학습
        held-out outcomes    →  확률 캘리브레이션

입력(문서·메시지)과 질문, 그리고 2~16개의 선택지를 JSONL 로 주면, Apple Silicon 의 MLX 위에서 Qwen3.5-4B 에 LoRA 어댑터를 붙여 정답 선택지의 교차엔트로피로만 학습한다. 추론 때는 답을 “생성”하지 않는다 — 선언된 선택지 토큰들의 네이티브 로짓을 직접 읽어 softmax 를 취한다. 모델이 쓴 JSON 을 파싱해 고치는 루프가 아예 없고, 태스크별 분류 헤드를 설계할 필요도 없다. 출력은 answer·선택지별 logits·probabilities 가 담긴 타입 있는 결과다. 학습·추론 전부 로컬이라 API 키가 없다 (리포 기준 요구 사양은 Apple Silicon + Python 3.12+, 실측 환경은 M5 Max 128 GiB).

기반은 SemIfMLX-LM이고, README 가 명시하듯 Jev/TypeSafe 류의 비공개 학습 시스템 구현체가 아니다.

비트코인으로 시작해서, 정직하게 진 이야기

리포의 서사가 특이하다. 시작은 대놓고 나쁜 아이디어였다고 적는다 — “LLM 이 비트코인을 예측할 수 있을까?” 결과: 32개 테스트 행에서 빈도 베이스라인·프로즌 모델·학습 모델이 전부 똑같이 56.25%. 학습 모델의 검증 손실은 오히려 나빠졌다. 보통은 이 실험을 지우고 잘 된 것만 올리는데, 이 리포는 그 결과 파일을 results/bitcoin/ 에 보존하고 “트레이딩 시그널이 아니라 워크플로와 한계를 보여주려고 남겨 둔다”고 적는다.

그다음에야 증거가 입력 안에 있는 문제들 — 결제 상담 라우팅, 범위 밖(OOS) 판별, 계약서 체크리스트 — 로 넘어간다. 같은 모델, 같은 학습 루프, 데이터셋만 다르게.

실측 결과 — 이긴 것과 “더 흥미로운 것” (리포 공개 실측)

아래 수치는 리포가 공개한 단일 시드·고정 예산 실측이다(리더보드 제출이 아니라고 스스로 명시하고, 원 결과 파일과 재현 스크립트를 저장소에 보존한다):

데모 테스트 행 TF-IDF Frozen LLM LoRA LLM
BANKING77-10 (결제 의도 10종) 400 87.75% 87.75% 92.50%
CLINC banking-10 + OOS 1,300 77.77% 94.54% 93.69%
ContractNLI 단문 부분집합 170 40.59% 71.76% 72.35%
Bitcoin 탐색 토이 32 56.25% 56.25%

헤드라인 승리는 뱅킹 태스크의 +4.75%p (옵티마이저 업데이트 128회짜리 소예산 학습으로). 그런데 README 가 “더 흥미로운 결과”라고 부르는 건 CLINC 쪽의 트레이드오프다: 전체 정확도는 내려갔는데, 지원 의도 정확도는 77.33%→95.00%로 뛰고 범위 내 오거부율은 21.67%→2.00%로 떨어진 대신 OOS 재현율이 99.70%→93.30%로 후퇴했다. 리포는 이 중 예쁜 숫자 하나를 고르는 대신 양쪽을 다 표로 공개한다. ContractNLI 의 +0.59%p 도 “170개 결정 중 정답 1개 차이라 견고한 이득의 증거가 아니다”라고 스스로 김을 뺀다.

캘리브레이션 처리도 교과서적이다 — 온도 스케일링은 별도 held-out 세트에서 학습하고, “과신을 눅일 수는 있어도 승자 클래스를 바꿀 수는 없다” 고 명시한다. 캘리브레이션 전 학습 모델의 로그 손실이 CLINC·ContractNLI 에서 오히려 나빠졌던 것까지 숨기지 않고 적었다.

증거 설계 — “운 좋은 답변 스크린샷”의 반대편

이 리포에서 배울 만한 리서치 위생이 몇 개 있다:

  • 4분할 데이터: train / validation / calibration / test 를 분리하고, 텍스트는 문서 그룹 단위로, 시계열은 horizon purging 으로 누수를 점검한다.
  • 재현 아티팩트: 소스 리비전·데이터셋 해시·선택된 ID·어댑터 체크섬·원시 예측을 매 run 에 남기고, verify-run 이 새 프로세스에서 어댑터를 다시 로드해 저장된 출력이 재현되는지 검사한다.
  • create-only 출력: 출력 디렉터리는 덮어쓰기가 안 된다 — 실패한 실험이 조용히 사라지는 걸 구조로 막는다.
  • 로컬 리플레이 대시보드: python3 -m http.server 하나로 뜨는 시각화 랩이 있는데, 라이브 추론이 아니라 기록된 실험의 리플레이다. CDN·분석 스크립트·외부 서비스 없이 캘리브레이션 곡선·혼동 행렬·실제 학습 손실 트레이스를 열람한다.

Limitations 섹션도 마케팅 문서의 반대다: 범용 에이전트가 아니고, 지원 백엔드는 핀 고정된 Qwen3.5-4B/MLX 하나이며, 77개·150개 라벨을 16지선다에 욱여넣고 풀 벤치마크라 부르지 않고, 해시는 출처 증명이지 인증이 아니며, 파인튜닝이 항상 이긴다는 주장을 하지 않는다 — “실패한 파인튜닝은 숨길 것이 아니라 결과다.”

정리

ifllm-learn 은 크기로 승부하는 리포가 아니다. 4B 로컬 모델 + LoRA 128 스텝이라는 소박한 설정으로, 분류형 결정 문제에서 파인튜닝이 언제 이기고 언제 비기는지를 ‘돌려볼 수 있는 비교’로 만들어 둔 것이 본체다. 프로즌 모델과 TF-IDF 베이스라인을 항상 비교선에 세우고, 트레이드오프와 실패를 결과 파일째 보존하는 방식은 — 벤치마크 인플레이션이 일상인 요즘 — 그 자체로 참고할 만한 본보기다. LLM 에게 에세이 말고 if 를 시키고 싶은 사람이라면 README 만 읽어도 얻어 가는 게 있다.


References

본 글은 저장소 공개 문서·결과 파일의 소개이며, 위 수치를 본인이 독립 재현하지는 않았다.