1) 백엔드에서 고객 서비스 매뉴얼 파일 업로드 하고, 이를 vector store 데이터베이스에 업로드
2) 유저의 텍스트 인풋에 따라 상담의 의도를 LLM이 파악
3) RAG, Vector Search를 같이 사용해 LLM 에이전트가 상담 매뉴얼 DB에서 정확한 결과 검색
4) 할루시네이션이 나오면 후처리해서 LLM이 답하는 것보다 인간 상담원에게 연결할 수 있도록 디자인
* 필요한 라이브러리 모듈 불러오기
import dotenv
dotenv.load_dotenv()
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import ChatOpenAI
from langchain.agents.agent_toolkits import create_retriever_tool
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import AgentExecutor, ConversationalChatAgent
import streamlit as st
from langchain_community.chat_message_histories import StreamlitChatMessageHistory
from langchain.memory import ConversationBufferMemory
from langchain_community.callbacks import StreamlitCallbackHandler
from langchain_core.runnables import RunnableConfig
1) 벡터 스토어에 데이터 저장
# 벡터 스토어에 데이터 저장
loader = WebBaseLoader("https://dalpha.so/ko/howtouse?scrollTo=custom")
data = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
all_splits = text_splitter.split_documents(data)
vectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())
retriever = vectorstore.as_retriever()
2) 에이전트가 사용할 툴 지정 - 검색
# 에이전트가 사용할 툴
tool = create_retriever_tool(
retriever,
"customer_service",
"Searches and returns documents regarding the customer service guide."
)
tools = [tool]
# 에이전트 생성
system_messages = """You are a nice customer service agent.
Do your best to answer the questions.
Feel free to use any tools available to look up relevant information, only if necessary.
Do not generate false answers to questions that are not related to the customer service guide.
If you don't know the answer, just say that you don't know. Don't try to make up an answer.
항상 한국어로 답변해."""
llm = ChatOpenAI(temperature=0, streaming=True)
agent = ConversationalChatAgent.from_llm_and_tools(llm=llm, tools=tools)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
memory=memory,
system_message=system_messages,
verbose=True,
return_intermediate_steps=True,
handle_parsing_errors=True,
)
5) 프론트 페이지 (streamlit)
# Front
st.set_page_config(page_title="ChatWebsite", page_icon="🔗")
st.title("Customer Service")
if "openai_model" not in st.session_state:
st.session_state["openai_model"] = "gpt-3.5-turbo"
# Initialize chat history
if len(msgs.messages) == 0 or st.sidebar.button("Reset chat history"):
msgs.clear()
msgs.add_ai_message("무엇을 도와드릴까요?")
st.session_state.steps = {}
st.session_state["messages"] = []
LLM 모델 선택 (gpt-3.5-turbo)
메세지가 없거나, Reset 버튼을 누르면 "무엇을 도와드릴까요?"라고 먼저 묻기
5-1) 기존 대화 내역 보여주기
# Display chat messages from history on app rerun
avatars = {"human": "user", "ai": "assistant"}
for idx, msg in enumerate(msgs.messages):
with st.chat_message(avatars[msg.type]):
# Render intermediate steps if any were saved
for step in st.session_state.steps.get(str(idx), []):
if step[0].tool == "_Exception":
continue
with st.status(f"**{step[0].tool}**: {step[0].tool_input}", state="complete"):
st.write(step[0].log)
st.write(step[1])
st.write(msg.content)
5-2) 새로운 채팅이 들어오면, LLM 으로 결과를 생성해 보여주기
# Accept user input
if prompt := st.chat_input(placeholder="What is up?"):
st.chat_message("user").write(prompt)
with st.chat_message("assistant"):
st_cb = StreamlitCallbackHandler(st.container(), expand_new_thoughts=False)
cfg = RunnableConfig()
cfg["callbacks"] = [st_cb]
response = agent_executor.invoke(prompt, cfg)
st.write(response["output"])
st.session_state.steps[str(len(msgs.messages) - 1)] = response["intermediate_steps"]