앞서 Qdrant, GPT, WebClient로 만든 요약/질문 생성 시스템 에 대한 주제로 글을 포스팅했었다.
이전 글에선 RAG에 대한 설명이 없어, 추가적으로 RAG 시스템에 대한 설계와 구현에 초점을 맞춰 글을 작성하려 한다.
우선 프로젝트를 소개하자면,
사용자의 글 내용을 요약하고 해당 내용을 기반으로 GPT를 통해 심층 면접 질문과 답변을 생성하는 시스템을 구현하는 것이 목표이다.
핵심 기술로 OpenAI GPT API, Qdrant 벡터 DB, WebFlux 비동기 처리 그리고 Redis 분산 락을 활용했으며
RAG 아키텍처에 기반하여 정보를 검색/보강/생성하는 전체 흐름을 구성했다.
RAG 시스템
RAG 도입한 이유
내가 프로젝트에 RAG를 도입하게 된 이유는,
사용자가 입력했던 데이터들을 기억하고 이를 기반으로 맞춤화된 면접 질문을 생성하도록 만들고 싶었다.
그렇기에 Qdrant를 사용해 입력한 글에 대한 임베딩 벡터를 생성하고 저장하고 유사한 글을 검색하는 시스템을 구축하고자 했다.
RAG의 개념은 외부 지식 소스에서 관련 정보를 검색한 뒤 그 정보를 바탕으로 답변을 생성하는것이다.
RAG 작동원리
검색(Retrieval)
- 사용자의 질문을 분석해 외부 지식 베이스(데이터베이스, 내부 문서, 웹 등)에서 관련 정보를 검색한다.
- 검색 과정에서 질문과 문서를 벡터로 변환(임베딩)하고, 유사도 계산을 통해 가장 관련성 높은 정보를 추출한다.
증강(Augmentation)
- 검색된 정보를 사용자의 질문과 결합하여 답변 생성에 활용할 수 있는 풍부한 컨텍스트를 만든다.
생성(Generation)
- LLM이 검색된 정보와 질문을 바탕으로, 자연스럽고 정확한 텍스트 답변을 생성한다.
위의 개념들이 일반적인 RAG이다.
하지만 RAG에 대해 공부하며, GPT와 퍼플렉시티의 인터넷 기반 검색 기능은 어떻게 외부 지식 베이스를 가져오는 것인지 궁금했다.
인터넷의 방대한 데이터를 모두 벡터 DB에 넣어 관리하게 되면 비용이 천문학적으로 나갈 것 같았다.
찾아보니 검색엔진이 웹에서 관련 문서를 찾아주고 그 문서를 LLM에 전달하는 방식이었다.
물론 검색엔진이 벡터 기반 인덱스를 지원하면 벡터 유사도를 검색할 수 있지만, 모든 웹페이지가 벡터 DB에 저장되는 것은 아니다.
최근에는 일부 검색엔진 Google Vertex AI Search, Bing Chat 등이 웹페이지를 임베딩해서 저장하거나 하이브리드 (키워드 + 벡터) 방식으로 검색한다.
또 다른 궁금한 점은 LLM은 일반적인 RAG로 동작하는가였다.
GPT는 대화 기억에 대한 이슈가 있었고, 나 또한 GPT를 사용하며 이전 대화의 맥락을 다시 설명해야 하는 불편함을 감수해야 했다.
하지만 최근 4월에 메모리 기능이 업데이트 되어 이전 대화 내용을 기억할 수 있게 되었다고 기사를 봤었다.
이 메모리 기능이 RAG를 도입한건가 해서 찾아보니 RAG와 비슷해보이지만 RAG는 아니다.
RAG는 외부 문서나 벡터 DB에서 정보를 검색해 답변에 반영하는 것이고, GPT의 메모리 기능은 사용자의 대화 기록을 저장하고 이를 새로운 대화의 프롬프트에 반영하는 방식이다.
다른 LLM 모델인 클로드는 공식적으로 Contextual Retrieval 기반 RAG를 지원한다고 한다.
프로젝트에 적용한 RAG 시스템 흐름
- 사용자가 글을 입력
- 입력된 글을 GPT가 요약
- 요약된 텍스트를 Qdrant에 넘겨 벡터로 변환 후 저장
- 벡터 DB(Qdrant)에서 유사한 벡터를 검색
- 검색된 벡터의 payload(텍스트)를 추출
- GPT 프롬프트 생성 (요약 + 유사 요약 포함)
- 질문/답변 생성 (OpenAI GPT)
- 생성된 답변을 사용자에게 텍스트로 응답
위와 같이 RAG 시스템 흐름을 설계했다.
Retrieval (검색)
사용자의 입력 내용을 요약 후 벡터화하여 Qdrant에서 유사한 과거 글을 벡터 기반으로 검색했다.
- OpenAI 임베딩 모델 text-embedding-3-small로 벡터를 생성했다.
- Qdrant를 통해 코사인 유사도 기반 검색을 했다.
- payload.summary를 추출하여 프롬프트에 사용
Augmentation (보강)
Qdrant에서 가져온 유사 글 요약을 GPT 프롬프트에 삽입하여 질문 생성의 맥락을 보강했다.
프롬프트는 아래와 같이 구성했다.
현재 글 요약: [summary]
유사 글 요약들:
- 유사 글 1
- 유사 글 2
- 유사 글 3
→ 이들을 참고하여 심층 질문 생성
Generation (생성)
요약 및 유사 맥락 기반으로 GPT가 면접 질문과 모범 답변을 생성한다.
생성 포맷은 아래와 같다.
1. 질문: ~
답변: ~
2. 질문: ~
답변: ~
3. 질문: ~
답변: ~
- GPT-3.5 Turbo API를 사용했다. (비용도 저렴하고 성능도 괜찮아서 선택했다)
- 질문 유형을 지정하고 답변 구성 방식까지 구체적으로 컨트롤했다.
벡터화 작업을 하기위해 text-embedding-3-small를 선택했다.
text-embedding-3-small은 ada-002보다 더 빠르고 저렴하면서도 유사하거나 더 나은 품질의 벡터를 생성할 수 있어 RAG 시스템에 적합하다고 생각했다. 3-large는 정확도가 더 높지만 비용이 크고 응답 시간도 길어 대량 요청이 많은 서비스 환경에는 과한것 같다.
따라서 비용 대비 성능 균형을 고려해 3-samll을 선택한 것은 실용성과 확장성 모두를 충족하기 위한 결정이었다.
마무리
RAG 시스템을 도입해보며 떠오르는 여러 궁금증들을 해결해보며 글을 작성해 보았다.
아키텍처 설계하는 것은 코드를 구현하는 것과는 또 다른 재미가 있었고, 설계한 흐름도에 맞춰 구현을 하니 훨씬 수월하게 진행할 수 있었다. 다음 프로젝트에는 정말 AI Agent를 가능하게 해주는 MCP를 사용하는 프로젝트를 구현해 보고 싶다.
특정 분야에마다 함께 사용되는 여러 툴이 있을테고 이를 MCP로 연결하는 프로젝트를하면 재미있을 것 같다.
'프로젝트 > 기술 면접 복습 플랫폼' 카테고리의 다른 글
Gatling 성능 테스트 (0) | 2025.05.20 |
---|---|
JMeter를 이용한 성능 측정 - JMeter 설정, 결과 분석 (0) | 2025.05.19 |
GitHub Actions로 EC2 자동 배포 (0) | 2025.05.08 |
도메인 연결, HTTPS 적용하기 (0) | 2025.05.06 |
Nginx가 왜 필요했는가 (0) | 2025.05.05 |