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

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

by Toddler_AD 2025. 10. 3.
  • 진행할 실습은 RAG와 관련되어 있어, 참고할 파일들이 필요합니다. 참고 파일은 d:/data에 저장해주세요. 실습은 모든 파일이 d:/data에 저장되어 있다는 가정 하에 진행되며, 필요에 따라 경로를 변경해 사용해도 됩니다.

5.1 자동차 데이터 검색하기

  • 랭체인을 활용하여 AI 기반 검색 및 자연어 처리 시스템을 구축할 때 필요한 주요 라이브러리를 설치합니다.
%pip install langchain langchain-community langchain-openai faiss-cpu pandas openpyxl
  • 설치한 라이브러리는 다음과 같습니다.
    • langchain : 랭체인은 대화형 AI 애플리케이션을 구축하는 데 사용되는 프레임워크로, Open AI GPT 모델을 포함한 다양한 LLM과의 상호작용을 쉽게 할 수 있도록 도와줍니다.
    • langchain-community : 랭체인의 확장 기능으로, LLM 기반 애플리케이션을 쉽게 구축할 수 있도록 돕는 라이브러리입니다.
    • langchain-openai : Open AI의 GPT 모델과 상호작용하는 라이브러리입니다. 이전에는 OpenAIEmbeddings 등 OpenAI 관련 기능이 랭체인에 포함되어 있었지만, 최근 업데이트에서 별도의 패키지로 분리되었습니다.
    • faiss-cpu : 메타 AI Research에서 개발한 벡터 검색 라이브러리로, 대량의 벡터 데이터를 효율적으로 검색하는 데 사용됩니다.
    • pandas : 데이터 분석 및 조작을 위한 필수 라이브러리로, 엑셀 파일, CSV 파일 등을 쉽게 읽고, 변환하고, 분석하는 데 사용됩니다.
    • openpyxl : 엑셀(.xlsx) 파일을 읽고 쓰는 파이썬 라이브러리입니다.
  • 설치 결과는 다음과 같습니다.
Collecting langchain
  Downloading langchain-0.3.27-py3-none-any.whl.metadata (7.8 kB)
Collecting langchain-community
  Downloading langchain_community-0.3.30-py3-none-any.whl.metadata (3.0 kB)
Collecting langchain-openai
  Downloading langchain_openai-0.3.34-py3-none-any.whl.metadata (2.4 kB)
Collecting faiss-cpu
  Downloading faiss_cpu-1.12.0-cp312-cp312-win_amd64.whl.metadata (5.2 kB)
Collecting pandas
  Downloading pandas-2.3.3-cp312-cp312-win_amd64.whl.metadata (19 kB)
Collecting openpyxl
  Using cached openpyxl-3.1.5-py2.py3-none-any.whl.metadata (2.5 kB)
Collecting langchain-core<1.0.0,>=0.3.72 (from langchain)
  Downloading langchain_core-0.3.77-py3-none-any.whl.metadata (3.2 kB)
Collecting langchain-text-splitters<1.0.0,>=0.3.9 (from langchain)
  Downloading langchain_text_splitters-0.3.11-py3-none-any.whl.metadata (1.8 kB)
Collecting langsmith>=0.1.17 (from langchain)
  Downloading langsmith-0.4.31-py3-none-any.whl.metadata (14 kB)
Collecting pydantic<3.0.0,>=2.7.4 (from langchain)
  Downloading pydantic-2.11.9-py3-none-any.whl.metadata (68 kB)
Collecting SQLAlchemy<3,>=1.4 (from langchain)
  Downloading sqlalchemy-2.0.43-cp312-cp312-win_amd64.whl.metadata (9.8 kB)
Collecting requests<3,>=2 (from langchain)
  Downloading requests-2.32.5-py3-none-any.whl.metadata (4.9 kB)
Collecting PyYAML>=5.3 (from langchain)
...
   ---------------------------------------- 57/57 [langchain-community]

