챗 스토어 — 대화 기록을 저장하는 중앙 인터페이스

챗 스토어 — 대화 기록을 저장하는 중앙 인터페이스

멀티턴 챗봇을 만들다 보면 이전 대화를 기억해야 해요. 그런데 대화 기록은 다른 데이터와 달리 취급이 조금 특별합니다. 메시지의 순서가 대화 전체를 유지하는 데 중요하기 때문이에요. 챗 스토어는 이런 대화 기록을 저장하기 위한 중앙 인터페이스예요.

출처: 공식문서

챗 스토어는 메시지 시퀀스를 키(예: user_ids나 다른 고유한 식별 문자열) 단위로 정리하고, delete·insert·get 연산을 처리해요. 즉 "이 사용자의 대화 기록을 꺼내기", "메시지 추가하기", "마지막 메시지 삭제하기" 같은 작업을 키를 기준으로 수행하는 구조입니다.

SimpleChatStore

가장 기본적인 챗 스토어는 SimpleChatStore예요. 메시지를 메모리에 저장하고, 디스크에 저장/로드하거나 문자열로 직렬화해 다른 곳에 보관할 수 있어요.

보통 챗 스토어를 인스턴스화해서 메모리 모듈에 넘겨줍니다. 챗 스토어를 쓰는 메모리 모듈은 별도로 지정하지 않으면 기본적으로 SimpleChatStore를 사용해요.

from llama_index.core.storage.chat_store import SimpleChatStore
from llama_index.core.memory import ChatMemoryBuffer

chat_store = SimpleChatStore()

chat_memory = ChatMemoryBuffer.from_defaults(
    token_limit=3000,
    chat_store=chat_store,
    chat_store_key="user1",
)

이렇게 메모리를 만들면 에이전트나 챗 엔진에 포함시킬 수 있어요.

agent = FunctionAgent(tools=tools, llm=llm)
await agent.run("...", memory=memory)
# OR
chat_engine = index.as_chat_engine(memory=memory)

chat_store_key가 바로 "이 대화가 어떤 키에 속하는지"를 구분하는 값이에요. 사용자별로 다른 키를 주면 사용자마다 별도의 대화 기록을 유지할 수 있어요.

챗 스토어를 나중에 쓰기 위해 저장하려면 디스크로 저장/로드하거나,

chat_store.persist(persist_path="chat_store.json")
loaded_chat_store = SimpleChatStore.from_persist_path(
    persist_path="chat_store.json"
)

문자열로 변환해 그 문자열을 다른 곳에 저장할 수도 있어요.

chat_store_string = chat_store.json()
loaded_chat_store = SimpleChatStore.parse_raw(chat_store_string)

UpstashChatStore

UpstashChatStore를 쓰면 대화 기록을 Upstash Redis(서버리스 Redis)에 원격 저장할 수 있어요. 확장 가능하고 효율적인 챗 저장이 필요한 앱에 적합하며, 동기·비동기 연산을 모두 지원합니다.

pip install llama-index-storage-chat-store-upstash
from llama_index.storage.chat_store.upstash import UpstashChatStore
from llama_index.core.memory import ChatMemoryBuffer

chat_store = UpstashChatStore(
    redis_url="YOUR_UPSTASH_REDIS_URL",
    redis_token="YOUR_UPSTASH_REDIS_TOKEN",
    ttl=300,  # Optional: Time to live in seconds
)

chat_memory = ChatMemoryBuffer.from_defaults(
    token_limit=3000,
    chat_store=chat_store,
    chat_store_key="user1",
)

ttl(초 단위)로 메시지가 유지될 시간을 정할 수 있어요. 비동기로 쓸 땐 async_set_messages, async_get_messages, async_delete_last_message 같은 메서드를 await로 호출하면 됩니다.

RedisChatStore

RedisChatStore를 쓰면 대화 기록을 Redis에 원격 저장해, 수동으로 저장·로드할 걱정 없이 쓸 수 있어요.

from llama_index.storage.chat_store.redis import RedisChatStore
from llama_index.core.memory import ChatMemoryBuffer

chat_store = RedisChatStore(redis_url="redis://localhost:6379", ttl=300)

