RAG - 리트리버 비교하기

Annie·2025년 4월 11일

소개

RAG을 공부하다가 데이터를 잘 못가져오는 리트리버 때문에 어떤 방법을 써야 데이터를 잘 가져올지 고민하게 되었습니다
코딩 공모전 수상작 정보를 분석하는 프로젝트를 통해 다양한 리트리버 방식의 성능을 비교해보겠습니다.

프로젝트 설정

먼저 필요한 라이브러리를 임포트하고 기본 설정을 진행합니다.

import bs4
import os
from dotenv import load_dotenv
from langchain import hub
from langchain_core.prompts import ChatPromptTemplate
from langchain_chroma import Chroma
from langchain_openai import ChatOpenAI
from langchain_openai import OpenAIEmbeddings
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter

# LLM 설정 및 API 키 확인
load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")
print(f"API key exists: {api_key is not None}")

llm = ChatOpenAI(model="gpt-4o-mini", api_key=api_key)

데이터 준비

웹페이지에서 정보를 가져와 처리합니다.

# 웹페이지 불러오기
loader = WebBaseLoader(
  web_paths=("https://spartacodingclub.kr/blog/all-in-challenge_winner",),
  bs_kwargs=dict(
    parse_only=bs4.SoupStrainer(
            class_=("css-j3idia", "editedContent")
        )
  ),
)

docs = loader.load()
print(f"로드된 문서 수: {len(docs)}")
print(f"첫 번째 문서 내용 일부: {docs[0].page_content[:100] if docs else 'No content'}")

# 문서 청크로 나누기
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=10
)

splits = text_splitter.split_documents(docs)
print(f"분할된 청크 수: {len(splits)}")

if len(splits) == 0:
    print("청크가 없어 원본 문서를 사용합니다.")
    splits = docs

벡터 스토어 설정

# 벡터 스토어 생성
vectorstore = Chroma.from_documents(
    documents=splits,
    embedding=OpenAIEmbeddings(api_key=os.getenv("OPENAI_API_KEY"))
)

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

프롬프트 템플릿 설정

검색된 문서를 활용하여 질문에 답변하기 위한 프롬프트를 설정합니다.

# 프롬프트 생성
prompt = ChatPromptTemplate.from_template("""너는 이 공모전을 평가했던 심사위원이이야. 한국어로 대답하고,
  다음에 이 공모전을 참가할 사람들이 참고할 수 있도록 유익한 정보들을 보기 쉽게 정리해줄 수 있어야해.
  정보를 찾은 후 대답을 정리할 때는 너의 의견이 들어가면 안돼. 리트리버에서 가져온 정보는 가능한 모두 활용해.
  그리고 내가 제공한 문서에서 질문에 대한 대답을 찾을 수 없다면, 모른다고 대답해야해. <context>: {context} <question>: {question}""")

user_msg = "ALL-in 코딩 공모전 수상작들을 요약해줘."

다양한 리트리버 방식 비교

1. Similarity 리트리버

가장 기본적인 형태로, 질문과 문서 간의 유사도를 기반으로 검색합니다.
장점

단점

retriever_similarity = vectorstore.as_retriever(
    search_type="similarity", 
    search_kwargs={"k": 50}
)
retrieved_docs_similarity = retriever_similarity.invoke(user_msg)

2. MMR(Maximum Marginal Relevance) 리트리버

관련성과 다양성을 모두 고려하여 검색 결과의 중복을 줄이고 다양한 정보를 제공합니다.
장점
단점

retriever_mmr = vectorstore.as_retriever(
    search_type="mmr", 
    search_kwargs={"k": 50}
)
retrieved_docs_mmr = retriever_mmr.invoke(user_msg)

3. 문서압축 리트리버

LLM을 이용해 검색된 문서를 압축하여 질문과 관련된 핵심 내용만 추출합니다.
장점
단점

from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor

base_retriever_context = vectorstore.as_retriever(
    search_type='similarity',
    search_kwargs={'k': 50}
)
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor, 
    base_retriever=base_retriever_context
)

compressed_docs_context = compression_retriever.get_relevant_documents(user_msg)

4. Self-Query 리트리버

메타데이터 필드를 정의하여 LLM이 사용자 질문을 구조화된 쿼리로 변환하도록 합니다.
장점
단점

from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain.chains.query_constructor.base import AttributeInfo

# 수상 정보 메타데이터 정의
metadata_field_info = [
    AttributeInfo(
        name="award_type",
        description="상장 종류 (대상, 최우수상, 우수상, 입선 등)",
        type="string",
    ),
    AttributeInfo(
        name="competition_name", 
        description="공모전 이름", 
        type="string"
    ),
    AttributeInfo(
        name="recipients_name", 
        description="수상자들의 이름", 
        type="string"
    ),
    AttributeInfo(
        name="recipient_work_decription", 
        description="수상작에 대한 설명", 
        type="string"
    ),
    AttributeInfo(
        name="tech_stack", 
        description="사용한 기술", 
        type="string"
    ),
]

self_query_retriever = SelfQueryRetriever.from_llm(
    llm,
    vectorstore,
    document_contents="ALL-in 코딩 공모전 수상작 정보",
    metadata_field_info=metadata_field_info,
    enable_limit=True,
    search_kwargs={"k": 50},
)

retrieved_docs_self_query = self_query_retriever.get_relevant_documents(user_msg)

결과 비교

각 리트리버 방식으로 검색한 결과를 LLM에 전달하여 답변을 생성하고 비교했습니다.

1. search type: similarity
'AII-in 코딩 공모전' 수상작 요약:

1. **대상: Lexi Note**
   - **서비스 내용:** 언어공부 필기 웹 서비스
   - **제작자:** 다나와(김다애, 박나경)
   - **기술 스택:** 정보 없음

2. **우수상: 에코 클래스룸**
   - **서비스 내용:** 수업 실시간 소통 서비스
   - **제작자:** This is 스파게티!!!(박지성, 김서원, 박범수)
   - **기술 스택:** Flutter, Socket.IO, Expo CLI, Axios, TanStack Query, Spring Boot, Spring Security, JWT, MySQL, Spring WebSocket, AWS

3. **우수상: 우리집 히어로즈**
   - **서비스 내용:** 벌레 퇴치 영웅 매칭 서비스
   - **제작자:** 인트(배정연, 한지수)
   - **기술 스택:** React, Tesseract.js, React-Quill, HTML, CSS, JavaScript, Java, Spring Boot, MariaDB

4. **입선: Crewing**
   - **서비스 내용:** 연합동아리 정보 플랫폼
   - **제작자:** 동학대학운동(김민아, 임경진, 신은혜, 고수)
   - **기술 스택:** Spring Boot, Redis, MySQL, SwiftUI Framework, OAuth 2.0

5. **입선: 학교생활 매니저**
   - **서비스 내용:** 학교생활 관리 서비스
   - **제작자:** 아이칼F4(조민제, 이민기, 강건, 박근우)
   - **기술 스택:** 정보 없음

이번 공모전은 대학생들이 캠퍼스에서 경험한 문제를 해결하기 위한 다양한 아이디어와 혁신적인 프로젝트가 발표되었습니다. 각 수상작들은 실용적이고 참신한 해결책을 제시하여 참가자들의 열정을 엿볼 수 있는 기회를 제공했습니다.



2. search type: mmr
### AII-in 코딩 공모전 수상작 요약

#### 1. 대상 수상작
- **[Lexi Note] 언어공부 필기 웹 서비스**
  - **제작자**: 다나와 (김다애, 박나경)
  - **소개**: 어문학 전공 학생이 효율적으로 단어와 문장 구조를 학습하기 위해 개발한 서비스.

#### 2. 입선작
- **[학교생활 매니저] 학교생활 관리 서비스**
  - **제작자**: 아이칼F4 (조민제, 이민기, 강건, 박근우)
  - **소개**: 과제 관리, 성적 예측, 학점 계산 등을 지원하는 앱.

- **[Crewing] 연합동아리 정보 플랫폼**
  - **제작자**: 동학대학운동 (김민아, 임경진, 신은혜, 고수)
  - **소개**: 신입생들이 자신에게 적합한 연합동아리를 쉽게 찾고 가입할 수 있도록 돕는 아카이빙 플랫폼.

#### 3. 우수상 수상작
- **[에코 클래스룸] 수업 실시간 소통 서비스**
  - **제작자**: This is 스파게티!!! (박지성, 김서원, 박범수)
  - **소개**: 교수와 학생 간의 소통을 개선하기 위해, 수업 중 학생들의 이해도를 실시간으로 확인할 수 있는 서비스.

- **[우리집 히어로즈] 벌레 퇴치 영웅 매칭 서비스**
  - **제작자**: 인트 (배정연, 한지수)
  - **소개**: 자취생들이 자취방에서 발생하는 벌레 문제를 해결하기 위해 필요한 사람과 매칭해주는 서비스.

이 공모전은 대학생들이 겪는 캠퍼스의 다양한 문제를 해결하는 아이디어를 실현할 수 있는 기회를 제공하는 대회로, 각 수상작들은 실제 문제를 기반으로 한 혁신적인 접근 방식을 보여주고 있습니다.



3. contextual compression retriever
**AII-in 코딩 공모전 수상작 요약**

이번 AII-in 코딩 공모전에서는 대학생들이 팀 프로젝트를 통해 만들어낸 다양한 웹/앱 서비스들이 수상하였습니다. 이 대회는 캠퍼스에서의 문제를 해결하는 것을 목표로 하며, 차별화된 아이디어와 혁신적인 접근 방식이 돋보였습니다. 수상작들은 다음과 같습니다:

1. **대상: [Lexi Note] 언어공부 필기 웹 서비스**
   - 제작자: 다나와 (김다애, 박나경)
   - 언어 학습의 효율성을 높이기 위해 개발된 필기 지원 웹 서비스.