Successfully installed PyYAML-6.0.3 SQLAlchemy-2.0.43 aiohappyeyeballs-2.6.1 aiohttp-3.12.15 aiosignal-1.4.0 annotated-types-0.7.0 anyio-4.11.0 attrs-25.3.0 certifi-2025.8.3 charset_normalizer-3.4.3 dataclasses-json-0.6.7 distro-1.9.0 et-xmlfile-2.0.0 faiss-cpu-1.12.0 frozenlist-1.7.0 greenlet-3.2.4 h11-0.16.0 httpcore-1.0.9 httpx-0.28.1 httpx-sse-0.4.1 idna-3.10 jiter-0.11.0 jsonpatch-1.33 jsonpointer-3.0.0 langchain-0.3.27 langchain-community-0.3.30 langchain-core-0.3.77 langchain-openai-0.3.34 langchain-text-splitters-0.3.11 langsmith-0.4.31 marshmallow-3.26.1 multidict-6.6.4 mypy-extensions-1.1.0 numpy-2.3.3 openai-2.0.1 openpyxl-3.1.5 orjson-3.11.3 pandas-2.3.3 propcache-0.3.2 pydantic-2.11.9 pydantic-core-2.33.2 pydantic-settings-2.11.0 python-dotenv-1.1.1 pytz-2025.2 regex-2025.9.18 requests-2.32.5 requests-toolbelt-1.0.0 sniffio-1.3.1 tenacity-9.1.2 tiktoken-0.11.0 tqdm-4.67.1 typing-inspect-0.9.0 typing-inspection-0.4.2 tzdata-2025.2 urllib3-2.5.0 yarl-1.20.1 zstandard-0.25.0
Note: you may need to restart the kernel to use updated packages.
  • OpenAI의 API 키를 위한 환경 변수를 설정하고, gpt-4o 모델을 사용할 수 있도록 준비합니다. 코드의 "sk..." 부분에는 자신의 API 키를 넣어주세요.
import os
os.environ["OPENAI_API_KEY"] = "sk" #openai 키 입력, OpenAI API 키를 환경 변수(os.environ)에 저장

from langchain_openai import ChatOpenAI # 랭체인을 사용하여 OpenAI의 GPT-4o 모델을 불러오는 클래스
llm = ChatOpenAI(
    model="gpt-4o",
)
  • 자동차 가격 데이터를 벡터화하여 FAISS 벡터 데이터베이스에 저장하고, OpenAI GPT 모델을 활용하여 자연어 질의에 답변하도록 합니다.
import pandas as pd # 엑셀 데이터를 불러와서 전처리
from langchain_openai import OpenAIEmbeddings # 텍스트 데이터를 벡터(Embedding)로 변환
from langchain.vectorstores import FAISS # 벡터 데이터를 저장하고 유사도 검색을 수행
from langchain.llms import OpenAI # GPT-4o 모델을 활용하여 검색된 데이터를 바탕으로 답변 생성
from langchain.chains import RetrievalQA # 검색된 데이터를 기반으로 LLM(GPT-4)이 질의응답(QA) 수행

# 엑셀 파일(car_prices.xlsx)을 불러와서 데이터프레임(df)에 저장
file_path = "d:/data/car_prices.xlsx"
df = pd.read_excel(file_path)

# 데이터 전처리 (데이터를 벡터화하기 전에 텍스트 형태로 변환)
df["text"] = df.apply(lambda row: f"{row['제조사']} {row['모델']} 가격: {row['가격(만원)']}만원", axis=1)

# 문장을 벡터(숫자 배열)로 변환
embeddings = OpenAIEmbeddings()

# 벡터로 변환 후 FAISS 인덱스에 저장 
vectorstore = FAISS.from_texts(df["text"].tolist(), embeddings)

# 추후 빠르게 불러올 수 있도록 FAISS 인덱스를 저장
faiss_db_path = "d:/data/faiss_car_prices"
vectorstore.save_local(faiss_db_path)

