적응형 사고(Adaptive Thinking)가 내 토큰 예산 코드를 망쳤다: budget_tokens로부터의 마이그레이션
요약
Claude Opus 4.8 등 최신 모델에서 도입된 '적응형 사고(Adaptive Thinking)' 방식에 따른 토큰 예산 관리 마이그레이션 가이드를 제공합니다. 기존의 고정된 budget_tokens 방식 대신 effort 레벨을 사용하여 모델이 스스로 사고량을 결정하도록 구현하는 방법을 다룹니다.
핵심 포인트
- 고정된 budget_tokens 방식에서 adaptive thinking 및 effort 조절 방식으로 전환 필요
- effort 레벨(low, medium, max 등)은 작업 부하(workload)에 따라 선택해야 함
- 에이전트 작업 시 높은 effort 설정이 오히려 전체 토큰 비용을 절감할 수 있음
- 기존의 수동적인 토큰 예산 계산 헬퍼 함수는 더 이상 불필요함
입력 크기에 따라 사고 예산(thinking budget)을 계산하는 깔끔하고 작은 도우미가 있었습니다. "모델에게 컨텍스트의 30%를 사고 공간으로 할당하라"와 같은 방식이었죠. Opus 4.5에서는 아주 잘 작동했습니다. 그러다 Opus 4.8을 대상으로 시도했더니 400 에러가 발생했습니다. 제가 구축해 온 전체 개념이 현재 모델들에서는 사라져 버렸습니다. 무엇이 그것을 대체했는지, 그리고 제가 어떻게 마이그레이션했는지 소개합니다.
무엇이 망가졌나
기존 패턴은 다음과 같았습니다:
// Opus 4.5 및 이전 버전
const response = await client.messages.create({
model: "claude-opus-4-5",
...
Opus 4.7, 4.8, 그리고 Fable 5에서는 thinking: { type: "enabled", budget_tokens: N }를 사용하면 400 에러가 반환됩니다. 고정된 토큰 예산(fixed token budget) 시대는 끝났습니다. 그 대체제는 모델이 얼마나 생각할지를 스스로 결정하는 적응형 사고(adaptive thinking)이며, 여기에 전체적인 토큰 소비를 제어하는 effort 조절 노브(knob)가 추가되었습니다.
// Opus 4.8
const response = await client.messages.create({
model: "claude-opus-4-8",
...
이것이 실제로 더 나은 이유 (충격을 극복한 후)
저의 기존 예산 코드는 계산으로 포장된 추측에 불과했습니다. "컨텍스트의 30%"라는 말에 실질적인 근거가 없었습니다. 그저 합리적으로 느껴졌고 결과물도 괜찮아 보였기에 선택했을 뿐입니다. 적응형 사고(adaptive thinking)는 그 결정을 실제 문제를 파악하고 있는 모델에게 넘깁니다.
사고 모델의 변화: budget_tokens는 모델이 얼마나 생각할 수 있는지를 제어했습니다. 반면 effort는 모델이 얼마나 생각하고(thinks) 행동할지(acts)를 제어합니다. 이 둘은 동일한 축이 아니므로 깔끔한 1:1 매핑이 존재하지 않습니다. 저는 "8000 토큰"을 특정 effort 레벨로 변환하려는 시도를 멈추고, 대신 작업 부하(workload)에 따라 선택하기 시작했습니다.
effort 레벨을 선택하는 방법
직접적인 평가(evals)를 수행한 결과, 저는 다음과 같은 결론에 도달했습니다:
| 작업 부하 (Workload) | Effort | 비고 |
|---|---|---|
| 분류(Classification), 라우팅(routing) | low | 빠르고 범위가 제한적이며, 지능에 민감하지 않음 |
| ... |
저를 놀라게 했던 한 가지는, 에이전트 작업(agentic work)에서 초기에 더 높은 effort를 설정하는 것이 종종 전체 비용을 감소시킨다는 점이었습니다. 모델이 더 잘 계획하고 더 적은 턴(turns)을 소모했기 때문입니다. 저는 max가 항상 더 많은 토큰을 의미한다고 가정했었습니다. 하지만 다단계 작업(multi-step tasks)에서는 때때로 더 적은 토큰을 의미하기도 했습니다.
제가 실제로 사용한 마이그레이션 체크리스트
- 코드베이스 전체에서
budget_tokens를 Grep(검색)합니다. thinking: { type: "enabled", budget_tokens: N }를thinking: { type: "adaptive" }로 교체합니다.output_config: { effort: "..." }를 추가하고, 하나의 전역 값이 아닌 각 호출 지점(call site)마다 수준을 선택합니다.- 예산 계산(budget-calculation) 헬퍼 함수를 완전히 삭제합니다. 그것은 불필요한 짐(dead weight)이었습니다.
- 모든
temperature/top_p/top_k파라미터를 제거합니다 (이것들 또한 4.7+ 버전에서는 400(deprecated) 상태입니다). - 모델당 하나의 테스트 요청을 실행하고
response.model을 통해 확인(assert)합니다.
const r = await client.messages.create({
model: "claude-opus-4-8",
max_tokens: 64,
...
사고(thinking) 표시와 관련된 주의사항(gotcha)
Opus 4.7+ 및 Fable 5에서는 사고 블록(thinking blocks)이 여전히 스트리밍(stream)되지만, 기본적으로 텍스트는 비어 있습니다. 만약 추론(reasoning) 과정을 UI에 렌더링하고 있었다면, 진행 상황 대신 긴 일시 정지 상태를 보게 될 것입니다. 다시 활성화하려면 다음과 같이 설정하세요:
thinking: { type: "adaptive", display: "summarized" }
저는 이 부분을 놓쳐서 오후 내내 스트리밍이 고장 난 줄 알았습니다. 단지 새로운 기본값(omitted) 때문이었을 뿐입니다.
교훈
저는 플랫폼이 나중에 제거할 파라미터 위에 추상화(abstraction)를 구축했습니다. 이것이 바로 해당 노브(knob)가 근본적인 것인지 부수적인 것인지 이해하기 전에, 벤더(vendor)의 노브를 자신의 로직으로 감싸는(wrapping) 데 따르는 위험입니다. budget_tokens는 부수적인 것이었습니다. 근본적인 것은 "모델이 도움이 될 때 생각하게 하라"는 것이었으며, 적응형 사고(adaptive thinking)는 이를 직접적으로 표현합니다. 제 코드는 줄어들었고, 그들의 코드는 늘어났으며, 출력 결과는 더 좋아졌습니다. 저는 기꺼이 그 거래를 수용하겠습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기