본문 바로가기
생성형 AI/랭체인으로 RAG 개발하기: VectorRAG & GraphRAG

5. VectorRAG 실습 : OpenAI API 사용 - 3

by Toddler_AD 2025. 10. 3.

5.3 PDF에서 다육이 데이터 검색하기

  • FAISS를 사용한 벡터 검색, 랭체인을 활용한 검색 및 데이터 분석, OpenAI를 활용한 LLM 연동을 위해 필요한 라이브러리를 설치합니다.
%pip install faiss-cpu langchain pandas pypdf langchain-openai
  • 새로 설치한 라이브러리는 다음과 같습니다.
    • pypdf : PDF 파일을 다룰 수 있는 라이브러리로 PDF 파일을 읽기, 병합, 나누기, 텍스트 추출하는 기능을 제공합니다.
  • 설치 결과는 다음과 같습니다.
Requirement already satisfied: faiss-cpu in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (1.10.0)
Requirement already satisfied: langchain in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (0.3.17)
Requirement already satisfied: pandas in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (2.2.3)
Collecting pypdf
  Using cached pypdf-5.2.0-py3-none-any.whl.metadata (7.2 kB)
Requirement already satisfied: langchain-openai in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (0.3.4)
Requirement already satisfied: numpy<3.0,>=1.25.0 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from faiss-cpu) (1.26.4)
Requirement already satisfied: packaging in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from faiss-cpu) (24.2)
Requirement already satisfied: PyYAML>=5.3 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain) (6.0.2)
Requirement already satisfied: SQLAlchemy<3,>=1.4 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain) (2.0.37)
Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain) (3.11.11)
Requirement already satisfied: async-timeout<5.0.0,>=4.0.0 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain) (4.0.3)
Requirement already satisfied: langchain-core<0.4.0,>=0.3.33 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain) (0.3.34)
Requirement already satisfied: langchain-text-splitters<0.4.0,>=0.3.3 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain) (0.3.5)
Requirement already satisfied: langsmith<0.4,>=0.1.17 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain) (0.3.2)
Requirement already satisfied: pydantic<3.0.0,>=2.7.4 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain) (2.10.6)
Requirement already satisfied: requests<3,>=2 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain) (2.32.3)
Requirement already satisfied: tenacity!=8.4.0,<10,>=8.1.0 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain) (9.0.0)
Requirement already satisfied: python-dateutil>=2.8.2 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from pandas) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from pandas) (2024.2)
Requirement already satisfied: tzdata>=2022.7 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from pandas) (2025.1)
Requirement already satisfied: typing_extensions>=4.0 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from pypdf) (4.12.2)
Requirement already satisfied: openai<2.0.0,>=1.58.1 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain-openai) (1.61.1)
Requirement already satisfied: tiktoken<1,>=0.7 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from langchain-openai) (0.8.0)
Requirement already satisfied: aiohappyeyeballs>=2.3.0 in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (2.4.4)
...
Requirement already satisfied: colorama in c:\users\jyseo\anaconda3\envs\graph\lib\site-packages (from tqdm>4->openai<2.0.0,>=1.58.1->langchain-openai) (0.4.6)
Using cached pypdf-5.2.0-py3-none-any.whl (298 kB)
Installing collected packages: pypdf
Successfully installed pypdf-5.2.0
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
  • OpenAI의 gpt-4o 모델을 설정하고 사용할 수 있도록 준비합니다.
import os
os.environ["OPENAI_API_KEY"] = "sk" #openai 키 입력

from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
    model="gpt-4o",
)
  • PDF 문서를 가져와서 텍스트 데이터를 추출합니다.
from langchain.document_loaders import PyPDFLoader
docs = [] # 추출된 문서를 저장할 리스트를 초기화

loader = PyPDFLoader("d:/data/succulent.pdf") # "d:/data/succulent.pdf" 경로의 PDF 파일을 PyPDFLoader로 로드

# PDF에서 텍스트 데이터를 추출하여 텍스트 데이터로 반환
text_content = loader.load() 

# PDF의 각 페이지를 하나씩 가져와 docs에 저장
for doc in text_content:
    docs.append(doc)
print(docs[0].page_content[:100]) # 첫 번째 페이지의 처음 100자 출력
print(docs[0].metadata) # 첫 번째 문서(첫 페이지)의 메타데이터 출력
  • 그러면 다음과 같이 처음 100자와 메타데이터를 보여줍니다.
🌵 다육이 키우는 방법 
1. 햇빛과 온도 관리 
• 햇빛: 다육이는 햇빛을 좋아하는 식물이므로 하루 4~6 시간 이상은 직사광선을 받게 
해주세요. 
o 창가, 베란다, 야외 등
{'source': 'd:/data/succulent.pdf', 'page': 0, 'page_label': '1'}
  • 랭체인과 FAISS를 사용하여 텍스트 데이터를 벡터화하고, 이를 검색할 수 있도록 벡터 데이터베이스(FAISS)를 구축합니다.
