Jeff v1.3: Jeff-Code가 Qwen 3.8-27B의 코딩 작업을 평균 47% 더 빠르게 완료하도록 만듦 (동일한 통과율에서 32%
요약
Jeff v1.3이 Qwen 3.8-27B 기반 코딩 에이전트인 Jeff-Code를 업데이트했습니다. 이 모델은 동일한 통과율을 유지하면서도 평균 작업 시간을 47% 단축하는 성능 향상을 보여주었습니다. 특히 일반적인 소프트웨어 엔지니어링 작업에서 뛰어난 속도 개선 효과를 입증했습니다.
핵심 포인트
- Jeff-Code는 Qwen 3.8-27B에 특화된 코딩 에이전트입니다.
- 동일한 품질(통과율)을 유지하며 평균 처리 속도를 47% 향상시켰습니다.
- SWE-bench, SWE-rebench 등 일반적인 소프트웨어 엔지니어링 작업에서 효과적입니다.
Jeff v1.3이 공개되었으며, 이를 통해 여러 업데이트가 함께 제공됩니다. 전체 세부 정보는 jeffhub.ai와 github.com/firelex/jeff를 참조하십시오.
주요 내용: Jeff-Code
Jeff-Code는 Qwen 3.8-27B에 맞춰 특별히 훈련된 두 개의 Jeff v1.3 어댑터를 갖춘 코딩 에이전트입니다. Jeff-Code는 Mario Zechner의 Pi를 포크(fork)한 것입니다 (MIT licence).
저희가 Pi를 포크한 이유는 그 확장 프레임워크가 현재 빠른 의사 결정 모델을 에이전트 루프 깊숙한 곳에 배치하는 것을 허용하지 않기 때문입니다. 이 과정에서 여러 다른 변경 사항들도 추가했습니다 (아래 참조).
Jeff-Code는 Qwen 3.8-27B를 로컬에서 일일 코딩 모델로 사용하는 사람들에게 유용할 것으로 기대되는 것 외에도, 개념적으로 흥미로운 실험이기도 합니다: System 1 모델을 코딩 에이전트 내부 깊숙한 곳까지 얼마나 가져갈 수 있는가?
결과는 쌍으로 구성된 블록에서 나란히 실행되었습니다:
동일한 품질: Jeff의 사고 임계값(thinking threshold)을 0.6으로 설정했을 때, Jeff-Code는 Qwen 3.8-27B와 동일한 통과율을 보입니다: 1,242개의 쌍으로 구성된 작업에서 62.4% 대 62.8%; 쌍별 차이는 −0.2 포인트이며, 95% 신뢰 구간은 −2.6에서 +2.1 사이입니다.
47% 더 빠름 (작업당 32% 시간 단축)¹: 평균적으로 작업 하나를 수행하는 데 기준선 대비 0.68배의 시간이 걸립니다 (작업별 시간 비율의 기하평균, 95% 신뢰 구간 0.64–0.72; 중앙값 작업은 0.70배).
가장 도움이 되는 영역: 일반적인 소프트웨어 엔지니어링 작업입니다. SWE-bench Verified 0.63배, SWE-rebench 0.66배, Terminal-Bench Pro 0.64배 (둘 다 두 라운드 이상), Harbor Index 0.71배. 긴 난이도의 작업을 가진 Terminal-Bench 2.0에서는 명확한 속도 향상이 없습니다 (0.96배, 신뢰 구간 0.78–1.16); SkillsBench에서도 마찬가지입니다 (0.91배, 신뢰 구간 0.68–1.20).
벤치마크: 저희는 Jeff가 훈련 과정에서 본 적 없는 작업에 대해서만 평가했습니다. SWE-bench Verified는 전체(모든 500개 작업; 그 어떤 리포지토리도 훈련에 사용되지 않음)로 실행되었습니다. 저희가 훈련에 사용한 벤치마크의 경우, 작업을 분할하여 모든 보류된 작업(held-out task)을 실행했습니다. 반복적인 인프라 장애를 겪은 몇 쌍의 작업은 제외되었습니다 (아래 참조).
터미널-벤치 2.0(총 89개 작업 중 40개, 각 3회 시도; 45개는 학습에 사용되었고 나머지 4개는 평가 작업과 유사한 것이므로 사용되지 않음), SWE-rebench(189개의 보류된 작업, 2라운드), Terminal-Bench Pro(100개 보류됨, 2라운드), SkillsBench(44개 보류됨) 및 Harbor Index(41개 보류됨)를 실행했습니다. 이 분할된 세트 내에서는 아무것도 샘플링하지 않았습니다. 또한 기존의 Terminal-Bench와 Terminal-Bench Science도 실행했지만, Qwen은 어떤 설정에서도 이 작업들의 거의 어느 것도 해결하지 못하므로 차이를 보여줄 수 없어 통합된 수치에서는 제외되었습니다.
비교 대상: 모든 Jeff 기능이 꺼진 동일한 Jeff-Code 빌드의 Qwen 3.8-27B 단독 실행입니다. 이때는 매 턴마다 전체적으로 생각하고(thinking at full on every turn) 사고 제한(thinking limit)이 없습니다. 이는 순수한 Pi가 작동하는 방식과 같습니다. 각 작업은 두 설정에서 나란히, 동일한 Qwen 서버에서 동시에 실행되었으며, 모든 비교는 작업을 기준으로 쌍을 이루었습니다. 원래의 Pi와 다른 점은 거의 발생하지 않는 무한 루프 차단(runaway cut-off) 기능(3번 작동함)과 추적 로깅입니다. 인프라 장애(메모리 부족, 세션 정지, 시작되지 않은 테스트 환경 등)를 겪은 작업 쌍은 한 번 더 실행되었습니다. 다시 실패한 쌍과 출시 시점에 아직 완료되지 않은 소수의 재실행 건은 양쪽 모두에서 제외되었으며(쌍의 3% 미만), 전체 보고서에 나열되어 있습니다. Terminal-Bench 2.0 작업 중 하나인 pytorch-model-recovery는 모든 비교에서 제외되었습니다. 이는 하네스 버그가 기본 세션을 시작하기도 전에 중단시켰기 때문입니다.
왜 생각 기능을 그냥 끄지 않는가? 저희가 시도해 보았습니다: Qwen의 생각 기능(thinking)을 전체적으로 끈 상태(및 동일한 안전장치)에서 작업은 여전히 빠르지만 명확하게 성능이 떨어집니다. Terminal-Bench 2.0에서는 −7.6점 (−10.6점에서 −4.5점으로), 최대 −13.5점까지 하락합니다. Qwen에게 언제 생각해야 할지 결정하는 것이 Jeff의 역할이며, 이것이 품질을 유지하게 합니다. 이는 작은 의사결정 모델(decision model)의 경우에도 마찬가지입니다.
¹ 모든 작업을 종합했을 때, 총 시간이 덜 줄어들어 14%(0.86×, 구간 0.80–0.93)에 그쳤습니다.
이러한 격차의 대부분은 소수의 작업에서 발생합니다. 약 5%의 작업에서는 Jeff-Code가 Qwen 단독으로 몇 분 만에 포기하는 지점에서도 계속 진행하기 때문에 Qwen만 사용할 때보다 30분 이상 더 오래 실행됩니다. 좋은 점은, 가끔 이것이 보상받는다는 것입니다. Jeff-Code는 이들 작업에서 26을 해결한 반면, Qwen은 24를 해결했습니다. 희망 없는 실행만 중단하는 것은 최상의 경우 총 시간을 약 0.7배로 줄일 수 있겠지만, 우리는 아직 이를 사전에 신뢰성 있게 인식할 수 없습니다(학습된 중지 규칙은 겨우 약 0.85배 수준을 유지했습니다). 이것이 다음 단계입니다.
벤치마크별 비교 (Qwen 3.8-27B 단독 사용 대비):
| 벤치마크 | 페어링 작업 수 | Qwen 단독 성공률 | Jeff-Code 성공률 | 차이, 포인트 (95% 구간) | 시간/작업 |
|---|---|---|---|---|---|
| SWE-bench Verified | 486 | 70.6% | 70.8% | +0.4 (−3.5 to +4.3) | 0.63× |
| SWE-rebench (2 라운드) | 370 | 58.9% | 58.1% | −0.8 (−5.7 to +3.5) | 0.66× |
| Terminal-Bench Pro (2 라운드) | 195 | 61.2% | 62.8% | +1.5 (−4.6 to +7.7) | 0.64× |
| Terminal-Bench 2.0 (3 시도) | 108 | 75.9% | 70.0% | −4.6 (−12.1 to +3.7) | 0.96× |
| SkillsBench | 42 | 28.6% | 31.0% | +2.4 (−11.9 to +16.7) | 0.91× |
| Harbor Index | 41 | 12.2% | 9.8% | −2.4 (−12.2 to +7.3) | 0.71× |
| 총 6개, 통합 | 1,242 | 62.8% | 62.4% | −0.2 (−2.6 to +2.1) | 0.68× |
어떤 벤치마크도 명확한 성공률 차이를 보여주지 않습니다. 모든 구간에 0이 포함되어 있습니다. 두 번 실행한 벤치마크는 통합되었으며, 구간은 두 라운드 모두를 기준으로 계산되었습니다. 성공률은 완료된 세션마다 카운트하며, 차이는 양쪽 설정 모두에서 완료된 작업만 카운트하므로 두 성공률 간의 정확한 격차는 아닙니다.
작동 방식: Jeff는 모든 Qwen 턴 주위에 두 가지 종류의 결정을 내립니다. 각각은 동일한 Jeff 기반 위에 있는 작은 어댑터에 의해 처리됩니다.
첫째, Jeff는 Qwen보다 앞서 작업합니다. 만약 스스로 다음 정보 수집 단계를 수행할 수 있다면(파일 읽기, 폴더 목록화, 코드 검색, 설치된 도구 확인 등), 그렇게 합니다. 먼저 도구를 선택하고 그 인수를 결정하며, 확신이 있으면 여러 단계를 연속으로 진행할 수 있습니다. 그러면 Qwen은 느린 턴을 할애하여 정보를 가져오는 대신, 이미 준비된 결과와 함께 자신의 턴을 시작합니다.
또한 테스트나 빌드를 실행하거나, Qwen의 마지막 명령을 반복하고, run-approval 설정을 사용한 평가를 통해 Qwen이 작성한 스크립트를 실행하거나 누락된 패키지를 설치할 수 있습니다. 파일 쓰기 및 편집은 항상 Qwen에게 맡겨지며, Jeff가 확신하지 못할 때는 언제든지 Qwen에게 넘깁니다. 이는 System 1 모델의 예시로서, 단순히 도구를 선택하는 것뿐만 아니라 그 도구에 매개변수(parameterize)까지 부여한다는 점에서 흥미롭습니다.
둘째, Jeff는 Qwen이 다음 턴에서 깊게 생각할 필요가 있는지 여부를 결정합니다. '생각하기(Thinking)'는 Jeff가 해당 턴에 그것이 필요하다고 확신하는 경우에만 활성화됩니다 (위의 0.6이 그 임계값입니다). Jeff가 모든 선택에 대해 보정된 확률을 반환하기 때문에, 이러한 각 행동은 단일 설정으로 제어됩니다.
학습 방법: Jeff는 Qwen이 다음에 무엇을 할지 예측합니다.
정보 수집의 경우, 각 학습 레이블은 단순히 Qwen이 실제로 취한 다음 단계입니다. 만약 Jeff가 그 단계를 일찍 수행할 수 있다면, Qwen은 그 단계에 턴을 소비하지 않고 결과를 얻게 됩니다. 이러한 레이블들은 다른 모델 없이 코드만으로 Qwen 세션에서 직접 구축되었습니다.
'생각하기' 결정은 다르게 레이블링됩니다. 전체 '생각하기'가 적용된 기록된 Qwen 턴 각각에 대해, 우리는 생각하기를 끄고(thinking off), 낮은 수준으로(low), 중간 수준으로(medium) 동일한 요청을 다시 했습니다. 이 레이블은 원래의 행동만큼 좋은 성능을 보인 가장 저렴한 수준이거나, 아무것도 없었다면 전체 '생각하기'가 됩니다.
'충분히 좋다(as good)'는 가능한 한 코드에 의해 결정됩니다. 예를 들어, 동일한 대상에 대한 동일한 종류의 단계입니다. 그렇지 않은 경우, thinking off 상태의 Qwen3.8-Max가 해당 순간에 더 저렴한 단계가 작업을 똑같이 잘 수행할지 판단합니다.
턴 중 약 27%는 아예 생각할 필요가 없었습니다.
이러한 레이블들은 의도적으로 엄격하여 라우터(router)를 신중하게 만들었고, 이것이 통과율을 유지하는 비결입니다. 우리는 또한 더 느슨한 질문인
전체적인 사고(thinking-off) 실행 결과가 보여주듯이, 이는 전체 작업 과정에서 품질을 희생하게 만듭니다.
위에 언급된 모든 것은 어댑터(adapters)를 사용하여 측정되었습니다. 즉, 고정된 Jeff v1.3 기반에 적용된 작은 LoRA 파일들입니다. 이것이 이 설계의 핵심 목표입니다. 또한 두 가지 결정을 내리기 위해 단일 전체 파인튜닝(full fine-tune)도 훈련하여 오프라인으로 비교했습니다. 그 정확도는 사실상 동일했습니다. 따라서 우리는 다중 어댑터 아키텍처를 유지하면서 정확도를 포기하지 않는 어댑터를 출시합니다.
Pi와 Jeff-Code의 주요 차이점은 다음과 같습니다:
턴별 사고(Thinking per turn): Pi는 사고 기능을 켜거나 끄는 것만 할 수 있으므로, Qwen은 항상 최고 수준에서 생각했습니다 (저희 테스트에서는 Qwen의 낮은 수준과 중간 수준도 가장 높은 수준만큼 오래 생각했기 때문에 시간 절약이 없었습니다). Jeff-Code는 각 턴마다 Qwen의 사고 수준을 설정하며, 이는 고정되거나 Jeff가 결정합니다.
사고 중단 안전장치(Safeguards for thinking off): 루프 가드(loop guard)는 최대 여섯 단계 전까지 반복되거나 거의 동일한 행동을 포착합니다 (파일 쓰기는 내용이 변경될 때만 진행으로 간주됩니다). 포착된 반복은 무시되고 해당 턴은 전체 사고를 통해 다시 요청되며, 거의 동일한 출력이나 연속 두 번의 실패한 명령어는 다음 턴을 전체 사고로 보내게 합니다. 사고 중단 비교 실행은 정확히 같은 안전장치, 낮은 사고 한계(thinking limit), 그리고 전체 사고로의 동일한 에스컬레이션(약 3%의 턴이 생각하는 것으로 끝남)을 가졌습니다. Jeff-Code와 다른 점은 오직 Jeff의 결정뿐입니다. 따라서 품질 격차는 Jeff에게 달려 있습니다.
실행 이탈 방지(Runaway cut-off): Qwen의 사고나 텍스트가 계속 반복되면, 답변이 중단되고 전체 사고를 통해 재요청됩니다. 이것은 전체 사고 기준선(full-thinking baseline)을 포함하여 모든 실행에서 활성화되었습니다 (여기에만 여섯 개의 통합 벤치마크에 걸쳐 3번 작동했습니다).
사고 한계(Thinking limit): 8,000개의 사고 토큰(thinking tokens)에서 Qwen은 지금까지 생각한 내용을 바탕으로 답변합니다. 이는 또한 Pi 세션을 종료시키는 32K 출력 제한에 도달할 경우의 답변도 구제해줍니다. 전체 사고 기준선은 순수한 Pi처럼 이 제한 없이 실행되었고, 사고 중단 실행과 Jeff-Code는 이 한계를 가졌습니다.
Jeff steps: Qwen의 각 턴(turn) 전에 Jeff-Code가 이미 알려진 정보들을 바탕으로 구체적인 다음 단계들의 메뉴를 구성하고, 자신감이 있을 때 Jeff가 직접 그 단계를 수행합니다.
GPU당 하나의 Jeff 서버 풀을 운영하여 각 결정에 약 0.2초가 소요되며, 모든 Qwen 요청과 Jeff의 결정 과정이 기록되어 학습 데이터와 평가가 가능했습니다.
저희는 이 시스템을 유지할 것이며, Pi가 가져가고 싶어 하는 것은 무엇이든 기꺼이 상위 호환(upstream)해 드릴 것입니다.
새로운 기반 모델 (A new base model)
Jeff v1.3과 v1.2의 주요 차이점:
라이브-라스트 프롬프트 구조(Live-last prompt structure). 이제 프롬프트의 고정된 부분(지침 및 옵션)이 먼저 오고, 실시간 데이터가 마지막에 오게 되어 접두사 캐싱(prefix caching)이 훨씬 잘 작동하고 동일한 옵션들에 대한 반복적인 결정들이 더 빨라졌습니다.
신중한 벤치마크 트레이드오프. 이로 인해 Jeff-base의 긴 옵션 목록에서의 제로샷 성능은 상당히 떨어졌습니다. 새로운 프롬프트 순서에서는 모델이 입력을 보기 전에 모든 옵션을 읽게 되는데, 0.8B 모델은 입력과 함께 옵션을 읽는 것보다 긴 옵션 목록을 다시 살펴보는 데 훨씬 취약합니다. 저희의 일반 패널에서 v1.3 base는 v1.2와 대략 비슷한 수준입니다(78.6% vs 78.8%, 보정 오차(calibration error) 0.028 vs 0.024). 하지만 생소한 작업, 특히 긴 옵션 목록이 있는 경우, base 모델 자체만으로는 성능 저하가 심합니다:
| task (어댑터 없음) | options v1.2 base | v1.3 base |
|---|---|---|
| legal-clause classification | 100 | 66.0% |
| support intents | 7–64 | 85.1% |
| triage | 2–36 | 67.1% |
| tool choice | 4–136 | 57.8% |
좋은 소식은 다음과 같습니다: 올바른 어댑터를 추가하면 base 모델에서 손실된 정확도의 거의 모든 부분이 되돌아옵니다. v1.3 + 어댑터는 legal-clauses를 제외한 모든 작업에서 v1.2 + 어댑터와 -0.7점에서 +0.3점 범위 내에 있습니다(83.6% vs 85.7%). 일단 어댑터가 옵션들을 학습하면, 이를 맨 앞에 배치하는 비용은 거의 들지 않으며 프롬프트의 고정 부분은 캐싱할 수 있습니다. 저희는 이 속도 향상이 그만한 가치가 있다고 판단했습니다.
새로운 철학: 모든 것에 대한 제로샷(Zero-shot)이 더 이상 목표가 아닙니다.
v1.3에서 우리는 방향에 큰 변화를 주었습니다. Jeff-base는 더 이상 제로샷 벤치마크에서 경쟁하려고 하지 않습니다. 대신, 항상 어댑터와 함께 사용하도록 설계되었습니다. 베이스(base)는 어댑터가 학습되는 기반이며, 어댑터는 Jeff가 특정 작업에 능숙해지는 곳입니다. 어댑터는 베이스에 병합되지 않습니다. 하나의 베이스와 필요한 모든 어댑터를 로드한 다음, 요청마다 하나를 선택하여 사용합니다. 우리는 v1.2와 동일한 정확도를 가진 어댑터로 속도의 큰 향상을 얻을 수 있다는 점에 집중하기로 결정했습니다.
요청별로 어댑터를 전환하는 비용은 llama.cpp 라이브러리에서 약 11ms, GPU에서 llama-server에서는 약 20ms가 소요됩니다. 이는 주로 오늘날의 서버가 구축되는 방식 때문입니다. llama.cpp는 활성 어댑터가 변경될 때 컴퓨팅 설정의 일부를 재구축하며, 한 어댑터 하에서 계산된 캐시된 프롬프트 접두사(prompt prefix)는 다른 어댑터에 의해 재사용될 수 없습니다. 이 두 가지 문제는 각 어댑터별 전용 접두사 캐시와 fa를 위해 설계된 서버를 사용하면 대부분 피할 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Reddit AI Engineering의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기