chat_memory = ChatMemoryBuffer.from_defaults(
    token_limit=3000,
    chat_store=chat_store,
    chat_store_key="user1",
)

AzureChatStore

AzureChatStore를 쓰면 대화 기록을 Azure Table Storage나 CosmosDB에 원격 저장할 수 있어요.

pip install llama-index
pip install llama-index-llms-azure-openai
pip install llama-index-storage-chat-store-azure
from llama_index.core.chat_engine import SimpleChatEngine
from llama_index.core.memory import ChatMemoryBuffer
from llama_index.storage.chat_store.azure import AzureChatStore

chat_store = AzureChatStore.from_account_and_key(
    account_name="",
    account_key="",
    chat_table_name="ChatUser",
)

memory = ChatMemoryBuffer.from_defaults(
    token_limit=3000,
    chat_store=chat_store,
    chat_store_key="conversation1",
)

chat_engine = SimpleChatEngine(
    memory=memory, llm=Settings.llm, prefix_messages=[]
)

response = chat_engine.chat("Hello.")

DynamoDBChatStore

DynamoDBChatStore를 쓰면 대화 기록을 AWS DynamoDB에 저장할 수 있어요.

pip install llama-index-storage-chat-store-dynamodb

먼저 적절한 스키마로 DynamoDB 테이블을 만들어야 해요. 기본 예시는 다음과 같아요.

import boto3

dynamodb = boto3.resource("dynamodb")

table = dynamodb.create_table(
    TableName="EXAMPLE_TABLE",
    KeySchema=[{"AttributeName": "SessionId", "KeyType": "HASH"}],
    AttributeDefinitions=[
        {"AttributeName": "SessionId", "AttributeType": "S"}
    ],
    BillingMode="PAY_PER_REQUEST",
)

그다음 DynamoDBChatStore로 대화 기록을 영속·조회해요.

import os
from llama_index.core.llms import ChatMessage, MessageRole
from llama_index.storage.chat_store.dynamodb.base import DynamoDBChatStore

chat_store = DynamoDBChatStore(
    table_name="EXAMPLE_TABLE", profile_name=os.getenv("AWS_PROFILE")
)

# A chat history, which doesn't exist yet, returns an empty array.
print(chat_store.get_messages("123"))  # >>> []

messages = [
    ChatMessage(role=MessageRole.USER, content="Who are you?"),
    ChatMessage(role=MessageRole.ASSISTANT, content="I am your helpful AI assistant."),
]
chat_store.set_messages(key="123", messages=messages)

# Appending a message to an existing chat history
message = ChatMessage(role=MessageRole.USER, content="What can you do?")
chat_store.add_message(key="123", message=message)

아직 없는 키로 조회하면 빈 배열을 돌려주고, set_messages로 기록을 초기화하며, add_message로 기존 기록에 메시지를 덧붙이는 식이에요.

PostgresChatStore

PostgresChatStore를 쓰면 대화 기록을 Postgres에 원격 저장할 수 있어요.

from llama_index.storage.chat_store.postgres import PostgresChatStore
from llama_index.core.memory import ChatMemoryBuffer

chat_store = PostgresChatStore.from_uri(
    uri="postgresql+asyncpg://postgres:[email protected]:5432/database",
)

chat_memory = ChatMemoryBuffer.from_defaults(
    token_limit=3000,
    chat_store=chat_store,
    chat_store_key="user1",
)

TablestoreChatStore

TablestoreChatStore를 쓰면 대화 기록을 Alibaba Cloud Tablestore에 원격 저장할 수 있어요.

pip install llama-index-storage-chat-store-tablestore
from llama_index.storage.chat_store.tablestore import TablestoreChatStore
from llama_index.core.memory import ChatMemoryBuffer

chat_store = TablestoreChatStore(
    endpoint="<end_point>",
    instance_name="<instance_name>",
    access_key_id="<access_key_id>",
    access_key_secret="<access_key_secret>",
)
# You need to create a table for the first use
chat_store.create_table_if_not_exist()

chat_memory = ChatMemoryBuffer.from_defaults(
    token_limit=3000,
    chat_store=chat_store,
    chat_store_key="user1",
)

처음 사용할 땐 create_table_if_not_exist()로 테이블을 만들어야 해요.

Google AlloyDB ChatStore

AlloyDBChatStore를 쓰면 대화 기록을 AlloyDB에 저장할 수 있어요.

pip install llama-index
pip install llama-index-alloydb-pg
pip install llama-index-llms-vertex
from llama_index.core.chat_engine import SimpleChatEngine
from llama_index.core.memory import ChatMemoryBuffer
from llama_index_alloydb_pg import AlloyDBChatStore, AlloyDBEngine
from llama_index.llms.vertex import Vertex

engine = AlloyDBEngine.from_instance(
    project_id=PROJECT_ID,
    region=REGION,
    cluster=CLUSTER,
    instance=INSTANCE,
    database=DATABASE,
    user=USER,
    password=PASSWORD,
)

engine.init_chat_store_table(table_name=TABLE_NAME)

chat_store = AlloyDBChatStore.create_sync(engine=engine, table_name=TABLE_NAME)

memory = ChatMemoryBuffer.from_defaults(
    token_limit=3000,
    chat_store=chat_store,
    chat_store_key="user1",
)

llm = Vertex(model="gemini-1.5-flash-002", project=PROJECT_ID)

chat_engine = SimpleChatEngine(memory=memory, llm=llm, prefix_messages=[])
response = chat_engine.chat("Hello.")
print(response)

Google Cloud SQL for PostgreSQL ChatStore

Cloud SQL for Postgres에서도 PostgresChatStore로 대화 기록을 저장할 수 있어요.

pip install llama-index
pip install llama-index-cloud-sql-pg
pip install llama-index-llms-vertex
from llama_index.core.chat_engine import SimpleChatEngine
from llama_index.core.memory import ChatMemoryBuffer
from llama_index_cloud_sql_pg import PostgresChatStore, PostgresEngine
from llama_index.llms.vertex import Vertex

engine = PostgresEngine.from_instance(
    project_id=PROJECT_ID,
    region=REGION,
    instance=INSTANCE,
    database=DATABASE,
    user=USER,
    password=PASSWORD,
)

engine.init_chat_store_table(table_name=TABLE_NAME)

chat_store = PostgresChatStore.create_sync(engine=engine, table_name=TABLE_NAME)

memory = ChatMemoryBuffer.from_defaults(
    token_limit=3000,
    chat_store=chat_store,
    chat_store_key="user1",
)

llm = Vertex(model="gemini-1.5-flash-002", project=PROJECT_ID)

chat_engine = SimpleChatEngine(memory=memory, llm=llm, prefix_messages=[])
response = chat_engine.chat("Hello.")
print(response)

YugabyteDBChatStore

YugabyteDBChatStore를 쓰면 대화 기록을 YugabyteDB에 원격 저장할 수 있어요. 먼저 YugabyteDB 인스턴스가 실행 중이어야 합니다.

pip install llama-index-storage-chat-store-yugabytedb
from llama_index.storage.chat_store.yugabytedb import YugabyteDBChatStore
from llama_index.core.memory import ChatMemoryBuffer

chat_store = YugabyteDBChatStore.from_uri(
    uri="yugabytedb+psycopg2://yugabyte:[email protected]:5433/yugabyte?load_balance=true",
)

chat_memory = ChatMemoryBuffer.from_defaults(
    token_limit=3000,
    chat_store=chat_store,
    chat_store_key="user1",
)

from_uri()에 전달하는 커넥션 문자열은 여러 파라미터를 지원해요. YugabyteDB 특유의 값으로는 load_balance(로드밸런싱 켜기/끄기, 기본 false), topology_keys(연결 라우팅에 쓸 선호 노드), yb_servers_refresh_interval(가용 서버 목록 갱신 주기), fallback_to_topology_keys_only(topology_keys에 지정된 노드만 연결), failed_host_ttl_seconds(실패 노드 재시도 대기 시간) 등이 있어요.

더 알아보기

  • Customizing Storage — 저장 계층을 바꾸는 방법
  • Chat Engine 배포 가이드 — 챗 엔진에 챗 스토어를 연결하는 방법
  • LlamaParse 퀵스타트 — 파싱으로 다룰 문서 준비하기