본문으로 건너뛰기

© 2026 Molayo

GitHub요약2026. 06. 15. 07:12

PDF-Assistant-RAG: 에이전트 기반 RAG 파이프라인을 갖춘 AI 문서 어시스턴트

요약

에이전트 기반 RAG 파이프라인을 활용하여 PDF, 재무 보고서 등을 분석하는 프로덕션급 AI 문서 어시스턴트 프로젝트입니다. 의미 검색과 크로스-인코더 재랭킹을 결합하여 답변의 정확도를 높였으며, 스트리밍 응답과 데이터 격리 기능을 제공합니다.

핵심 포인트

  • 의미 검색 및 크로스-인코더 재랭킹을 통한 고품질 RAG 구현
  • FastAPI와 Next.js를 활용한 엔드투엔드 아키텍처 구축
  • SSE를 이용한 토큰 단위 스트리밍 응답 지원
  • ChromaDB 기반의 벡터 임베딩 및 세션별 데이터 격리 적용
titleDocument AI Analyst
emoji🧠
...
██████╗ ██████╗ ███████╗ █████╗ ███████╗███████╗██╗███████╗████████╗ █████╗ ███╗ ██╗████████╗
██╔══██╗██╔══██╗██╔════╝ ██╔══██╗██╔════╝██╔════╝██║██╔════╝╚══██╔══╝██╔══██╗████╗ ██║╚══██╔══╝
██████╔╝██║ ██║█████╗ ███████║███████╗███████╗██║███████╗ ██║ ███████║██╔██╗ ██║ ██║
... 

Upload · Embed · Retrieve · Chat— 에이전트 기반 RAG 파이프라인, 스트리밍 응답, 사용자별 데이터 격리를 통해 엔드투엔드로 구축된 프로덕션급 AI 문서 어시스턴트.

Features · Tech Stack · Getting Started · Architecture · RAG Pipeline · API Reference · Deployment · Contributing

PDF-Assistant-RAG에 기여한 모든 훌륭한 분들께 감사드립니다! 🎉

🌟

참여하고 싶으신가요? CONTRIBUTING.md에서 기여 가이드라인을 확인하고 시작할 좋은 첫 이슈를 찾아보세요!

PDF-Assistant-RAG는 사용자가 복잡한 PDF, 재무 보고서, 법률 계약서 및 연구 논문을 업로드하면 — 다단계 Retrieval-Augmented Generation (RAG) 파이프라인으로 구동되는 정확하고 인용된 답변을 제공하는 AI와 채팅할 수 있게 해주는 완전하고 프로덕션 준비가 된 AI 문서 어시스턴트입니다.

이 시스템은 가장 관련성 높은 문서 청크를 찾기 위해 **의미 검색(semantic search) + 크로스-인코더 재랭킹(cross-encoder reranking)**을 사용하고, AI 생성 답변을 토큰 단위로 스트리밍하며, 세션 기반 사용자별 데이터 격리가 적용된 깔끔한 Flask 서버 UI 내에서 페이지 번호와 함께 정확한 출처 인용을 하이라이트합니다.

기여자 참고: 라우트별 시스템 맵, 요청 흐름 다이어그램, 소유 경계 및 Swagger/OpenAPI 문서화 가이드라인은 docs/ARCHITECTURE.md를 참조하세요.

graph TD
subgraph Frontend["Frontend (Next.js 16)"]
UI["Dashboard UI (React)"]
... 
  • 사용자는 Next.js 프론트엔드와 상호작용하여 문서를 업로드하고 질문을 합니다.
  • FastAPI는 인증 (Authentication), 문서 인제스션 (Ingestion), 그리고 채팅 API를 처리합니다.
  • 업로드된 문서는 파싱 (Parsing)되고, 청킹 (Chunking)되어 벡터 임베딩 (Vector Embeddings)으로 변환됩니다.
  • 임베딩은 의미론적 검색 (Semantic Retrieval)을 위해 ChromaDB에 저장됩니다.
  • 쿼리 (Querying) 시, 리트리버 (Retriever)가 ChromaDB에서 관련 청크를 가져옵니다.
  • 리랭커 (Reranker)가 LLM에 컨텍스트를 보내기 전에 검색 품질을 개선합니다.
  • Hugging Face Inference API가 최종 응답을 생성합니다.
  • 응답은 SSE를 사용하여 프론트엔드로 스트리밍 (Streaming)됩니다.
