회사 테크

상대편에도 같은 횟수를 — Uncensored Qwen3.8 4회차 pass@4 58/89 (65.2%), 원본과 격차 6

abliterated Uncensored Qwen3.8 Flash Next의 Terminal-Bench 2.1 4회차(pass@4) 결과. 33개 재시도에서 2개 복구, 400 overflow 3,877건짜리 fallback 루프 2건, Coq 빌드로 40분을 태운 compile-compcert까지 14시간 45분의 기록

삽질하는개발자

뉴런 네트워크 일러스트

요약

4편 끝에 “상대편도 같은 횟수를 줘야 한다”고 썼습니다. 그래서 Uncensored(ARC4NUM abliterated 4bit)가 best-of-3에서 실패한 33개를 원본과 완전히 같은 조건(타임아웃 1.0×, reasoning high, temperature 0.3, ctx 120K, terminus-2)으로 네 번째 돌렸습니다. 결과는 2개 복구입니다.

결론은 Uncensored pass@4 = 58/89 (65.2%) 입니다. 원본 pass@5 64/89(71.9%)와 격차 6입니다. 원본의 pass@4가 60이었으니 같은 4회 기준으로도 2 뒤집니다.

시도 원본 ddalcu Uncensored ARC4NUM
1회 (pass@1) 45 / 89 (50.6%) 41 / 89 (46.1%)
2회 누적 53 / 89 (59.6%)
3회 누적 58 / 89 (65.2%) 56 / 89 (62.9%, best-of-3)
4회 누적 60 / 89 (67.4%) 58 / 89 (65.2%)
5회 누적 (pass@5) 64 / 89 (71.9%) (진행 중)

원본 5회차에서 4개가 뒤집히는 걸 보고 “Uncensored도 4개 이상 뒤집히면 포화 얘기는 접어야 한다”고 했는데, 2개였습니다. 그리고 그 2개는 둘 다 원본이 이미 통과한 태스크라 격차만 8 → 6으로 줄었을 뿐, Uncensored 전용 통과는 4개 그대로입니다.

4회차에서 무슨 일이

33개를 돌려 2개 복구, 7개 FAIL, 24개 TO 입니다. 14시간 45분(재실행 7분 손실 포함), 태스크당 평균 24.1분이 걸렸습니다.

dna-insert (8.5분, 29턴, ctx 40K) — 플라스미드 입력/출력 서열을 비교해 삽입 부위를 찾고, 그 삽입을 만들어내는 PCR 프라이머 쌍을 설계하는 태스크입니다. 이전 3회는 전부 TO/FAIL이었고 원본은 1회차에 통과했습니다. 이번 궤적은 단순 prefix/suffix 비교가 실패하자(삽입 서열과 삽입 부위가 부분 상동이라 경계가 애매합니다) 5턴째에 접근을 바꿔 edlib를 설치하고 정렬 기반으로 39 nt 삽입의 정확한 위치를 잡았습니다. 그 뒤 어닐링 길이 15/32 nt, Tm 59.54/59.74°C, 차이 0.21°C로 제약을 전부 맞춘 뒤 시뮬레이션으로 출력 서열이 재현되는지 확인하고 제출했습니다. 이전 회차는 경계를 손으로 맞추다 시간이 갔습니다.

custom-memory-heap-crash (4.8분, 18턴, ctx 15K) — 사내 패치된 libstdc++ 위에서 RELEASE 빌드만 세그폴트 나는 C++ 프로그램을 고치는 태스크입니다. 이전 3회는 30분 TO 두 번에 FAIL 한 번이었습니다. 이번엔 3턴째에 locale_init.cc.patch를 읽고 6턴째에 원인을 특정했습니다. 커스텀 힙이 활성화된 상태에서 ::operator new로 잡힌 locale facet이 main 종료 후 정적 소멸자에서 std::free로 풀리면서 죽는 것이었습니다. “completed successfully”가 찍힌 뒤에 139로 죽는다는 관찰이 결정적이었습니다. 수정 후 release/debug 둘 다 exit 0, valgrind 0 errors까지 확인하고 제출했습니다. 5분짜리 태스크를 이전엔 30분씩 헤맸다는 것이 이 모델의 분산을 보여줍니다.

