Files
exAichatbot_agent/exAiChatBot-chatbot2.0-agent/docker-compose-slim.yml
T
Macbook 4b86b2a660 Agent 2.0 exdev 서버 배포 스택
- server-dev start/stop/deploy 및 Gitea push 자동 배포
- local-dev 로컬 개발 환경

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 22:57:30 +09:00

232 lines
9.4 KiB
YAML

services:
# ============================================
# 경량 버전 (외부 API 사용 + 로컬 MongoDB)
# ============================================
# 1) 임베딩 단계 (preprocess 생략, qa_raw.jsonl 직접 사용)
embed:
image: "${RAG_BATCH_IMAGE:-rag-batch-slim:latest}"
network_mode: host
build:
context: .
dockerfile: docker/batch-slim.Dockerfile
command: ["python", "/app/scripts/ingest_qa.py"]
working_dir: /app
depends_on:
- qdrant
# 모델 게이트웨이 호스트명 → IP 매핑 (DNS 미등록 대응)
extra_hosts:
- "llm-ai.ex.co.kr:${GATEWAY_IP:-172.16.163.96}"
- "embedding-ai.ex.co.kr:${GATEWAY_IP:-172.16.163.96}"
- "reranker-ai.ex.co.kr:${GATEWAY_IP:-172.16.163.96}"
environment:
# 프록시 비활성화 (명시적)
HTTP_PROXY: ""
HTTPS_PROXY: ""
http_proxy: ""
https_proxy: ""
# Python 출력 버퍼링 비활성화 (실시간 로그)
PYTHONUNBUFFERED: "1"
# 임베딩(게이트웨이) 설정
TEI_EMBED_URL: "${TEI_EMBED_URL:-https://embedding-ai.ex.co.kr}"
EMBED_MODEL_NAME: "${EMBED_MODEL_NAME:-Qwen/Qwen3-Embedding-8B}"
MODEL_API_KEY: "${MODEL_API_KEY:-}"
MODEL_VERIFY_SSL: "${MODEL_VERIFY_SSL:-false}"
API_TIMEOUT: "${API_TIMEOUT:-60}"
EMBED_BATCH_SIZE: "${EMBED_BATCH_SIZE:-100}"
# Qdrant 저장 배치 (4096차원 → 32MB 요청 한도 초과 방지, 100 권장)
VECTOR_BATCH_SIZE: "${VECTOR_BATCH_SIZE:-100}"
# 벡터 DB 설정
VECTOR_STORE: "${VECTOR_STORE:-qdrant}"
QDRANT_HOST: "${QDRANT_HOST:-127.0.0.1}"
QDRANT_PORT: "${QDRANT_PORT:-6333}"
QDRANT_COLLECTION: "${QDRANT_COLLECTION:-qa_vectors}"
HYBRID_SEARCH_ENABLED: "${HYBRID_SEARCH_ENABLED:-false}"
SPARSE_SEARCH_ENABLED: "${SPARSE_SEARCH_ENABLED:-true}"
SPARSE_TOP_K: "${SPARSE_TOP_K:-30}"
HYBRID_MERGE_TOP_K: "${HYBRID_MERGE_TOP_K:-40}"
# 프록시 우회 (내부 IP 직접 연결)
NO_PROXY: "${NO_PROXY:-localhost,127.0.0.1,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8,.ex.co.kr}"
no_proxy: "${no_proxy:-localhost,127.0.0.1,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8,.ex.co.kr}"
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: "no"
# 2) 인덱싱 단계
index:
image: "${RAG_BATCH_IMAGE:-rag-batch-slim:latest}"
network_mode: host
command: ["python", "/app/scripts/build_index_qa.py"]
working_dir: /app
depends_on:
embed:
condition: service_completed_successfully
environment:
# 프록시 비활성화 (명시적)
HTTP_PROXY: ""
HTTPS_PROXY: ""
http_proxy: ""
https_proxy: ""
# Python 출력 버퍼링 비활성화 (실시간 로그)
PYTHONUNBUFFERED: "1"
# 벡터 DB 설정
VECTOR_STORE: "${VECTOR_STORE:-faiss}"
# 프록시 우회
NO_PROXY: "${NO_PROXY:-localhost,127.0.0.1,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8}"
no_proxy: "${no_proxy:-localhost,127.0.0.1,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8}"
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: "no"
# 3) API 서비스
api:
image: "${RAG_API_IMAGE:-rag-api-slim:latest}"
network_mode: host # embed/index/admin과 통일: 127.0.0.1로 qdrant/mongo 접근
build:
context: .
dockerfile: docker/service-slim.Dockerfile
depends_on:
- index
- qdrant
# 모델 게이트웨이 호스트명 → IP 매핑 (DNS 미등록 대응)
extra_hosts:
- "llm-ai.ex.co.kr:${GATEWAY_IP:-172.16.163.96}"
- "embedding-ai.ex.co.kr:${GATEWAY_IP:-172.16.163.96}"
- "reranker-ai.ex.co.kr:${GATEWAY_IP:-172.16.163.96}"
environment:
# 프록시 비활성화 (명시적)
HTTP_PROXY: ""
HTTPS_PROXY: ""
http_proxy: ""
https_proxy: ""
# Python 출력 버퍼링 비활성화 (실시간 로그)
PYTHONUNBUFFERED: "1"
# 모델 게이트웨이 공통 인증/TLS
MODEL_API_KEY: "${MODEL_API_KEY:-}"
MODEL_VERIFY_SSL: "${MODEL_VERIFY_SSL:-false}"
# LLM API (게이트웨이)
LLM_BASE_URL: "${LLM_BASE_URL:-https://llm-ai.ex.co.kr}"
LLM_MODEL_NAME: "${LLM_MODEL_NAME:-Qwen/Qwen3.6-27B-FP8}"
LLM_API_KEY: "${LLM_API_KEY:-}"
# 임베딩 / 리랭커 (게이트웨이)
TEI_EMBED_URL: "${TEI_EMBED_URL:-https://embedding-ai.ex.co.kr}"
EMBED_MODEL_NAME: "${EMBED_MODEL_NAME:-Qwen/Qwen3-Embedding-8B}"
TEI_RERANK_URL: "${TEI_RERANK_URL:-https://reranker-ai.ex.co.kr}"
TEI_RERANK_MODEL: "${TEI_RERANK_MODEL:-Qwen/Qwen3-Reranker-8B}"
EMBED_API_STYLE: "${EMBED_API_STYLE:-openai}"
RERANK_API_STYLE: "${RERANK_API_STYLE:-gateway}"
API_TIMEOUT: "${API_TIMEOUT:-60}"
# Agent tool loop → chatbotApi (WAS 동일 서버)
AGENT_MODE: "${AGENT_MODE:-legacy}"
AGENT_MAX_ROUNDS: "${AGENT_MAX_ROUNDS:-6}"
CHATBOT_API_BASE_URL: "${CHATBOT_API_BASE_URL:-http://127.0.0.1:8086/api}"
INTERNAL_TOOL_API_KEY: "${INTERNAL_TOOL_API_KEY:-}"
CHATBOT_TOOL_TIMEOUT: "${CHATBOT_TOOL_TIMEOUT:-30}"
# MongoDB (로컬 호스트 - 데이터베이스별 인증)
MONGO_HOST: "${MONGO_HOST:-127.0.0.1}"
MONGO_PORT: "${MONGO_PORT:-27017}"
MONGO_USER: "${MONGO_USER:-exlink}"
MONGO_PASSWORD: "${MONGO_PASSWORD:-!wkcproqkf1}"
MONGO_DATABASE: "${MONGO_DATABASE:-chat_history}"
MONGO_COLLECTION: "${MONGO_COLLECTION:-rag_conversations}"
# 벡터 DB
VECTOR_STORE: "${VECTOR_STORE:-qdrant}"
QDRANT_HOST: "${QDRANT_HOST:-127.0.0.1}"
QDRANT_PORT: "${QDRANT_PORT:-6333}"
QDRANT_COLLECTION: "${QDRANT_COLLECTION:-qa_vectors}"
HYBRID_SEARCH_ENABLED: "${HYBRID_SEARCH_ENABLED:-false}"
SPARSE_SEARCH_ENABLED: "${SPARSE_SEARCH_ENABLED:-true}"
SPARSE_TOP_K: "${SPARSE_TOP_K:-30}"
HYBRID_MERGE_TOP_K: "${HYBRID_MERGE_TOP_K:-40}"
# 성능 튜닝
FAISS_TOP_K: "${FAISS_TOP_K:-30}"
FAISS_THRESHOLD: "${FAISS_THRESHOLD:-0.55}"
FAISS_THRESHOLD_REWRITE: "${FAISS_THRESHOLD_REWRITE:-0.50}"
RERANK_CANDIDATES: "${RERANK_CANDIDATES:-20}"
RERANK_BATCH_SIZE: "${RERANK_BATCH_SIZE:-16}"
LOW_CONFIDENCE_THRESHOLD: "${LOW_CONFIDENCE_THRESHOLD:-0.65}"
HIGH_CONFIDENCE_THRESHOLD: "${HIGH_CONFIDENCE_THRESHOLD:-0.75}"
TOP_N_FOR_LLM: "${TOP_N_FOR_LLM:-5}"
LLM_MAX_TOKENS: "${LLM_MAX_TOKENS:-2048}"
QUERY_REWRITE_ENABLED: "${QUERY_REWRITE_ENABLED:-true}"
CHAT_HISTORY_LIMIT: "${CHAT_HISTORY_LIMIT:-10}"
CHAT_HISTORY_HOURS: "${CHAT_HISTORY_HOURS:-24}"
CHAT_HISTORY_ALWAYS_INCLUDE: "${CHAT_HISTORY_ALWAYS_INCLUDE:-true}"
# 프록시 우회 (내부 IP 직접 연결 + 게이트웨이 도메인)
NO_PROXY: "${NO_PROXY:-localhost,127.0.0.1,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8,.ex.co.kr}"
no_proxy: "${no_proxy:-localhost,127.0.0.1,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8,.ex.co.kr}"
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: unless-stopped
# Qdrant 벡터 DB (기본 벡터 스토어)
# ※ profiles 제거 → 별도 플래그 없이 항상 기동
qdrant:
image: qdrant/qdrant:v1.18.2 # 폐쇄망에 docker load 한 이미지 태그와 반드시 일치시킬 것
ports:
- "6333:6333" # REST / gRPC
- "6334:6334" # gRPC (선택)
volumes:
- ./qdrant_data:/qdrant/storage # 벡터 영속 저장 (컨테이너 재시작에도 유지)
restart: unless-stopped
# 4) 큐레이션 어드민 (벡터DB 검색/조회/삭제/추가 웹 UI)
# 실시간 api와 같은 이미지/모듈을 재사용하되 별도 프로세스로 분리
admin:
image: "${RAG_API_IMAGE:-rag-api-slim:latest}"
network_mode: host
command:
- python
- -m
- uvicorn
- scripts.admin_service:app
- --host
- 0.0.0.0
- --port
- "${ADMIN_PORT:-28013}"
working_dir: /app
depends_on:
- qdrant
# 모델 게이트웨이 호스트명 → IP 매핑 (어드민도 임베딩 호출)
extra_hosts:
- "embedding-ai.ex.co.kr:${GATEWAY_IP:-172.16.163.96}"
- "reranker-ai.ex.co.kr:${GATEWAY_IP:-172.16.163.96}"
- "llm-ai.ex.co.kr:${GATEWAY_IP:-172.16.163.96}"
environment:
HTTP_PROXY: ""
HTTPS_PROXY: ""
http_proxy: ""
https_proxy: ""
PYTHONUNBUFFERED: "1"
# 임베딩(게이트웨이) — 어드민 검색/추가 시 사용
TEI_EMBED_URL: "${TEI_EMBED_URL:-https://embedding-ai.ex.co.kr}"
EMBED_MODEL_NAME: "${EMBED_MODEL_NAME:-Qwen/Qwen3-Embedding-8B}"
MODEL_API_KEY: "${MODEL_API_KEY:-}"
MODEL_VERIFY_SSL: "${MODEL_VERIFY_SSL:-false}"
API_TIMEOUT: "${API_TIMEOUT:-60}"
VECTOR_STORE: "${VECTOR_STORE:-qdrant}"
QDRANT_HOST: "${QDRANT_HOST:-127.0.0.1}"
QDRANT_PORT: "${QDRANT_PORT:-6333}"
QDRANT_COLLECTION: "${QDRANT_COLLECTION:-qa_vectors}"
HYBRID_SEARCH_ENABLED: "${HYBRID_SEARCH_ENABLED:-false}"
SPARSE_SEARCH_ENABLED: "${SPARSE_SEARCH_ENABLED:-true}"
SPARSE_TOP_K: "${SPARSE_TOP_K:-30}"
HYBRID_MERGE_TOP_K: "${HYBRID_MERGE_TOP_K:-40}"
ADMIN_CORS_ORIGINS: "${ADMIN_CORS_ORIGINS:-*}" # 별도 프론트 origin 제한 시 콤마 구분으로 지정
NO_PROXY: "${NO_PROXY:-localhost,127.0.0.1,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8,.ex.co.kr}"
no_proxy: "${no_proxy:-localhost,127.0.0.1,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8,.ex.co.kr}"
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: unless-stopped