본문 바로가기
고민의 흔적../AI Agent 행동예측 해커톤

(연구일지 #13 자동화 하네스 구축)Dacon AI Agent 행동 예측 대회

by sungjinp0805 2026. 7. 21.

Fable도 엉성하다.. 

이전 글에서는 민트 데이터를 다시 검증하면서, 단순한 구현 실수가 실험 결론 전체를 바꿀 수 있다는 점을 확인했다.

 

민트의 CI 상태를 정확히 복원했다고 생각했지만 실제로는 rolling history 이전의 상태를 알 수 없었다.

text-only 사전학습이라고 생각한 실험에는 [META] 문자열이 남아 있었고, holdout 세션에서 나온 민트가 사전학습에 포함돼 있기도 했다.

 

이런 문제가 반복되자 처음에는 내가 Fable을 잘못 사용하고 있는 것은 아닌지 의심했다.

나는 Fable이 복잡한 문제를 분석하고 전략을 세우는 능력은 좋은 모델이라고 알고 있었다.

실제로 대회에서도 새로운 실험 방향을 찾거나 여러 결과를 연결해 다음 전략을 세울 때 좋은 판단을 보여줬다.

 

그런데 프로젝트가 커질수록 실수가 눈에 띄게 늘었다.

  • 실험했다고 보고했지만 핵심 단계가 빠져 있었다.
  • 여러 변수를 동시에 바꾼 뒤 하나의 효과처럼 설명했다.
  • holdout 누수나 입력 직렬화 차이를 놓쳤다.
  • raw logit과 probability를 혼용했다.
  • 이미 기각한 실험을 다른 이름으로 다시 제안했다.
  • 학습, 감시, 포장, 기록 중 일부가 누락되기도 했다.

처음에는 프롬프트를 더 자세히 작성하면 해결될 것이라고 생각했다.

규칙을 추가하고, 실험로그를 읽게 하고, 작업 전후 확인 항목도 계속 늘렸다.

 

하지만 컨텍스트와 책임이 커질수록 문제는 반복됐다.

그래서 원인을 모델의 절대적인 성능 부족보다 하나의 에이전트가 너무 넓은 범위를 동시에 담당하는 구조에서 찾기 시작했다.

전략 수립, 코드 수정, 학습 실행, 상태 감시, 결과 검증, 제출 포장, 문서 작성까지 하나의 에이전트가 모두 처리하면서 각 작업에 집중할 수 있는 범위가 지나치게 넓어졌다.

 

Fable의 성능이 나쁜 것이 아니라, 한 번에 너무 많은 책임과 컨텍스트를 맡기고 있었던 것은 아닐까?

이 가설을 바탕으로 실험 하네스를 다시 설계했다.


처음 만든 것은 모델이 아니라 기록 체계였다

대회 초반의 작업 상태는 대부분 대화와 실험로그 안에 흩어져 있었다.

실험이 적을 때는 큰 문제가 없었다.

하지만 모델, seed, 학습 서버, 제출 zip이 늘어나자 현재 챔피언이 무엇인지, 어떤 작업이 진행 중인지,

어느 파일이 실제 제출본인지조차 혼동되기 시작했다.

 

그래서 먼저 세 개의 문서를 견고히 했다.

HANDOFF.md

현재 프로젝트 상태를 이어받기 위한 문서였다.

여기에는 다음 내용을 기록했다.

  • 현재 챔피언과 LB
  • 실행 중인 학습
  • 다음 실험 후보
  • 사용 중인 모델과 파일 위치
  • 완료된 작업과 미완료 작업
  • 주의해야 할 운영 규칙

새 대화를 시작하거나 컨텍스트가 초기화되더라도 이 문서를 읽으면 현재 상태에서 이어갈 수 있도록 했다.

CLAUDE.md

프로젝트 안에서 AI가 항상 따라야 할 운영 규칙을 기록했다.

예를 들면 다음과 같은 규칙이다.

  • holdout은 제출 자격 필터로만 사용한다.
  • zip을 만들 때 목적과 비교 대상을 기록한다.
  • 학습 코드와 feature 코드가 바뀌면 기존 artifact를 그대로 쓰지 않는다.
  • 유료 GPU 사용과 제출은 사용자 승인을 받아야 한다.
  • 실험로그는 과거 기록을 덮어쓰지 않고 정정 항목을 추가한다.

제출 메모

각 제출 zip마다 다음 내용을 남기도록 했다.

  • 실험 목적
  • 기준 제출본
  • 변경한 변수
  • 유지한 조건
  • 예상되는 해석 범위
  • 실제 LB

처음 하네스는 거창한 자동화 시스템이 아니라, 현재 무엇을 하고 있는지 잃어버리지 않기 위한 문서 체계에서 시작했다.


“완료했다”는 보고만으로는 부족했다

문서를 만든 뒤에도 문제는 남았다.

AI가 “학습을 완료했다”, “zip을 검증했다”고 보고해도 실제 산출물을 확인하면 내용이 맞지 않는 경우가 있었다.

그래서 완료의 기준을 설명이 아니라 증거로 바꿨다.

 

작업 유형별로 체크리스트를 나눴다.

학습 전 데이터, split, seed, 하이퍼파라미터, 변경 변수
holdout/OOF 누수 여부, index, class order, 출력 형태
zip 생성 구성 파일, 모델 개수, 용량, 실행 경로
대조 실험 같은 seed·split·전처리, 단일변수 변경
제출 후 실제 LB, 실행시간, 비교 기준
오류 관측 원인, 영향 범위, 재발 방지 규칙

모든 항목이 확인돼야 “검증 완료”라고 기록할 수 있도록 했다.

zip 검증도 자동화했다.

 

verify_zip.py는 다음 항목을 확인했다.

  • 1GB 용량 제한
  • 압축파일 CRC 오류
  • 중복 경로와 path traversal
  • 불필요한 data/, output/ 포함 여부
  • 모델 파일의 SHA256
  • fp16 저장 여부
  • NaN과 Inf 존재 여부
  • 클래스 순서
  • metadata 차원
  • 모델 head 구조
  • 실제 추론 스모크 테스트

모델 파일이 존재한다는 것과 실제 제출 서버에서 실행 가능한 zip이라는 것은 다른 문제였다.

그래서 파일 검사뿐 아니라 몇 개의 입력을 끝까지 추론해 유효한 CSV가 만들어지는지도 확인했다.

이후에는 “zip을 만들었다”가 아니라,

어떤 파일이 들어 있고, 어느 학습 산출물과 SHA가 같으며, 실제 추론이 끝까지 실행됐는가

를 기준으로 완료를 판단했다.


결론적으로 체크리스트 7종, zip 자동 검사, 실행 설정 기록을 하네스의 기본 규칙으로 정리됐다.


설정은 사람이 쓴 메모가 아니라 코드가 기록해야 했다

실험 재현성에서도 문제가 생겼다.

환경변수로 seed, extra data, feature flag를 설정했지만, 실행 후에는 어떤 값이 실제 적용됐는지 확신하기 어려웠다.

 

단순히 printenv를 저장하는 것도 충분하지 않았다.

환경변수를 지정하지 않았을 때 코드 내부 기본값이 적용되는 경우가 있었기 때문이다.

그래서 학습 코드가 실제로 파싱한 설정을 effective_config로 저장하도록 바꿨다.

 

기록 대상은 다음과 같았다.

  • seed
  • epoch
  • batch size
  • gradient accumulation
  • max length
  • train data와 extra data
  • feature flag
  • class weight
  • stage별 설정
  • 코드와 데이터 SHA256

핵심은 명령어에 무엇을 적었는가가 아니라 프로그램이 최종적으로 어떤 값을 사용했는가였다.

 

이 규칙은 seed80 계열 모델을 복구하면서 중요성이 더 커졌다.

같은 seed 번호를 사용했더라도, 모델 생성 전 난수 고정 시점이나 holdout 단계를 거쳤는지에 따라 RNG 소비 순서가 달라질 수 있었다. 그래서 이후에는 모델을 생성하기 전에 seed를 고정하고, 실행 설정을 manifest로 남기도록 했다.


감사를 붙였지만, 감사자도 완벽하지 않았다

Claude가 실험을 만들고 Codex가 독립적으로 검사하는 구조도 도입했다.

Codex 감사는 실제로 여러 문제를 찾았다.

  • full-data refit 모델의 holdout 누수
  • transcript 직렬화 불일치
  • raw logit과 probability 혼용
  • 잘못된 CI 복원
  • 제출 zip과 기록의 불일치

하지만 감사 범위가 넓어질수록 한 명의 감사자가 코드, 데이터, 모델, zip, 문서를 모두 확인하는 구조에도 한계가 생겼다.

또한 검증자가 직접 코드를 수정하거나 zip을 만들면, 실행자와 감사자의 경계가 흐려졌다.

 

그래서 역할을 더 세분화했다.

최종적으로는 내부 판정, 실행, 포장, 기록 역할을 포함해 17개 역할로 나눴다.

예를 들면 다음과 같다.

  • 데이터 정합성 검사
  • split·누수 검사
  • 학습 설정 비교
  • probability contract 검사
  • zip 구성 검사
  • 실행시간 검사
  • 학습 실행
  • 모델 회수
  • zip 포장
  • 문서 기록

문서를 수정할 수 있는 역할은 docs-ledger-writer 하나로 제한했다.

여러 역할이 같은 실험로그를 동시에 수정하면 기록 순서가 꼬이거나, 서로 다른 판단이 하나의 사실처럼 합쳐질 수 있었기 때문이다.

 

즉, 하네스는 단순히 AI를 여러 개 호출하는 구조가 아니었다.

누가 판단하고, 누가 실행하고, 누가 기록할 수 있는지를 분리하는 권한 구조였다.


외부 감사도 준비와 실행을 분리했다

Codex 감사를 호출하는 과정에서도 문제가 있었다.

감사 요청을 준비하는 것과 실제 외부 감사를 실행하는 것이 하나의 명령에 묶여 있으면, 사용자의 승인 없이 호출되거나 실패 후 자동으로 재시도될 수 있었다.

그래서 외부 감사 러너를 두 단계로 분리했다.

PREPARE

감사에 필요한 증거를 모으는 단계다.

  • 비교 대상
  • 코드 diff
  • 데이터와 모델 SHA
  • holdout index
  • 실행 설정
  • 확인할 질문
  • 기대하는 출력 스키마

이 단계에서는 Codex를 호출하지 않는다.

EXECUTE

사용자가 명시 했을 때만 Codex 감사를 한 번 실행한다.

자동 재시도도 제거했다.

감사가 실패했다고 시스템이 임의로 다시 호출하면, 사용자 승인 범위를 넘어갈 수 있기 때문이다.

 

감사 상태는 다음처럼 관리했다.

DRAFT
→ PREPARED
→ WAITING_APPROVAL
→ RUNNING
→ PASS / BLOCK / NEEDS_HUMAN / INFRA_ERROR
 

여기에 작업 승인 상태를 별도로 뒀다.

WAITING_USER
→ AUTHORIZED
→ EXECUTED
 

두 상태를 분리한 이유는 단순했다.

감사에 통과했다는 것과 실제 작업을 실행해도 된다는 것은 다른 문제다.

감사가 PASS여도 학습 발사, 프로세스 종료, 파일 삭제, 유료 GPU 사용, 제출은 각각 별도의 승인 대상이었다.

 

이 원칙은 실제 사고 뒤에 만들어졌다.

한 번은 외부 감사 결과에 적힌 “다음 권장 순서는 서버 실측”이라는 문장을 발사 지시로 해석해 GPU 학습을 시작했다.

사용자는 해당 작업을 승인하지 않았고, 요청에 따라 즉시 중단했다.

 

이후 무료 GPU를 포함한 모든 신규 학습은 명시적 승인이 있어야만 실행하도록 규칙을 바꿨다.

감사 통과와 행동 승인을 분리한 구조는 이 사고에서 출발했다.


모든 명령을 승인받으면 자동화가 느려지는 문제

반대로 모든 세부 명령을 하나씩 승인받으면 자동화의 장점이 사라졌다.

특히 마지막 밤처럼 시간이 부족한 상황에서는 다음 작업을 순서대로 진행해야 했다.

  1. 데이터 생성
  2. Stage A 학습
  3. Stage B holdout
  4. 제출 자격 판정
  5. full refit
  6. fp16 변환
  7. zip 포장
  8. 내부 검증

각 단계마다 사용자가 다시 승인해야 한다면, 중간에 몇 시간씩 작업이 멈출 수 있었다.

그래서 캠페인 단위 승인 모델을 추가했다.

실행 전에 캠페인 manifest를 만들었다.

 

manifest에는 다음 내용이 들어갔다.

  • 캠페인의 목적
  • 사용할 GPU와 비용
  • 데이터와 코드
  • 각 stage의 설정
  • holdout 통과 기준
  • 실패 시 중단 조건
  • 만들어질 산출물
  • 허용된 다음 행동
  • 별도 승인이 필요한 행동

사용자가 manifest를 한 번 승인하면, 정의된 범위 안에서는 ZIP_READY까지 자동으로 진행할 수 있었다.

다만 다음 행동은 캠페인 승인에 포함하지 않았다.

  • 실제 대회 제출
  • 다른 실험 추가 발사
  • 유료 자원 확대
  • 기존 프로세스 종료
  • 파일 삭제

즉, 캠페인 승인은 무제한 실행 권한이 아니라 미리 합의한 경계 안에서만 작동하는 제한된 자동화 권한이었다.


하네스가 실제로 막아낸 문제

하네스가 의미 있으려면 문서와 규칙을 많이 만든 것만으로는 부족했다.

실제로 잘못된 실험을 막아야 했다.

마지막 밤에 세 개의 캠페인을 실행하면서 내부 감사가 발사 전 두 가지 문제를 차단했다.

Stage A 설정 누락

한 실험에서 Stage A에 들어가야 할 TARGET_BALANCE와 TB_V2가 manifest와 실제 실행 설정에서 빠져 있었다.

예전 같았으면 일단 학습을 시작한 뒤 결과가 이상한 이유를 추적했을 가능성이 컸다.

하지만 내부 교차검증이 설정 차이를 발견해 BLOCK을 냈고, 수정 후 다시 검증한 뒤 학습을 시작했다.

불량 zip 생성 가능성

포장 스크립트에 set -e가 없었다.

이 상태에서는 중간 명령이 실패해도 스크립트가 계속 진행해, 일부 파일이 빠진 zip을 만들 수 있었다.

파일이 존재하고 크기도 정상이라 단순 검사에서는 통과할 수 있었다.

 

하지만 end-to-end 검사에서 실행 실패가 발견됐고, 포장 스크립트를 수정했다.

이외에도 다음 문제가 발생했다.

  • SSH 터널은 열렸지만 실제 대상 서버가 없는 상태
  • zsh의 단어 분리 차이로 워처 대상이 잘못 해석됨
  • 2단계 학습에서 Stage A와 Stage B 설정이 덮어써짐
  • 장시간 워처가 종료돼 완료 모델을 수 시간 동안 회수하지 못함

중요한 것은 사고가 없었다는 게 아니다.

사고가 발생할 때마다 다음 순서로 하네스에 반영했다.

사고 발생 → 원인 확인 → 규칙 추가 → manifest 또는 자동 검사로 강제

마지막 밤에는 이 캠페인 승인 구조로 세 개의 실험을 자동 완주했고, 내부 검증이 학습 전 설정 누락과 불량 zip 생성 가능성을 실제로 차단했다.


하네스가 모델 성능을 올려준 것은 아니다

하네스를 재설계했다고 모델 점수가 자동으로 오른 것은 아니다.

검증을 강화하면 오히려 실험 속도가 느려지기도 했다.

 

이전에는 바로 실행했을 일을, 이제는 diff와 manifest를 만들고 검사를 통과해야 했다.

그럼에도 필요했다.

 

대회 후반의 점수 차이는 대부분 0.001 이하였다.

이 정도 차이에서는 다음 중 하나만 발생해도 결과 해석이 무너졌다.

  • seed 외에 다른 설정이 함께 바뀜
  • holdout 세션이 사전학습에 섞임
  • 모델별 출력에 softmax 적용 여부가 다름
  • 제출 zip이 의도한 모델이 아닌 다른 artifact를 포함함
  • 학습 설정과 기록이 일치하지 않음

따라서 성능을 올리는 것만큼, 상승이 실제로 어떤 변경에서 나왔는지 설명할 수 있는가가 중요해졌다.

하네스의 목적은 AI가 실수하지 않게 만드는 것이 아니었다.

AI도, 사람도 실수한다는 전제에서 다음을 보장하려는 구조였다.

  • 실수가 산출물에 남는다.
  • 기록과 실제 실행의 차이를 찾을 수 있다.
  • 감사와 실행 권한이 분리된다.
  • 같은 증거로 같은 판단을 재현할 수 있다.
  • 사고가 다음 실험의 규칙으로 남는다.

정리

처음에는 AI를 사용하면 더 많은 실험을 빠르게 수행할 수 있을 것이라고 생각했다.

실제로 Claude는 코드 작성, 학습 발사, 모델 회수, 제출본 포장 속도를 크게 높였다.

Codex는 별도의 시각에서 누수와 구현 오류를 찾는 데 도움을 줬다.

 

하지만 실험 수가 늘어나자 속도만으로는 부족했다.

AI가 “완료했다”고 말한 작업과 실제 코드·산출물이 일치하는지 확인해야 했다.

 

감사자가 내린 판단이 실행 승인으로 확대되지 않도록 해야 했고, 누가 코드를 바꾸고 누가 기록을 수정할 수 있는지도 구분해야 했다.

그래서 하네스는 다음과 같이 발전했다.

상태 관리 HANDOFF.md, CLAUDE.md, 제출 메모
검증 강제 작업별 체크리스트, verify_zip.py
재현성 effective_config, 코드·데이터 SHA
역할 분리 내부 판정·실행·포장·기록 역할 분리
외부 감사 PREPARE와 EXECUTE 분리
권한 관리 AUDIT_PASS ≠ 행동 승인
자동화 캠페인 manifest 승인 후 ZIP_READY까지 실행
개선 루프 사고를 다음 규칙과 자동 검사로 편입

이 대회에서 만든 것은 행동 예측 모델만이 아니었다.

AI Agent와 함께 실험을 수행할 때, 무엇을 믿고 무엇을 다시 확인해야 하는지를 코드와 절차로 강제하는 실험 운영 시스템도 함께 만들었다.

 

다음 글에서는 이 하네스를 적용한 상태에서 다시 모델 경쟁으로 돌아가, seed 후보와 멤버 교체를 통해 v58 신챔피언을 만든 과정과 H100 추가 실험을 정리할 예정이다.