RAG - 시맨틱 캐싱(Semantic Caching)
요약
RAG 시스템의 효율성을 높이기 위한 시맨틱 캐싱(Semantic Caching)의 개념과 구현 방법을 설명합니다. 유사한 쿼리에 대해 벡터 DB와 LLM 호출을 줄여 비용과 시간을 절약하는 원리를 다룹니다.
핵심 포인트
- 시맨틱 캐싱은 의미적으로 유사한 쿼리에 대해 캐시된 결과를 재사용함
- 검색 시간 절약, 토큰 소비 및 LLM/벡터 DB 호출 횟수 감소 효과
- Redis나 Valkey 같은 인메모리 데이터베이스를 활용하여 구현 가능
- 코사인 유사도를 사용하여 쿼리 간의 의미적 유사성을 판단
- 데이터의 정확성을 유지하기 위한 캐시 무효화 전략이 매우 중요함
사용자가 쿼리를 제출하면, 해당 쿼리는 임베딩으로 변환되어 벡터 데이터베이스에서 검색되고 관련 문서를 검색합니다.
하지만 사용자가 동일하거나 매우 유사한 쿼리를 다시 요청한다면 어떻게 될까요?
이곳에 **시맨틱 캐싱(semantic caching)**이 등장합니다.
시스템은 벡터 데이터베이스를 다시 검색하는 대신, 이전 검색 결과를 캐시에 저장합니다. 캐시는 자주 접근되거나 최근에 조회된 결과가 저장되는 임시 저장소입니다. 사용자가 동일하거나 시맨틱하게 유사한 쿼리를 다시 요청할 때, 시스템은 벡터 데이터베이스에 다시 쿼리하는 대신 캐시에서 직접 결과를 검색할 수 있습니다.
장점 (Benefits)
- 검색 시간 절약 (Saves retrieval time)
- 토큰 소비 감소 (Reduces token consumption)
- 벡터 데이터베이스 호출 횟수 감소 (Reduces the number of calls to the vector database)
- LLM 호출 횟수 감소 (Reduces the number of calls to the LLM)
캐시에 결과를 저장하는 방법은 무엇일까요?
시맨틱 캐싱을 위해 Redis 또는 Valkey를 사용할 수 있습니다.
이들은 **인메모리 데이터베이스(in-memory databases)**로, 디스크가 아닌 RAM에 데이터를 저장한다는 의미입니다. 데이터가 메모리에 저장되기 때문에, 전통적인 데이터베이스와 비교했을 때 검색 속도가 훨씬 빠릅니다.
일반적으로 다음과 같은 항목들을 저장합니다:
- 사용자 쿼리 (User query)
- 관련 답변 (Related answer)
- 메타데이터 (Metadata)
- 임베딩 (Embeddings)
예시 (Example)
사용자가 다음과 같이 질문했다고 가정해 봅시다:
"오늘의 금 가격은 얼마인가요?"
이 쿼리와 그에 해당하는 답변이 Redis에 저장됩니다.
나중에 다른 사용자가 다음과 같이 질문합니다:
"금 가격 오늘?"
두 쿼리가 의미는 같지만, Redis는 키가 정확히 일치하는 것을 기대하기 때문에 이전 답변을 직접 검색할 수 없습니다.
이것은 Redis를 단순한 키-값 저장소(key-value store)로 사용할 때의 한계점 중 하나입니다.
어떻게 해결할 수 있을까요?
한 가지 접근 방식은 다음과 같습니다:
- Redis에 저장된 모든 키를 검색합니다 (예:
KEYS *사용). - 저장된 각 쿼리에 대한 임베딩을 생성하거나 검색합니다.
- 현재 사용자 쿼리를 임베딩으로 변환합니다.
- **코사인 유사도(cosine similarity)**를 사용하여 현재 쿼리 임베딩과 저장된 쿼리 임베딩을 비교합니다.
- 유사도 점수가 미리 정의된 임계값보다 높으면, Redis에서 해당 답변을 검색합니다.
이를 통해 텍스트가 다르더라도 의미적으로 유사한 쿼리가 캐시된 결과를 재사용할 수 있게 합니다.
시맨틱 캐싱 구현 방법 (Ways to Implement Semantic Caching)
시맨틱 캐싱은 두 가지 방식으로 구현될 수 있습니다:
- LangChain과 같은 프레임워크 사용
- Redis, Valkey 또는 기타 유사 데이터베이스와 같은 인메모리(in-memory) 데이터베이스 사용
캐시 무효화 (Cache Invalidation)
시맨틱 캐싱에서 가장 중요한 측면 중 하나는 **캐시 무효화(cache invalidation)**이며, 이는 캐시된 데이터가 자동으로 제거되거나 새로 고쳐지기 전에 얼마나 오랫동안 유효해야 하는지를 결정합니다.
예를 들어, 사용자가 다음과 같이 질문했다고 가정해 봅시다:
"오늘의 금 시세는 얼마인가요?"
이 답변은 제한된 기간 동안만 유효해야 합니다. 만약 애플리케이션이 어제 금 시세를 반환한다면, 그 정보는 부정확해집니다.
캐시 무효화에 대한 단일 솔루션은 없습니다. 적절한 전략은 애플리케이션과 캐싱되는 데이터 유형에 따라 달라집니다.
언제 캐시된 데이터가 만료되어야 할지 결정하기 전에 다양한 시나리오를 고려해야 합니다.
인메모리 데이터베이스 사용 시점 (When Should In-Memory Databases Be Used?)
인메모리 데이터베이스는 다음과 같은 경우에 적합합니다:
- 임시 쿼리(Temporary queries)
- 자주 묻는 질문(Frequently asked questions)
- 반복적으로 접근되는 데이터
쿼리의 의미를 이해함으로써, 어떤 쿼리를 캐싱해야 하고 언제 캐시를 무효화해야 하는지를 결정하는 가드레일(guardrails)을 정의할 수 있습니다.
주요 목표는 벡터 데이터베이스와 LLM에 대한 불필요한 호출을 줄여 RAG 파이프라인을 최적화하는 것입니다.
중복 요청 자체를 완전히 제거하는 것은 불가능하지만, 시맨틱 캐싱은 이를 상당히 줄일 수 있습니다.
중요 고려 사항 (Important Consideration)
우리는 모든 쿼리를 인메모리 데이터베이스에 저장해서는 안 됩니다.
캐싱에 가치가 있는 쿼리만 저장해야 합니다. 왜냐하면 RAM은 제한된 저장 용량을 가지고 있기 때문입니다. 따라서 효과적인 캐싱 전략은 어떤 쿼리가 저장할 가치가 있는지, 그리고 얼마나 오랫동안 저장할지 신중하게 결정해야 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기