# 저장된 FAISS 데이터베이스를 로드하여 재사용
vectorstore = FAISS.load_local(faiss_db_path, embeddings, allow_dangerous_deserialization=True, )

# 유사한 데이터를 검색할 수 있는 retriever 생성, 최대 5개의 유사한 결과를 반환
retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 5})

# 랭체인의 RetrievalQA를 사용하여 질의응답 시스템 생성
qa_chain = RetrievalQA.from_chain_type(llm=llm, retriever=retriever, chain_type="stuff")

# 사용자의 질문에 대한 답변 생성
query = "현대에서 가장 비싼 자동차는 무엇인가요?"
response = qa_chain.invoke(query)

# 결과 출력
print("📌 질문:", query)
print("💡 답변:", response)
  • 그러면 다음과 같이 정확한 답변을 제공해 주지 않습니다. 참고로 LLM을 이용한 답변은 매번 결과가 다를 수 있습니다. 제공하는 결과와 답변이 다를 수 있으니 참고하세요.
📌 질문: 현대에서 가장 비싼 자동차는 무엇인가요?
💡 답변: {'query': '현대에서 가장 비싼 자동차는 무엇인가요?', 
'result': '제공된 정보에는 아우디와 볼보 자동차의 가격만 나와 있으므로, 
현대 자동차에 관한 정보는 포함되어 있지 않습니다. 현대에서 가장 비싼 자동차에 대한 정보는 별도의 
자료를 참고해 주시기 바랍니다.'
  • 이번에는 좀 더 쉬운 질문을 해볼까요?
query = "아반떼의 제조사는?"
response = qa_chain.invoke(query)

# 결과 출력
print("📌 질문:", query)
print("💡 답변:", response)
  • 아반떼 제조사는 현대라고 정확히 알려줍니다.
📌 질문: 아반떼의 제조사는?
💡 답변: {'query': '아반떼의 제조사는?', 'result': '아반떼는 현대자동차에서 제조합니다.'}
  • 이번에는 전체 데이터 중, 가격이 1억 이상 하는 자동차 모델을 알려달라고 질문해봅시다.
query = "1억 이상하는 모든 자동차 모델을 알려줘?"
response = qa_chain.invoke(query)

# 결과 출력
print("📌 질문:", query)
print("💡 답변:", response)
  • 다음은 답변 결과입니다.
📌 질문: 1억 이상하는 모든 자동차 모델을 알려줘?
💡 답변: {'query': '1억 이상하는 모든 자동차 모델을 알려줘?', 
'result': '제공된 정보를 보면, 1억(10,000만원) 이상인 가격을 가진 자동차 모델은 두 가지입니다
.\n\n• 볼보 XC60  \n• 맥라렌 720S\n\n따라서 1억 이상하는 자동차 모델은 볼보 XC60과 
맥라렌 720S입니다.'}
  • 앞에서 질문했던 "현대에서 가장 비싼 자동차는 무엇인가요?"에 대해 답변을 못했는데요, 이럴 때에는 프롬프트를 다음과 같이 바꿔서 시도해볼 수 있습니다.
"현대에서 가장 비싼 가격의 모델은?"
query = "현대에서 가장 비싼 가격의 모델은?"
response = qa_chain.invoke(query)

# 결과 출력
print("📌 질문:", query)
print("💡 답변:", response)
  • 그러면 다음과 같이 답변해줄 것입니다. 엑셀 파일에서는 아반떼가 가장 비싼 모델이기 때문에 정확한 답변은 아닙니다. 이와 같은 문제로 인간의 검증이 필요합니다.
📌 질문: 현대에서 가장 비싼 가격의 모델은?
💡 답변: {'query': '현대에서 가장 비싼 가격의 모델은?', 
'result': '현대에서 제공된 모델 중 가장 비싼 모델은 현대 소나타로, 가격은 5,485,000만원입니다.'}