brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Jul 08. 2024

AI 4탄-3. 랭체인-Retrival(검색)데이터

랭체인 완벽 입문-3/7

랭체인 모듈 2번째

Retrival(검색)는 언어 모델이 학습한 시점에 존재하지 않는 지식이나 개념에 대해 답변 할수 있게 하는 모듈.



<11> RAG (Retrieval-Augmented Generation)

<12> 벡터화?  

<13> 벡터 검색에서 RAG 통합

<14> 소스 - 유사도 검색등 (실습)

<15> 검색 및 프롬프트 구축 순서

<16> PDF 기반으로 답하는 챗봇 만들기 (실습)







<11> RAG (Retrieval-Augmented Generation)



사용자의 입력한 정보 관련 정보를 외부 데이터 베이스등에서 검색하여 , 그 정보를 이용해 프롬프트로 만들어 언어 모델을 호출한다.

학습하지 않은 지식이나 정보도 답변하게 되는 것이다.



<12> 벡터화? 


컴퓨터가 이해 할 수 있도록 텍스트를 숫자의 조합으로 표현하는 과정이 텍스트 벡터화이다.

단어나 문장을 벡터로 표현할 수 있다.

유사 문장 검색을 위한 벡터화

수치로 표현한 것을 텍스트의 벡터화.



<13> 벡터 검색에서 RAG 통합


1

문서에서 데이터베이스를 만들어 질문으로 검색하게 하자.



2

사전 준비?

PDF나 텍스트 파일 -> 텍스트 추출 -> 벡터화 데이터 베이스에 자장.

벡터에서 유사한 문장을 검색



3

사전 준비 ?

텍스트 추출

텍스트 분할

텍스트 벡터화

텍스트와 벡터를 벡터 데이터베이스에 저장



4

텍스트 추출 (Document loaders 모듈) - 문서 가져오기

PDF, 엑셀, URL을 입력하면 텍스트만 추출하는 기능.

원본 정보가 text이면 불필요




5

텍스트 분할 (Text splitters) - 문서 변환

너무 긴 텍스트는 언어모델이 처리할수 있는 글자 수 한계를 넘어간다.

적절히 쪼개어 의미 있게 볼수 있도록 나눠야 한다.



6

텍스트 벡터화 (text embedding models) - 문서 임베딩

벡터화는 의미가 가까운 문장을 검색하게 하는것.



7

텍스트와 벡터를 벡터 데이터베이스에 저장 (Vector stores) - 벡터 데이터 베이스

저장하자.

벡터 데이터베이스에 저장하자.

파인콘(Pinecone), 크로마DB(ChromaDB) 등이 있다.









<14> 소스 - 유사도 검색등 (실습)


코랩 사용


1

retrieval 소스

https://github.com/wikibook/langchain/tree/master/03_retrieval


# 유사도 계산

# sample_vector.py



pip install tiktoken



from langchain.embeddings import OpenAIEmbeddings  #← OpenAIEmbeddings를 가져오기

from numpy import dot  #← 벡터의 유사도를 계산하기 위해 dot을 가져오기

from numpy.linalg import norm  #← 벡터의 유사도를 계산하기 위해 norm을 가져오기

embeddings = OpenAIEmbeddings( #← OpenAIEmbeddings를 초기화

    model="text-embedding-ada-002"

)

query_vector = embeddings.embed_query("비행 자동차의 최고 속도는?") #← 질문을 벡터화

print(f"벡터화된 질문: {query_vector[:5]}") #← 벡터의 일부를 표시

document_1_vector = embeddings.embed_query("비행 자동차의 최고 속도는 시속 150km입니다.") #← 문서 1의 벡터를 얻음

document_2_vector = embeddings.embed_query("닭고기를 적당히 양념한 후 중불로 굽다가 가끔 뒤집어 주면서 겉은 고소하고 속은 부드럽게 익힌다.") #← 문서 2의 벡터를 얻음

cos_sim_1 = dot(query_vector, document_1_vector) / (norm(query_vector) * norm(document_1_vector)) #← 벡터의 유사도를 계산

print(f"문서 1과 질문의 유사도: {cos_sim_1}")

cos_sim_2 = dot(query_vector, document_2_vector) / (norm(query_vector) * norm(document_2_vector)) #← 벡터의 유사도를 계산

print(f"문서 2와 질문의 유사도: {cos_sim_2}")



결과

벡터화된 질문: [-0.011098354397281122, -0.01525458172337237, 0.014659910824393215, -0.029940346994397203, -0.025661308951329925]

문서 1과 질문의 유사도: 0.9328017194423175

문서 2와 질문의 유사도: 0.7341004230866145





<15> 검색 및 프롬프트 구축 순서



6

프롬프트 


7, 8

데이터베이스에서 검색해 문장 가져오기


9

유사 문장과 질문을 조합해 프롬프트 작성


10

프롬프트를 사용해 언어 모델 호출.





<16> PDF 기반으로 답하는 챗봇 만들기 (실습)


코랩 사용



1

https://github.com/wikibook/langchain/tree/master/03_retrieval



2

# 샘플 PDF 다운 로드 하기

https://raw.githubusercontent.com/wikibook/langchain/master/asset/sample.pdf




3

# PDF에서 문장 불러오기

# 코랩 사용

# prepare_1.py


pip install pymupdf


from langchain.document_loaders import PyMuPDFLoader

loader = PyMuPDFLoader("./sample.pdf") #← sample.pdf 로드

documents = loader.load()

print(f"문서 개수: {len(documents)}") #← 문서 개수 확인

print(f"첫 번째 문서의 내용: {documents[0].page_content}") #← 첫 번째 문서의 내용을 확인