기술 (Technology)용도 (Purpose)
Jinja2 (via Flask)서버 사이드 HTML 템플릿 (Server-side HTML templating)
HTML + CSS + JavaScript프론트엔드 UI (/static/templates에서 제공)
기술 (Technology)용도 (Purpose)
Docker Multi-Stage컨테이너화된 배포 (Containerized deployment)
GitHub ActionsCI 파이프라인 (dev 브랜치)
Git LFS바이너리 자산 관리 (Binary asset management)
HuggingFace Spaces프로덕션 배포 (Production deployment)

||
||
||

PDF-Assistant-RAG/
│
├── app.py # Flask 앱 — 모든 라우트 (업로드, 질문, 다운로드, 인증)
...

Python 3.11+
MongoDB (Atlas 무료 티어 또는 로컬)
Pinecone 계정 — pinecone.io
Google Gemini API key — aistudio.google.com
Groq API key — console.groq.com

git clone https://github.com/param20h/PDF-Assistant-RAG.git
cd PDF-Assistant-RAG
cp .env.example .env
`.env` 편집:
SECRET_KEY=your-strong-random-secret
...

huggingface.co/settings/tokens 에서 무료 HuggingFace 토큰을 받으세요.

비밀번호 등록은 사용자가 로그인하기 전에 이메일 인증이 필요합니다. 실제 인증 이메일을 보내려면 backend/.env에 SMTP 설정을 추가하세요.

:

FRONTEND_URL=http://localhost:3000
EMAIL_VERIFICATION_TOKEN_EXPIRE_HOURS=24
MAIL_USERNAME=your_smtp_username
...

Gmail의 경우, 발신자 Google 계정에서 2단계 인증을 활성화하고, Google 계정 > 보안 > 앱 비밀번호에서 16자리의 앱 비밀번호를 생성한 다음 다음을 사용하세요:

MAIL_USERNAME=yourgmail@gmail.com
MAIL_PASSWORD=your_16_character_app_password
MAIL_FROM=yourgmail@gmail.com
...

비운영 환경 (non-production environment)에서 SMTP 설정이 없으면, 기여자(contributors)들이 개인 이메일 자격 증명 없이도 흐름을 테스트할 수 있도록 로컬 인증 링크가 반환됩니다. SMTP가 구성되면 동일한 링크가 이메일로 전송됩니다.

URL 업로드 기능 (POST /api/v1/documents/urlupload)

은 Playwright 브라우저와 함께 crawl4ai를 사용하여 웹 페이지를 크롤링합니다. crawl4ai-setup은 Playwright 브라우저 설치를 자동으로 처리합니다. pip install 이후에 한 번 실행하세요:

crawl4ai-setup

# 단일 터미널 — Flask 앱
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
...
docker compose up --build
# → http://localhost:7860 에서 앱 실행 중
┌─────────────────────────────────────────────┐
│ PDF / DOCX 업로드 │
└───────────────────┬─────────────────────────┘
...
메서드 (Method)엔드포인트 (Endpoint)인증 (Auth)설명 (Description)
POST/api/v1/auth/register새 사용자 계정 생성
POST/api/v1/auth/login로그인 및 JWT 토큰 수신
GET/api/v1/auth/me현재 사용자 프로필 가져오기
POST/api/v1/documents/uploadPDF/DOCX 업로드 및 백그라운드 인덱싱 대기열 추가 (202 Accepted)
GET/api/v1/documents현재 사용자의 모든 문서 목록 조회
GET/api/v1/documents/{id}/status백그라운드 문서 처리 상태 폴링 (Poll)
DELETE/api/v1/documents/{id}문서 및 해당 벡터 데이터 삭제
POST/api/v1/chat/ask/stream질문하기 (SSE 스트리밍 응답)
GET/api/v1/chat/history/{doc_id}문서에 대한 채팅 기록 가져오기
DELETE/api/v1/chat/history/{doc_id}문서에 대한 채팅 기록 삭제
GET/health상태 확인 (db + chroma 상태)

로컬에서 실행 중일 때 /docs (Swagger UI)에서 전체 대화형 문서를 확인할 수 있습니다.

