시맨틱 캐싱
시맨틱 캐싱 (Semantic Caching)
시맨틱 캐시는 프롬프트를 임베딩하고, 코사인 유사도가 similarity_threshold를 넘는 가장 가까운 캐시 응답을 서빙해요. 그래서 동일하지 않고 유사한 프롬프트에도 히트할 수 있어요. LiteLLM은 이를 위해 Qdrant, Valkey, Redis의 세 백엔드를 지원해요. 시맨틱 캐시에서 서빙된 응답은 x-litellm-semantic-similarity 헤더를 담아요.
출처: 문서
본문
warning
시맨틱 캐싱은 단발(single-shot) 프롬프트를 위해 설계됐어요. 다중 턴이나 에이전트형 트래픽에서는 오래된 응답을 재생할 수 있어요. 그런 워크로드에 활성화하기 전에 Semantic Caching and Multi-Turn Agentic Traffic을 읽어보세요.
Qdrant
config.yaml에 cache 키를 추가하면 캐싱이 활성화돼요.
1단계: config.yaml에 캐시 추가
model_list:
- model_name: fake-openai-endpoint
litellm_params:
model: openai/fake
api_key: fake-key
api_base: https://exampleopenaiendpoint-production.up.railway.app/
- model_name: openai-embedding
litellm_params:
model: openai/text-embedding-3-small
api_key: os.environ/OPENAI_API_KEY
litellm_settings:
set_verbose: True
cache: True # set cache responses to True, litellm defaults to using a redis cache
cache_params:
type: qdrant-semantic
qdrant_semantic_cache_embedding_model: openai-embedding # the model should be defined on the model_list
qdrant_collection_name: test_collection
qdrant_quantization_config: binary
qdrant_semantic_cache_vector_size: 1536 # vector size must match embedding model dimensionality
similarity_threshold: 0.8 # similarity threshold for semantic cache
2단계: .env에 Qdrant 자격 증명 추가
QDRANT_API_KEY = "16rJUMBRx*************"
QDRANT_API_BASE = "https://5392d382-45*********.cloud.qdrant.io"
3단계: 콘피그로 프록시 실행
$ litellm --config /path/to/config.yaml
4단계: 테스트
curl -i http://localhost:4000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ***" \
-d '{
"model": "fake-openai-endpoint",
"messages": [
{"role": "user", "content": "Hello"}
]
}'
시맨틱 캐싱이 켜져 있으면 응답 헤더에 x-litellm-semantic-similarity가 보일 거예요.
Valkey
valkey-search 모듈을 실행하는 Valkey 인스턴스(AWS ElastiCache for Valkey 등)에서 시맨틱 캐싱을 사용할 수 있어요. RediSearch와 RedisVL은 필요 없어요.
요구사항
valkey-search 모듈이 로드되어야 해요 (MODULE LIST / FT._LIST로 확인). AWS ElastiCache에서 벡터 검색은 노드 기반 Valkey 8.2+ 클러스터가 필요해요. 클러스터 모드 비활성 노드 그룹이 지원되고 권장되며, 읽기 복제본이 있는 프라이머리도 괜찮아요(수평 샤딩만 지원되지 않음). ElastiCache Serverless는 벡터 검색을 지원하지 않아요. 멀티 샤드(클러스터 모드 활성) 엔드포인트는 여기서 지원되지 않으므로, 클러스터 모드 비활성 엔드포인트를 사용하고 수직 확장하세요.
1단계: config.yaml에 캐시 추가
model_list:
- model_name: fake-openai-endpoint
litellm_params:
model: openai/fake
api_key: fake-key
api_base: https://exampleopenaiendpoint-production.up.railway.app/
- model_name: openai-embedding
litellm_params:
model: openai/text-embedding-3-small
api_key: os.environ/OPENAI_API_KEY
litellm_settings:
set_verbose: True
cache: True
cache_params:
type: valkey-semantic
host: os.environ/VALKEY_HOST
port: os.environ/VALKEY_PORT
valkey_semantic_cache_embedding_model: openai-embedding # the model should be defined on the model_list
valkey_semantic_cache_index_name: litellm_semantic_cache_index # optional
similarity_threshold: 0.8 # similarity threshold for semantic cache
2단계: .env에 Valkey 자격 증명 추가
VALKEY_HOST = "your-valkey-host"
VALKEY_PORT = "6379"
VALKEY_PASSWORD = "your-password" # omit for passwordless / IAM-auth clusters
전송 중 암호화(TLS)가 있는 ElastiCache의 경우 cache_params 아래에 ssl: true를 추가하거나, host/port 대신 cache_params.redis_url을 rediss:// URL로 설정하세요. valkey-search를 로컬로 실행하려면 docker run -d -p 6379:6379 valkey/valkey-bundle:8.1.
3단계: 콘피그로 프록시 실행
$ litellm --config /path/to/config.yaml
4단계: 테스트
curl -i http://localhost:4000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ***" \
-d '{
"model": "fake-openai-endpoint",
"messages": [
{"role": "user", "content": "Hello"}
]
}'
시맨틱 캐싱이 켜져 있으면 응답 헤더에 x-litellm-semantic-similarity가 보일 거예요.
Redis
config.yaml에 cache 키를 추가하면 캐싱이 활성화돼요.
1단계: config.yaml에 캐시 추가
model_list:
- model_name: gpt-5.6-luna
litellm_params:
model: gpt-5.6-luna
- model_name: azure-embedding-model
litellm_params:
model: azure/azure-embedding-model
api_base: os.environ/AZURE_API_BASE
api_key: os.environ/AZURE_API_KEY
api_version: "2023-07-01-preview"
litellm_settings:
set_verbose: True
cache: True # set cache responses to True
cache_params:
type: "redis-semantic"
similarity_threshold: 0.8 # similarity threshold for semantic cache
redis_semantic_cache_embedding_model: azure-embedding-model # set this to a model_name set in model_list
Redis 자격 증명은 정확 일치 Redis 캐시와 같은 방식으로 설정하세요. Redis and Valkey 참고. 그런 다음 프록시 실행:
$ litellm --config /path/to/config.yaml
시맨틱 캐싱과 다중 턴 에이전트 트래픽 (Semantic Caching and Multi-Turn Agentic Traffic)
시맨틱 캐시(redis-semantic, qdrant-semantic, valkey-semantic)는 전체 메시지 배열의 텍스트 내용(system 프롬프트 포함)을 임베딩하고, 코사인 유사도가 similarity_threshold를 넘는 가장 가까운 캐시 응답을 서빙해요.
이는 단발 프롬프트에 잘 맞지만, 다중 턴이나 에이전트형 워크로드(코딩 에이전트, 도구 호출 루프, 매 턴 전체 대화를 재전송하는 모든 클라이언트)에는 적합하지 않아요. 각 새 턴은 이전 요청에 작은 델타를 덧붙인 것이므로, 연속적인 턴은 거의 동일한 텍스트이고 임베딩이 ~0.99 유사해요. 실용적인 임계값에서 매 턴이 이전 턴의 캐시 항목과 일치해 클라이언트는 오래된 응답을 재생하게 되며, 보통 에이전트가 같은 도구 호출을 반복하는 방식으로 나타나요. similarity_threshold를 올리는 건 이를 확실히 고치지 못해요. Assistant tool_calls도 임베딩 텍스트에 포함되지 않아서 연속적인 에이전트 턴을 구분하기가 더 어려워져요.
권장사항은 시맨틱 캐싱을 단발 트래픽에 유지하고 에이전트 트래픽을 제외하는 거예요. 가장 저렴한 방법은 에이전트가 사용하는 가상 키의 메타데이터에 "cache": {"no-cache": true}를 설정하는 거예요. 프록시는 그 키의 모든 요청에 이를 적용하며 클라이언트 측 변경이 없어요. per-key cache controls 참고. 모두에게 캐싱을 옵트인 방식(mode: default_off)으로 만들거나, dynamic cache controls로 클라이언트가 요청별로 옵트아웃하게 할 수도 있어요.
에이전트 트래픽에도 캐싱을 원한다면 정확 일치 캐시(type: redis)를 대신 사용하세요. 전체 요청의 해시를 키로 하므로 대화에 어떤 변화라도 있으면 캐시 미스가 되고 오래된 재생이 일어날 수 없어요.
note
캐싱은
supported_call_types에 나열된 호출 유형에서만 실행돼요 (/chat/completions, /completions, /embeddings, /responses 같은 OpenAI 호환 표면)./v1/messages(Anthropic 형식) 요청과 공급자 패스스루 라우트는 절대 캐시를 거치지 않아요.
시맨틱 캐싱과 최종 사용자 격리 (Semantic Caching and End-User Isolation)
시맨틱 캐시 키는 의도적으로 프롬프트를 뺀다. 그래서 두 호출자를 구분하는 유일한 것은 테넌트 범위, 즉 가상 키, 그 팀, 그 조직이에요. 따라서 하나의 가상 키 뒤의 모든 최종 사용자는 기본적으로 하나의 시맨틱 버킷을 공유하며, 그중 한 사용자를 위해 생성된 응답(도구 호출 포함)이 같은 키로 시맨틱하게 유사한 프롬프트를 보내는 다른 사용자에게 서빙될 수 있어요.
cache_params 아래에 semantic_cache_scope: end_user를 설정해 버킷을 최종 사용자별로도 격리하세요. 최종 사용자 id는 프록시가 요청에 대해 인증하는 id(user_api_key_end_user_id)예요: x-litellm-customer-id 헤더, 구성된 user_header_name, 또는 요청 user 필드. 이는 metadata와 litellm_metadata 양쪽에서 읽히므로 /v1/chat/completions, /v1/responses, /v1/messages 모두가 포함돼요. 최종 사용자 id가 없는 요청은 공유된 빈 버킷에 들어가지 않고 키/팀/조직 버킷으로 폴백해요. 기본인 key는 오늘날의 키/팀/조직 범위를 유지해요.
litellm_settings:
cache: true
cache_params:
type: redis-semantic
similarity_threshold: 0.8
redis_semantic_cache_embedding_model: my-embedding-model
semantic_cache_scope: end_user # key (default) | end_user
같은 설정은 캐시 유형이 redis-semantic일 때 Admin UI의 Caching -> Cache Settings에서 "Semantic Cache Scope"로도 사용할 수 있어요.
시맨틱 캐싱과 느린 임베딩 엔드포인트 (Semantic Caching and a Slow Embedding Endpoint)
시맨틱 캐시는 매 요청 전에 프롬프트를 임베딩하는데, 그 임베딩 호출이 인라인으로 실행돼서 완료 전까지 요청이 LLM에 도달할 수 없어요. LiteLLM은 이를 5초로 제한해요. 데드라인을 지나면 조회를 포기하고, 응답은 x-litellm-semantic-similarity: 0.0을 담으며, 요청은 캐시 미스로 모델로 진행돼요. 따라서 도달 불가하거나 멈춘 임베딩 엔드포인트는 요청을 지연시키는 대신 몇 초만 비용으로 삼아요.
임베딩 엔드포인트가 그보다 정당하게 느리다면 데드라인을 올리세요. cache_params 아래 semantic_cache_embedding_timeout으로 캐시별로, 또는 SEMANTIC_CACHE_EMBEDDING_TIMEOUT_SECONDS 환경 변수로 전역으로 설정할 수 있어요.
litellm_settings:
cache: true
cache_params:
type: redis-semantic
similarity_threshold: 0.8
redis_semantic_cache_embedding_model: my-embedding-model
semantic_cache_embedding_timeout: 10.0
더 높은 데드라인은 임베딩 엔드포인트가 응답을 멈췄을 때 모든 요청이 기다리는 시간이라는 점을 명심하세요. 그러니 엔드포인트의 실제 지연에 가깝게 유지하세요.