print(f"첫 번째 문서의 메타데이터: {documents[0].metadata}") #← 첫 번째 문서의 메타데이터를 확인



답변

문서 개수: 12 

첫 번째 문서의 내용: 하늘을 나는 자동차 관련  

법제도 

주의】이 글은 가상의 비행 자동차를 대상으로 한 법률 자동 생성 예시입니다. 

첫 번째 문서의 메타데이터: {'source': './sample.pdf', 'file_path': './sample.pdf', 'page': 0, 'total_pages': 12, 'format': 'PDF 1.7', 'title': '하늘을 나는 자동차 관련 법제도', 'author': '', 'subject': '', 'keywords': ', docId:825DD61FFAE9658C7293B36CB13F138





4

# 문장 나누기

# prepare_2.py



!pip install pymupdf
!python -m spacy download ko_core_news_sm # Download the Korean spaCy model



from langchain.document_loaders import PyMuPDFLoader

from langchain.text_splitter import SpacyTextSplitter  #← SpacyTextSplitter를 가져옴

loader = PyMuPDFLoader("./sample.pdf")

documents = loader.load()

text_splitter = SpacyTextSplitter(  #← SpacyTextSplitter를 초기화

    chunk_size=300,  #← 분할할 크기를 설정

    pipeline="ko_core_news_sm"  #← 분할에 사용할 언어 모델을 설정

)

splitted_documents = text_splitter.split_documents(documents) #← 문서를 분할

print(f"분할 전 문서 개수: {len(documents)}")

print(f"분할 후 문서 개수: {len(splitted_documents)}")



결과

분할 전 문서 개수: 12 

분할 후 문서 개수: 70



5

# 분할된 문장을 벡터화해 데이터베이스 저장하기

# prepare_3.py


pip install chromadb


from langchain.document_loaders import PyMuPDFLoader

from langchain.embeddings import OpenAIEmbeddings  #← OpenAIEmbeddings 가져오기

from langchain.text_splitter import SpacyTextSplitter

from langchain.vectorstores import Chroma  #← Chroma 가져오기

loader = PyMuPDFLoader("./sample.pdf")

documents = loader.load()

text_splitter = SpacyTextSplitter(

    chunk_size=300, 

    pipeline="ko_core_news_sm"

)

splitted_documents = text_splitter.split_documents(documents)

embeddings = OpenAIEmbeddings( #← OpenAIEmbeddings를 초기화

    model="text-embedding-ada-002" #← 모델명을 지정

)

database = Chroma(  #← Chroma를 초기화

    persist_directory="./.data",  #← 영속화 데이터 저장 위치 지정

    embedding_function=embeddings  #← 벡터화할 모델을 지정

)

database.add_documents(  #← 문서를 데이터베이스에 추가

    splitted_documents,  #← 추가할 문서 지정

)

print("데이터베이스 생성이 완료되었습니다.") #← 완료 알림




결과

데이터베이스 생성이 완료되었습니다.




6

# query_1.py


from langchain.embeddings import OpenAIEmbeddings

from langchain.vectorstores import Chroma

embeddings = OpenAIEmbeddings(

    model="text-embedding-ada-002"

)

database = Chroma(

    persist_directory="./.data", 

    embedding_function=embeddings

)

documents = database.similarity_search("비행 자동차의 최고 속도는?") #← 데이터베이스에서 유사도가 높은 문서를 가져옴

print(f"문서 개수: {len(documents)}") #← 문서 개수 표시

for document in documents:

    print(f"문서 내용: {document.page_content}") #← 문서 내용을 표시



답변

1. 도심에서 비행 자동차가 비행하는 경우 최대 속도는 시속 150km로 한다. 

2. 도시 외의 지역에서 비행 자동차가 비행하는 경우 최대 속도는 시속 250km로 한다. 

3. 문서 내용: 제3조(일반적 속도제한) 

1. 도심에서 비행 자동차가 비행하는 경우 최대 속도는 시속 150km로 한다. 

2. 도시 외의 지역에서 비행 자동차가 비행하는 경우 최대 속도는 시속 250km로 한다. 

3. 특정 지역이나 시설 상공 또는 특정 비행 코스에서는 별도의 속도 제한이 설정될 수 있다.





7

# 검색 결과와 질문을 조합해 질문에 답하게 한다.


방금 전 검색 결과의 문장과 질문을 조합해 프롬프트를 작성하고 언어 모델을 호출해보자.


# query_2.py


답변

도심에서는 최대 속도가 시속 150km이고, 도시 외의 지역에서는 최대 속도가 시속 250km입니다






8

#채팅 화면 만들기 , chat_1.py  - 오류


!pip install chainlit



import chainlit as cl

@cl.on_chat_start #← 채팅이 시작될 때 실행할 함수를 정의

async def on_chat_start():

    await cl.Message(content="준비되었습니다! 메시지를 입력하세요!").send() #← 초기에 표시할 메시지를 보냄

@cl.on_message #← 메시지를 보낼 때 실행할 함수를 정의

async def on_message(input_message):

    print("입력된 메시지: " + input_message)

    await cl.Message(content="안녕하세요!").send() #← 챗봇의 답변을 보냄




!pip install chainlit --upgrade


!pip install chainlit --upgrade --force-reinstall



# 오류!!! - 중지


PydanticUserError: `CodeSettings` is not fully defined; you should define `Action`, then call `pydantic.dataclasses.rebuild_dataclass(CodeSettings)`. For further information visit https://errors.pydantic.dev/2.10/u/class-not-fully-defined




10

# VSCODE 에서 작업시


 python3 -m pip install -r .\requirements.txt




다음

https://brunch.co.kr/@topasvga/3905


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari