멀티턴, 대화 요약를 위한 DB 설계

멀티턴, 대화 요약를 위한 DB 설계

멀티턴, summary를 지원할 수 있도록 DB 설계를 해보도록 하겠다.

DB 종류 선정

  1. SQLite : 간단하고 빠르며, 챗봇 애플리케이션의 대화 기록을 관리하는 데 적합.
  • 설치 및 설정이 간단 : 파일 기반 DB이므로 별도의 서버 설정이 필요 없고, 파일 하나로 데이터베이스를 다룰 수 있어 빠르게 사용 가능.

  • 경량화 된 구조 : 작은 규모의 데이터베이스에 적합하며, 챗봇 대화 로그와 같이 비교적 단순한 데이터 구조를 다룰 때 효과적

  • 빠른 성능 : 파일 기반 데이터베이스로, 챗봇 애플리케이션의 빠른 응답에 적합.

  • 호환성 : 대부분의 언어와 플랫폼에서 기본으로 지원

  • 결론 : 챗봇 대화 로그나 요약을 저장하는 정도의 용도라면 SQLite가 효율적, 만약 데이터베이스의 확장성과 분산 처리가 필요하다면 PostgreSQL 또는 MySQL 같은 데이터베이스로 전환하는 것이 좋다.
    09. SQLite 에 대화내용 저장

  1. Redis
  • 고속 데이터 처리 : 메모리 기반, I/O 빠르다, 대화 데이터의 실시간 처리가 중요한 챗봇 애플리케이션에 적합.

  • TTL 기능 : 데이터 만료시간 설정 가능

  • 경량 데이터 처리 : 데이터 구조가 간단하여 작은 규모의 데이터를 빠르게 저장하고 접근 가능.

  • 데이터 영구성 부족 : 인메모리DB, 서버 재기동시 데이터 손실 → 스냅샷과 AOF 설정 추가 필요, but 완전한 영구 저장 솔루션보다는 다소 제한적.

  • 대규모 데이터 저장에 적합하지 않음 : 인메모리DB, 메모리, 비용문제 발생 가능성

  • 데이터 일관성 문제 : 데이터일관성 보다는 속도에 중점 → 상관 없을것 같기도 함..

  1. PostgreSQL
  • 확장성 및 안정성 : 대규모 데이터를 안정적으로 처리할 수 있는 확장성이 뛰어난 데이터베이스.

  • 트랜잭선 지원 : 트랜잭션 처리 및 동시성 제어에 강력한 기능 제공. 데이터의 일관성과 무결성 보장.

  • 인덱싱및 고급 쿼리 지원 : 요약이나 특정 대화만 빠르게 조회해야 할 때 성능을 높이는 데 유리.

  • 설치 및 관리의 복잡성 : 서버 설치가 필요하고 구성도 다소 복잡함.

  • 메모리 및 디스크 요구사항 : 시스템 리소스를 더 많이 요구, 소규모 프로젝트나 단순한 대화 기록 저장 용도로는 다소 과함.

  • 결론 : 챗봇 데이터가 많아지고 검색이나 통계 분석이 중요한 경우 매우 적합한 선택. 다만 프로젝트 초기 개발 단계이거나 간단한 챗봇 로그 용도라면 PostgreSQL의 장점 활용 못할수도 있음.

1안 : SQLite 사용

테이블 정의서

한 턴의 대화마다 요약을 한다고 가정 했을 때.

Table 명 : interactions

No Column Name Attribute Name Type Null Keys Description
1 conversation_id transaction_id INTEGER NN PK Sequence
2 user_uuid user_id TEXT NN user id
3 user_input message TEXT NN user 발화
4 agent_response response TEXT NN agent 응답
5 summary summary TEXT NN 대화내용 요약
6 timestamp timestamp TIMESTAMP NN agent 응답