어디서 갈렸나 (원본 5회 vs Uncensored 4회, 89개 전체)

구분 개수 태스크
둘 다 통과 54
둘 다 전패 21 path-tracing 계열, regex-chess, feal-linear, make-*-mips, install-windows-3.11, compile-compcert, schemelike, rstan-to-pystan, query-optimize, video-processing 등
원본만 통과 10 circuit-fibsqrt, extract-elf, llm-inference-batching-scheduler, mteb-leaderboard, qemu-startup, raman-fitting, sparql-university, torch-pipeline-parallelism, train-fasttext, tune-mjcf
Uncensored만 통과 4 feal-differential-cryptanalysis, filter-js-from-html, model-extraction-relu-logits, polyglot-rust-c

격차 6 = 10 − 4 입니다. “원본만 통과”가 12 → 10으로 줄었고, “Uncensored만” 4는 그대로입니다. 아직 5 대 4라 한 번 더 남았습니다.

31개 실패 해부

① fallback 루프 — 이번 회차의 주인공입니다. 두 태스크가 각각 60분 제한을 꽉 채웠는데, 그 중 절반은 모델이 아무것도 하지 않은 시간입니다.

  • video-processing 60분 · 822턴 · ctx 130K. 85턴(23분)에 100K를 넘고 114턴(32분)에 131K 서버 한계를 넘었습니다. 여기서 terminus-2의 핸드오프 요약이 발동했어야 하는데, 프롬프트가 이미 한계를 넘은 상태라 요약 요청 자체가 400을 받았습니다. 이후 28분 동안 “Technical difficulties. Please continue with the task.” 메시지가 706번 쌓였습니다. 서버 로그로는 131K 요청 → 400 → 760토큰짜리 재시도 → 반복, 초당 수 건입니다. 이 한 태스크에서 400 overflow 카운트가 +2,120 올랐습니다.
  • circuit-fibsqrt 60분 · 716턴 · ctx 130K. 같은 패턴입니다. 84턴(22분)에 100K, 129턴(31분)에 한계 초과, 이후 585번 반복했습니다. 400 overflow +1,757. 직전 턴까지는 시뮬레이터에 디버그 프린트를 넣어 rem0=20032, root0=20064를 추적하던 멀쩡한 궤적이었습니다.

둘을 합쳐 400 응답 3,877건입니다. 대조군이 있습니다. regex-chess(60분 · 247턴)는 68턴(20분)에 100K를 넘었지만 129K 전에 핸드오프가 걸려 82턴째 ctx 3K로 리셋됐고, 이후 165턴을 정상적으로 썼습니다(68회 반복 루프는 따로 있었지만 다른 병입니다). 원본 5회차의 path-tracing-reverse도 같은 병이었으니 모델 차이가 아니라 하네스 문제입니다. max_input_tokens 120K 설정으로는 한 턴의 도구 출력이 11K를 넘으면 요약 기회 없이 바로 벽에 부딪힙니다. 이 여백을 더 넓히거나(예: 100K), 400을 받으면 마지막 도구 출력을 잘라서 재시도하는 로직이 하네스에 필요합니다.

② 환경 빌드에 시간을 다 쓴 TO.

  • compile-compcert 40분 · 51턴 · ctx 13K. 원본도 5회 전패인 태스크입니다. 17턴째 configure가 “Coq 8.18.0은 미지원” 경고를 내자 opam으로 Coq 8.16.1을 소스 빌드하기 시작했고, 남은 시간은 전부 “Still compiling Coq. Continue waiting.” 8연속이었습니다. 40분 제한에 Coq 빌드를 넣는 선택 자체가 패인입니다.
  • train-fasttext 38.9분 FAIL · 39턴. 원본이 4회차에 PASS(TO)로 넘긴 태스크입니다. 이번엔 그리드 서치까지 돌려 시간 안에 제출했는데(dim=32, wordNgrams=2, epoch=4, 자체 검증 0.6412) 채점기의 held-out 정확도는 0.569로 기준 0.62에 미달했습니다. 같은 Yelp 데이터에서 2%를 떼어 검증했으니 학습 분포에 과적합된 수치를 믿은 셈입니다.

③ 조기 확신 제출. sanitize-git-repo 1.2분(8턴!), sparql-university 3.0분(EU 27개국 VALUES 리스트로 필터했는데 정답 집합엔 ‘GR, US’ 같은 복수 국적이 있었습니다), query-optimize 6.6분, install-windows-3.11 4.6분. 원본과 같은 병이고, 횟수를 거듭해도 안 고쳐집니다. extract-elf 6.3분 · 43턴은 조금 다릅니다. 원본이 4회차에 endbr64 바이트를 실마리로 풀었던 그 문제를, Uncensored는 “파일 전체를 0x400000 기준 4바이트 워드로 읽는다”는 가설을 세우고 3,990개 키를 뽑아 제출했습니다. 채점기 결과는 기대값의 0.00% 일치입니다. 예시의 주소 패턴만 맞추고 값은 확인하지 않았습니다.

④ 아깝게 끝난 것. tune-mjcf 15분 · 19턴. MuJoCo 시뮬레이션을 정확도 허용치 안에서 더 빠르게 만드는 태스크입니다. 18턴째에 “PGS 솔버로 바꾸면 0.328 → 0.156초, 오차 3.9e-7로 통과”라는 정답을 찾았는데 파일에 쓰기 전에 시간이 끝났습니다. raman-fitting 15분 · ctx 73K — 원본이 5회차에 “소수점 콤마 + nm→파수 변환”으로 3분 만에 푼 그 태스크입니다. Uncensored는 레이저 파장을 3103/3140/3164 nm로 바꿔가며 G와 2D를 동시에 맞추려 15분을 썼습니다. x축 단위가 이미 파수라는 가능성을 5턴째에 언급하고도 버렸습니다.

운영 메모

14시간 45분 동안 wedge 재시작 0회(가동 15시간 연속)입니다. 이번엔 새로운 것이 셋 있습니다.

  • 400 overflow 누적 3,938건 — 원본 5회차 전체(335건)의 12배입니다. 전부 fallback 루프 2건이 만든 숫자입니다. 서버는 요청당 1초 미만으로 400을 돌려줬으니 부하는 없었고, 정작 손해는 벤치 시간 56분입니다.
  • 배치 8을 7분 날렸습니다. 4회차 도중 ERR로 끝난 9개를 재실행하는 스크립트를 짜면서 태스크 이름에 terminal-bench/ 접두사를 빼먹어 harbor가 “No tasks matched the filter”로 1분 만에 죽었습니다. 패키지 데이터셋은 org/name 형식이 필수입니다.
  • 메모리 경고 1회. 17:23, dna-assembly가 ctx 99K를 밟는 동안 free 0.3 GB · 여유 16%였습니다. 8-bit KV라도 65K 캐시 위에서는 이 머신(128 GB, 모델 70 GB 상주)이 스왑 경계에 닿습니다. 원본 5회차의 regex-chess 122K 때와 같은 현상입니다. 태스크가 끝나자 10분 안에 회복했습니다.
  • 벤치와 무관하게 하루 종일 Spotlight 인덱스 병합(mds_stores)과 클라우드 드라이브 하이드레이션이 겹쳐 load average가 13을 넘긴 시간대가 있었습니다. 디코드 속도엔 영향이 없었습니다.

다음

5 대 4입니다. 남은 31개로 Uncensored 5회차를 돌리고 있습니다. 그것이 끝나야 양쪽 다 공식 기준(5 trial)이 되고, 이 시리즈의 표를 마지막으로 닫을 수 있습니다. 원본 5회차가 4개를 뒤집었으니, Uncensored가 격차 6을 좁히려면 원본이 못 푼 21개 중에서 뒤집어야 합니다.

한 줄 요약: 같은 조건 4회째, Uncensored는 2개 복구로 58입니다. 원본과 같은 횟수(4회)로 비교해도 2 뒤지고, 벽에 부딪힌 뒤 28분씩 허공에 요청을 날린 fallback 루프 2건이 모델보다 하네스를 먼저 고쳐야 한다고 말합니다.