변수 (Variable)필수 (Required)기본값 (Default)설명 (Description)획득 방법 (Where to Get It)
SECRET_KEYJWT 서명 및 세션 비밀키 (session secret). 강력한 무작위 문자열을 사용하세요.생성: python -c "import secrets; print(secrets.token_urlsafe(32))"
HF_TOKENInference API를 통한 LLM 추론을 위한 HuggingFace API 토큰.huggingface.co/settings/tokens (무료)
HF_CLIENT_IDHuggingFace OAuth 클라이언트 ID (Client ID). Hugging Face 로그인 시에만 필요합니다.HuggingFace Developer Settings
HF_CLIENT_SECRETHuggingFace OAuth 클라이언트 비밀키 (Client Secret). Hugging Face 로그인 시에만 필요합니다.HuggingFace Developer Settings
HF_REDIRECT_URIhttp://localhost:8000/api/v1/auth/callback/huggingfaceHuggingFace OAuth 콜백 리다이렉트 URI (redirect URI).
FRONTEND_URLhttp://localhost:3000OAuth 리다이렉트 및 이메일 인증 링크에 사용되는 공개 프론트엔드 URL.배포된 프론트엔드 URL
ENVIRONMENTdevelopment런타임 모드 (Runtime mode). 배포 시 CORS를 잠그려면 production으로 설정하세요.
DEBUGFalse상세한 에러 페이지를 포함하는 디버그 모드 (debug mode) 활성화. 프로덕션 환경에서는 절대 활성화하지 마세요.
ALLOWED_ORIGINShttp://localhost:3000,http://localhost:7860쉼표로 구분된 CORS 허용 오리진 (production 환경에서만 적용됨).배포된 도메인(들)
DATABASE_URLsqlite:///./data/app.dbSQLAlchemy 데이터베이스 연결 문자열 (connection string).SQLite (기본값), 또는 Postgres/MySQL 연결 문자열
JWT_ALGORITHMHS256JWT 서명 알고리즘.
JWT_EXPIRY_HOURS72재로그인이 필요하기 전까지의 JWT 토큰 유효 시간 (시간 단위).
GOOGLE_CLIENT_IDFastAPI가 ID 토큰을 검증하는 데 사용하는 Google OAuth 웹 클라이언트 ID.Google Cloud Console
NEXT_PUBLIC_GOOGLE_CLIENT_IDNext.js Google 로그인 버튼에 노출되는 Google OAuth 웹 클라이언트 ID.Google Cloud Console
EMAIL_VERIFICATION_TOKEN_EXPIRE_HOURS24이메일 인증 토큰의 유효 시간 (시간 단위).

| — |
MAIL_USERNAME | ❌ | — | 계정 인증 이메일을 위한 SMTP 사용자 이름 (username). | SMTP 제공업체 또는 Gmail 앱 비밀번호 설정 |
MAIL_PASSWORD | ❌ | — | SMTP 비밀번호 또는 Gmail 16자리 앱 비밀번호 (App Password). | SMTP 제공업체 또는 Gmail 앱 비밀번호 설정 |
MAIL_FROM | ❌ | — | 인증 이메일의 발신자 이메일 주소. | 인증된 발신자 주소 |
MAIL_SERVER | ❌ | — | SMTP 서버 호스트 이름 (예: smtp.gmail.com). | SMTP 제공업체 |
MAIL_PORT | ❌ | 587 | SMTP 서버 포트. | SMTP 제공업체 |
MAIL_STARTTLS | ❌ | True | SMTP를 위한 STARTTLS 활성화. | SMTP 제공업체 |
MAIL_SSL_TLS | ❌ | False | SMTP를 위한 SSL/TLS 활성화. | SMTP 제공업체 |
CELERY_BROKER_URL | ❌ | redis://localhost:6379/0 | FastAPI가 문서 인제스션 (Ingestion) 작업을 큐에 넣기 위해 사용하는 Redis 브로커 (Broker) URL. | Redis |
CELERY_RESULT_BACKEND | ❌ | redis://localhost:6379/1 | Celery가 작업 상태 및 결과를 저장하기 위해 사용하는 Redis 백엔드 (Backend) URL. | Redis |
UPLOAD_DIR | ❌ | ./data/uploads | 업로드된 문서를 저장하기 위한 로컬 디렉토리. | — |
MAX_FILE_SIZE_MB | ❌ | 50 | 허용되는 최대 업로드 파일 크기 (MB 단위). | — |
ALLOWED_EXTENSIONS | ❌ | pdf,docx,txt,md | 허용된 파일 확장자 목록 (쉼표로 구분). | — |
CHROMA_PERSIST_DIR | ❌ | ./data/chroma_db | ChromaDB가 벡터 인덱스 (Vector Index)를 영구 저장하는 디렉토리. | — |
LLM_MODEL | ❌ | Qwen/Qwen2.5-72B-Instruct | 답변 생성을 위한 HuggingFace 모델 ID. | huggingface.co/models |
LLM_TEMPERATURE | ❌ | 0.3 | LLM 샘플링 온도 (0 = 결정론적 (Deterministic), 1 = 창의적 (Creative)). | — |
LLM_MAX_NEW_TOKENS | ❌ | 1024 | LLM 응답당 최대 토큰 수. | — |
EMBEDDING_MODEL | ❌ | sentence-transformers/all-MiniLM-L6-v2 | 로컬 임베딩 (Embedding)을 위한 SentenceTransformer 모델 (외부 API 미사용). | huggingface.co/sentence-transformers |
EMBEDDING_DIMENSION | ❌ | 384 | 임베딩 벡터 차원 (모델과 일치해야 함). | — |
RERANKER_MODEL | ❌ | cross-encoder/ms-marco-MiniLM-L-6-v2 | 검색된 청크 (Chunk)를 관련성에 따라 재순위화 (Reranking)하기 위한 크로스 인코더 (Cross-encoder) 모델.

