환경설정 및 LangChain과 Chroma를 활용한 검증 및 RAG 구성해보기.

2025. 7. 20. 11:55·RAG 을 활용하여 LLM 만들어보기

이제 LangChain 을 활용하여 어떻게 openAI를 사용할 수 있는지, 간단하게 만들어보려고 한다.

 

개인적으로 macos 에서도 함께 활용하고는 있지만 해당 포스팅은 windows 기준으로 진행한다.

 

먼저 pyenv가 설치되있다는 가정 하에 powershell 에서 작업 폴더에 3.10.0 을 기본 버전으로 지정 후

`python -m venv llm-application` 로 가상환경을 생성한 뒤 가상환경을 활성화 한다. 

 

이후 `python -m venv .venv` 로 가상환경 이름을 .venv 로 설정하면 나중에 자동으로 인식된다.

 

이후 터미널에서 아래와 같이 필요한 라이브러리 설치한다. 참고로 나는 gemini api 를 기준으로 진행했다.

 

이후 아래와 같이 코드를 실행하면 결과값을 받아볼 수 있다. 참고로 나는 API_KEY 는 .env 파일에 따로 관리했다.

 

그 밖에 chatgpt 의 OpenAI, ChatUpstage 그리고 local ai 를 위한 ollama 까지 다양하기 때문에

API모델은 본인의 필요에 따라 결정하면 되지만, ollama 의 경우 API가 필요하지 않다는 점만 알고있으면 된다.

 

여담으로 ollama 를 써본적은 있지만 성능이 좋지 않아 포기했고, 추후 성능이 개선되면 사용해볼 예정이다.


1. 문서의 내용 읽기

본격적으로 langchain 을 활용하여 RAG 구성하기 전에, langchain 에게 문서를 전달해야 하는데,

각 문서 형식마다 전달 방법은 하단의 링크를 통해 알아볼 수 있으며, 나는 docx 타입의 파일을 사용할 예정이다.

 

 

Document loaders | 🦜️🔗 LangChain

DocumentLoaders load data into the standard LangChain Document format.

python.langchain.com

 

 

docx 파일을 사용하기 위해서는 먼저 아래와 같은 명령어로 라이브러리를 설치해준 뒤에

진행해야 하며 그밖에 본인이 원하는 문서 형식에 맞게 다운로드를 진행하면 된다.

pip install --upgrade --quiet  docx2txt
pip install langchain_community

 

이후 아래와 같이 docx 파일을 불러온 뒤 몇개의 chunk로 나뉘어져 있는지 출력해보면 1개로 나오는데,

문서 내용이 긴 경우, 답변 생성이 오래걸리기도 하고 토큰수 초과로 답변을 생성하지 못할 수 있어서 문서를 쪼개야 한다.

 

 

2. 문서 쪼개기

 

문서를 쪼개는 Text Splitters 는 주로 Recursive Character Text Splitter 나 Character Splitter 을 사용하고

recursive character 의 경우, 리스트 형식으로 여러 구분자를 분리할 수 있다는 장점이 있다.

 

나는 recursive character 를 사용할 예정인데, 아래 링크를 통해 좀더 자세한 사용방법을 알 수 있다.

 

How to recursively split text by characters | 🦜️🔗 LangChain

This text splitter is the recommended one for generic text. It is parameterized by a list of characters. It tries to split on them in order until the chunks are small enough. The default list is ["\n\n", "\n", " ", ""]. This has the effect of trying to kee

python.langchain.com

나는 아래와 같이 계산했는데, LLM 가 토큰 수를 계산할 때, chunk_size 는 문서를 쪼갤 때

하나의 청크가 가질 수 있는 토큰이고 chunk_overlap 문서끼리 겹치는 부분 의미한다.

 

이렇게 겹치게 함으로써 유사도 검색을 할 때 우리가 원하는 문서를 가져올 수 있는 확률을 올릴 수 있다.

아래 코딩을 보면 내가 나눈 영역은 총 168개의 리스트로 나뉘어진 것을 확인할 수 있다.

 

3. 임베딩 하여 백터 데이터에 저장

