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 코딩 공모전 수상작들을 요약해줘."
가장 기본적인 형태로, 질문과 문서 간의 유사도를 기반으로 검색합니다.
장점
단점
retriever_similarity = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 50}
)
retrieved_docs_similarity = retriever_similarity.invoke(user_msg)
관련성과 다양성을 모두 고려하여 검색 결과의 중복을 줄이고 다양한 정보를 제공합니다.
장점
단점
retriever_mmr = vectorstore.as_retriever(
search_type="mmr",
search_kwargs={"k": 50}
)
retrieved_docs_mmr = retriever_mmr.invoke(user_msg)
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)
메타데이터 필드를 정의하여 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 리트리버가 가장 효과적인 결과를 보여주었습니다.
구조화된 정보 검색: 메타데이터 필드(상장 종류, 공모전 이름, 수상자 등)를 명확히 정의하여 LLM이 사용자 질문을 구조화된 쿼리로 변환할 수 있었습니다.
포괄적인 정보 제공: 다른 리트리버들이 놓친 "BLOTIE" 입선작까지 포함한 더 완전한 정보를 검색했습니다.
체계적인 정보 추출: 프론트엔드/백엔드 기술 스택 구분, 서비스 기능 설명, 문제 해결 방식 등 더 체계적인 정보를 제공했습니다.