다양한 활동/대회 참가

[대회/데이콘-새싹톤🌱] pre. 챗봇 만들기 학습(4) : 챗봇 만들기 실습(Langchain 과 맞춤형 챗봇 만들기)

토끼개발자 조르디 2024. 7. 19. 15:53

1. 프로젝트 소개 및 환경 설정

1.1. 프로젝트 소개👾

LangChain 과 RAG 를 활용한 '서울시 정책 전문가 챗봇 만들기'

  • 최근 서울시에서 실행하는 정책을 참고해, 유저의 질문에 대답을 할 수 있도록 챗봇 만들기
  • 서울시 정책 PDF 문서를 데이터로 사용, ChatGPT 등의 LLM을 이용해 프로젝트를 진행

1.2. 환경 설정

LangChain 사용 위한 라이브러리 설치

!pip install langchain-community
!pip install langchain-openai

 

필수 환경 변수 설정 : 이전에 저장한 API KEY 입력

# LangSmith API 키 설정
os.environ["LANGCHAIN_API_KEY"] = ""

# LangSmith 프로젝트 이름 설정
os.environ["LANGCHAIN_PROJECT"] = ""

 

2. 데이터 불러오기

2.1. PDF 문서 로드 및 확인

EX : "2024 달라지는 서울 생활" 문서 활용

 

PyMuPDFLoader

  • LangChain 라이브러리의 일부
  • PDF 를 효율적으로 로드하고 처리하는데 사용되는 도구

PyMuPDFLoader 설치

!pip install pymupdf

 

2.2. 코드 예시

pdf 파일을 불러오는 파이썬 코드 예시

from langchain_community.document_loaders import PyMuPDFLoader
# 단계 1: 문서 로드(Load Documents)
loader = PyMuPDFLoader("seoul_life_2024.pdf")
docs = loader.load()

# 문서 요약 정보 출력
print(f"로드된 문서 수: {len(docs)}")
if docs:
    print("\n첫 번째 문서 요약:")
    print(f"페이지 수: {docs[0].metadata.get('page', 'N/A')}")
    print(f"총 페이지 수: {docs[0].metadata.get('total_pages', 'N/A')}")
    print(f"내용 미리보기: {docs[0].page_content[:100]}...")  # 처음 100자만 출력

 

⬇️ 위의 코드 실행 결과 ⬇️

로드된 문서 수: 158 첫 번째 문서 요약: 페이지 수: 0 총 페이지 수: 158 내용 미리보기: 2024 서울시 정책 미리 알고 알차게 즐겨요! 발 간 등 록 번 호 51-6110000-001430-10 달라지는 ...

 

결과 사진

 

 

3. 문서 분할

RecursiveCharacterTextSplitter

: 로드된 문서를 작은 청크 단위로 분할

 

파라미터

  • chunk_size : 분할된 청크의 크기
  • chunk_overlap : 인접한 청크 사이에 겹치는 문자의 개수
from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)

splits = text_splitter.split_documents(docs)
len(splits)

 

⬇️ 위의 코드 실행 결과 ⬇️

166

 

4. 벡터 스토어 생성

  1. OpenAI의 임베딩 모델을 사용해 분할된 문서를 벡터화
  2. 이를 FAISS 벡터스토어에 저장
  3. 생성된 벡터스토어의 유형, 저장된 문서 수, 벡터의 차원 등 기본 특성을 출력해 확인

FAISS 벡터스토어 및 OpenAIEmbeddings 사용

라이브러리 설치

!pip install faiss-cpu
!pip install langchain-openai

 

파이썬 코드 예시

from langchain_community.vectorstores import FAISS 
from langchain_openai import OpenAIEmbeddings 

vectorstore = FAISS.from_documents(documents=splits, embedding=OpenAIEmbeddings())

print(f"벡터스토어 유형: {type(vectorstore)}")
print(f"저장된 문서 수: {vectorstore.index.ntotal}")
print(f"벡터의 차원: {vectorstore.index.d}")

 

⬇️ 위의 코드 실행 결과 ⬇️

벡터스토어 유형: <class 'langchain_community.vectorstores.faiss.FAISS'>
저장된 문서 수: 166
벡터의 차원: 1536

결과 사진

 

5. Retriever(검색기) 생성

벡터스토어 기반으로 retriever(검색기) 생성

Retriever

  • 질문에 관련된 문서를 효율적으로 검색하는데 사용
  • 간단한 검색 테스트를 통해 기능 확인

코드 예시

#벡터스토어를 retriever로 변환
retriever = vectorstore.as_retriever()

#Retriever 정보 확인
print(f"Retriever 유형: {type(retriever)}")
print(f"검색 유형: {retriever.search_type}")
print(f"검색 파라미터: {retriever.search_kwargs}")

 

⬇️ 위의 코드 실행 결과 ⬇️

Retriever 유형: <class 'langchain_core.vectorstores.base.VectorStoreRetriever'>
검색 유형: similarity
검색 파라미터: {}

결과 사진

 

6. 프롬프트 탬플릿 정의

프롬프트 템플릿

  • 챗봇이 어떤 방식으로 대답해야할지 프롬프트에 상세하고 명확하게 적어주기
  • EX : 서울시 정책에 대해 설명해줄 수 있는 챗봇

코드 예시

from langchain_core.prompts import PromptTemplate

text = """
당신은 서울시의 정책에 대해 상세히 알고 있는 친절한 시민 상담사입니다. 당신의 임무는 서울 시민들에게 서울시의 다양한 정책을 쉽고 친절하게 설명하는 것입니다.

주어진 문맥(context)을 바탕으로 질문(question)에 답해주세요. 답변할 때는 다음 지침을 따라주세요:
1. 항상 친절하고 이해하기 쉬운 말로 설명해주세요.
2. 가능한 한 구체적인 정보를 제공하되, 불필요한 세부사항은 생략하세요.
3. 정책의 목적과 시민들에게 어떤 혜택이 있는지 강조해주세요.
4. 만약 주어진 문맥에서 답을 찾을 수 없다면, "죄송합니다. 현재 가지고 있는 정보로는 이 질문에 답하기 어렵습니다. 서울시 공식 홈페이지나 다산콜센터(120)에서 더 자세한 정보를 얻으실 수 있습니다."라고 답하세요.
5. 기술적인 용어나 정책 이름은 그대로 사용하되, 필요하다면 간단한 설명을 덧붙여주세요.

질문에 대해 단계적으로 생각하고, 논리적으로 답변을 구성해주세요.

#질문: 
{question} 

#제공된 정보: 
{context} 

#답변:
"""

prompt = PromptTemplate.from_template(text)

 

 

7. RAG (Retrieval-Augmented Generation) 체인 구성

검색기(Retriever), 프롬프트 템플릿, 언어 모델(LLM), StrOutputParser을 결합하여 RAG 체인을 구성, 실행

| 연산자

  • 구성요소를 연결

체인 가장 앞 부분

  • 프롬프트 탬플릿에 맞는 데이터 들어감
  • (체인에 입력데이터를 넣어줌)
  • "context": retriever ➡️ 비슷한 말을 검색해줌
  • "question": RunnablePassthrough() ➡️ 데이터를 입력받고, 입력받은 데이터 그대로 돌려줌 / 템플릿에서는 입력받은 질문 그대로 question 으로 들어감

StrOutputParser

  • 모델의 출력을 문자열 형태로 파싱해줌

 

코드 예시

from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

#ChatGPT 모델 초기화
llm = ChatOpenAI(model_name="gpt-4o", temperature=0)

# RAG 체인 구성
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

print(f"RAG 체인 타입: {type(rag_chain)}")

 

 

⬇️ 위의 코드 실행 결과 ⬇️

RAG 체인 타입: <class 'langchain_core.runnables.base.RunnableSequence'>

 

위의 코드를 활용하는 질문 코드

test_question = "서울시의 주요 복지 정책은 무엇인가요?"
response = rag_chain.invoke(test_question)
print(f"\n질문: {test_question}")
print(f"응답: {response}")

 

⬇️ 위의 코드 실행 결과 ⬇️

질문: 서울시의 주요 복지 정책은 무엇인가요? 응답: 안녕하세요! 서울시의 주요 복지 정책에 대해 궁금해하시는군요. 서울시는 다양한 복지 정책을 통해 시민들의 삶의 질을 높이고자 노력하고 있습니다. 몇 가지 주요 복지 정책을 소개해드릴게요. 1. **돌봄 서비스**: - **목적**: 돌봄이 필요한 시민들에게 맞춤형 돌봄 서비스를 제공하여 생활의 편의를 돕습니다. - **혜택**: 돌봄대상자의 건강 상태에 따라 필요한 서비스를 제공받을 수 있으며, 후원사업과 연계하여 추가적인 지원도 받을 수 있습니다. - **문의**: 서울복지포털(https://wis.seoul.go.kr) 또는 서울시복지재단(https://welfare.seoul.kr)에서 더 자세한 정보를 확인하실 수 있습니다. 2. **청년 취업 지원**: - **목적**: 청년들의 취업을 돕기 위해 다양한 교육과정을 제공하고, 취업 준비를 지원합니다. - **혜택**: 청년취업사관학교를 통해 다양한 교육과정을 수강하고, 레벨테스트와 면접을 통해 선발된 후 취업 지원을 받을 수 있습니다. - **문의**: 청년취업사관학교(https://sesac.seoul.kr)에서 신청 가능하며, 일자리정책과(02-2133-5448)로 문의하시면 됩니다. 3. **마약관리센터**: - **목적**: 마약류 중독자들을 보호하고 치료, 재활을 지원합니다. - **혜택**: 전문의 상담과 진료를 통해 마약류 중독자 치료보호비를 지원받을 수 있으며, 통합 서비스를 통해 중독자 회복을 돕습니다. - **문의**: 서울시 마약관리센터는 시립은평병원 내에 조성되어 있으며, 의료자원과(02-2133-7518)로 문의하시면 됩니다. 이 외에도 서울시는 다양한 복지 정책을 통해 시민들의 삶을 지원하고 있습니다. 더 자세한 정보는 서울시 공식 홈페이지나 다산콜센터(120)에서 확인하실 수 있습니다. 도움이 되셨길 바랍니다!

결과 사진