Skip to content

Datajang/gg-chatbot

Repository files navigation

Visual RAG — 경기도 데이터 분석 보고서 질의응답 시스템

텍스트 추출 없이 문서 페이지를 이미지로 변환하여 시각적으로 검색하는 RAG(Retrieval-Augmented Generation) 시스템입니다. PPTX/HWP 형식의 경기도 데이터 분석 보고서를 대상으로, ColQwen2.5 멀티벡터 임베딩으로 검색하고 Qwen2.5-VL-7B로 답변을 생성합니다.

대상 하드웨어: GCP L4 GPU (24GB VRAM)


아키텍처

데이터 흐름

[문서 입력]
PPTX / HWP
    │
    ▼ LibreOffice (headless)
   PDF
    │
    ▼ pdf2image (DPI=400)
   PNG 이미지 (페이지별)
    │
    ├─ [인덱싱] ──────────────────────────────────────────────────────────┐
    │  ColQwen2.5 (GPU, bfloat16)                                        │
    │      │ 멀티벡터 임베딩 (128차원, ColBERT MAX_SIM)                   │
    │      ▼                                                              │
    │    Qdrant (MultiVector 컬렉션)                                      │
    └─────────────────────────────────────────────────────────────────────┘
    
[쿼리 응답]
사용자 질문
    │
    ▼ ColQwen2.5 (CPU, float32)
 MaxSim 검색 → 상위 5개 PNG
    │
    ▼ Qwen2.5-VL-7B-AWQ (vLLM, GPU)
   최종 답변

VRAM 사용 전략

단계 ColQwen2.5 vLLM (Qwen2.5-VL) 비고
인덱싱 GPU (~6GB) 미사용 서버 중지 필요
서빙 CPU GPU (~13GB) 인덱싱 중지 필요

중요: 인덱서와 서버는 절대 동시에 실행하지 마세요. VRAM 충돌이 발생합니다.

모듈 구조

src/
├── main.py               # FastAPI 앱 — /upload, /chat, /health 엔드포인트
├── auth/
│   └── middleware.py     # X-API-Key 헤더 인증 (관리자 / 일반 사용자 구분)
├── utils/
│   └── config.py         # .env 기반 타입 상수
├── ingestion/
│   ├── converter.py      # LibreOffice → PDF → PNG 변환
│   └── indexer.py        # ColQwen2.5 GPU → Qdrant 적재 (CLI 진입점)
├── retrieval/
│   └── searcher.py       # ColQwen2.5 CPU 싱글턴 + Qdrant MaxSim 검색
├── generation/
│   └── llm_client.py     # vLLM 싱글턴 + Qwen2.5-VL 프롬프트 포맷
└── static/
    └── index.html        # 웹 UI (Vanilla JS, Catppuccin Mocha 테마)

인프라 구성

  • Qdrant + Nginx: Docker 컨테이너로 실행 (docker-compose.yml)
  • FastAPI: 호스트에서 직접 실행 (GPU 접근을 위해 Docker 외부)
  • Nginx → FastAPI 통신은 host.docker.internal을 통해 연결

설치 및 환경 설정

1단계 — 시스템 의존성 설치 (재부팅 필요)

sudo bash setup.sh && sudo reboot

2단계 — GPU 확인

nvidia-smi

3단계 — Python 패키지 설치

# uv 설치 (없는 경우)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 핵심 패키지 설치
uv sync

# vLLM은 별도 설치 (pyproject.toml 미추적)
uv pip install vllm

4단계 — 환경 변수 설정

cp .env.example .env

.env 파일을 열어 아래 값을 설정합니다:

변수 설명 예시
ADMIN_API_KEY 관리자 API 키 (업로드 + 채팅) my-secret-admin-key
USER_API_KEYS 일반 사용자 키 목록 (쉼표 구분) key-001,key-002
QDRANT_HOST Qdrant 호스트 localhost
QDRANT_PORT Qdrant 포트 6333
COLLECTION_NAME Qdrant 컬렉션 이름 visual_rag
RETRIEVAL_MODEL 검색 모델 vidore/colqwen2.5-v0.2
GENERATION_MODEL 생성 모델 Qwen/Qwen2.5-VL-7B-Instruct-AWQ
TOP_K 검색 결과 이미지 수 5
IMAGE_DPI 이미지 변환 해상도 400
MAX_CONCURRENT_REQUESTS 최대 동시 요청 수 3
REQUEST_TIMEOUT_SECONDS 요청 타임아웃 (초) 180

5단계 — 인프라 실행

docker-compose up -d

인덱싱 (서버 실행 전 1회)

# data/raw/ 하위 전체 파일 인덱싱
uv run python src/ingestion/indexer.py --input data/raw/

# 특정 연도 디렉토리만 인덱싱
uv run python src/ingestion/indexer.py --input data/raw/2025/

# 단일 파일 인덱싱
uv run python src/ingestion/indexer.py --input data/raw/파일.pptx

# 컬렉션 초기화 후 재인덱싱 (기존 데이터 삭제)
uv run python src/ingestion/indexer.py --input data/raw/ --recreate

지원 형식: .pptx, .ppt, .hwp, .odp


서버 실행

# --no-sync: vllm은 pyproject.toml 미추적이므로 필수
uv run --no-sync uvicorn src.main:app --host 0.0.0.0 --port 8000

서버가 뜨면 http://localhost:8000 에서 웹 UI에 접근할 수 있습니다.


API 엔드포인트

모든 요청은 X-API-Key 헤더에 인증 키를 포함해야 합니다.

GET /health

인증 없이 서버 및 Qdrant 연결 상태 확인.

curl http://localhost:8000/health

POST /upload (관리자 전용)

문서 파일을 업로드하고 자동으로 변환 및 인덱싱합니다.

curl -X POST http://localhost:8000/upload \
  -H "X-API-Key: $ADMIN_API_KEY" \
  -F "file=@data/raw/보고서.pptx"

POST /chat

자연어 질문으로 보고서 내용을 검색하고 답변을 받습니다.

curl -X POST http://localhost:8000/chat \
  -H "X-API-Key: $USER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "경기도 미세먼지 계절관리제 효과는?"}'

응답 형식:

{
  "answer": "...",
  "sources": [
    {"file": "보고서.pptx", "page": 3},
    ...
  ]
}

HTTPS 설정 (도메인 연결 후)

bash enable_https.sh your.domain.com

도메인 연결 전 접속방법

서버 실행 뒤 아래 주소로 접속
http://35.184.63.251/

DNS가 서버 IP로 전파된 후 실행하면 Nginx에 SSL 인증서가 자동으로 설정됩니다.


구현 제약 사항

항목 이유
IMAGE_DPI 400 한국어 표/숫자 가독성 보장
TOP_K 5 vLLM limit_mm_per_prompt 상한
Qwen VL 이미지 토큰 <|vision_start|><|image_pad|><|vision_end|> 모델 고정 형식 — 변경 금지
벡터 차원 128 ColQwen2.5 고정 출력 차원
Qdrant 컬렉션 MultiVectorConfig(MAX_SIM) 단일 벡터 컬렉션과 호환 불가

기술 스택

역할 기술
문서 변환 LibreOffice (headless), pdf2image
검색 임베딩 ColQwen2.5 (vidore/colqwen2.5-v0.2)
벡터 DB Qdrant (MultiVector MAX_SIM)
언어 모델 Qwen2.5-VL-7B-Instruct-AWQ
추론 엔진 vLLM
웹 프레임워크 FastAPI
리버스 프록시 Nginx (Docker)
패키지 관리 uv

About

경기도청 챗봇 프로토타입

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors