본문으로 이동
문서 탐색프롬프트 캐싱
설정레퍼런스

프롬프트 캐싱

static/dynamic 경계, 롤링 메시지 breakpoint, 그리고 prefix를 캐시 가능하게 유지하는 append 전용 대화 계약을 다룹니다.

프롬프트 캐싱은 prefix 매치입니다. 요청 앞부분이 직전 호출과 바이트 단위로 같아야 적중합니다. GEODE의 캐싱 설계는 이 한 문장에서 다 나옵니다. 변하지 않는 것을 앞에, 변하는 것을 뒤에 두고, 턴마다 바뀌는 조각이 prefix를 다시 키잉하지 못하게 막습니다.

static/dynamic 경계

시스템 프롬프트는 core/agent/system_prompt.pyPROMPT_CACHE_BOUNDARY마커(<dynamic_context> 여는 태그)로 두 쪽이 납니다. 마커 앞은 턴 사이 불변(베이스 스캐폴드, 스타일 가이드, 기본 ON identity), 마커 뒤는 턴마다 변합니다(model card, 날짜, 메모리 레이어, 사용자 컨텍스트).

Anthropic 어댑터(core/llm/providers/anthropic.py)가 이 마커에서 시스템 문자열을 갈라 static 블록에cache_control: {"type": "ephemeral"}을 붙입니다. dynamic 쪽은 캐시 없이 나갑니다. static이 비어 있으면(audit 모드에서 레이어를 벗긴 경우) 빈 텍스트 블록에 cache_control을 붙이는 400 오류를 피해 dynamic 쪽을 단일 캐시 블록으로 승격합니다.

롤링 메시지 breakpoint

Anthropic은 요청당 cache_control breakpoint를 4개까지 허용합니다. 시스템 블록이 1-2개를 쓰고, 나머지는apply_messages_cache_control이 대화 이력의 마지막 메시지들에 붙입니다. 몇 개를 붙일지(0-3)는 cache-policy SoT(core/llm/cache_policy.py)가 정하고 기본값은 3입니다. breakpoint가 많을수록 긴 멀티턴 루프의 적중률이 오르지만, 캐시된 블록마다 적중 여부와 무관하게 쓰기 오버헤드가 붙습니다. 짧은 작업이라면 낮추는 쪽이 맞습니다.

비용 산식은 단가표 기준으로 cache write가 input의 1.25배, cache read가 input의 0.1배입니다 (core/llm/pricing_loader.py).

대화 이력은 실제 turn만 append

AgenticLoop는 라운드 번호나 날짜를 합성 user message로 만들지 않습니다. 날짜와 runtime rule은 이미 core/agent/system_prompt.py의 동적 시스템 영역에 있고, 한 실행 안에서 대화 이력에는 실제 user, assistant, tool turn만 뒤에 붙습니다. 따라서 다음 요청의 메시지열은 이전 요청의 메시지열을 정확한 prefix로 보존합니다.

  • 턴마다 바뀌는 시스템 정보는 메시지 이력에 중복 주입하지 않습니다.
  • 컨텍스트 정리는 공유 이력을 직접 갱신하고, 그 뒤 adapter request를 조립합니다.

이 계약은 연속 AgenticLoop._call_llm 요청의 실제 AdapterCallRequest.messages prefix를 비교하는 회귀 테스트로 고정합니다.

실패 모드

증상원인해법
cache_read가 늘 0prefix가 매 호출 변함. static 영역에 턴별 값이 새어 들어간 경우턴마다 변하는 값은 경계 마커 뒤로 옮깁니다.
짧은 작업의 비용 증가breakpoint 쓰기 오버헤드가 적중 이득을 초과cache-policy SoT에서 messages_breakpoints를 낮춥니다.
400: empty text block에 cache_control빈 static에 breakpoint를 붙이려는 시도어댑터가 dynamic 승격으로 처리합니다. 직접 어댑터를 다룰 때만 해당합니다.

다음