Amazon Bedrock, LangChain과 사용하기
2. Amazon Bedrock API, LangChain 사용해보기
6. 간단한 검색증강(RAG : Retrieval Augmented Generation) 구현
7. 간단한 챗봇 구현 (Conversation Memory)
8. 챗봇 구현 (RAG + Conversation Memory)
Amazon Bedrock과 일반적인 LLM의 경우 상태나 메모리에 대한 개념이 존재하지 않습니다. 모든 데이터는 외부적으로 추적된 다음 새로운 메세지와 함께 모델로 전달되어야합니다. 이번에는 채팅 기록을 추적하기위해 LangChain의 ConversationSummaryBufferMemory를 사용해보도록 하겠습니다. 모델이 처리할 수 있는 토큰은 제한되어있으므로 충분한 공간이 남도록 채팅을 정리해야하는데, 해당 클래스는 가장 최근 메세지를 추적하고 이전 메세지를 요약하여 저장하기때문에 효율적입니다.
이전에 진행하였던 검색증강(RAG)과의 차이점은 해당 애플리케이션의 응답은 데이터 소스없이 순수한 FM모델과 이전메세지만을 기반으로하고, RAG모델은 데이터 소스가 존재하여 데이터 소스를 참조한 응답을 내놓는다는점입니다. 추후 포스팅에서는 Conversation Mem과 RAG를 결합한 보다 강력한 챗봇을 만들 예정입니다.
챗봇 생성
아키텍쳐는 다음과 같고 각 Flow에 대해 간단히 설명하도록 하겠습니다.
- 과거의 상호작용을 채팅메모리 개체에서 추적합니다.
- 새로운 메세지를 유저로부터 입력받습니다.
- 채팅기록은 메모리 개체에서 검색되게 되고, 새로운 메세지 앞에 추가됩니다.
- 결합된 기록과 새 메세지가 LLM으로 전송됩니다.
- 모델의 응답이 유저에게 출력됩니다.
라이브러리 파일 (lib.py)
라이브러리를 임포트합니다. Conversation Memory와 이를 위한 Chain 또한 임포트합니다.
from langchain.memory import ConversationSummaryBufferMemory
from langchain.llms.bedrock import Bedrock
from langchain.chains import ConversationChain
Bedrock LangChain 클라이언트를 생성합니다. 이전과 같이 인퍼런스 파라미터를 조정하여 정확한 값을 얻도록 합니다.
def get_llm():
model_kwargs = { #AI21
"maxTokens": 1024,
"temperature": 0,
"topP": 0.5,
"stopSequences": ["Human:"],
"countPenalty": {"scale": 0 },
"presencePenalty": {"scale": 0 },
"frequencyPenalty": {"scale": 0 }
}
llm = Bedrock(
region_name='us-east-1',
endpoint_url="https://bedrock-runtime.us-east-1.amazonaws.com",
model_id="ai21.j2-ultra-v1",
model_kwargs=model_kwargs)
return llm
LangChain 메모리 개체를 초기화하는 함수를 추가하도록 하겠습니다. ConversationSummaryBufferMemory 클래스를 사용하여 가장 최근 메세지를 추적, 요약한 후 메모리에 저장합니다.
def get_memory():
llm = get_llm()
memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=1024)
return memory
Bedrock을 호출하기위한 함수를 추가합니다. 메모리로 이전에 생성한 메모리를 받을 수 있도록합니다.
def get_chat_response(input_text, memory):
llm = get_llm()
conversation_with_summary = ConversationChain(
llm = llm,
memory = memory,
verbose = True
)
chat_response = conversation_with_summary.predict(input=input_text)
return chat_response
전체 코드는 다음과 같습니다.
from langchain.memory import ConversationSummaryBufferMemory
from langchain.llms.bedrock import Bedrock
from langchain.chains import ConversationChain
def get_llm():
model_kwargs = { #AI21
"maxTokens": 1024,
"temperature": 0,
"topP": 0.5,
"stopSequences": ["Human:"],
"countPenalty": {"scale": 0 },
"presencePenalty": {"scale": 0 },
"frequencyPenalty": {"scale": 0 }
}
llm = Bedrock(
region_name='us-east-1',
endpoint_url="https://bedrock-runtime.us-east-1.amazonaws.com",
model_id="ai21.j2-ultra-v1",
model_kwargs=model_kwargs)
return llm
def get_memory():
llm = get_llm()
memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=1024)
return memory
def get_chat_response(input_text, memory):
llm = get_llm()
conversation_with_summary = ConversationChain(
llm = llm,
memory = memory,
verbose = True
)
chat_response = conversation_with_summary.predict(input=input_text)
return chat_response
Streamlit Application (front.py)
라이브러리와 Streamlit을 임포트합니다.
import streamlit as st
import lib as glib
페이지를 구성하고 세션 캐시에 메모리를 추가합니다. 이를통해 세션당 고유한 채팅메모리를 유지하고 채팅 기록을 추가할 수 있습니다.
st.set_page_config(page_title="Chatbot")
st.title("Chatbot")
if 'memory' not in st.session_state:
st.session_state.memory = glib.get_memory()
if 'chat_history' not in st.session_state:
st.session_state.chat_history = []
이전 채팅 메세지를 렌더링하기위한 for 루프를 추가합니다.
for message in st.session_state.chat_history:
with st.chat_message(message["role"]):
st.markdown(message["text"])
입출력 요소를 추가합니다.
input_text = st.chat_input("Chat with your bot here")
if input_text:
with st.chat_message("user"):
st.markdown(input_text)
st.session_state.chat_history.append({"role":"user", "text":input_text})
chat_response = glib.get_chat_response(input_text=input_text, memory=st.session_state.memory)
with st.chat_message("assistant"):
st.markdown(chat_response)
st.session_state.chat_history.append({"role":"assistant", "text":chat_response})
전체 코드는 다음과 같습니다.
import streamlit as st
import lib as glib
st.set_page_config(page_title="Chatbot")
st.title("Chatbot")
if 'memory' not in st.session_state:
st.session_state.memory = glib.get_memory()
if 'chat_history' not in st.session_state:
st.session_state.chat_history = []
for message in st.session_state.chat_history:
with st.chat_message(message["role"]):
st.markdown(message["text"])
input_text = st.chat_input("Chat with your bot here")
if input_text:
with st.chat_message("user"):
st.markdown(input_text)
st.session_state.chat_history.append({"role":"user", "text":input_text})
chat_response = glib.get_chat_response(input_text=input_text, memory=st.session_state.memory)
with st.chat_message("assistant"):
st.markdown(chat_response)
st.session_state.chat_history.append({"role":"assistant", "text":chat_response})
결과 확인
정상적으로 확인됩니다.
'Bedrock' 카테고리의 다른 글
Amazon Bedrock, LangChain과 사용하기 - 8. 챗봇 구현 (RAG + Conversation Memory) (0) | 2023.10.18 |
---|---|
Amazon Bedrock, LangChain과 사용하기 - 6. 간단한 검색증강(RAG : Retrieval Augmented Generation) 구현 (0) | 2023.10.18 |
Amazon Bedrock, LangChain과 사용하기 - 5. Streamlit, 텍스트/이미지 생성 (0) | 2023.10.18 |
Amazon Bedrock, LangChain과 사용하기 - 4. 스트리밍 API, 벡터 임베딩 (0) | 2023.10.18 |
Amazon Bedrock, LangChain과 사용하기 - 3. 추론 매개변수 (0) | 2023.10.18 |