# Local GPU inference stack — 10.11.10.18 (2x H200 NVL) # GPU 0: Qwen3.5-35B-A3B (LLM) + Whisper (audio) # GPU 1: BusterX++ (deepfake video) + bge-m3 (embeddings) + bge-reranker-v2-m3 (rerank) # All services on the shared `didi-network` so the dashboard can probe them by name. networks: didi-network: external: true services: # ===================== vLLM model servers ===================== # BusterX++ — served OFFLINE from the on-disk HF cache (no download) vllm-buster: container_name: didiAI-video-vllm-buster # qwen3_5 image (vLLM 0.16 / transformers 4.57) — BusterX++ config was saved # with transformers 5.x and the older 0.8.5 image can't parse its nested text_config. image: vllm/vllm-openai:qwen3_5 networks: [didi-network] ports: ["54500:54500"] volumes: - ${MODELS_DIR}:/root/.cache/huggingface/hub:ro environment: - HF_HOME=/root/.cache/huggingface - HF_HUB_OFFLINE=1 - TRANSFORMERS_OFFLINE=1 command: > --model l8cv/BusterX_plusplus --host 0.0.0.0 --port 54500 --served-model-name busterx --tensor-parallel-size 1 --max-model-len 32768 --gpu-memory-utilization 0.25 --trust-remote-code --enable-prefix-caching --disable-log-requests deploy: resources: reservations: devices: - driver: nvidia device_ids: ['1'] capabilities: [gpu] restart: unless-stopped # Qwen3.5-35B-A3B — downloads ~72GB on first start vllm-qwen: container_name: didiAI-vllm-qwen3.5 image: vllm/vllm-openai:qwen3_5 networks: [didi-network] ports: ["14001:14001"] volumes: - ${MODELS_DIR}:/root/.cache/huggingface/hub:ro environment: - HF_HOME=/root/.cache/huggingface - HF_HUB_OFFLINE=1 - TRANSFORMERS_OFFLINE=1 - VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 command: > --model Qwen/Qwen3.5-35B-A3B --host 0.0.0.0 --port 14001 --served-model-name qwen3.5 --tensor-parallel-size 1 --max-model-len 32000 --gpu-memory-utilization 0.65 --trust-remote-code --disable-log-requests deploy: resources: reservations: devices: - driver: nvidia device_ids: ['0'] capabilities: [gpu] restart: unless-stopped # bge-m3 embeddings — downloads ~2GB on first start vllm-embeddings: container_name: didiAI-vllm-embeddings image: vllm/vllm-openai:v0.8.5 networks: [didi-network] ports: ["14101:14101"] volumes: - ${MODELS_DIR}:/root/.cache/huggingface/hub:ro environment: - HF_HOME=/root/.cache/huggingface - HF_HUB_OFFLINE=1 - TRANSFORMERS_OFFLINE=1 command: > --model BAAI/bge-m3 --host 0.0.0.0 --port 14101 --served-model-name bge-m3 --task embed --gpu-memory-utilization 0.10 --trust-remote-code --disable-log-requests deploy: resources: reservations: devices: - driver: nvidia device_ids: ['1'] capabilities: [gpu] restart: unless-stopped # bge-reranker-v2-m3 — downloads ~2GB on first start vllm-rerank: container_name: didiAI-vllm-rerank image: vllm/vllm-openai:v0.8.5 networks: [didi-network] ports: ["14201:14201"] volumes: - ${MODELS_DIR}:/root/.cache/huggingface/hub:ro environment: - HF_HOME=/root/.cache/huggingface - HF_HUB_OFFLINE=1 - TRANSFORMERS_OFFLINE=1 command: > --model BAAI/bge-reranker-v2-m3 --host 0.0.0.0 --port 14201 --served-model-name bge-reranker-v2-m3 --task score --gpu-memory-utilization 0.10 --trust-remote-code --disable-log-requests deploy: resources: reservations: devices: - driver: nvidia device_ids: ['1'] capabilities: [gpu] restart: unless-stopped # ===================== FastAPI app wrappers ===================== llm-api: container_name: didiAI-llm-api image: didiai-llm-inference:audit networks: [didi-network] ports: ["14011:14011"] environment: - LLM_HOST=0.0.0.0 - LLM_PORT=14011 - LLM_DEFAULT_BACKEND=vllm - LLM_ENABLE_VLLM=true - LLM_ENABLE_LLAMACPP=false - LLM_VLLM_BASE_URL=http://didiAI-vllm-qwen3.5:14001 - LLM_DEFAULT_MODEL=qwen3.5 - LLM_EXTERNAL_URL=http://${HOST_IP}:14011 restart: unless-stopped embeddings-api: container_name: didiAI-embeddings-api image: didiai-embeddings:audit networks: [didi-network] ports: ["14100:14100"] environment: - EMB_HOST=0.0.0.0 - EMB_PORT=14100 - EMB_DEFAULT_BACKEND=vllm - EMB_ENABLE_VLLM=true - EMB_ENABLE_LLAMACPP=false - EMB_VLLM_BASE_URL=http://didiAI-vllm-embeddings:14101 - EMB_VLLM_MODEL=bge-m3 - EMB_EXTERNAL_URL=http://${HOST_IP}:14100 restart: unless-stopped rerank-api: container_name: didiAI-rerank-api image: didiai-rerank:audit networks: [didi-network] ports: ["14200:14200"] environment: - RERANK_HOST=0.0.0.0 - RERANK_PORT=14200 - RERANK_DEFAULT_BACKEND=vllm - RERANK_ENABLE_VLLM=true - RERANK_ENABLE_LLAMACPP=false - RERANK_VLLM_BASE_URL=http://didiAI-vllm-rerank:14201 - RERANK_VLLM_MODEL=bge-reranker-v2-m3 - RERANK_EXTERNAL_URL=http://${HOST_IP}:14200 restart: unless-stopped video-api: container_name: didiAI-video-api image: didiai-video-analysis:audit networks: [didi-network] ports: ["54600:54600"] volumes: - ./runs:/app/runs environment: - VIDEO_ANALYSIS_HOST=0.0.0.0 - VIDEO_ANALYSIS_PORT=54600 - VIDEO_ANALYSIS_EXTERNAL_URL=http://${HOST_IP}:54600 - VIDEO_ANALYSIS_VLLM_BASE_URL=http://didiAI-video-vllm-buster:54500 - VIDEO_ANALYSIS_VLLM_MODEL=busterx - VIDEO_ANALYSIS_RUNS_DIR=/app/runs - VIDEO_ANALYSIS_SEMANTIC_LLM_BASE_URL=http://didiAI-llm-api:14011 - VIDEO_ANALYSIS_SEMANTIC_AGGREGATION_MODEL=qwen3.5 - VIDEO_ANALYSIS_SEMANTIC_LLM_API_KEY=none restart: unless-stopped # ===================== Non-GPU services ===================== catalog-api: container_name: didiAI-catalog-api image: didiai-catalog-api:audit networks: [didi-network] environment: - CATALOG_HOST=0.0.0.0 - CATALOG_PORT=11000 - CATALOG_EXTERNAL_URL=http://${HOST_IP} - CATALOG_LLM_URL=http://didiAI-llm-api:14011 - CATALOG_AUDIO_URL=http://didiAI-audio:54300 - CATALOG_VIDEO_URL=http://didiAI-video-api:54600 - CATALOG_WEB_URL=http://didiAI-web-api:51100 restart: unless-stopped extractors: container_name: didiAI-extractors image: didiai-extractors:audit networks: [didi-network] ports: ["54400:54400"] volumes: # GLiNER (+ backbone mdeberta) servit offline din zona locala de modele - ${MODELS_DIR}:/models-hf/hub:ro environment: - EXTRACTORS_HOST=0.0.0.0 - EXTRACTORS_PORT=54400 - EXTRACTORS_LLM_GATEWAY_URL=http://didiAI-llm-api:14011 - EXTRACTORS_DETECT_MODEL=/tmp/yolov8n.pt - YOLO_CONFIG_DIR=/tmp/ultralytics - HF_HOME=/models-hf - HF_HUB_OFFLINE=1 - TRANSFORMERS_OFFLINE=1 restart: unless-stopped forensic: container_name: didiAI-forensic image: didiai-forensic:audit networks: [didi-network] ports: ["8085:8080"] environment: - API_PORT=8080 restart: unless-stopped # cloak — scraper SERP stealth (tier-3 fallback pentru web) cloak: container_name: didiAI-cloak image: didiai-cloak:audit networks: [didi-network] ports: ["8770:8770"] environment: - CLOAK_HOST=0.0.0.0 - CLOAK_PORT=8770 restart: unless-stopped # SearXNG metasearch (motorul de cautare liber folosit de web-api) searxng: container_name: didiAI-web-searxng image: docker.io/searxng/searxng:latest networks: [didi-network] volumes: - ../../modules/web/deploy/metasearch/searxng:/etc/searxng:ro environment: - SEARXNG_BASE_URL=http://${HOST_IP}:8080/ restart: unless-stopped web-api: container_name: didiAI-web-api image: didiai-web:audit networks: [didi-network] ports: ["51100:51100"] depends_on: [searxng] environment: - WEB_HOST=0.0.0.0 - WEB_PORT=51100 - WEB_EXTERNAL_URL=http://${HOST_IP}:51100 - WEB_SEARXNG_BASE_URL=http://didiAI-web-searxng:8080 - WEB_LLM_BASE_URL=http://didiAI-llm-api:14011 restart: unless-stopped # Whisper STT — faster-whisper loads in-process on GPU 0 audio-api: container_name: didiAI-audio image: didiai-audio:audit networks: [didi-network] ports: ["54300:54300"] volumes: # faster-whisper foloseste download_root=cache_dir -> models-- direct sub el (nu /hub) - ${MODELS_DIR}:/root/.cache/huggingface:ro environment: - AUDIO_HOST=0.0.0.0 - AUDIO_PORT=54300 - AUDIO_MODEL=large-v3-turbo - AUDIO_DEVICE=cuda - AUDIO_COMPUTE_TYPE=float16 - AUDIO_CACHE_DIR=/root/.cache/huggingface - HF_HUB_OFFLINE=1 - TRANSFORMERS_OFFLINE=1 - AUDIO_EXTERNAL_URL=http://${HOST_IP}:54300 deploy: resources: reservations: devices: - driver: nvidia device_ids: ['0'] capabilities: [gpu] restart: unless-stopped