Gemini API와 Python으로 간단한 RAG 시스템 구축하기: 문서 기반 자동 답변 생성 실습
요약
본 글은 Gemini API와 Python을 활용하여 사내 문서를 기반으로 자동 답변을 생성하는 간단한 RAG(Retrieval-Augmented Generation) 시스템 구축 방법을 안내합니다. 방대한 내부 문서에서 필요한 정보를 효율적으로 검색하고, 이를 LLM에 전달하여 질문에 자동으로 답할 수 있는 실습 중심의 가이드를 제공합니다.
핵심 포인트
- Gemini API와 Python을 이용한 RAG 시스템 구현 실습 기회 제공
- 사내 문서를 활용해 정보 검색 비효율성 및 반복 답변 부담 해소 가능
- 복잡한 벡터 DB 대신 간단한 문서 로드 및 프롬프트 엔지니어링으로 접근
서론
안녕하세요, ahic입니다.
저는 일상 업무를 13개의 AI 에이전트와 RPA로 자동화하며 생산성 향상을 위해 노력하고 있습니다. Claude Code, Python, launchd, Gemini API 등을 활용하여 번거로운 작업을 AI에게 맡기고 있습니다.
이번 글에서는 Gemini API와 Python을 활용하여 사내 문서의 정보 검색을 효율화하는 '간단 RAG(Retrieval-Augmented Generation) 시스템'의 실질적인 구축 방법을 소개합니다.
사내에는 방대한 양의 문서가 존재하는데, 필요한 정보를 찾기 어렵거나 같은 질문에 반복적으로 답변해야 했던 경험이 있으신가요? 본문에서 소개하는 시스템은 사용자의 로컬 문서를 기반으로 AI가 질문에 자동으로 답변해주므로, 정보 검색 수고를 대폭 줄일 수 있습니다. 오늘 이 글대로 따라 해 보시면 동일한 결과물을 얻을 수 있도록 상세히 설명하겠습니다.
과제: 방대한 문서로부터의 정보 검색 비효율성
제가 담당하는 프로젝트에서는 매일 대량의 문서(사양서, 회의록, 매뉴얼, 기술 메모 등)가 생성됩니다. 이 문서들은 프로젝트 진행에 따라 계속 늘어나기 때문에, 막상 필요한 정보를 찾으려고 하면 어디에 무엇이 적혀 있는지 알기 어려워지곤 합니다.
특히 다음과 같은 문제에 직면했습니다.
- 정보 검색의 비효율성: 필요한 정보를 찾기 위해 여러 문서를 가로질러 검색하거나 키워드를 시행착오적으로 시도하는 시간이 많습니다.
- 질문 대응 부담: 신규 멤버의 정형적인 질문이나 문서에 분명히 적혀 있어야 할 질문에 반복적으로 수동 답변을 해야 합니다.
- 정보의 일원화 어려움: 문서들이 여러 장소에 흩어져 있어 전체를 파악하기 어렵습니다.
이러한 문제들은 프로젝트 전체의 생산성을 저하시키는 요인이었습니다. 그래서 저는 AI의 힘을 빌려 이 문서들로부터 효율적으로 정보를 추출하고, 질문에 자동으로 답변할 수 있는 시스템을 구축하는 것을 구상했습니다.
간단 RAG 시스템 설계 사상
이번에 구축할 시스템은 Retrieval-Augmented Generation (RAG)의 간이 버전입니다. RAG란 대규모 언어 모델(LLM)이 질문에 답변할 때, 외부 지식 기반(문서 등)에서 관련 정보를 검색(Retrieval)하고, 이를 바탕으로 답변을 생성(Generation)하는 방법을 의미합니다.
일반적인 RAG 시스템에서는 벡터 데이터베이스를 사용하여 문서를 임베딩 벡터화하고, 질문과 관련성이 높은 문서 청크를 고속으로 검색 및 추출하여 LLM에 전달합니다. 하지만 이번에는 더 간편하고 즉시 도입할 수 있는 것을 중시하여 다음과 같은 설계 사상으로 구축합니다.
- 간단한 문서 로드: 여러 텍스트 파일을 연결하여 하나의 큰 컨텍스트로 취급합니다.
- 프롬프트 엔지니어링 활용: Gemini API에 질문과 연결된 문서를 전달하고, 프롬프트 내에서
이름의 파일을 생성하고, 다음 형식으로 저장합니다. GEMINI_API_KEY=YOUR_API_KEY
YOUR_API_KEY
부분은 획득한 실제 API 키로 대체해 주세요. .env
파일은 Git 등에서 공유하지 않도록 .gitignore에 추가하는 것을 권장합니다. -
질의응답시키고 싶은 문서 준비: 프로젝트 루트 디렉터리에 documents라는 이름의 폴더를 생성하고, 그 안에 질의응답시키고 싶은 텍스트 파일(예: internal_guideline.txt, project_a_memo.txt 등)을 배치해 주세요. .env main.py documents/ ├── internal_guideline.txt └── project_a_memo.txt
이번에는 다음과 같은 내용의 텍스트 파일을 가정하고 진행합니다.
documents/internal_guideline.txt 예시: 사내 가이드라인: 1. 휴가 신청은 3일 전까지 인사 시스템에서 합니다. 2. 경비 정산은 월말 마감, 다음 달 5일까지 신청이 필요합니다. 3. 원격 근무는 주 2일까지 허가되지만, 사전에 상사에게 신청이 필요합니다. 4. 채용 프로세스에 관한 질문은 인사부에 직접 문의해 주세요. 5. 신규 프로젝트 제안은 분기별로 받고 있습니다.
documents/project_a_memo.txt 예시: 프로젝트 A 관련 메모: - 개발 단계는 2024년 7월 1일에 완료 예정입니다. - 주요 고객은 ABC사와 XYZ사입니다. - 다음 정례 회의는 7월 15일 10시, 온라인 개최입니다. - 마일스톤 1은 예정대로 달성했습니다.
2. 문서 로딩 함수
다음으로, documents 디렉터리 내의 모든 텍스트 파일을 읽어 하나의 문자열로 결합하는 Python 코드를 작성합니다. 이것이 Gemini에 전달할 '지식 기반'이 됩니다.
main.py를 생성하고 다음 코드를 기재합니다.
import os
from dotenv import load_dotenv
import google.generativeai as genai
...
이 load_documents_from_directory 함수는 documents 디렉터리 내의 모든 .txt 파일을 읽어, 그것들을 하나의 문자열로 연결합니다. 이를 통해 Gemini가 참조해야 할 '지식'이 준비됩니다.
3. Gemini API 연동 및 질의응답 로직
다음으로, 읽어온 문서를 Gemini에 전달하고 사용자 질문에 대해 답변을 생성하는 메인 로직을 구현합니다. main.py에 다음 코드를 추가해 주세요.
# (위 코드의 계속)
def main():
"""
...
이 코드의 핵심은 prompt_parts 부분입니다.
- 읽어온
combined_documents를 프롬프트에 직접 포함합니다. - '문서에 기반하여 답변할 것', '문서에 없는 내용은 답변하지 않고, 「문서에는 기재되어 있지 않습니다.」라고 답변할 것'이라는 명확한 지시를 줌으로써, 모델이 참조해야 할 범위와 답변의 스타일을 제어하고 있습니다. 이것이 간이 RAG의 핵심입니다.
이제 준비는 완료되었습니다. 터미널에서 다음 명령어를 실행하여 시스템을 구동해 주세요.
python main.py
샘플 문서에 기반하여, 예를 들어 다음과 같은 질문을 해보세요.
- 「휴가 신청은 며칠 전까지 필요합니까?」
- 「프로젝트 A의 다음 정례 회의는 언제입니까?」
- 「영업부 직원의 급여에 대해 알려주세요.」
마지막 질문처럼, 문서에 기재되지 않은 내용에 대해서는 「문서에는 기재되어 있지 않습니다.」라고 답변될 것입니다.
막히는 부분과 해결책
제가 이 시스템을 구축하면서 경험했던 '막히는 부분'과 그 해결책에 대해 소개해 드립니다.
1. API 키 관리와 보안
막히는 부분: API 키를 코드 내에 직접 기재하거나, Git 리포지토리에 커밋해 버리면 보안상의 위험이 발생합니다. 만일 키가 유출되면 부정 이용될 가능성이 있습니다.
해결책: python-dotenv
라이브러리를 사용하고, API 키를 .env 파일에 저장함으로써 코드와 API 키를 분리합니다. 나아가, .gitignore 파일에 .env를 추가하여 API 키가 실수로 버전 관리 시스템에 커밋되지 않도록 철저히 합니다.
2. 프롬프트 엔지니어링의 깊이
막혔던 부분: 처음에는 단순히 '이 문서를 기반으로 질문에 답해줘'라고 지시하는 것만으로 충분했지만, 모델이 문서에 없는 내용을 추측하여 답변하거나, 답변이 모호해지는 경우가 있었습니다.
해결책: 프롬프트의 지시를 구체적이고 엄격하게 함으로써 답변의 질을 대폭 향상시킬 수 있었습니다.
- '다음 문서 내용에 기반하여 질문에 구체적으로 답변해 주세요.'라고, 참조원을 명확히 지시했습니다. - '문서에 기재되지 않은 내용은 『문서에는 기재되어 있지 않습니다.』라고 답변하고, 그 외의 정보는 추가하지 마세요.'라고, 문서 외부 정보 생성을 엄격하게 제한했습니다.
이처럼 몇 줄의 지시문을 추가하는 것만으로 모델의 동작을 제어할 수 있다는 것이 프롬프트 엔지니어링의 재미이자 중요한 포인트입니다. 다양한 패턴을 시도하고 오류를 수정하며 최적의 프롬프트를 찾아내는 과정은 실용적인 AI 에이전트를 구축하는 데 필수적입니다.
3. 토큰 제한 문제
막혔던 부분: Gemini API에는 한 번에 처리할 수 있는 토큰 수에 상한선이 있습니다. 매우 긴 문서를 다수 로드하여 그것들을 모두 결합해 프롬프트에 포함하면, 이 토큰 제한을 초과하여 API 오류가 발생할 가능성이 있습니다.
해결책: 이번 간이 버전은 비교적 짧은 문서를 가정하고 있어 문제가 되기 어렵지만, 실운영에서 대량의 장문 문서를 다룰 경우에는 노력이 필요합니다.
- 청킹(Chunking): 문서를 작은 단위(청크)로 분할합니다. - 관련성 검색: 질문 내용과 관련성이 높은 청크만을 추출하여 프롬프트에 전달합니다. 여기에는 벡터 임베딩(vector embedding)과 벡터 데이터베이스(vector database)의 활용이 일반적입니다.
이번에는 간이 버전으로 전체를 전달했지만, 향후 확장으로 이러한 방법들을 검토하는 것이 좋을 것입니다.
요약
이번 글에서는 Gemini API와 Python을 사용하여, 가지고 있는 문서로부터 질문에 자동으로 답변하는 간이 RAG 시스템을 구축하는 방법을 소개했습니다.
이 시스템을 도입함으로써 다음과 같은 효과를 기대할 수 있습니다.
- 정보 검색 시간 단축: 필요한 정보를 AI가 즉시 제시해주기 때문에, 문서를 읽어볼 필요가 줄어듭니다. - 정형적인 질문 대응 자동화: 신규 멤버의 질문이나 FAQ 대응을 AI에게 맡겨, 인적 리소스를 더 중요한 업무에 집중할 수 있습니다. - 지식 활용 촉진: 묻혀 있던 문서 지식이 AI를 통해 쉽게 끌어낼 수 있게 됩니다.
제 업무에서는 이러한 AI 에이전트를 다수 운영함으로써, 일상적인 정보 수집이나 분석, 정형 업무의 자동화를 진행하고 있습니다. Python과 Gemini API를 조합함으로써, 비교적 적은 코드량으로 실용적인 업무 개선 도구를 구축할 수 있다는 것을 체감하셨을 것입니다.
이 시스템은 어디까지나 간이 버전이며, 장래적으로는 다음과 같은 확장이 가능합니다.
- 웹 UI 추가: Streamlit이나 Gradio 등을 활용하여 브라우저에서 조작 가능한 사용자 인터페이스를 구현합니다. - 다양한 문서 포맷 대응: PDF나 Markdown 파일 등도 읽을 수 있도록 확장합니다. - 더 고도화된 RAG 구현: 벡터 데이터베이스를 도입하여, 대규모 문서군으로부터 정밀한 검색과 답변 생성을 실현합니다.
부디 이번 글을 참고하시어, 여러분의 업무 효율화에도 Gemini API와 Python을 활용해 보시길 바랍니다. 끝까지 읽어주셔서 감사합니다. ahic이었습니다.
Discussion
AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기