그럼 다음으로 임베딩을 진행해야 하는데, 앞서 임베딩에 대해 설명하자면 사람이 쓰는 자연어를

기계가 이해할 수 있는 숫자의 나열인 벡터로 바꾼 결과나 과정을 의미한다고 볼 수 있다.

 

즉 위에서 나눈 문서를 어쨋거나 컴퓨터가 처리할 수 있는 숫자로 바꾸는 것이 선행되어야 한다는 것이다.

 

임베딩을 진행하면서 중간중간 이슈가 나길래 python package tool 을 아래와 같이 설정했다.

pip install -U pydantic==2.7.4 langchain==0.3.26 langchain-core==0.3.66 langchain-openai langchain-community langchain-google-genai langchain-text-splitters

 

나는 upstage 모델을 활용하여 임베딩을 진행했고, 관련 자세한 문서는 위 링크를 통해 확인 가능하다.

 

먼저 pip install openai 를 진행 후, 아래와 같이 solar-embedding-1-large 모델을 사용하여 임베딩을 진행했다.

from langchain_upstage import UpstageEmbeddings
from dotenv import load_dotenv

load_dotenv()
embeddings = UpstageEmbeddings(model="solar-embedding-1-large")

임베딩한 것을 벡터 DB 에 넣기 위해 chroma 를 사용하는데, inmemory 벡터DB 로 간편하게 해볼 수 있다.

아래와 같이 embedding 과 document 를 사용하는데, 나는 위에서 쪼개놓은 문서를 사용해 봤다.

 

먼저 pip install langchain-chroma 를 진행 후, chroma에  embedding한 document list 저장한다.

from langchain_chroma import Chroma
database = Chroma.from_documents(documents=document_list,
                   embedding=embeddings,
                   collection_name="chroma_tax",
                   persist_directory="./chroma")
Chroma DB 가 날아가지 않도록 설정

 

참고로 Chroma 는 inmemory DB 이기 때문에, 내용이 날아가지 않게 하고 싶다면

위와 같이 persist_directory 를 활용하여 하위 파일에 DB 내용을 저장해두는 것이 좋다.

이 다음부터는 아래와 같이 DB 를 직접 가져올 수도 있다.

database = Chroma(collection_name="chroma_tax",
                   persist_directory="./chroma",
                   embedding_function=embeddings)

4. 질문이 있을 때, 백터 데이터베이스에 유사도 검색

이제 본격적으로 query를 활용하여 위에서 만든 DB 에 질문을 할 수 있는데,

아래와 같이 similarity_search 를 활용하면 벡터 유사도 검색 후 3개의 문서를 가져온다. 

query = "세금 신고를 위한 서류는 무엇이 있나요?"
retriever = database.similarity_search(query, k=3)
retrievalQA를 활용하여 prompt 효율화

 

이때 retriever 을 좀더 효과적으로 할 수 있는데, retrievalQA 를 활용하는 방법이 있다.

 

pip install -U langchain langchainhub --quiet 를 통해 langchain 과 langchainhub 를 설치한다.

이후 아래와 같이 RAG 시스템에서 자주 사용하는 포맷으로 context와 question 을 조합해

LLM이 답변할 수 있도록 설계되어 있어 프롬프트를 짜는 시간을 세이브할 수 있다.

from langchain import hub
prompt = hub.pull("rlm/rag-prompt")

5. 유사도 검색으로 가져온 문서를 LLM 에 질문과 같이 전달

이제 가져온 문서를 가지고 LLM에 질문을 해야 한다.

아래와 같이 ChatUpstage 클래스를 llm에 변수에 저장하는데, LangChain에서 llm을 호출하는 객체로 사용된다.

from langchain_upstage import ChatUpstage
llm = ChatUpstage()

이후 아래와같이 페르소나를 지정하여 질문을 하면 더욱 자세한 답변을 받을 수 있다.

prompt = f"""[Iedntity]
당신은 최고의 한국 소득세 전문가입니다. 고객의 질문에 답변해 주세요.
[Context] 를 참고하여 사용자 질문에 답변해 주세요[Context]
{retriever}
Question: {query}
"""
retrievalQA 를 활용하여 LLM 에게 질문 전달

