박정기
박정기
🗡️ AI 레전드
🎖️ 마스터 파트너
🚀 SNS 챌린지 달성자

[1DAY 1랭그래프] 챗봇 메세지 요약 & 외부 sqlite memory 에 대하여 #7일차

배경 및 목적

이번 13기 AI 스터디에 앞서, 1DAY 1랭그래프, 즉 하루에 1개의 랭그래프 개념을 설명하는 부분을 기획하게 됐습니다.

-> 랭그래프 스터디에 관심이 있다면 신청해주세요!

주황색 배경의 한국 광고

스터디 신청링크

이 프로젝트의 목표는 랭그래프를 쉽게 입문하실 수 있게 상세한 개념부터 코드까지 함께 공부해보실 수 있게 정리해서 드릴 예정입니다.

저는 랭그래프를 처음들어봐요!, 1일차 글을 보고 싶다면!?

-> 링크로 접속하기!

참고 자료

코랩 실습 링크

공식 랭그래프 강의 링크

활용 툴

파이썬, 코랩, 랭그래프, 랭체인

메시지 요약 및 외부 DB 메모리를 갖춘 LangGraph 챗봇 구축하기

1. 핵심 요약

  • LangGraph와 LLM을 활용하여 대화의 실시간 요약을 생성하고, 이를 시스템 메시지에 통합하여 효율성을 높입니다.

  • MemorySaver 체크포인터를 사용해 대화 상태를 SQLite와 같은 외부 데이터베이스에 영구 저장하여 장기 대화를 지원합니다.

  • 메시지 수에 따라 자동으로 대화를 요약하는 조건부 로직과 스레드 ID를 통해 유연한 대화 흐름을 관리합니다.

대화의 흐름도

2. 핵심 기능

1. 대화 요약 통합:

- LangGraph와 대형 언어 모델(LLM)을 활용하여 대화의 실시간 요약을 생성합니다.

- 요약된 정보를 시스템 메시지로 포함시켜, 대화의 핵심 내용을 유지하면서 토큰 비용과 응답 지연 시간을 절감합니다.

2. 외부 DB 메모리 도입:

- MemorySaver와 같은 체크포인터를 사용하여 대화 상태를 SQLite와 같은 외부 데이터베이스에 영구적으로 저장합니다.

- 이를 통해 노트북 커널, 혹은 서버를 재시작하더라도 이전 대화 상태를 복원할 수 있어, 장기적인 대화 유지가 가능합니다.

3. 조건부 로직 및 요약 트리거:

- 대화 메시지 수가 일정 기준(예: 6개)을 초과하면 자동으로 대화를 요약하는 조건부 에지를 설정합니다.

- RemoveMessage를 사용하여 요약 후 불필요한 메시지를 상태에서 제거함으로써, 상태 관리를 효율적으로 수행합니다.

3. 구현 단계

1. 환경 설정 및 라이브러리 설치:

```python

%%capture --no-stderr

%pip install --quiet -U langgraph-checkpoint-sqlite langchain_core langgraph langchain_openai

```

2. API 키 설정:

```python

import os, getpass

def setenv(var: str):

if not os.environ.get(var):

os.environ[var] = getpass.getpass(f"{var}: ")

setenv("OPENAI_API_KEY")

```

3. SQLite 체크포인터 설정:

- 인메모리 SQLite 데이터베이스를 사용하거나, 파일 경로를 지정하여 영구적인 저장소를 생성합니다.

```python

import sqlite3

from langgraph.checkpoint.sqlite import SqliteSaver

# 파일 경로를 지정하여 SQLite 데이터베이스 연결

db_path = "state_db/example.db"

conn = sqlite3.connect(db_path, check_same_thread=False)

# SqliteSaver 체크포인터 초기화

memory = SqliteSaver(conn)

```

4. 챗봇 로직 정의:

- LLM을 호출하여 메시지에 요약을 통합하고, 대화 길이에 따라 요약을 생성합니다.

```python

from langchain_openai import ChatOpenAI

from langchain_core.messages import SystemMessage, HumanMessage, RemoveMessage

from langgraph.graph import END, MessagesState

model = ChatOpenAI(model="gpt-4o", temperature=0)

class State(MessagesState):

summary: str

def call_model(state: State):

summary = state.get("summary", "")

if summary:

system_message = f"Summary of conversation earlier: {summary}"

messages = [SystemMessage(content=system_message)] + state["messages"]

else:

messages = state["messages"]

response = model.invoke(messages)

return {"messages": response}

def summarize_conversation(state: State):

summary = state.get("summary", "")

if summary:

summary_message = (

f"This is summary of the conversation to date: {summary}\n\n"

"Extend the summary by taking into account the new messages above:"

)

else:

summary_message = "Create a summary of the conversation above:"

messages = state["messages"] + [HumanMessage(content=summary_message)]

response = model.invoke(messages)

delete_messages = [RemoveMessage(id=m.id) for m in state["messages"][:-2]]

return {"summary": response.content, "messages": delete_messages}

```

5. 그래프 빌드 및 메모리 통합:

```python

from langgraph.graph import StateGraph, START

from IPython.display import Image, display

def should_continue(state: State):

return "summarize_conversation" if len(state["messages"]) > 6 else END

# 그래프 빌더 초기화 및 노드 추가

builder = StateGraph(State)

builder.add_node("conversation", call_model)

builder.add_node("summarize_conversation", summarize_conversation)

# 에지 추가

builder.add_edge(START, "conversation")

builder.add_conditional_edges("conversation", should_continue)

builder.add_edge("summarize_conversation", END)

# 그래프 컴파일 및 메모리 체크포인터 통합

graph = builder.compile(checkpointer=memory)

# 그래프 시각화

display(Image(graph.get_graph().draw_mermaid_png()))

```

6. 대화 시작 및 스레드 관리:

```python

config = {"configurable": {"thread_id": "1"}}

# 초기 대화

input_message = HumanMessage(content="hi! I'm Lance")

output = graph.invoke({"messages": [input_message]}, config)

for m in output['messages'][-1:]:

m.pretty_print()

# 이어지는 대화

input_message = HumanMessage(content="what's my name?")

output = graph.invoke({"messages": [input_message]}, config)

for m in output['messages'][-1:]:

m.pretty_print()

input_message = HumanMessage(content="i like the 49ers!")

output = graph.invoke({"messages": [input_message]}, config)

for m in output['messages'][-1:]:

m.pretty_print()

# 요약 트리거 전 상태 확인

graph_state = graph.get_state(config)

print(graph_state)

```

4. 결론

  1. LangGraph를 이용한 메시지 요약과 외부 DB 메모리 통합으로 챗봇의 대화 관리 능력이 크게 향상됩니다.

  2. 이를 통해 장기적이고 복잡한 대화를 효율적으로 처리하며, 토큰 비용과 응답 지연 시간을 절감할 수 있습니다.

  3. 외부 데이터베이스를 통한 지속성 도입과 유연한 상태 스키마 정의로 다양한 대화 시나리오에 맞춘 챗봇 커스터마이징이 가능합니다.


랭그래프, AI 에이전트 구현에 관심이 생겼나요?

->지금바로 랭그래프 스터디에 관심이 있다면 신청해주세요!

주황색 배경의 한국 광고

지피터스 13기 스터디 신청링크

뉴스레터 무료 구독

👉 이 게시글도 읽어보세요