langchain / / 2024. 8. 26. 06:38

[langchain] Model Caches 사용하기

LLM을 사용할 때, 동일한 입력에 대해 반복적으로 호출되는 쿼리의 결과를 캐싱하는 것이 효율적이다. 이를 위해 LangChain에서는 다양한 방식으로 캐싱을 지원한다. LangChain에서 캐시를 사용하는 방법을 알아보고, 특히 Memory, SQLite, SQLAlchemy, Elasticsearch에서 어떻게 캐싱하는지 확인해보자.

1. Model Caches란?

Model Caches는 특정 입력에 대한 모델의 응답을 저장해두었다가, 동일한 입력에 대한 요청이 있을 때 저장된 응답을 반환하는 기능이다. 이를 통해 반복적인 연산을 피하고, 응답 시간을 단축할 수 있다. LangChain은 이 기능을 기본적으로 지원하며, 여러 유형의 저장소를 캐시로 사용할 수 있다.

ModelCaches를 사용할 수 있는 종류는 아래와 같다.

  • In-Memory Cache: 테스트 및 단기 프로젝트에 적합.
  • SQLite Cache: 단일 사용자 애플리케이션에 적합.
  • SQLAlchemy Cache: 복수의 사용자가 접근하는 애플리케이션 또는 다양한 DBMS 지원이 필요한 경우.
  • Elasticsearch Cache: 대규모 데이터, 고급 검색 및 분석이 필요한 경우.
  • Redis Cache: 매우 빠른 접근이 필요하거나 복잡한 데이터 구조를 캐시할 때.
  • DynamoDB Cache: 서버리스 환경에서 확장 가능한 캐시를 구현하고자 할 때.
  • MongoDB Cache: NoSQL 기반 애플리케이션에서 캐시를 구현하고자 할 때.
  • Filesystem Cache: 간단한 영속성 캐시를 원할 때.
  • Custom Cache: 특수한 요구 사항이 있는 경우.

기본 코드

다양한 캐시를 실행하기 위한 기본 코드이다. 여러 가지 종류의 캐시를 실행할 때 동일한 코드를 통해 작성한다.

import time
from functools import wraps

from dotenv import load_dotenv
from langchain.globals import set_llm_cache
from langchain.prompts import PromptTemplate
from langchain_community.cache import InMemoryCache
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI

load_dotenv()


def elapsed_time(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.perf_counter()
        result = func(*args, **kwargs)
        end_time = time.perf_counter()
        print("Sync execution time:", (end_time - start_time))
        return result

    return wrapper

llm = ChatOpenAI(
    temperature=0,  # 창의성 (0.0 ~ 2.0)
    model_name="gpt-4o",  # 모델명
)

template = "{country}의 수도는?"

prompt = PromptTemplate.from_template(template=template)
chain = prompt | llm | StrOutputParser()


@elapsed_time
def invoke():
    response = chain.invoke({"country": "서울"})
    print(response)

2. Memory Cache

Memory Cache는 캐시를 메모리에 저장한다. 이는 가장 간단한 캐시 방식으로, 애플리케이션이 실행되는 동안만 유효하다. 따라서 빠른 응답이 필요하지만, 지속적인 저장이 필요하지 않은 경우에 적합하다.

예제: Memory Cache 사용

set_llm_cache(InMemoryCache()) # 캐쉬 설정

llm = ChatOpenAI(
    temperature=0,  # 창의성 (0.0 ~ 2.0)
    model_name="gpt-4o",  # 모델명
)

...

invoke()
# 서울은 대한민국의 수도입니다. 대한민국의 정치, 경제, 문화의 중심지로서 중요한 역할을 하고 있습니다.
# Sync execution time: 0.8379083819454536

invoke()
# 서울은 대한민국의 수도입니다. 대한민국의 정치, 경제, 문화의 중심지로서 중요한 역할을 하고 있습니다.
# Sync execution time: 0.002842582995072007

이 예제에서는 InMemoryCache를 사용하여 메모리에 캐시를 저장한다. 첫 번째 invoke() 호출 시에는 0.8초 정도 걸렸지만 두 번째 invoke() 호출 시에는 시간(0.002)이 거의 걸리지 않았다. 이는 동일한 질문이 다시 실행되면, 캐시된 응답이 반환된다.

3. SQLite Cache

SQLite Cache는 SQLite 데이터베이스를 사용하여 캐시를 저장한다. 이 방식은 메모리 기반 캐시와 비교해 더 영구적이며, 애플리케이션이 재시작되어도 캐시된 데이터를 유지할 수 있다.

예제: SQLite Cache 사용

set_llm_cache(SQLiteCache(database_path="llm_cache.db")) # 캐쉬 설정

llm = ChatOpenAI(
    temperature=0,  # 창의성 (0.0 ~ 2.0)
    model_name="gpt-4o",  # 모델명
)

...

invoke()

이 예제에서는 SQLiteCache를 사용하여 캐시를 SQLite 데이터베이스(llm_cache.db)에 저장한다. 데이터베이스 파일은 디스크에 저장되므로, 애플리케이션이 재시작되어도 캐시가 유지된다.

  • 첫 번째 invoke()를 호출

    • Sync execution time: 0.8655317070661113
  • 두 번째 invoke()를 호출

    • Sync execution time: 0.09248012094758451

4. SQLAlchemy Cache

SQLAlchemy Cache는 다양한 데이터베이스를 지원하는 SQLAlchemy를 사용하여 캐시를 관리한다. 이를 통해 MySQL, PostgreSQL 등 다양한 데이터베이스에서 캐시를 사용할 수 있다.

예제: SQLAlchemy Cache 사용

engine = create_engine("sqlite:///sqlalchemy_cache.db")
llm_cache = SQLAlchemyCache(engine=engine)
set_llm_cache(llm_cache) # 캐쉬 설정

llm = ChatOpenAI(
    temperature=0,  # 창의성 (0.0 ~ 2.0)
    model_name="gpt-4o",  # 모델명
)

...

invoke()

이 예제에서는 SQLAlchemy를 사용하여 SQLite 데이터베이스에 캐시를 저장한다. SQLAlchemy를 사용하면 여러 데이터베이스 시스템에서 동일한 코드를 사용할 수 있다.

invoke 실행

  • 첫 번째 실행: Sync execution time: 0.8620363980298862
  • 두 번째 실행: Sync execution time: 0.10310529498383403

5. Elasticsearch Cache

Elasticsearch Cache는 Elasticsearch를 사용하여 캐시를 저장한다.

예제: Elasticsearch Cache 사용

llm_cache = ElasticsearchCache(
    es_url="http://localhost:9200",
    index_name="llm_cache",
)
set_llm_cache(llm_cache) # 캐쉬 설정

llm = ChatOpenAI(
    temperature=0,  # 창의성 (0.0 ~ 2.0)
    model_name="gpt-4o",  # 모델명
)

...

invoke()

이 예제에서는 Elasticsearch를 사용하여 캐시를 저장한다. ElasticsearchCache는 빠르고 강력한 검색 기능을 제공하며, 대규모 데이터 세트에서 캐시를 관리하는 데 적합하다.

invoke 실행

  • 첫 번째 실행: Sync execution time: 1.0384672500003944
  • 두 번째 실행: Sync execution time: 0.009674749999248888
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유