만약 4. 에서 retrievalQA를 활용했다면, 아래와같이 retrievalQA를 활용하여 질문을 전달하고 대답을 받는다.

특히 `retriever=database.as_retriever(),` 해당 부분은 chroma 뿐 아니라 다른 다양한 DB에서도 활용 가능하다.

# DB 에 as_retriever 를 사용하여 연결.
# as_retriever 는 chroma 뿐만 아니라 다양한 데이터베이스에서 사용할 수 있다.
from langchain.chains import RetrievalQA
qa_chain = RetrievalQA.from_chain_type(
        llm,
        retriever=database.as_retriever(),
        chain_type_kwargs={"prompt": prompt}
        )
ai_message = qa_chain.invoke(query)
print(ai_message)

일단 이렇게 RAG 를 활용해서 LangChain과 Chroma 를 활용하여 RAG 구성을 진행해봤는데,

며칠동안 끙끙거리면서 진행해봤지만 아직까지 완벽하게 이해한건 아닌 상태이다.

 

하지만 RAG 가 어떤식으로 진행되며, API를 활용해서 어떻게 프롬프트를 전달하고 답변을 받는지

간단한 흐름을 이해할 수 있게 되었고, RAG 를 공부하면서 잘 이해가 되지 않는 단어나

이해했다고 생각했는데, 들을 때마다 찾아봐야하는 단어에 대해서 한번 정리를 해야될 것 같다.

'RAG 을 활용하여 LLM 만들어보기' 카테고리의 다른 글

Retrieval 효율 개선을 위한 데이터 전처리  (2) 2025.08.04
Pinecone 과 LangChain을 활용한 Vector Database 변경  (2) 2025.07.30
LangChain을 활용하지 않고 RAG 구성해보기  (2) 2025.07.27
RAG 을 활용한 LLM 만들기 필수 용어 및 흐름  (0) 2025.07.21
LLM에 관심을 가지게 된 계기와 필요 배경 지식  (4) 2025.07.09
'RAG 을 활용하여 LLM 만들어보기' 카테고리의 다른 글
  • Pinecone 과 LangChain을 활용한 Vector Database 변경
  • LangChain을 활용하지 않고 RAG 구성해보기
  • RAG 을 활용한 LLM 만들기 필수 용어 및 흐름
  • LLM에 관심을 가지게 된 계기와 필요 배경 지식
몽자비루
몽자비루
QA에 대한것을 공부하기 위한 블로그입니다.
  • 몽자비루
    공부하는 블로그
    몽자비루
  • 전체
    오늘
    어제
    • 분류 전체보기 (197)
      • python (31)
        • python_selenium (16)
        • python_pygame (3)
      • appium (0)
      • 쿠버네티스 (60)
        • linux (8)
        • shell programming (8)
        • docker (18)
        • cka (23)
      • postman&API (16)
      • QA성장하기 (33)
        • 개발자에서 아키텍트로 스터디 (6)
        • 소프트웨어 공학 이해도 높이기 (6)
        • 테스팅 전문 지식 쌓기 (18)
        • 제4회 QA conference (3)
      • 에러일기 (1)
      • Server&load (36)
        • AWS (27)
        • load test (5)
        • CI CD (4)
        • Jmeter (0)
      • RAG 을 활용하여 LLM 만들어보기 (12)
      • git&github (7)
      • 개인 프로젝트 웹사이트 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    qa 컨퍼런스
    로스트아크api
    k8s
    스터디
    도커
    테스트스크립트
    postman
    QAKOREA
    애플리케이션로그
    cka
    qa
    LOSTARK
    공존성테스트
    e2c
    쿠버네티스
    사드웨어리소스
    개발자에서아키텍트로
    리눅스
    linux
    네트워크 테스트
    qa conference
    application log
    포스트맨
    python
    API
    앱공존성
    vi에디터
    .cpu
    테스트 결과보고서
    로스트아크
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
몽자비루
환경설정 및 LangChain과 Chroma를 활용한 검증 및 RAG 구성해보기.
상단으로

티스토리툴바