[LangChain] Chatbot Message History

DHยท2024๋…„ 8์›” 6์ผ
0

LangChain

๋ชฉ๋ก ๋ณด๊ธฐ
3/5
post-thumbnail

๐Ÿค“ Message History๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 


model์„ loadํ•˜์—ฌ ์ด๋ฆ„์„ ์•Œ๋ ค์ฃผ๊ณ  ๋‚ด ์ด๋ฆ„์ด ๋ฌด์—‡์ธ์ง€ ๋‹ค์‹œ ์งˆ๋ฌธํ•ด๋ณด์ž.

from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.messages import HumanMessage

model = ChatGoogleGenerativeAI(model="gemini-pro",
                               convert_system_message_to_human=True,
                               )
model.invoke([HumanMessage(content="Hi! I'm Bob")])

model.invoke([HumanMessage(content="What's my name?")])

์ด๋ฆ„์„ ์•Œ๋ ค์ค€ ์ฒซ๋ฒˆ์งธ ๋Œ€ํ™”์™€ ๋‚˜์˜ ์ด๋ฆ„์„ ๋ฌผ์–ด๋ณด๋Š” ๋‘๋ฒˆ์งธ ๋Œ€ํ™”๊ฐ€ ๊ฐ™์€ ๋งฅ๋ฝ์œผ๋กœ ์ด์–ด์ง€์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋Œ€ํ™” 1)

๋Œ€ํ™” 2)

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„  ์ „์ฒด ๋Œ€ํ™” ๊ธฐ๋ก์„ ๋ชจ๋ธ์— ์ „๋‹ฌํ•ด์•ผํ•œ๋‹ค.

ํ•˜๋‚˜์˜ invoke() ๋ฉ”์†Œ๋“œ์— ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ๋กœ HumanMessage๋ฅผ ์ „๋‹ฌํ•ด๋ณด์ž.

from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.messages import HumanMessage
from langchain_core.messages import AIMessage

model.invoke(
  [
    HumanMessage(content="Hi, I'm Bob"),
    AIMessage(content="Hello Bob! How can i assist you today?"),
    HumanMessage(content="What's my name?")
  ]
)

์ด์ „๊ณผ ๋‹ฌ๋ฆฌ ์ด์ „ ๋Œ€ํ™” ๊ธฐ๋ก์„ ๊ธฐ์–ตํ•˜๊ณ  ๋‹ต๋ณ€ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“‘ Message History ๊ตฌํ˜„

Message History ์‚ฌ์šฉ๋ฒ•

Message History ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ์„ ๋ž˜ํ•‘ํ•˜์—ฌ ๋Œ€ํ™” ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋„๋ก ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•˜๋ฉด ๋ชจ๋ธ์˜ ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์„ ์ถ”์ ํ•ด ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ์— ์ €์žฅํ•˜๊ณ  ์ดํ›„์˜ ์ƒํ˜ธ์ž‘์šฉ์—์„œ ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ฒด์ธ์˜ ์ผ๋ถ€๋กœ ์ „๋‹ฌํ•œ๋‹ค.

from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI

from langchain_core.messages import (
  HumanMessage,
  AIMessage 
)

from langchain_core.chat_history import (
  BaseChatMessageHistory,
  InMemoryChatMessageHistory,
)
from langchain_core.runnables.history import RunnableWithMessageHistory

# load settings
load_dotenv()

# define model
model = ChatGoogleGenerativeAI(model="gemini-pro",
                               convert_system_message_to_human=True,
)

# session_id๋ฅผ ์ €์žฅํ•  ์ €์žฅ์†Œ
store = {}

def get_session_history(session_id: str) -> BaseChatMessageHistory:
  if session_id not in store:
    store[session_id] = InMemoryChatMessageHistory()
  return store[session_id]

with_message_history = RunnableWithMessageHistory(model, get_session_history)

config = {"configurable":
    {"session_id": "ABC"}
  }

response = with_message_history.invoke(
  [HumanMessage(content="Hi, I'm Bob")],
  config=config,
)
print(response.content)

response = with_message_history.invoke(
  [HumanMessage(content="What's my name?")],
  config=config,
)
print(response.content)

get_session_history() ํ•จ์ˆ˜๋Š” ๊ธฐ๋ก๋œ session_id๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น session_id๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ RunnableWithMessageHistory๋ฅผ ํ†ตํ•ด ์ฑ—๋ด‡๊ณผ ๋Œ€ํ™”๋ฅผ ์ด์–ด๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

๋งŒ์•ฝ ๋‹ค๋ฅธ session_id๊ฐ€ ์ „๋‹ฌ๋˜๋Š” ๊ฒฝ์šฐ ์ƒˆ๋กœ์šด ๋Œ€ํ™”๋กœ ์ธ์‹ํ•œ๋‹ค.

PromptTemplate ์ ์šฉ

...
prompt = ChatPromptTemplate.from_messages(
  [
    (
      "system",
      "๋„ˆ๋Š” ํ›Œ๋ฅญํ•œ ์™ธ๊ตญ์–ด ๊ณต๋ถ€ ๋ณด์กฐ AI์•ผ. ํ•œ๊ตญ์–ด๋กœ ๋จผ์ € ๋‹ต๋ณ€ํ•ด์ฃผ๊ณ  ์ด์–ด์„œ {language}๋กœ ๋‹ต๋ณ€ํ•ด์ค˜."
    ),
    MessagesPlaceholder(variable_name="messages"),
  ]
)

chain = prompt | model

with_message_history = RunnableWithMessageHistory(chain, get_session_history, input_messages_key="messages",)

response = with_message_history.invoke(
    {"messages": [HumanMessage(content="๋‚œ ํ•œ๊ตญ์—์„œ ํƒœ์–ด๋‚œ ๋‚จ์ž์•ผ! ์˜์–ด๋ฅผ ๊ณต๋ถ€ํ•˜๊ณ  ์‹ถ์–ด!")], "language": "english",},
    config=config,
)

response = with_message_history.invoke(
    {"messages": [HumanMessage(content="์ผ๋ณธ์–ด๋„ ๊ณต๋ถ€ํ•˜๊ณ ์‹ถ์€๋ฐ ๋‚ด ์„ฑ๋ณ„์˜ ๋งํˆฌ๋กœ ์ธ์‚ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค˜!")], "language": "japanese"},
    config=config,
)

๋Œ€ํ™” 1)

๋Œ€ํ™” 2)

๐Ÿ›  Conversation History ๊ด€๋ฆฌ

์ฑ—๋ด‡์„ ๊ตฌ์ถ•ํ•  ๋•Œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜๋Š” ๋Œ€ํ™” ๊ธฐ๋ก์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
๋Œ€ํ™” ๊ธฐ๋ก์„ ๊ด€๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉด ์งˆ๋ฌธ๋งˆ๋‹ค ๋ฉ”์„ธ์ง€ ๋ชฉ๋ก์ด ์ฆ๊ฐ€ํ•˜์—ฌ LLM์˜ Context Window๋ฅผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค.

LangChain์—์„œ ์ œ๊ณตํ•˜๋Š” Trimmer๋ฅผ ์ด์šฉํ•ด ๊ธฐ์กด์˜ ๋Œ€ํ™”๋‚ด์—ญ์„ ๋ชจ๋ธ์˜ ์ œ์•ฝ์กฐ๊ฑด์— ๋งž์ถ”์–ด ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๋จผ์ € ํ…Œ์ŠคํŠธ์šฉ ๋Œ€ํ™”๋‚ด์—ญ์„ ๋งŒ๋“ค๊ณ  Trimmer์— ์ ์šฉํ•œ๋‹ค. ์ด ๋•Œ Trimmer์˜ max_tokens ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ด์šฉํ•ด ์ตœ๋Œ€๋กœ ์œ ์ง€ํ•˜๋Š” ๋Œ€ํ™”๋‚ด์—ญ์„ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ๋‹ค.

from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, trim_messages

trimmer = trim_messages(
    max_tokens=1000,
    strategy="last",
    token_counter=model,
    include_system=True,
    allow_partial=False,
    start_on="human",
)

messages = [
    HumanMessage(content="์•ˆ๋…• ๋‚œ ๊ณ ๊ธธ๋™์ด์•ผ! ๊ณง ์œ ํ•™์„ ๋– ๋‚  ์˜ˆ์ •์ธ๋ฐ ํšŒํ™”์ข€ ๋„์™€์ค„๋ž˜?"),
    AIMessage(content="๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค! ์ œ๊ฐ€ ๋„์™€๋“œ๋ฆด๊ฒŒ์š”!"),
    HumanMessage(content="์™ธ๊ตญ์ธ ์นœ๊ตฌ ์—ญํ• ๋กœ ๋Œ€๋‹ตํ•ด์ค˜!"),
    AIMessage(content="๋„ค ์ข‹์•„์š”! ์ตœ์„ ์„ ๋‹คํ•ด ๋„์™€๋“œ๋ฆด๊ฒŒ์š”."),
]

trimmer.invoke(messages)
from operator import itemgetter

chain = (
    RunnablePassthrough.assign(messages=itemgetter("messages") | trimmer)
    | prompt
    | model
)

with_message_history = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key="messages",
)

with_message_history.invoke(
    {
        "messages": messages + [HumanMessage(content="๋‚ด ์ด๋ฆ„์ด ๋ญ๋ผ๊ณ ~?")],
        "language": "English",
    },
    config=config,
)

๐Ÿค– Streaming

Streaming ๋ฐฉ์‹์˜ ๋‹ต๋ณ€์„ ์›ํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

# Streaming
for r in with_message_history.stream(
    {
        "messages": [HumanMessage(content="๋‚ด ์ฒซ ์™ธ๊ตญ์ธ ์นœ๊ตฌ์•ผ! ์•ž์œผ๋กœ ์นœํ•˜๊ฒŒ ์ง€๋‚ด์ž!")],
        "language": "English",
    },
    config=config,
):
    print(r.content, end="|")

>>> ์ €๋„ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ฒซ ์™ธ๊ตญ์ธ ์นœ๊ตฌ๊ฐ€ ๋  ์ˆ˜ ์žˆ์–ด์„œ ๊ธฐ|์ฉ๋‹ˆ๋‹ค! ์•ž์œผ๋กœ ์นœํ•˜๊ฒŒ ์ง€๋‚ด๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค!|

Ref : https://python.langchain.com/v0.2/docs/tutorials/chatbot/

profile
To infinity and beyond!

0๊ฐœ์˜ ๋Œ“๊ธ€