from langchain_openai import OpenAIEmbeddings
from langchain import FAISS # Facebook에서 개발한 벡터 검색을 위한 Similarity Search 라이브러리
from langchain.text_splitter import CharacterTextSplitter

# 문서 분할 (텍스트를 작은 단위로 나누기)
text_splitter = CharacterTextSplitter(
    separator="\n\n", # 두 줄 띄움(\n\n)을 기준으로 분할
    chunk_size=100, # 긴 텍스트를 100자 단위로 분할
    chunk_overlap=10, # 각 청크 사이에 10자 겹치도록 설정
    length_function=len,
    is_separator_regex=False,
)

splits = text_splitter.split_documents(text_content) # text_content에서 텍스트를 가져와 분할
# 문서를 FAISS가 처리할 수 있도록, 텍스트(page_content)만 추출해서 texts에 저장
texts = [doc.page_content for doc in splits]

# OpenAI 임베딩 모델 로드
embeddings = OpenAIEmbeddings()

# 변환된 벡터를 FAISS 벡터 데이터베이스에 저장
vectorstore = FAISS.from_texts(texts, embeddings)

# FAISS 벡터 인덱스를 로컬 파일(d:/data/db_faiss_complete_open_ai)에 저장
vectorstore.save_local('d:/data/db_faiss_complete_open_ai')
  • 랭체인을 사용하여 특정 주제(다육이 키우기)에 특화된 프롬프트를 설정합니다. 여기서 '한글로 답변을 작성해주세요'와 같은 제약을 작성해도 좋습니다.
from langchain_core.prompts import PromptTemplate
# PromptTemplate를 사용하여 맞춤형 프롬프트 생성
custom_prompt_template = PromptTemplate(
    template = """당신은 다육이를 키우는 정보를 제공하는 챗봇입니다.

{context}

제공된 소스 데이터만 사용하여 고객의 질문에 답하세요.
모르겠다면 "잘 모르겠습니다."라고 답하세요.
친절하고 예의 바르며 전문적인 어조를 사용하세요.
답변은 간결하게 유지하세요.

질문: {question}

답변:
""",
input_variables=["context"]
)
chain_type_kwargs = {"prompt": custom_prompt_template} # 프롬프트를 랭체인 체인(chain_type_kwargs)에 전달
  • 저장된 벡터 데이터베이스(FAISS)를 로드하고, 주어진 쿼리와 관련된 문서를 검색할 수 있도록 검색 기능(retriever)을 설정합니다.
# FAISS 데이터베이스 로드 (FAISS.load_local)
retriever = FAISS.load_local(
    "d:/data/db_faiss_complete_open_ai", 
    OpenAIEmbeddings(),  # 저장된 벡터 데이터를 OpenAI Embeddings 모델을 사용하여 변환
    allow_dangerous_deserialization=True  
).as_retriever(
    search_type="similarity", # 유사한 문서를 검색
    search_kwargs={"k": 8} # 최대 8개의 유사한 문서를 반환
) # as_retriever()를 사용하여 문서 검색 가능하도록 변환
  • FAISS 검색과 GPT 모델을 결합하여 LLM 기반의 질의응답(QA) 시스템을 구축합니다.
from langchain.chains import RetrievalQA # 검색과 질의응답(QA)을 결합한 랭체인 체인

qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff", # 검색된 문서를 합쳐서 하나의 입력(prompt)으로 전달
    retriever=retriever, # 	FAISS 기반의 관련 문서 검색
    chain_type_kwargs=chain_type_kwargs # 프롬프트(PromptTemplate) 적용
)

# 사용자의 질문을 입력하여 검색 및 응답 생성
query = "겨울철 다육이 키우는 방법은?"
response = qa_chain.invoke(query)

print(response)
  • 질문에 대한 답변은 다음과 같습니다.
{'query': '겨울철 다육이 키우는 방법은?', 
'result': '겨울철 다육이 관리는 휴면기를 고려하여 다음 사항을 유의해 주세요.
\n\n• 온도: 다육이의 성장은 겨울에 멈추므로, 실내에서 5℃ 이상, 가능하면 15~25℃ 범위를 유지해주세요.
\n• 물주기: 겨울에는 휴면기이므로 거의 주지 않거나 한 달에 한 번 소량만 공급해 주세요.
\n• 환기: 실내에서도 공기가 잘 통하도록 창문을 자주 열어 주세요.
\n\n이렇게 관리하시면 겨울에도 다육이를 건강하게 유지할 수 있습니다.'}
  • 또 다른 질문을 해봅시다.
query = "겨울철 물은 몇 번 주는 것이 적당해?"
response = qa_chain.invoke(query)

print(response)
  • 역시 정확한 답변을 해줍니다.
{'query': '겨울철 물은 몇 번 주는 것이 적당해?', 
'result': '겨울철은 다육이의 휴면기이므로 물을 거의 주지 않거나 한 달에 한 번 소량만 주는 것이 적당합니다.'}
  • PDF의 내용을 찾아보고, 답변이 정확한 지 확인해보세요.