| huggingface.co/cross-encoder |
CHUNK_SIZE | ❌ | 1000 | 문서 청크당 문자 수. 크기가 클수록 더 많은 컨텍스트를 얻고, 작을수록 정밀도가 높아집니다. | — |
CHUNK_OVERLAP | ❌ | 200 | 연속된 청크 간의 중복(Overlap)으로 경계 컨텍스트 유지. | — |
TOP_K_RETRIEVAL | ❌ | 10 | 의미론적 검색 과정에서 벡터 스토어로부터 검색되는 후보 청크 수. | — |
TOP_K_RERANK | ❌ | 5 | 재순위화(reranking) 후 LLM에 전달되는 최종 청크 수 (반드시 TOP_K_RETRIEVAL 이하여야 함). | — |

명령어설명
uvicorn app.main:app --reload핫 리로드를 사용하여 FastAPI 시작
uvicorn app.main:app --port 8000포트 8000에서 FastAPI 시작
python scripts/run_ragas_eval.py --user-id <user-id>벡터 검색과 GraphRAG에 대한 50개 질문의 RAGAS 비교 실행

RAGAS 스크립트는 backend/evaluation/ragas_sample_questions.jsonl에서 읽어와, 표준 벡터 컨텍스트 및 벡터+GraphRAG 컨텍스트로부터 답변을 생성한 후, 집계 점수를 backend/evaluation/ragas_results.json에 작성합니다.
문서 하나를 평가하려면 --document-id <document-id>를 전달하세요.

명령어설명
npm run devNext.js 개발 서버 시작
npm run build프로덕션 빌드 → out/ (정적 내보내기)
npm run lintESLint 실행
npm run test:e2ePlaywright 엔드-투-엔드 테스트 실행
명령어설명
docker compose --profile cpu up --build전체 스택 빌드 및 시작 (CPU 전용, GPU 불필요)
docker compose --profile gpu up --buildNVIDIA GPU 가속을 사용하여 전체 스택 빌드 및 시작
docker compose --profile debug uphttp://localhost:5050에서 pgAdmin도 함께 시작
docker compose down모든 컨테이너 중지

CPU 프로필— 어떤 기기에서도 작동합니다. 임베딩은 all-MiniLM-L6-v2를 통해 CPU에서 실행됩니다.

GPU 프로필— NVIDIA Container Toolkit이 필요합니다. 가속화된 임베딩 추론을 위해 DEVICE=cuda가 설정됩니다.

본 프로젝트는 Docker를 사용하여 HuggingFace Spaces에 배포되었습니다.

  • 이 저장소(repo)를 Fork한 후 huggingface.co/new-space에서 새로운 Space를 생성하세요 (SDK: Docker)

  • 다음 Space secrets를 설정하세요:
    HF_TOKEN — 귀하의 HuggingFace API 토큰
    SECRET_KEY — 강력한 무작위 문자열

  • hf 원격(remote)으로 Push하면 Space가 자동으로 빌드됩니다.

git remote add hf https://<username>:<HF_TOKEN>@huggingface.co/spaces/<username>/<space-name>
git push hf main
docker compose up -d --build
# 앱은 http://your-server:7860 에서 사용 가능합니다

이 프로젝트는 GirlScript Summer of Code에 참여하고 있습니다! 모든 숙련도의 기여자(contributor)를 환영합니다.

브랜치 전략 (Branch Strategy):

브랜치 (Branch)목적 (Purpose)
main프로덕션 (Production) — HuggingFace에 배포됨 (관리자 전용)
dev모든 기여자의 PR(Pull Request) 대상
feature/* / fix/* / docs/*작업용 브랜치
# 항상 dev에서 브랜치를 생성하세요
git checkout -b feature/my-feature upstream/dev

빠른 링크 (Quick links):

**MIT 라이선스 (MIT License)**에 따라 배포됩니다. 자세한 내용은 LICENSE를 참조하세요.

AI 자동 생성 콘텐츠

본 콘텐츠는 GitHub AI Tools의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0