LLM은 똑똑해졌는데, 왜 코딩 에이전트는 여전히 비쌀까(NVIDIA SoL-Pi)
NVIDIA SoL-Pi가 보여주는 ‘모델이 아니라 하네스를 최적화하는 방법’
최근 AI 코딩 에이전트를 사용하다 보면 한 가지 재미있는 현상을 볼 수 있다.
모델 자체는 상당히 똑똑하다.
그런데 일을 오래 시키기 시작하면 토큰 사용량이 빠르게 늘어나고, 응답은 점점 무거워진다.
특히 Codex나 Claude Code 같은 코딩 에이전트가 실제 작업을 수행하는 과정을 살펴보면 그 이유를 어느 정도 이해할 수 있다.
대략 다음과 같은 루프가 반복된다.
사용자 요청
↓
LLM 판단
↓
Tool 호출
↓
실행 결과
↓
LLM 판단
↓
다음 Tool 호출
↓
실행 결과
↓
LLM 판단
...
파일을 읽고, 수정하고, 테스트를 실행하고, 로그를 읽고, 다시 수정한다.
이 방식은 에이전트 시스템의 기본적인 동작 방식이지만 작업 시간이 길어지면 다른 문제가 생긴다.
LLM이 굳이 판단하지 않아도 되는 일까지 LLM에게 다시 물어보고 있는 것은 아닐까?
NVIDIA의 연구 프로젝트 SoL-Pi는 바로 이 문제를 다룬다.
SoL-Pi의 목표는 모델 자체를 더 똑똑하게 만드는 것이 아니다.
에이전트가 같은 일을 수행하면서도 LLM 호출, 컨텍스트 재전송, 긴 Tool 결과 읽기 등에 드는 비용을 줄이는 것이다. NVIDIA는 이를 Pi 코딩 에이전트 위에서 동작하는 독립적인 확장 기능으로 구현했고, 네 가지 효율화 메커니즘을 공개했다.
모델보다 먼저 ‘하네스’를 봐야 한다
AI 에이전트를 만들 때 흔히 모델 선택부터 고민한다.
GPT 계열을 쓸 것인가.
Claude를 쓸 것인가.
더 큰 모델을 쓸 것인가.
추론 강도를 높일 것인가.
하지만 실제 에이전트 시스템에는 모델 바깥에 상당히 많은 코드가 존재한다.
┌─────────────────────────────┐
│ Agent Harness │
│ │
│ Context / Memory │
│ ↓ │
│ LLM │
│ ↓ │
│ Tool Router │
│ ↓ │
│ File / Shell / Search ... │
│ ↓ │
│ Observation │
│ └────────→ LLM │
└─────────────────────────────┘
모델에게 어떤 정보를 보낼지,
Tool 결과를 얼마만큼 다시 보여줄지,
언제 컨텍스트를 압축할지,
어떤 작업을 큰 모델에게 맡길지,
Tool을 몇 번 호출할지 결정하는 부분이 바로 Agent Harness다.
[Inference] 그래서 실제 코딩 에이전트의 비용과 체감 속도를 결정하는 것은 모델 성능만이 아니라 모델을 어떻게 운용하느냐에도 크게 영향을 받는다.
NVIDIA가 SoL-Pi에서 손댄 곳도 정확히 이 부분이다.
152개의 아이디어를 실험해 살아남은 4개
SoL-Pi에서 흥미로운 것은 네 가지 기능 자체뿐만이 아니다.
NVIDIA는 이를 찾기 위해 Auto-Research Loop를 구성했다.
공식 프로젝트 설명에 따르면 첫 번째 탐색에서 총 152개의 개선 아이디어가 제안됐고, 반복 실험과 검증 과정을 거쳐 최종적으로 네 가지 메커니즘이 살아남았다.
연구 루프는 대략 다음과 같다.
Trajectory Rollouts
↓
Map-Reduce Analysis
↓
Proposal
↓
Implementation Agent
↓
Reviewer Agent
↓
In-Trajectory Validation
↓
Held-Out Validation
즉 에이전트의 실행 로그를 분석하고,
개선 아이디어를 만들고,
다른 에이전트가 실제 구현하고,
다시 다른 에이전트가 검토하고,
실험을 통해 살아남은 방법만 유지했다.
최종적으로 남은 것은 다음 네 가지였다.
1. Action Fusion
2. ObservationPack
3. Evidence-Preserving Reducer
4. Online Context Compact
흥미롭게도 네 가지 모두 모델 자체의 지능을 높이는 기술이 아니다.
이미 충분히 똑똑한 모델을 더 경제적으로 사용하는 방법에 가깝다.
1. Action Fusion
LLM에게 두 번 물어볼 일을 한 번에 처리한다
코딩 에이전트에서 정말 많이 발생하는 패턴이 있다.
LLM
↓
파일 수정
↓
결과 반환
↓
LLM
↓
테스트 실행
↓
결과 반환
↓
LLM
코드를 수정한 다음 테스트하는 것은 너무나 자연스러운 과정이다.
그런데 여기에는 중간 LLM 호출이 하나 들어가 있다.
SoL-Pi의 Action Fusion은 이것을 다음처럼 바꾼다.
LLM
↓
파일 수정 + 테스트 실행
↓
통합 결과
↓
LLM
실제 구현을 보면 기존 edit, write Tool에 then_run이라는 옵션을 추가한다.
edit
└─ then_run: npm test
파일 수정이 성공하면 하네스가 바로 후속 명령까지 실행하고 그 결과를 하나의 Observation으로 반환한다.
소스 코드에도 이 목적이 명확하게 적혀 있다.
파일 변경과 후속 명령을 하나의 turn으로 합쳐 중간의 model decision을 없애는 구조다. 성공하면 SoL-Pi는 내부적으로 1 model round-trip avoided라고 표시한다.
이 방식이 중요한 이유는 간단하다.
LLM은 비싼 의사결정 장치다.
그런데 모든 상태 전이에 LLM이 필요한 것은 아니다.
코드 수정 성공
→ 테스트 실행
처럼 다음 행동이 사실상 결정되어 있다면, 굳이 모델을 한 번 더 호출하지 않아도 된다.
NVIDIA의 사전 trajectory 분석에서는 edit/write 이후 명령 실행으로 이어질 수 있는 후보가 cross-turn transition의 **12.3%**에서 관찰됐다.
연구 페이지에는 만약 관찰된 149개의 후보가 모두 fusion 됐다는 가정하에 모델 turn이
1,386 → 1,237
-10.8%
토큰이
32.38M → 28.64M
-11.5%
감소했을 것으로 계산한다.
다만 NVIDIA도 이것을 실제 재실행 측정치가 아니라 기존 trajectory에서 계산한 counterfactual이라고 명확히 밝히고 있다.
이 차이는 중요하다.
-10.8%, -11.5%를 실제 전체 SoL-Pi 성능 개선치로 해석해서는 안 된다.
2. ObservationPack
Tool 결과를 계속 들고 다니지 않는다
두 번째는 개인적으로 상당히 실용적인 구조라고 생각한다.
에이전트가 큰 파일이나 긴 명령 결과를 읽었다고 해보자.
예를 들어 Tool이 30KB짜리 결과를 돌려줬다.
일반적인 대화형 에이전트에서는 이 결과가 conversation history에 들어간다.
그리고 이후 요청에서도 과거 context의 일부로 계속 모델에 전달될 수 있다.
Request #1
[30KB Tool Result]
Request #2
[30KB Tool Result]
+ 새로운 내용
Request #3
[30KB Tool Result]
+ 이전 내용
+ 새로운 내용
문제는 모델이 그 30KB를 매번 다시 볼 필요가 없을 수도 있다는 것이다.
ObservationPack은 방식을 바꾼다.
큰 Tool Result
↓
로컬 Archive
↓
Observation ID 생성
obs_xxxxxxxxxxxxxxxx
이후 모델 context에는 원본 전체 대신 짧은 placeholder를 넣는다.
필요할 때만
obs_recall
Tool을 이용해 해당 Observation의 일부를 다시 불러온다.
현재 공개 코드에서는 10KiB를 초과하는 텍스트 Tool 결과가 대상이며, 처음 두 번의 provider request에는 원본을 보내고 이후부터 placeholder로 대체한다. 원본은 세션 스토리지에 보관된다.
obs_recall도 전체를 무조건 다시 가져오지 않는다.
필요한 위치에서 페이지처럼 나눠 읽는다. 공개 구현에서는 한 번의 recall 결과도 최대 약 16KiB와 400라인 범위로 제한한다.
구조적으로 보면 이렇다.
기존
Tool
↓
30KB Result
↓
Context
↓
Context
↓
Context
↓
Context
ObservationPack
Tool
↓
30KB Result
↓
Archive ──────────────┐
↓ │
obs_xxx │
↓ │
Context │
│
필요할 때 obs_recall ─┘
[Inference] 일반적인 소프트웨어 시스템 관점에서 보면 이것은 큰 데이터를 메시지에 계속 복사하지 않고 handle/reference로 관리하는 방식과 상당히 닮아 있다.
에이전트의 context도 결국 비용이 발생하는 데이터 구조라고 보는 것이다.
3. Evidence-Preserving Reducer
긴 로그는 비싼 모델이 처음부터 읽을 필요가 없다
세 번째가 특히 재미있다.
컴파일 로그를 생각해보자.
Building...
Building...
Building...
Warning...
Building...
Building...
...
...
error TS2322: Type ...
...
로그가 2만 줄이어도 실제 다음 행동을 결정하는 데 필요한 것은 오류 주변 몇 줄일 수 있다.
그런데 frontier model에게 로그 전체를 전달하면 비싼 모델이 모든 토큰을 읽는다.
SoL-Pi는 여기서 모델 라우팅을 사용한다.
긴 Build/Test Log
↓
Reducer Model
↓
핵심 Evidence
↓
Frontier Model
↓
실제 판단
현재 공개 코드의 기본 reducer route는
Provider : openai-codex
Model : gpt-5.6-luna
로 설정되어 있으며 사용자가 다른 provider/model로 바꿀 수도 있다. 대상 역시 아무 텍스트가 아니라 pytest, cargo test, npm test, go test, cmake --build, bazel test 등 진단성 build/test 명령 결과를 중심으로 제한되어 있다.
그런데 여기에는 중요한 문제가 있다.
작은 모델에게
“로그 요약해줘.”
라고 시킨 뒤 결과를 무조건 믿는다면 오류가 생길 수 있다.
SoL-Pi는 이 문제를 Evidence-Preserving 방식으로 처리한다.
먼저 원본 로그를 archive 한다.
Reducer가 결과를 만들면 포함된 evidence가 실제 원본 로그 안에 존재하는지 검사한다.
코드를 보면 인용된 모든 line이 archive에 byte-for-byte 존재해야 receipt를 채택한다.
검증에 실패하거나 reducer 호출 자체가 실패하면 축약 결과를 버리고 원본 Tool 결과를 그대로 frontier agent에게 전달하는 fallback 구조다.
즉 단순한
LLM → 작은 LLM
구조가 아니다.
Cheap Model
↓
Evidence 추출
↓
Deterministic Verification
↓
통과
↙ ↘
YES NO
↓ ↓
Receipt Original Log
↓ ↓
Frontier Model
이 부분은 최근 multi-model agent 설계에서 상당히 참고할 만하다.
[Inference] 핵심은 작은 모델에게 ‘판단’을 전부 넘기는 것이 아니라, 상대적으로 저렴한 모델에게 정보 압축 작업을 맡기고 정확성이 필요한 부분은 deterministic verification으로 보완한다는 것이다.
4. Online Context Compact
컨텍스트 압축에도 손익분기점을 계산한다
네 번째 기능은 더 공학적이다.
긴 에이전트 작업에서는 결국 context compaction이 필요하다.
오래된 대화와 작업 내용을 요약해서
100K Context
↓
Summary
↓
30K Context
처럼 줄이는 것이다.
하지만 무조건 빨리 압축한다고 좋은 것은 아니다.
Prompt Cache 때문이다.
이미 provider가 긴 prefix를 cache하고 있다면, context를 새롭게 요약해 다시 쓰는 순간 새로운 cache write 비용이 발생할 수 있다.
그래서 SoL-Pi는 단순히
컨텍스트가 길다
→ 압축
하지 않는다.
먼저 작업을 subtask 단위로 관리한다.
1. API 수정 ✅
2. 테스트 수정 ✅
3. UI 연결 ⏳
4. 통합 테스트 ⏳
그리고 하나의 subtask가 끝나는 지점을 compaction candidate boundary로 본다.
그 시점에서 경제성을 계산한다.
실제 코드에는 다음과 같은 변수들이 들어 있다.
현재 Context Token
압축 후 예상 Token
Cache Write / Read Ratio
앞으로 예상되는 Request 수
남아 있는 Subtask 수
Context Window 여유
기존 Compaction 비용
그리고 대략적으로
압축 비용
────────────
요청당 절약 Token
= 손익분기점까지 필요한 Request 수
를 계산한다.
향후 남은 요청 횟수가 이 손익분기점을 넘어설 것으로 판단되거나 context window가 위험 구간에 진입했을 때 compaction을 실행한다. 실제 economics.ts에는 breakeven request, cache 비용, remaining request horizon, compaction debt 등을 계산하는 로직이 구현되어 있다.
기본 설정에서도 이런 의도가 드러난다.
Context window reserve : 16,384 tokens
Keep recent : 20,000 tokens
Native summary estimate: 1,000 tokens
Cache write/read ratio : 12.5
cacheWriteReadRatio 12.5는 기본 configuration 값이며, 실제 provider의 비용을 자동 측정한 값이 아니라 compaction 의사결정에 사용하는 설정값이라는 점도 문서에 명시되어 있다.
[Inference] 이 부분에서 SoL-Pi는 LLM 에이전트를 상당히 전통적인 시스템 최적화 문제처럼 다루고 있다.
단순히 “context가 길어지면 요약한다”가 아니라,
지금 압축하는 비용과 앞으로 절약할 비용 중 어느 쪽이 큰지를 계산한다.
결국 SoL-Pi가 줄이려는 것은 네 가지다
네 메커니즘을 다시 정리하면 꽤 명확하다.
┌───────────────────────────┬─────────────────────────┐
│ 문제 │ SoL-Pi │
├───────────────────────────┼─────────────────────────┤
│ 불필요한 LLM 왕복 호출 │ Action Fusion │
│ 반복되는 큰 Tool 결과 │ ObservationPack │
│ 비싼 모델의 긴 로그 읽기 │ Evidence Reducer │
│ 계속 커지는 Context │ Online Context Compact │
└───────────────────────────┴─────────────────────────┘
그리고 이것을 에이전트 루프에 넣어보면 더 이해하기 쉽다.
┌─────────────────────┐
│ Context Compact │
│ 필요할 때만 압축 │
└──────────┬──────────┘
↓
┌──────┐ ┌──────────────────────┐
│ Task │ ─────→ │ Frontier LLM │
└──────┘ └──────────┬───────────┘
│
↓
┌─────────────────┐
│ Action Fusion │
│ edit + test │
└────────┬────────┘
↓
Environment
│
↓
Tool Observation
↙ ↘
짧은 결과 긴 결과
│ │
│ ObservationPack
│ │
│ 긴 진단 로그라면
│ ↓
│ Cheap Reducer
│ ↓
│ Evidence Verify
└───────────────┬──────
↓
Frontier LLM
[Inference] 결국 SoL-Pi의 핵심은 “LLM을 덜 쓴다”라기보다 비싼 LLM이 개입해야 할 위치를 줄이고, 나머지 부분을 하네스가 처리한다는 데 있다.
그래서 실제로 얼마나 줄었을까
NVIDIA는 최종 평가에 EdgeBench 51개 task를 사용했다고 설명한다.
공식 결과에 따르면 SoL-Pi는 두 모델 backend 모두에서 Pi 대비 평균 점수의 약 **94%**를 유지했다.
반면 효율에서는 Pi 대비
Total Tokens
-45% ~ -49%
Cost
약 1/3 감소
를 보고했다.
각 모델의 native harness와 비교하면
Total Tokens
-35% ~ -64%
List-price API Cost
-50% ~ -54%
였다고 설명한다. GPT-5.6 Sol을 사용한 평가에서는 평균 EdgeBench 점수가 native Codex harness보다 높았다는 결과도 제시한다.
NVIDIA가 제시한 또 다른 표현도 재미있다.
하나의 문제를 계속 연구하는 전문 연구자 기준으로 API-equivalent 비용을 계산했을 때 SoL-Pi는 시간당
Native Codex / Claude Code 대비
$8.75 ~ $13.50 절감
Pi 대비
$4.36 ~ $5.71 절감
이라고 추산한다.
다만 여기서 주의할 점이 있다.
SoL-Pi가 Pi와 완전히 동일한 성능을 유지하면서 비용만 줄였다고 해석하면 안 된다.
NVIDIA가 공개한 최종 combined harness의 평균 점수는 Pi의 약 94%다.
각 메커니즘에 capability preservation gate를 적용했지만 작은 손실이 여러 메커니즘을 조합하면서 누적될 수 있다고 연구 페이지에서도 설명한다.
즉 이것은 공짜 최적화가 아니라 성능과 비용 사이에서 검증된 engineering trade-off를 찾는 연구에 더 가깝다.
ObservationPack 하나만으로도 결과가 꽤 흥미롭다
개별 메커니즘 실험도 볼 만하다.
ObservationPack을 대상으로 한 EdgeBench A/B 실험은 11개 task를 두 개 arm으로 동시에 실행했다.
NVIDIA가 공개한 결과는
Provider Bill
-23.58%
Cost / Response
-23.73%
Normalized Score
+22.92%
였다.
두 그룹 사이 response count 차이는 0.20%였다고 설명한다.
다만 이것 역시 ObservationPack에 대한 제한된 11-task paired experiment이므로 전체 에이전트 환경에서 항상 같은 개선폭이 나온다고 일반화할 수는 없다.
이 프로젝트에서 가장 흥미로운 부분
[Inference] 개인적으로 SoL-Pi에서 가장 중요한 부분은 “토큰을 몇 % 줄였다”는 숫자만은 아니다.
이 프로젝트는 AI 에이전트를 보는 관점 자체가 바뀌고 있다는 것을 보여준다.
지금까지는 주로 이런 질문을 했다.
어떤 LLM이 더 똑똑한가?
그런데 에이전트가 장시간 작업하기 시작하면 질문이 달라진다.
어떤 일에 LLM을 호출해야 하는가?
어떤 일은 프로그램으로 처리할 수 있는가?
어떤 정보는 context에 계속 남겨야 하는가?
어떤 정보는 필요할 때만 가져오면 되는가?
작은 모델에게 무엇을 맡길 수 있는가?
언제 context를 압축해야 경제적인가?
이건 모델 연구라기보다 상당 부분 시스템 엔지니어링 문제다.
CPU 최적화와도 묘하게 닮았다
[Inference] 전통적인 컴퓨터 시스템과 비교해보면 이해가 쉽다.
LLM을 매우 비싼 연산 장치라고 생각해보자.
그렇다면 좋은 시스템은 모든 작업을 그 장치에 보내지 않는다.
LLM 호출 감소
→ Function Call Overhead 감소
ObservationPack
→ Memory / Cache 관리
Context Compact
→ Garbage Collection / Compaction
Cheap Model Routing
→ Heterogeneous Computing
Action Fusion
→ Operation Fusion
물론 LLM 시스템과 CPU 구조가 동일하다는 뜻은 아니다.
다만 비싼 자원을 필요한 곳에만 사용한다는 최적화 원리는 유사하다.
GPU에서 kernel fusion을 하는 이유도 작은 operation을 계속 따로 실행하는 overhead를 줄이기 위해서다.
SoL-Pi의 Action Fusion 역시 에이전트 수준에서 비슷한 문제를 겨냥한다.
작은 모델을 쓰는 것도 이제 하나의 시스템 설계다
SoL-Pi의 Evidence-Preserving Reducer는 특히 앞으로 에이전트를 설계할 때 참고할 부분이 많다.
모든 일을 최고 성능 모델에게 맡기는 구조는 간단하다.
Everything
↓
Best Model
하지만 비용은 높다.
반대로 모든 것을 작은 모델에게 넘기면 성능 문제가 발생할 수 있다.
SoL-Pi가 택한 구조는 그 중간이다.
Low Decision Density
↓
Cheaper Model
High Decision Density
↓
Frontier Model
그리고 작은 모델의 결과를 그대로 신뢰하지 않고 검증 가능한 evidence를 요구한다.
[Inference] 장기적으로 multi-agent 시스템에서 중요한 능력 가운데 하나는 “어떤 모델이 가장 똑똑한가”보다 어떤 작업을 어느 모델에 배정할 것인가가 될 가능성이 있다.
물론 보안상 주의점도 있다
SoL-Pi는 sandbox가 아니다.
공식 보안 문서도 SoL-Pi가 Pi 프로세스와 동일한 filesystem, process, network, credential 권한으로 실행된다고 명시한다.
Action Fusion은 모델이 요청한 파일 변경과 shell 명령을 실행할 수 있고, ObservationPack은 Tool 결과를 세션 디렉터리에 저장한다.
Evidence-Preserving Reducer를 활성화하면 대상 진단 로그가 설정된 reducer model로 전송될 수도 있다.
secret으로 보이는 문자열을 걸러내는 detector가 존재하지만 NVIDIA 역시 이것을 완전한 secret scanner가 아닌 precaution이라고 설명한다. 민감한 로그를 외부 모델로 보내면 안 되는 환경에서는 remote reduction을 활성화하지 말라고 명시한다.
또한 네 가지 기능은 기본적으로 모두 비활성화되어 있고 명시적으로 opt-in해야 한다.
앞으로 코딩 에이전트 경쟁은 모델만의 경쟁이 아닐 수 있다
[Inference] SoL-Pi를 보면 앞으로 코딩 에이전트 성능을 평가할 때 모델 이름 하나만 보는 것은 부족해질 가능성이 있다.
같은 모델을 사용하더라도 하네스에 따라
Model Turn 수
Tool Call 구조
Prompt Cache 적중률
Context Replay
Observation 크기
Compaction 시점
Model Routing
Verification 방식
이 모두가 달라질 수 있기 때문이다.
그래서 앞으로는 이런 지표가 더 중요해질 수 있다.
Task Success / $
Task Success / Token
Useful Work / Model Turn
Verification / Cost
Long-Horizon Cost
SoL-Pi가 흥미로운 이유도 여기에 있다.
더 강력한 모델을 만드는 대신,
이미 존재하는 강력한 모델을 얼마나 효율적으로 사용할 수 있는가를 연구 대상으로 삼았다.
좋은 에이전트는 무조건 많이 생각하는 에이전트가 아니다
지금까지 AI 에이전트를 만들면서 우리는 모델에게 너무 많은 일을 시켰는지도 모른다.
파일을 수정했으니 테스트할지 다시 물어본다.
이미 읽었던 30KB 결과를 또 보여준다.
몇 줄만 필요한 로그 전체를 최고급 모델에게 읽힌다.
컨텍스트가 커졌다는 이유만으로 무조건 압축한다.
SoL-Pi는 이런 작은 비효율을 하나씩 찾아낸다.
Predictable Action
→ Fuse
Large Observation
→ Archive & Recall
Long Diagnostic Log
→ Delegate & Verify
Growing Context
→ Compact only when economical
[Inference] 결국 좋은 에이전트의 기준은 단순히 얼마나 오래 생각할 수 있는가가 아니라,
어디에서 비싼 추론이 필요하고 어디에서는 필요하지 않은지를 얼마나 잘 구분하는가가 될 수도 있다.
그리고 NVIDIA의 SoL-Pi는 그 방향을 꽤 구체적인 코드와 실험으로 보여주는 프로젝트다.
프로젝트
NVIDIA NVlabs — SoL-Pi
Scaling Auto-Research Loops for Efficient Agent Harnesses
GitHub
https://github.com/NVlabs/SoL-Pi
프로젝트 페이지
https://nvlabs.github.io/SoL-Pi/
MIT License / TypeScript 기반 공개 프로젝트. 현재 저장소는 Pi의 소스를 직접 수정하지 않고 public extension API 위에서 동작하도록 구성되어 있다.
사용방법
가장 간단한 사용 흐름은 다음입니다.
1. Pi 설치
Node.js 22.19 이상이 필요합니다. NVIDIA가 현재 테스트한 Pi 버전은 0.84.2입니다.
node -v
npm install -g @earendil-works/pi-coding-agent@0.84.2
설치 확인:
pi --version
2. SoL-Pi 설치
전역으로 사용하려면:
pi install git:github.com/NVlabs/SoL-Pi
특정 프로젝트에서만 쓰려면 프로젝트 디렉터리에서:
cd my-project
pi install git:github.com/NVlabs/SoL-Pi --local --approve
공식 README에 제시된 설치 방식입니다.
3. 설정 파일 만들기
중요한 점이 있습니다.
SoL-Pi를 설치하기만 해서는 4가지 최적화가 켜지지 않습니다. 기본값이 모두 false입니다.
프로젝트별 설정은:
프로젝트/
├── .pi/
│ └── sol-pi.json
├── src/
└── ...
즉,
mkdir -p .pi
nano .pi/sol-pi.json
우선 저는 아래처럼 시작하는 것을 권합니다.
{
"version": 1,
"actionFusion": true,
"observationPack": true,
"evidencePreservingReducer": false,
"onlineContextCompact": false,
"cacheWriteReadRatio": 12.5
}
NVIDIA도 README에서 추가 모델 호출이 없고 현재 실행을 중단시키지 않는 두 로컬 메커니즘인 Action Fusion과 ObservationPack만 먼저 켜는 보수적 설정을 예시로 제공합니다.
전역으로 모든 프로젝트에 적용하고 싶다면:
~/.pi/agent/sol-pi.json
에 넣으면 됩니다.
프로젝트 .pi/sol-pi.json이 있으면 전역 설정보다 우선하며 두 파일을 merge하지 않고 프로젝트 설정 전체가 적용됩니다.
4. 이제 평소처럼 Pi 실행
별도의 sol-pi 명령을 실행하는 구조가 아닙니다.
cd my-project
pi
그리고 그냥 코딩 작업을 시킵니다.
예를 들어:
로그인 API에서 refresh token 처리에 문제가 있어.
관련 코드를 분석해서 수정하고 테스트까지 실행해.
이제 뒤에서 SoL-Pi가 활성화됩니다.
Action Fusion은 이렇게 동작합니다
보통 에이전트는:
LLM
↓
edit
↓
LLM
↓
npm test
↓
LLM
처럼 행동합니다.
SoL-Pi가 활성화되면 edit, write Tool 자체에 then_run 필드가 추가됩니다.
내부적으로는 예를 들어:
{
"path": "src/auth.ts",
"oldText": "...",
"newText": "...",
"then_run": {
"command": "npm test"
}
}
같은 형태가 가능합니다.
그러면:
LLM
↓
edit + npm test
↓
통합 결과
↓
LLM
가 됩니다.
성공하면 실제 코드에서 SoL-Pi가
1 model round-trip avoided
를 savings로 표시하게 되어 있습니다.
중요한 점
사용자가 매번
then_run을 사용해
라고 지시할 필요는 없습니다.
Tool schema가 에이전트에게 노출되므로 모델이 적절하다고 판단하면 사용합니다.
그래도 테스트 목적으로 명확하게 유도하려면:
파일 수정 뒤 테스트해야 하는 경우에는
가능하면 Action Fusion의 then_run을 사용해.
라고 요청할 수 있습니다.
ObservationPack은 거의 자동입니다
이건 사용자가 특별히 할 일이 더 적습니다.
현재 공개 코드에서 10KiB를 초과하는 순수 텍스트 Tool 결과가 대상입니다.
예를 들어:
npm test
결과가 50KB라면 처음에는:
50KB LOG
전체를 모델에게 전달합니다.
공개 구현은 처음 2번 provider request까지 전체를 보내고, 그 뒤에는:
[large tool result replaced...]
id: obs_ab123...
original_bytes: 51200
original_lines: 1200
retrieve:
obs_recall(...)
처럼 바뀝니다.
모델이 과거 결과가 다시 필요하면 자체적으로:
obs_recall
을 호출합니다.
즉 사용자는 그냥:
이 프로젝트 전체를 분석해서 문제를 찾아줘.
테스트도 실행해.
라고 하면 됩니다.
SoL-Pi가 뒤에서 큰 Observation을 관리합니다.
Evidence-Preserving Reducer까지 켜기
긴 빌드/테스트 로그를 작은 모델에게 먼저 읽히고 싶다면:
{
"version": 1,
"actionFusion": true,
"observationPack": true,
"evidencePreservingReducer": true,
"onlineContextCompact": false,
"cacheWriteReadRatio": 12.5
}
이 기능은 일반 대화 전체를 작은 모델에 보내는 것이 아닙니다.
현재 코드에는 예를 들어 다음 명령들이 diagnostic candidate로 정의되어 있습니다.
cargo build
cargo test
cargo check
pytest
python -m pytest
npm test
pnpm test
yarn test
go test
cmake --build
ninja
make
bazel test
...
긴 로그가 발생하면:
npm test
↓
긴 로그
↓
Reducer Model
↓
핵심 오류 evidence
↓
원본 로그와 검증
↓
Main Agent
로 동작합니다.
현재 공개 코드의 기본 reducer route는:
provider: openai-codex
model: gpt-5.6-luna
입니다.
원한다면 명시적으로:
{
"version": 1,
"actionFusion": true,
"observationPack": true,
"evidencePreservingReducer": true,
"evidencePreservingReducerProvider": "openai-codex",
"evidencePreservingReducerModel": "gpt-5.6-luna",
"onlineContextCompact": false,
"cacheWriteReadRatio": 12.5
}
처럼 지정할 수 있습니다.
단, Pi의 model registry에서 해당 provider/model이 실제로 사용 가능해야 합니다. 설정된 reducer가 unavailable이거나 호출에 실패하면 원래 Tool 결과를 그대로 사용하도록 fallback합니다.
Online Context Compact도 켜기
장시간 에이전트를 돌릴 때 사용합니다.
{
"version": 1,
"actionFusion": true,
"observationPack": true,
"evidencePreservingReducer": true,
"onlineContextCompact": true,
"cacheWriteReadRatio": 12.5
}
그러면 에이전트에게 update_plan Tool도 등록됩니다.
예를 들어 내부적으로:
Plan
1. 코드 구조 분석 completed
2. DB 문제 수정 completed
3. API 수정 in_progress
4. 테스트 pending
처럼 작업을 관리합니다.
작업 단계 하나가 끝날 때마다:
지금 compaction 할 것인가?
를 검토합니다.
그런데 무조건 압축하지 않습니다.
현재 구현은 다음을 계산합니다.
현재 context 크기
+
cache write 비용
+
예상 남은 request
+
남은 작업 단계
+
압축 후 절감 token
↓
Compaction 경제성 계산
실제로 코드에 breakevenRequests, expectedRemainingRequests, cacheWriteReadRatio, windowProtection 등의 계산이 구현되어 있습니다.
압축 후에는 숨겨진 메시지로 에이전트에게 다시 plan을 구축하게 하고 같은 작업을 계속 수행하도록 구현되어 있습니다.
저는 실제 사용에서는 이렇게 시작하겠습니다
처음부터 네 개를 전부 켜기보다:
{
"version": 1,
"actionFusion": true,
"observationPack": true,
"evidencePreservingReducer": false,
"onlineContextCompact": false,
"cacheWriteReadRatio": 12.5
}
로 시작합니다.
그리고 평소처럼:
pi
를 실행합니다.
충분히 긴 프로젝트를 돌릴 때:
Evidence-Preserving Reducer = ON
그다음 정말 몇십 턴 이상 가는 agent workflow를 사용할 때:
Online Context Compact = ON
으로 확장하는 방식이 적합합니다.
특히 Reducer는 로그를 별도의 모델에 전달할 수 있기 때문에 보안에 주의해야 합니다. NVIDIA도 secret detector가 완전한 secret scanner는 아니며, 외부로 전송되어서는 안 되는 로그가 있는 환경에서는 remote reduction을 활성화하지 말라고 명시합니다.
그리고 중요한 차이가 하나 있습니다.
현재 공개 SoL-Pi를 codex 명령이나 claude 명령에 그대로 붙이는 것은 아닙니다.
Codex CLI ─X→ SoL-Pi
Claude Code ─X→ SoL-Pi
Pi
↓
SoL-Pi Extension
↓
GPT / Claude 등 Pi에서 지원하는 model
라는 구조입니다.
따라서 Codex/Claude Code에서 아이디어만 가져와 비슷한 하네스를 직접 구현할 수는 있지만, NVIDIA 공개판을 그대로 사용하려면 Pi를 실행해야 합니다.
토큰 소모량이 줄어드나?
NVIDIA가 EdgeBench 51개 작업으로 측정한 최종 결과는 다음과 같습니다. SoL-Pi는 기본 Pi 대비 총 토큰을 45~49% 적게 사용했고, GPT/Claude의 네이티브 코딩 하네스와 비교하면 35~64% 적은 총 토큰을 사용했다고 보고했습니다. 동시에 평균 작업 점수는 Pi의 약 94%를 유지했습니다.
즉 예를 들어 기존 Pi가 한 장기 작업에서 총 1,000,000 토큰을 사용하던 패턴이라면, 벤치마크 비율을 단순 적용했을 때 SoL-Pi는 대략 510,000~550,000 토큰 수준이 되는 셈입니다. 이 숫자는 설명을 위한 계산이지 특정 작업에서 실제로 이만큼 감소한다는 의미는 아닙니다.
왜 실제 토큰이 줄어드는지는 네 기능을 보면 명확합니다.
기능실제 토큰 감소가 발생하는 지점
| Action Fusion | 중간 LLM 호출 자체를 제거 |
| ObservationPack | 과거의 긴 Tool 결과를 매 요청마다 재전송하지 않음 |
| Evidence-Preserving Reducer | 메인 고급 모델이 긴 로그 전체를 읽지 않음 |
| Online Context Compact | 오래된 Context를 압축해 이후 요청의 입력 토큰 감소 |
특히 ObservationPack이 가장 직관적입니다. 현재 구현은 10KiB보다 큰 텍스트 Tool 결과에 대해 처음 두 provider request에는 원문을 보내지만, 이후에는 원문 대신 작은 placeholder만 전달합니다. 원문이 필요하면 obs_recall로 일부만 다시 읽습니다.
예를 들어 에이전트가 50,000토큰짜리 로그를 한번 읽은 뒤 앞으로 LLM 호출을 20번 더 한다고 가정해 보겠습니다.
일반적인 방식
50K × 20번
≈ 1,000K 토큰의 반복 context
ObservationPack에서는 개념적으로:
처음 몇 번
50K
이후
작은 placeholder
작은 placeholder
작은 placeholder
...
필요한 경우에만
obs_recall → 일부 구간
이런 식이라 context replay에서 발생하는 실제 input token이 크게 줄어듭니다.
Action Fusion은 더 직접적입니다.
기존:
LLM
↓
edit
↓
LLM ← 이 LLM 호출
↓
test
↓
LLM
SoL-Pi:
LLM
↓
edit + test
↓
LLM
실제 구현에서도 성공한 Action Fusion에 대해 1 model round-trip avoided라고 기록합니다.
NVIDIA가 기존 trajectory에서 계산한 Action Fusion의 별도 counterfactual 분석에서는:
Model turns
1,386 → 1,237
-10.8%
Total tokens
32.38M → 28.64M
-11.5%
로 계산했습니다. 단, 이 수치는 실제 전체 재실행 결과가 아니라 관찰된 149개 후보가 모두 fusion됐다고 가정한 counterfactual입니다.
그런데 Reducer는 토큰을 추가로 쓰지 않나?
맞습니다. 이 부분이 중요합니다.
긴 로그
↓
싼 Reducer 모델 호출 ← 여기도 토큰 소비
↓
축약
↓
비싼 Main Model
따라서 Reducer 호출 자체는 추가 토큰을 소비합니다.
SoL-Pi의 아이디어는 단순한
총 LLM 토큰 호출 횟수를 무조건 최소화한다
가 아니라,
비싼 메인 모델과 이후 반복 context가 처리해야 하는 토큰을 줄였을 때 전체 경제성이 좋아지는가
를 보는 것입니다.
그래서 Online Context Compact에는 아예 이런 계산이 들어가 있습니다.
압축 비용
vs
앞으로 절약될 Context Token
vs
남은 Request 수
vs
Cache Write/Read 비용
그리고 손익분기점이 맞지 않으면 압축하지 않습니다. 실제 구현에 breakevenRequests, expectedRemainingRequests, cacheWriteReadRatio 등이 들어가 있습니다.
결국 이 프로젝트의 핵심을 한 문장으로 정리하면 이겁니다.
“LLM에게 같은 정보를 계속 읽히지 말고, LLM이 판단할 필요가 없는 순간에는 LLM 자체를 호출하지 말자.”
그래서 실제 총 토큰 소비도 줄어듭니다. NVIDIA 측 최종 EdgeBench 결과로는 Pi 대비 45~49% 감소가 측정됐습니다. 다만 짧은 작업이나 Tool 출력이 거의 없는 작업에서는 절감폭이 작을 수 있고, 장시간 코딩·대형 로그·많은 Tool 호출·긴 컨텍스트가 있는 작업일수록 SoL-Pi의 설계가 유리해질 가능성이 큽니다.