2. **우수상: [에코 클래스룸] 수업 실시간 소통 서비스**
   - 제작자: This is 스파게티!!! (박지성, 김서원, 박범수)
   - 교수와 학생 간의 실시간 소통을 통한 수업 이해도를 높이기 위한 서비스.

3. **우수상: [학교생활 매니저] 학교생활 관리 서비스**
   - 제작자: 아이칼F4 (조민제, 이민기, 강건, 박근우)
   - 학교 생활을 효율적으로 관리할 수 있도록 돕는 앱으로, 일정과 과제 관리 기능 포함.

4. **우수상: [우리집 히어로즈] 벌레 퇴치 영웅 매칭 서비스**
   - 제작자: 인트 (배정연, 한지수)
   - 자취생들이 겪는 벌레 문제를 해결하기 위해, 필요한 서비스를 찾고 매칭하는 앱.

위와 같이, AII-in 코딩 공모전에서는 대학생들이 자신들의 아이디어를 바탕으로 실제 문제를 해결하는 노력을 보여주었습니다. 각 수상작은 특정한 문제를 해결하기 위한 창의적인 접근 방식을 가지고 있으며, 이 대회는 참가자들에게 코딩을 통해 자신의 아이디어를 실현할 수 있는 기회를 제공합니다.



4. self-query retriever
### ALL-in 코딩 공모전 수상작 요약

1. **우수상: 우리집 히어로즈**
   - **서비스 설명**: 벌레 퇴치 영웅 매칭 서비스로, 대학생 자취생들이 자취방에서 발생하는 벌레 문제를 해결할 수 있도록 돕는 앱.
   - **문제 해결**: 사용자 개인정보 노출 없이 안전하게 문제를 해결하고, 벌레를 퇴치하는 히어로에게 추가 수입 기회를 제공.
   - **기능**: 실시간 알림, 평가 시스템.
   - **사용한 기술 스택**: 프론트엔드(FE) - React Native, Expo, Axios; 백엔드(BE) - Spring Boot, Spring Security, MySQL, SSE, FCM, JWT, Postman.

2. **우수상: 에코 클래스룸**
   - **서비스 설명**: 수업 실시간 소통 서비스로, 학생과 교수 간 소통을 혁신적으로 개선.
   - **기능**: 학생의 이해도를 테스트할 수 있는 퀴즈 생성, 수업 난이도에 대한 피드백 수집.
   - **사용한 기술 스택**: 프론트엔드(FE) - Flutter, Socket.IO, Expo CLI, Axios, TanStack Query; 백엔드(BE) - Spring Boot, Spring Security, JWT, MySQL, Spring WebSocket, AWS.

3. **입선작: 학교생활 매니저**
   - **서비스 설명**: 대학생의 학교 생활을 효율적으로 관리할 수 있도록 돕는 관리 앱.
   - **기능**: 일정과 과제 관리, 성적 예측, 캘린더 기능.
   - **사용한 기술 스택**: 프론트엔드(FE) - Flutter; 백엔드(BE) - Firebase.

4. **입선작: BLOTIE**
   - **서비스 설명**: 교내 외국인과 내국인 매칭 및 교류 플랫폼으로, 외국인 학생들에게 한국 대학 생활 적응을 돕기 위해 개발됨.
   - **기능**: 1:1 매칭 기능.
   - **사용한 기술 스택**: 프론트엔드(FE) - Flutter, Socket.IO, Expo CLI, Axios, TanStack Query; 백엔드(BE) - Spring Boot, Spring Security, JWT, MySQL, Spring WebSocket, AWS.

5. **입선작: Crewing**
   - **서비스 설명**: 대학생들이 다양한 연합 동아리에 쉽게 가입하고 적합한 동아리를 추천받을 수 있도록 지원하는 아카이빙 플랫폼.
   - **기능**: 동아리 서류 전형, 인터뷰 일정 관리 및 솔직한 후기를 통한 정보 제공.
   - **사용한 기술 스택**: 프론트엔드(FE) - Spring Boot, Redis, MySQL; 백엔드(BE) - SwiftUI Framework, OAuth 2.0.

이와 같은 수상작들은 참가자들이 대학 생활의 문제를 해결하기 위한 창의적인 아이디어와 기술력을 활용해 개발된 앱 및 웹 서비스입니다.

결론

여러 리트리버 방식 중 Self-Query 리트리버가 가장 효과적인 결과를 보여주었습니다.

  1. 구조화된 정보 검색: 메타데이터 필드(상장 종류, 공모전 이름, 수상자 등)를 명확히 정의하여 LLM이 사용자 질문을 구조화된 쿼리로 변환할 수 있었습니다.

  2. 포괄적인 정보 제공: 다른 리트리버들이 놓친 "BLOTIE" 입선작까지 포함한 더 완전한 정보를 검색했습니다.

  3. 체계적인 정보 추출: 프론트엔드/백엔드 기술 스택 구분, 서비스 기능 설명, 문제 해결 방식 등 더 체계적인 정보를 제공했습니다.

0개의 댓글