온프레미스 배포 + 모델 연동 가이드 — eval-system-premium
jodal-eval-ai/pps-mono-repo · H100 GPU 클러스터 + vLLM + KURE-v1
branch: feat/onprem-h100-deploy · HEAD: bd5d51a (PR #197 merged) · 2026-05-22
요약: alpha 의 모든 최신 변경 (35 PR) 이 feat/onprem-h100-deploy 에 squash 머지됨.
온프렘 배포는 start.sh 한 명령 — .env.onprem → .env 자동 복사 후
docker compose up. 모델은 로컬 vLLM (Qwen3-32B :8305 + Qwen3-VL :8303 + KURE-v1 :8306) ,
외부 OpenRouter 비활성. 추가 인프라 0 (postgres·minio·redis·qdrant 도커 컨테이너 그대로).
1. 시스템 아키텍처
┌─────────────────────────────────────────────────────────────┐
│ portal-nginx :80 │
│ (인증 게이트웨이 + /app/* 라우팅) │
└────┬──────────────────────────┬────────────────────────────┘
│ │
┌────────────▼─────────┐ ┌───────────▼──────────────┐
│ frontend :3030 │ │ BFF :4001 (FastAPI) │
│ Next.js 16 standalone│◀──▶│ — 헥사고날 (domain/ports)│
└──────────────────────┘ └────┬───────────┬─────────┘
│ │
┌───────────────────────────┘ └────────┐
│ │
┌──────────▼─────────┐ ┌──────────────┐ ┌────────────────▼─────────┐
│ hwpx-intelligence │ │ postgres :5432 │ │ MinIO :9000 │
│ :8001 (FastAPI) │ │ pps_rfp/eval_ │ │ eval-premium-images │
│ │ │ system/premium │ │ + __source__/ (원본) │
└─────┬──────────────┘ └────────────────┘ └─────────────────────────┘
│
├─▶ Qwen3-32B vLLM :8305 (LLM)
├─▶ Qwen3-VL-8B :8303 (Vision)
└─▶ KURE-v1 :8306 (Embedding)
2. 컴포넌트 인벤토리
컴포넌트 포트 실행 역할
portal-nginx 80 docker 인증 게이트웨이, /app/* 서브패스 프록시
frontend 3030 docker Next.js 16 standalone — 비교 표 UI
BFF (eval-system-premium) 4001 docker FastAPI 헥사고날, proposals CRUD + 이미지 + 검색
hwpx-intelligence 8001 uvicorn (host) HWP/HWPX 파싱 + LLM/VLM 호출 + 이미지 추출
postgres 5432 docker pps_rfp / eval_system / eval_system_premium
pgadmin 5050 docker DB 관리 UI
MinIO 9000/9001 docker 이미지·원본파일 S3 호환 스토리지
Redis 6379 docker Celery 브로커, BullMQ
Qdrant 6333/6334 docker 벡터 검색 (RFP/proposal 임베딩)
Qwen3-32B vLLM 8305 vLLM LLM (RFP 구조화 + eval-chatbot)
Qwen3-VL-8B 8303 vLLM 이미지 분석 (도면 OCR)
KURE-v1 임베딩 8306 자체 서빙 한국어 임베딩 (semantic-search)
GPU info service 8500 자체 GPU 가용성 모니터링
3. 모델 연동 — .env.onprem
MODEL_CONFIG_*_ENABLED 스위치로 dev/prod 분기. 온프렘은 전부 TYPE=local + URL=http://localhost:830X.
# LLM — RFP 구조화 + 평가 챗봇
MODEL_CONFIG_qwen3_32b_ENABLED=true
MODEL_CONFIG_qwen3_32b_TYPE=local
MODEL_CONFIG_qwen3_32b_PROVIDER=qwen
MODEL_CONFIG_qwen3_32b_URL=http://localhost:8305
MODEL_CONFIG_qwen3_32b_MODEL_NAME=Qwen/Qwen3-32B
MODEL_CONFIG_qwen3_32b_GPU_INFO_URL=http://localhost:8500
MODEL_CONFIG_qwen3_32b_PURPOSE=rfp-structure
# Vision — 도면/이미지 분석
MODEL_CONFIG_qwen3_vl_8b_instruct_ENABLED=true
MODEL_CONFIG_qwen3_vl_8b_instruct_TYPE=local
MODEL_CONFIG_qwen3_vl_8b_instruct_URL=http://localhost:8303/v1
MODEL_CONFIG_qwen3_vl_8b_instruct_MODEL_NAME=Qwen/Qwen3-VL-8B-Instruct
MODEL_CONFIG_qwen3_vl_8b_instruct_PURPOSE=rfp-image-analysis
# 평가 챗봇 (별도 alias — same vLLM 인스턴스 재사용)
MODEL_CONFIG_qwen3_32b_eval_ENABLED=true
MODEL_CONFIG_qwen3_32b_eval_URL=http://localhost:8305
MODEL_CONFIG_qwen3_32b_eval_PURPOSE=eval-chatbot
# Embedding — 한국어 KURE-v1
MODEL_CONFIG_local_embedding_ENABLED=true
MODEL_CONFIG_local_embedding_TYPE=local
MODEL_CONFIG_local_embedding_PROVIDER=kure
MODEL_CONFIG_local_embedding_URL=http://localhost:8306
MODEL_CONFIG_local_embedding_MODEL_NAME=nlpai-lab/KURE-v1
MODEL_CONFIG_local_embedding_PURPOSE=semantic-search
EMBEDDING_DIM=1536
# 외부 API 키 — 온프렘은 비활성
GEMINI_API_KEY=
OPENROUTER_API_KEY= # 데모 후 revoke 권장
UPSTAGE_API_KEY=
USE_UPSTAGE_API=false
4. 부팅 절차 (1회성 — start.sh)
GPU 모델 서빙 시작 (호스트 systemd 또는 별도 supervisor)
# Qwen3-32B vLLM
vllm serve Qwen/Qwen3-32B --port 8305 --tensor-parallel-size 2
# Qwen3-VL-8B
vllm serve Qwen/Qwen3-VL-8B-Instruct --port 8303 --tensor-parallel-size 1
# KURE-v1 임베딩
python -m kure_v1.server --port 8306
hwpx-intelligence 부팅 (호스트 uvicorn, BFF 보다 먼저)
cd ~/Github/1_Projects/hwpx-intelligence
uv sync
nohup uv run hpwx serve --host 0.0.0.0 --port 8001 > /var/log/hwpx.log 2>&1 &
온프렘 start.sh 실행 (이미지 tar 로드 + .env 자동 복사 + docker compose up)
cd ~/Github/1_Projects/pps-mono-repo
git pull origin feat/onprem-h100-deploy # alpha 최신 squash 머지된 상태
bash start.sh
내부 동작:
docker load < docker-images/pps-images.tar (이미지 로드, 첫 부팅만)
cp .env.onprem .env
docker compose up -d --no-build
MinIO 버킷 자동 생성 — minio-init 컨테이너가 MINIO_BUCKETS env 의 버킷 자동 생성 (eval-premium-images, pps-rfp-processed, pps-rfp-ingest)
postgres 자동 migration — BFF entrypoint 가 alembic upgrade head 실행
헬스체크
curl localhost:4001/api/health # {"status":"ok"}
curl localhost:8001/api/health # hwpx
curl localhost:8305/v1/models # vLLM
docker compose ps # 모두 healthy
5. 데모 5/22 안전 체크리스트
항목 확인 명령 기대
vLLM Qwen3-32B curl localhost:8305/v1/models 200
vLLM Qwen3-VL curl localhost:8303/v1/models 200
KURE-v1 임베딩 curl localhost:8306/health 200 (dim=1536)
hwpx-intelligence curl localhost:8001/api/health 200
BFF curl localhost:4001/api/health {"status":"ok"}
BFF self-poller 가동 env | grep PREMIUM_BFF_DISABLE_SELF_POLLER false
proposals 테이블 psql ... -c "SELECT COUNT(*) FROM proposals" ≥1
MinIO 영구화 mc ls local/eval-premium-images/ __source__/, prop-*
frontend /upload curl -o /dev/null -w '%{http_code}' localhost:3030/upload 200
frontend /eval 비교 .../eval?bid_id=demo-bid-1 200 + 비교표
6. 운영 가이드 — 보안·백업·모니터링
영역 P0 (즉시) P1 (2주)
보안
OpenRouter 키 revoke (메일 노출됨) → 새 키 발급 + Infisical/Doppler 시크릿 매니저 이전. PORTAL_JWT_SECRET openssl rand -hex 64 로 재생성
portal-nginx 사내 CA 인증서 mount (HTTPS), admin endpoint JWT scope 강제
백업
postgres pg_dump cron (30분 간격) → MinIO pps-backups 버킷. retention 7일
MinIO 객체 cross-region replication 또는 R2 sync
모니터링
Sentry DSN (BFF + Frontend) — 무료 tier 5분 셋업
Prometheus + Grafana (LLM 호출 count/latency/cost 메트릭)
로그
structlog JSON formatter + correlation_id (proposal_id) — BFF requirements 에 이미 있음, 적용만
Loki + Grafana log aggregation
LLM 안정성
vLLM 응답 timeout 120s (hwpx_client 적용됨), tenacity retry 추가
모델 fallback chain (vLLM 다운 시 OpenRouter)
7. 트러블슈팅
증상 원인 해결
BFF self-poller 가 무한 polling
hwpx-intelligence 가 callback URL 미호출 (webhook 미구현)
self-poller가 backup — 정상. webhook 구현 후 비활성 가능
큰 hwp (88K 단락) LLM stuck 27분
OpenRouter rate limit + LLM 호출 chunk 과대
per-zone 5분 timeout + status='partial' fallback (P0 권장 — 별도 PR)
/api/proposals 응답 4.5MB
raw (extraction JSONB) 포함 — 33 proposal × 140KB
?include_raw=false opt-in → 32KB (~170× 슬림). PR #188
이미지 안 보임
frontend 가 옛 hwpx /api/records/.../images/ 호출
BFF endpoint /api/proposals/{id}/images/{filename} 사용 (PR #175, #179)
원본보기 404 source file not found
PR #182 이전 업로드 = MinIO 미저장
hwpx /api/uploads/{job_id} lazy fetch → MinIO 자동 영구화 (PR #185)
표 헤더 분리 안 보임
border-collapse 환경에서 thead shadow 가 렌더 안 됨
각 th 에 border-b-4 border-[#1F48B8] (PR #184)
migration head 2개 → exit 255
alembic 분기
DDL 없는 merge-only revision 으로 수렴. CI 에 alembic heads | wc -l ≤ 1 검증 (P1)
8. 자주 쓰는 명령
# 전체 재시작
docker compose down && bash start.sh
# 특정 컨테이너 재기동 (BFF)
docker compose up -d --force-recreate eval-system-premium-bff
# 로그
docker compose logs -f eval-system-premium-bff
docker compose logs -f eval-system-premium-frontend
# DB 직접 조회
docker exec pps-postgres-1 psql -U pps_user -d eval_system_premium
# MinIO 객체 목록
docker exec pps-minio-1 mc ls --recursive local/eval-premium-images/
# 마이그레이션 (기존 proposal data_uri → MinIO)
curl -X POST http://localhost:4001/api/admin/migrate-images
# keyset 페이지네이션 테스트
curl "localhost:4001/api/proposals?limit=10&include_raw=false&cursor=..."
generated 2026-05-22 · ai-real-estate-service workspace · jodal-eval-ai