Redis + PostgreSQL?

  1. Redis로 실시간 대화 기록 처리
  • 최신 대화 기록과 같은 실시간 데이터를 Redis에 저장하여 빠르게 읽고 쓰기 가능.
  • 대화 중에는 Redis에서 데이터 관리.
  1. PostgreSQL로 영구 데이터 저장
  • 주요 대화 기록이나 요약, 사용자 정보 등의 영구적인 데이터를 PostgreSQL에 저장해 장기적으로 유지
  1. Redis에서 PostgreSQL로 데이터마이그레이션
  • Redis에 저장된 데이터를 주기적으로 PostgreSQL로 이전하는 스케줄러 사용. (배치 작업 등)

단점

  1. 시스템 복잡성 증가
  • 각 데이터베이스의 설정, 관리, 모니터링이 필요하며, 장애 대응이나 성능 최적화도 각각 별도로 수행해야 한다.
  • 데이터 동기화가 실패하거나 지연되면 Redis와 PostgreSQL 간의 데이터 불일치 문제가 발생할 수 있어, 이를 해결하기 위한 모니터링과 에러 핸들링이 필요
  1. 메모리 비용 증가
  • Redis는 대량의 데이터를 저장할 경우 메모리 비용 높다.
  • Redis의 메모리 사용량을 줄이기 위해 TTL을 설정 -> 필요한 경우 모든 데이터를 PostgreSQL에 영구 저장해야 하므로 Redis와 PostgreSQL의 데이터 저장 비용이 중복
  1. 두 시스템의 상이한 데이터 모델
  • Redis와 PostgreSQL은 서로 다른 데이터 모델과 쿼리 방식을 사용 (키-값 vs SQL)

Langchain.memory의 ConversationSummaryBufferMemory 등이 Redis를 대체 가능한가?

ConversationSummaryMemory는?

  • 대화 요약에 특화 : 요약을 기반으로 챗봇의 기억을 관리하는 것이 목적
  • 메모리 기반 : 임시 메모리에 저장. 서버 재기동 하거나 메모리 초기화 시 데이터 소실 → Redis는 스냅샷과 AOF 설정으로 반 영구 저장 가능
  • 속도 및 접근성 : conversationSummaryMemory는 단일 프로세스 내의 임시 메모리로 사용되기 때문에 Redis처럼 여러 클라이언트가 접근하는 다중 프로세스 환경에서 사용하기는 제한적.

→ ConversationSummaryBufferMemory는 대화 내용을 요약하고 간단히 참조하는 메모리 역할에는 유용하지만 Redis를 대체할 수 있는 완전한 데이터 저장 솔루션은 아님.

→ 영구적이고 구조화된 대화 데이터를 저장하려면 Redis와 같은 외부 영구 저장소가 필요하며, ConversationSummaryBufferMemory는 Redis를 보완하는 임시 요약 메모리로 활용 가능.

RunnableWithMessageHistory + Redis

RunnableWithMessageHistory : 대화 기록과 맥락을 효과적으로 관리하기 위해 LangChain에서 제공하는 클래스

  • 이전 메시지의 맥락을 유지해야 할 때 유용.
  • 메시지 기록이 시간 순으로 관리되므로, 대화의 특정 메시지를 빠르게 조회가능
  • RunnableWithMessageHistory와 함께 대화 요약 모델(예: GPT-3, GPT-4 등)을 연결하여 요약 기능을 구현. 이 클래스는 요약이 필요한 메시지를 정리하여 전달하고, 요약된 응답을 받아 메시지 히스토리에 추가하는 방식으로 동작
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
store = {} # 세션 기록을 저장할 딕셔너리
# 세션 ID를 기반으로 세션 기록을 가져오는 함수
def get_session_history(session_ids: str) -> BaseChatMessageHistory:
print(session_ids)
if session_ids not in store: # 세션 ID가 store에 없는 경우
# 새로운 ChatMessageHistory 객체를 생성하여 store에 저장
store[session_ids] = ChatMessageHistory()
return store[session_ids] # 해당 세션 ID에 대한 세션 기록 반환
with_message_history = (
RunnableWithMessageHistory( # RunnableWithMessageHistory 객체 생성
runnable, # 실행할 Runnable 객체
get_session_history, # 세션 기록을 가져오는 함수
input_messages_key="input", # 입력 메시지의 키
history_messages_key="history", # 기록 메시지의 키
)
)

메시지 기록을 효과적으로 관리하려면 두 가지 요소 필요

  1. Runnable : 주로 Retriever, Chain과 같이 BaseChatMessageHistory와 상호작용하는 runnable 객체
  2. BaseChatMessageHistory의 인스턴스를 반환하는 호출 가능한 객체 (callable)
  • 메시지 기록을 관리하기 위한 객체
  • 메시지 기록을 저장, 검색, 업데이트하는 데 사용.

무엇을 이용해 요약을 하는가?

  1. 언어 모델을 사용한 요약
  • RunnableWithMessageHistory를 특정 언어 모델(예: OpenAI의 GPT)과 함께 설정하면, 대화 내용을 요약하는 요청을 모델에 전달
  1. LangChain의 요약 도구
  • LangChain에서는 특정 요약 알고리즘을 사용하거나, SummaryMemory 클래스를 추가하여 반복적인 요약을 통해 핵심 내용을 추려나가는 구조를 제공

요약할 시점 커스터마이징

RunnableWithMessageHistory와 ConversationSummaryMemory를 사용할 때, 특정 조건에 따라 요약을 트리거할 수 있도록 커스터마이징 가능

대화의 길이, 특정 이벤트 발생, 주기적인 타이밍 등 요약 시점을 유연하게 조정 가능

  1. 메시지 수에 따른 요약 트리거
    1
    2
    if len(runnable.message_history) >= 10:
    summary_memory.update_summary(runnable.message_history)
  2. 특정 키워드 또는 이벤트에 따라 요약
    1
    2
    3
    user_input = "요약해줘"
    if "요약" in user_input:
    summary_memory.update_summary(runnable.message_history)
  3. 주기적 요약 (타이머 기반)
    1
    2
    3
    4
    5
    import time
    def periodic_summary():
    while True:
    time.sleep(300) # 5분마다 요약
    summary_memory.update_summary(runnable.message_history)
  4. 대화의 특정 단계에서 요약
    1
    2
    def on_conversation_end():
    summary_memory.update_summary(runnable.message_history)

저장소 옵션

  1. 인메모리 ChatMessageHistory 사용
  • 메모리 내 메시지 기록 관리
  • 빠른 I/O
  • 재기동 시 기록 삭제
  1. RedisChatMessageHistory 사용
  • Redis 사용, 메시지 기록 영구 저장 가능

장점

  1. 고속 데이터 처리와 실시간 응답성
  • Redis는 인메모리 데이터 저장소, 대화 데이터 I/O 빠름.
  • RunnableWithMessageHistory와 결합하여 사용자의 메시지를 실시간으로 Redis에 기록
  1. 대화 흐름 관리와 일관성 유지
  • RunnableWithMessageHistory는 대화의 흐름을 자연스럽게 관리
  • Redis에 기록된 이전 메시지들을 참조할 수 있어 대화의 일관성을 유지한다.
  1. TTL을 통한 효율적 메모리 관리
  • Redis에서는 대화 데이터를 일정 시간 동안만 유지하는 TTL(Time to Live) 설정이 가능.
  • 오래된 대화 데이터를 자동으로 삭제하고, 최신 대화에 필요한 정보만 유지할 수 있어 메모리 사용을 최적화.
  • RunnableWithMessageHistory와 함께 활용하면 최신 대화 기록만을 기반으로 챗봇이 응답하도록 구성 가능.
  1. 주기적인 요약 저장으로 메모리 절약
  • RunnableWithMessageHistory를 사용하여 대화 흐름이 길어지면 요약을 주기적으로 생성해 Redis에 저장
  • 불필요한 세부 메시지를 줄이고 요약본을 중심으로 대화 맥락을 유지.
  1. 확장성과 유연성
  • Redis는 분산 환경에서 확장이 용이하므로, 대규모 사용자와의 대화 기록을 효과적으로 처리.
  • RunnableWithMessageHistory를 통해 각 대화의 맥락을 관리하면서, Redis에 저장된 대화 기록을 다른 인스턴스나 마이크로서비스에서도 참조할 수 있어 유연한 확장이 가능.
  1. 대화 기록과 요약에 대한 손쉬운 접근성
  • Redis는 다양한 데이터 구조(List, Hash, Set 등)를 지원하므로, RunnableWithMessageHistory와 함께 대화 기록을 효율적으로 구조화하여 저장 가능.

2안: RunnableWithMessageHistory + Redis

  1. 대화 기록 저장: RunnableWithMessageHistory의 메시지를 받아서 Redis에 저장한다.
  2. 요약 저장: 주기적으로 요약을 업데이트하거나, 대화 종료 시 요약을 Redis에 저장한다.

Redis 데이터 구조 설계

  1. 대화별 메시지 리스트
  • Key: conversation:{conversation_id}:messages
  • Type: List
  • 설명
    • 특정 대화의 메시지를 순서대로 저장.
    • 각 메시지는 JSON 형식으로 저장, sender, message, timestamp 정보 기록
    • 예시
      1
      2
      3
      RPUSH conversation:conv_001:messages 
      '{"sender": "user", "message": "Hello!", "timestamp": "2024-10-30T10:00:00"}'
      '{"sender": "bot", "message": "Hi! How can I help you?", "timestamp": "2024-10-30T10:00:01"}'
      2.대화 요약
  • Key: conversation:{conversation_id}:summary
  • Type: Hash
  • 설명
    • 대화의 요약을 저장합니다. 요약을 주기적으로 업데이트.
    • 예시
      1
      2
      3
      HMSET conversation:conv_001:summary
      "summary" "User asked about product details"
      "timestamp" "2024-10-30T10:15:00"
  1. 사용자별 대화 목록
  • Key: user:{user_id}:conversations
  • Type: List
  • 설명
    • 사용자의 대화 ID를 시간순으로 저장.
    • 예시 - 사용자가 conv_001, conv_002, conv_003 대화를 순서대로 진행했다면
      1
      LPUSH user:123:conversations conv_003 conv_002 conv_001
    • user:123:conversations 리스트를 조회하면 사용자가 진행한 대화 목록을 시간 순서대로 볼 수 있다.
    • 이 리스트는 사용자가 이전에 진행했던 대화 기록을 관리하거나, 특정 사용자의 과거 대화 요약을 불러올 때 유용

전체 워크플로우 예시

  1. 사용자가 메시지를 보내면
  • RunnableWithMessageHistory는 해당 메시지를 conversation:{conversation_id}:messages 리스트에 저장.
  • 이때 각 메시지는 sender, message, timestamp와 함께 JSON 형식으로 저장.
  1. 대화가 일정 수준으로 진행되면 요약을 업데이트:
  • 주기적으로 대화의 요약을 생성하여 conversation:{conversation_id}:summary 해시에 업데이트.
  • 요약은 전체 대화의 주요 내용이나 주제를 간략하게 표현하며, 대화가 종료될 때, 일정수준으로 길어지면 업데이트
  1. 사용자별 대화 기록 관리
  • 각 대화가 시작될 때마다 user:{user_id}:conversations 리스트에 해당 대화 ID를 추가.
  • 이를 통해 사용자의 전체 대화이력을 관리, 특정 사용자의 과거 대화 조회

References

RunnableWithMessageHistory
Providers|LangChain

멀티턴, 대화 요약를 위한 DB 설계

https://hamin7.github.io/2024/11/03/LangChain-Memory-1/

Author

hamin

Posted on

2024-11-03

Updated on

2024-11-03

Licensed under

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

Comments

You forgot to set the shortname for Disqus. Please set it in _config.yml.
You need to set client_id and slot_id to show this AD unit. Please set it in _config.yml.