From a3e24adbe434312d9df76deffdd9297326c14863 Mon Sep 17 00:00:00 2001 From: Mikhail Limarenko Date: Sun, 28 Dec 2025 05:33:00 +0300 Subject: [PATCH] Add Makefile for quick deployment --- Makefile | 60 + docs/DockerDeployment.md | 56 + docs/InteractiveSetup.md | 51 + env.example | 30 +- scripts/setup/lib/file_ops.sh | 144 +++ scripts/setup/lib/presets.sh | 32 + scripts/setup/lib/prompts.sh | 76 ++ scripts/setup/lib/storage_requirements.sh | 72 ++ scripts/setup/lib/validation.sh | 156 +++ scripts/setup/presets/development.sh | 14 + scripts/setup/presets/local.sh | 14 + scripts/setup/presets/production.sh | 14 + scripts/setup/setup.sh | 1218 +++++++++++++++++++ scripts/setup/templates/memgraph.yml | 7 + scripts/setup/templates/milvus.yml | 43 + scripts/setup/templates/mongodb.yml | 7 + scripts/setup/templates/neo4j.yml | 11 + scripts/setup/templates/postgres.yml | 11 + scripts/setup/templates/qdrant.yml | 7 + scripts/setup/templates/redis.yml | 7 + scripts/setup/templates/vllm-rerank-gpu.yml | 16 + scripts/setup/templates/vllm-rerank.yml | 12 + 22 files changed, 2057 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 docs/InteractiveSetup.md create mode 100644 scripts/setup/lib/file_ops.sh create mode 100644 scripts/setup/lib/presets.sh create mode 100644 scripts/setup/lib/prompts.sh create mode 100644 scripts/setup/lib/storage_requirements.sh create mode 100644 scripts/setup/lib/validation.sh create mode 100644 scripts/setup/presets/development.sh create mode 100644 scripts/setup/presets/local.sh create mode 100644 scripts/setup/presets/production.sh create mode 100644 scripts/setup/setup.sh create mode 100644 scripts/setup/templates/memgraph.yml create mode 100644 scripts/setup/templates/milvus.yml create mode 100644 scripts/setup/templates/mongodb.yml create mode 100644 scripts/setup/templates/neo4j.yml create mode 100644 scripts/setup/templates/postgres.yml create mode 100644 scripts/setup/templates/qdrant.yml create mode 100644 scripts/setup/templates/redis.yml create mode 100644 scripts/setup/templates/vllm-rerank-gpu.yml create mode 100644 scripts/setup/templates/vllm-rerank.yml diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..0361b9fe61 --- /dev/null +++ b/Makefile @@ -0,0 +1,60 @@ +SHELL := /bin/bash +SETUP_SCRIPT := scripts/setup/setup.sh +SETUP_OPTS ?= +COLOR_RESET := \033[0m +COLOR_BOLD := \033[1m +COLOR_BLUE := \033[34m +COLOR_GREEN := \033[32m +COLOR_YELLOW := \033[33m + +ifeq ($(NO_COLOR),1) +COLOR_RESET := +COLOR_BOLD := +COLOR_BLUE := +COLOR_GREEN := +COLOR_YELLOW := +endif + +.PHONY: help setup configure setup-quick setup-production setup-validate setup-backup setup-help + +help: + @printf "$(COLOR_BOLD)Interactive setup targets$(COLOR_RESET)\n" + @printf " $(COLOR_GREEN)make setup$(COLOR_RESET) Full wizard (development/production/custom)\n" + @printf " $(COLOR_GREEN)make setup-quick$(COLOR_RESET) Development preset, minimal prompts\n" + @printf " $(COLOR_GREEN)make setup-production$(COLOR_RESET) Production preset + SSL/security prompts\n" + @printf " $(COLOR_GREEN)make setup-validate$(COLOR_RESET) Validate existing .env\n" + @printf " $(COLOR_GREEN)make setup-backup$(COLOR_RESET) Backup current .env\n" + @printf " $(COLOR_GREEN)make setup-help$(COLOR_RESET) Script help and options\n\n" + @printf "$(COLOR_BOLD)Install types$(COLOR_RESET)\n" + @printf " $(COLOR_BLUE)development$(COLOR_RESET): local JSON/NetworkX defaults, fastest to start\n" + @printf " $(COLOR_BLUE)production$(COLOR_RESET): database-backed defaults, security prompts, docker services optional\n" + @printf " $(COLOR_BLUE)custom$(COLOR_RESET): pick each storage backend manually\n\n" + @printf "$(COLOR_BOLD)Examples$(COLOR_RESET)\n" + @printf " make setup\n" + @printf " make setup-quick\n" + @printf " make setup-production SETUP_OPTS=--debug\n\n" + @printf "$(COLOR_BOLD)Image tags$(COLOR_RESET)\n" + @printf " Wizard will show image tags for selected services and let you override them.\n" + @printf " You can also edit POSTGRES_IMAGE_TAG, NEO4J_IMAGE_TAG, etc. in .env.\n" + @printf " Compose file output: docker-compose..yml\n" + +setup: + @bash $(SETUP_SCRIPT) $(SETUP_OPTS) + +configure: + @bash $(SETUP_SCRIPT) $(SETUP_OPTS) + +setup-quick: + @bash $(SETUP_SCRIPT) --quick $(SETUP_OPTS) + +setup-production: + @bash $(SETUP_SCRIPT) --production $(SETUP_OPTS) + +setup-validate: + @bash $(SETUP_SCRIPT) --validate $(SETUP_OPTS) + +setup-backup: + @bash $(SETUP_SCRIPT) --backup $(SETUP_OPTS) + +setup-help: + @bash $(SETUP_SCRIPT) --help $(SETUP_OPTS) diff --git a/docs/DockerDeployment.md b/docs/DockerDeployment.md index 575359b4ed..4a4f81c4b6 100644 --- a/docs/DockerDeployment.md +++ b/docs/DockerDeployment.md @@ -74,6 +74,12 @@ The Dockerfile uses BuildKit cache mounts to significantly improve build perform docker compose up -d ``` +If you used the interactive setup, start the generated stack with: + +```bash +docker compose -f docker-compose.development.yml up -d +``` + LightRAG Server uses the following paths for data storage: ``` @@ -82,6 +88,56 @@ data/ └── inputs/ # Input documents ``` +### Optional: local vLLM reranker + +To enable local reranking with vLLM, run a vLLM container exposing the Cohere-compatible rerank endpoint and point LightRAG to it. +You can select `vllm` in the interactive setup to add the `vllm-rerank` service automatically. +vLLM provides a `v1/rerank` endpoint that works with the `cohere` binding. + +Example `docker-compose.override.yml`: + +```yaml +services: + vllm-rerank: + image: vllm/vllm-openai:latest + command: > + --model BAAI/bge-reranker-v2-m3 + --port 8000 + --dtype float16 + ports: + - "8000:8000" + volumes: + - ./data/hf-cache:/root/.cache/huggingface + runtime: nvidia +``` + +Add the rerank config to `.env`: + +```bash +RERANK_BINDING=cohere +RERANK_MODEL=BAAI/bge-reranker-v2-m3 +RERANK_BINDING_HOST=http://vllm-rerank:8000/v1/rerank +RERANK_BINDING_API_KEY=local-key +VLLM_RERANK_DEVICE=cpu +VLLM_RERANK_DTYPE=float32 +``` + +If you run vLLM on the host instead of Docker, use: + +```bash +RERANK_BINDING_HOST=http://host.docker.internal:8000/v1/rerank +``` + +For GPU, set: + +```bash +VLLM_RERANK_DEVICE=cuda +VLLM_RERANK_DTYPE=float16 +``` + +Ensure the NVIDIA Container Toolkit is installed and the host has CUDA drivers available. +The default vLLM image is GPU-only; CPU setups require a CPU-compatible image tag. + ### Updates To update the Docker container: diff --git a/docs/InteractiveSetup.md b/docs/InteractiveSetup.md new file mode 100644 index 0000000000..a1a6de0c89 --- /dev/null +++ b/docs/InteractiveSetup.md @@ -0,0 +1,51 @@ +# Interactive Setup (Make Targets) + +Use the Make targets below to configure and deploy LightRAG with an interactive wizard. + +## Targets + +- `make setup`: Full wizard. Choose development/production/custom and all backends. +- `make setup-quick`: Development preset, minimal prompts (API keys only). +- `make setup-production`: Production preset with security and SSL prompts. +- `make setup-validate`: Validate current `.env`. +- `make setup-backup`: Backup current `.env`. +- `make setup-help`: Show CLI help. + +## Install Types + +- **development**: Local JSON/NetworkX defaults. Quickest start. +- **production**: Database-backed defaults with security prompts. +- **custom**: Manual selection of each storage backend. + +## Compose Output + +The wizard writes a dedicated compose file to avoid overwriting `docker-compose.yml`: + +- `docker-compose.development.yml` +- `docker-compose.production.yml` +- `docker-compose.custom.yml` + +You can let the wizard start the services immediately after generation. + +## Image Tags + +The wizard lists Docker image tags for selected services and lets you override them. +You can also edit these in `.env`: + +- `POSTGRES_IMAGE_TAG` +- `NEO4J_IMAGE_TAG` +- `MONGODB_IMAGE_TAG` +- `REDIS_IMAGE_TAG` +- `MILVUS_IMAGE_TAG` +- `QDRANT_IMAGE_TAG` +- `MEMGRAPH_IMAGE_TAG` +- `VLLM_RERANK_IMAGE_TAG` + +## Tips + +- Add `SETUP_OPTS=--debug` to `make` for debug logging. +- Use `SETUP_WAIT_TIMEOUT=120` to increase the startup wait for dependent services. +- Set `NO_COLOR=1` to disable colored output. +- Choose `vllm` in the rerank prompt to add a local vLLM reranker service to `docker-compose.yml`. +- For GPU setups, set `VLLM_RERANK_DEVICE=cuda` and `VLLM_RERANK_DTYPE=float16` (requires NVIDIA Container Toolkit). +- CPU-only vLLM requires a CPU-compatible image tag (the default image is GPU-only). diff --git a/env.example b/env.example index 894e7e85c4..618269bf10 100644 --- a/env.example +++ b/env.example @@ -40,6 +40,20 @@ OLLAMA_EMULATING_MODEL_TAG=latest ### Logfile location (defaults to current working directory) # LOG_DIR=/path/to/log/directory +############################ +### Docker Image Tag Overrides +############################ +# POSTGRES_IMAGE_TAG=18 +# NEO4J_IMAGE_TAG=5.26.19-community +# MONGODB_IMAGE_TAG=8.2.3 +# REDIS_IMAGE_TAG=8.4 +# MILVUS_IMAGE_TAG=2.6-20251227-44275071 +# ETCD_IMAGE_TAG=v3.5.16 +# MINIO_IMAGE_TAG=RELEASE.2024-12-13T22-19-12Z +# QDRANT_IMAGE_TAG=v1.16-gpu-nvidia +# MEMGRAPH_IMAGE_TAG=3.7.2 +# VLLM_RERANK_IMAGE_TAG=latest + ##################################### ### Login and API-Key Configuration ##################################### @@ -114,6 +128,18 @@ RERANK_BINDING=null # RERANK_MODEL=BAAI/bge-reranker-v2-m3 # RERANK_BINDING_HOST=http://localhost:8000/v1/rerank # RERANK_BINDING_API_KEY=your_rerank_api_key_here +# VLLM_RERANK_MODEL=BAAI/bge-reranker-v2-m3 +# VLLM_RERANK_PORT=8000 +# VLLM_RERANK_DEVICE=cuda +# VLLM_RERANK_DTYPE=float16 +# # Use float16 for GPU mode. CPU-only requires a CPU-compatible vLLM image. +# VLLM_USE_CPU=1 +# # Set to 1 for CPU mode, unset for GPU mode +# CUDA_VISIBLE_DEVICES=-1 +# # Set to -1 to disable CUDA (CPU mode), or specific GPU IDs for GPU mode +# VLLM_RERANK_EXTRA_ARGS= +# Note: vLLM typically requires GPU. For CPU-only, you may need a CPU-compatible build. +# If you have GPU, remove VLLM_USE_CPU and CUDA_VISIBLE_DEVICES, set VLLM_RERANK_DTYPE=float16. ### Default value for Cohere AI # RERANK_MODEL=rerank-v3.5 @@ -450,10 +476,12 @@ MONGO_DATABASE=LightRAG ### Milvus Configuration MILVUS_URI=http://localhost:19530 -MILVUS_DB_NAME=lightrag +MILVUS_DB_NAME=default # MILVUS_USER=root # MILVUS_PASSWORD=your_password # MILVUS_TOKEN=your_token +# MINIO_ACCESS_KEY_ID=minioadmin +# MINIO_SECRET_ACCESS_KEY=minioadmin ### DB specific workspace should not be set, keep for compatible only ### MILVUS_WORKSPACE=forced_workspace_name diff --git a/scripts/setup/lib/file_ops.sh b/scripts/setup/lib/file_ops.sh new file mode 100644 index 0000000000..abc34c8620 --- /dev/null +++ b/scripts/setup/lib/file_ops.sh @@ -0,0 +1,144 @@ +# File operations for interactive setup. + +format_env_value() { + local value="$1" + local escaped + + if [[ -z "$value" ]]; then + printf '' + return + fi + + if [[ "$value" =~ [[:space:]] || "$value" == *"\""* || "$value" == *"$"* ]]; then + escaped="${value//\\/\\\\}" + escaped="${escaped//\"/\\\"}" + printf '"%s"' "$escaped" + return + fi + + printf '%s' "$value" +} + +backup_env_file() { + local env_file="${1:-${REPO_ROOT:-.}/.env}" + local backup_file="" + + if [[ -f "$env_file" ]]; then + backup_file="${env_file}.backup.$(date +%Y%m%d_%H%M%S)" + cp "$env_file" "$backup_file" + printf '%s' "$backup_file" + fi +} + +generate_env_file() { + local template_file="${1:-${REPO_ROOT:-.}/env.example}" + local output_file="${2:-${REPO_ROOT:-.}/.env}" + local tmp_file="${output_file}.tmp" + local line key value + local -A written_keys=() + + if [[ ! -f "$template_file" ]]; then + echo "env.example not found at $template_file" >&2 + return 1 + fi + + : > "$tmp_file" + + while IFS= read -r line || [[ -n "$line" ]]; do + if [[ "$line" =~ ^[A-Z0-9_]+= ]]; then + key="${line%%=*}" + if [[ -z "${written_keys[$key]+set}" ]]; then + if [[ -n "${ENV_VALUES[$key]+set}" ]]; then + value="${ENV_VALUES[$key]}" + printf '%s=%s\n' "$key" "$(format_env_value "$value")" >> "$tmp_file" + else + printf '%s\n' "$line" >> "$tmp_file" + fi + written_keys["$key"]=1 + else + printf '%s\n' "$line" >> "$tmp_file" + fi + elif [[ "$line" =~ ^#[[:space:]]*([A-Z0-9_]+)= ]]; then + key="${BASH_REMATCH[1]}" + if [[ -z "${written_keys[$key]+set}" && -n "${ENV_VALUES[$key]+set}" ]]; then + value="${ENV_VALUES[$key]}" + printf '%s=%s\n' "$key" "$(format_env_value "$value")" >> "$tmp_file" + written_keys["$key"]=1 + else + printf '%s\n' "$line" >> "$tmp_file" + fi + else + printf '%s\n' "$line" >> "$tmp_file" + fi + done < "$template_file" + + mv "$tmp_file" "$output_file" +} + +generate_docker_compose() { + local output_file="${1:-${REPO_ROOT:-.}/docker-compose.yml}" + local base_file="${REPO_ROOT:-.}/docker-compose.yml" + local tmp_file="${output_file}.tmp" + local template_file + local volume_names=() + + if [[ -f "$base_file" ]]; then + cp "$base_file" "$tmp_file" + else + printf 'services:\n' > "$tmp_file" + fi + + for service in "${DOCKER_SERVICES[@]}"; do + template_file="$TEMPLATES_DIR/${service}.yml" + if [[ "$service" == "vllm-rerank" ]]; then + if [[ "${ENV_VALUES[VLLM_RERANK_DEVICE]:-cpu}" == "cuda" ]]; then + if [[ -f "$TEMPLATES_DIR/${service}-gpu.yml" ]]; then + template_file="$TEMPLATES_DIR/${service}-gpu.yml" + fi + fi + fi + if [[ ! -f "$template_file" ]]; then + format_error "Missing docker template: $template_file" "Reinstall the setup scripts." + return 1 + fi + + printf '\n' >> "$tmp_file" + cat "$template_file" >> "$tmp_file" + + case "$service" in + postgres) + volume_names+=("postgres_data") + ;; + neo4j) + volume_names+=("neo4j_data") + ;; + mongodb) + volume_names+=("mongo_data") + ;; + redis) + volume_names+=("redis_data") + ;; + milvus) + volume_names+=("milvus_data" "etcd_data" "minio_data") + ;; + qdrant) + volume_names+=("qdrant_data") + ;; + memgraph) + volume_names+=("memgraph_data") + ;; + vllm-rerank) + volume_names+=("vllm_rerank_cache") + ;; + esac + done + + if ((${#volume_names[@]} > 0)); then + printf '\nvolumes:\n' >> "$tmp_file" + for volume in "${volume_names[@]}"; do + printf ' %s:\n' "$volume" >> "$tmp_file" + done + fi + + mv "$tmp_file" "$output_file" +} diff --git a/scripts/setup/lib/presets.sh b/scripts/setup/lib/presets.sh new file mode 100644 index 0000000000..f73cb71d8a --- /dev/null +++ b/scripts/setup/lib/presets.sh @@ -0,0 +1,32 @@ +# Preset loading helpers. +# shellcheck disable=SC2034 + +apply_preset() { + local entry key value + + for entry in "$@"; do + key="${entry%%=*}" + value="${entry#*=}" + ENV_VALUES["$key"]="$value" + done +} + +load_preset() { + local preset_name="$1" + + case "$preset_name" in + development) + apply_preset "${PRESET_DEVELOPMENT[@]}" + ;; + production) + apply_preset "${PRESET_PRODUCTION[@]}" + ;; + local) + apply_preset "${PRESET_LOCAL[@]}" + ;; + *) + echo "Unknown preset: $preset_name" >&2 + return 1 + ;; + esac +} diff --git a/scripts/setup/lib/prompts.sh b/scripts/setup/lib/prompts.sh new file mode 100644 index 0000000000..be9a4646be --- /dev/null +++ b/scripts/setup/lib/prompts.sh @@ -0,0 +1,76 @@ +# Prompt helpers for interactive setup. + +mask_sensitive_input() { + local prompt="$1" + local value + + read -r -s -p "$prompt" value + echo >&2 + printf '%s' "$value" +} + +prompt_with_default() { + local prompt="$1" + local default="$2" + local value + + if [[ -n "$default" ]]; then + read -r -p "$prompt [$default]: " value + else + read -r -p "$prompt: " value + fi + + if [[ -z "$value" ]]; then + value="$default" + fi + + printf '%s' "$value" +} + +confirm() { + local prompt="$1" + local response + + read -r -p "$prompt [y/N]: " response + case "${response,,}" in + y|yes) + return 0 + ;; + *) + return 1 + ;; + esac +} + +prompt_until_valid() { + local prompt="$1" + local default="$2" + local validator="$3" + shift 3 + local value + + while true; do + value="$(prompt_with_default "$prompt" "$default")" + if "$validator" "$value" "$@"; then + printf '%s' "$value" + return 0 + fi + echo "Invalid value. Please try again." + done +} + +prompt_secret_until_valid() { + local prompt="$1" + local validator="$2" + shift 2 + local value + + while true; do + value="$(mask_sensitive_input "$prompt")" + if "$validator" "$value" "$@"; then + printf '%s' "$value" + return 0 + fi + echo "Invalid value. Please try again." + done +} diff --git a/scripts/setup/lib/storage_requirements.sh b/scripts/setup/lib/storage_requirements.sh new file mode 100644 index 0000000000..e76a329210 --- /dev/null +++ b/scripts/setup/lib/storage_requirements.sh @@ -0,0 +1,72 @@ +# Storage backend options and required environment variables. +# shellcheck disable=SC2034 + +declare -ag KV_STORAGE_OPTIONS=( + "JsonKVStorage" + "RedisKVStorage" + "PGKVStorage" + "MongoKVStorage" +) + +declare -ag GRAPH_STORAGE_OPTIONS=( + "NetworkXStorage" + "Neo4JStorage" + "PGGraphStorage" + "MongoGraphStorage" + "MemgraphStorage" +) + +declare -ag VECTOR_STORAGE_OPTIONS=( + "NanoVectorDBStorage" + "MilvusVectorDBStorage" + "PGVectorStorage" + "FaissVectorDBStorage" + "QdrantVectorDBStorage" + "MongoVectorDBStorage" +) + +declare -ag DOC_STATUS_STORAGE_OPTIONS=( + "JsonDocStatusStorage" + "RedisDocStatusStorage" + "PGDocStatusStorage" + "MongoDocStatusStorage" +) + +declare -Ag STORAGE_ENV_REQUIREMENTS=( + ["JsonKVStorage"]="" + ["MongoKVStorage"]="MONGO_URI MONGO_DATABASE" + ["RedisKVStorage"]="REDIS_URI" + ["PGKVStorage"]="POSTGRES_USER POSTGRES_PASSWORD POSTGRES_DATABASE" + ["NetworkXStorage"]="" + ["Neo4JStorage"]="NEO4J_URI NEO4J_USERNAME NEO4J_PASSWORD" + ["MongoGraphStorage"]="MONGO_URI MONGO_DATABASE" + ["MemgraphStorage"]="MEMGRAPH_URI" + ["PGGraphStorage"]="POSTGRES_USER POSTGRES_PASSWORD POSTGRES_DATABASE" + ["NanoVectorDBStorage"]="" + ["MilvusVectorDBStorage"]="MILVUS_URI MILVUS_DB_NAME" + ["PGVectorStorage"]="POSTGRES_USER POSTGRES_PASSWORD POSTGRES_DATABASE" + ["FaissVectorDBStorage"]="" + ["QdrantVectorDBStorage"]="QDRANT_URL" + ["MongoVectorDBStorage"]="MONGO_URI MONGO_DATABASE" + ["JsonDocStatusStorage"]="" + ["RedisDocStatusStorage"]="REDIS_URI" + ["PGDocStatusStorage"]="POSTGRES_USER POSTGRES_PASSWORD POSTGRES_DATABASE" + ["MongoDocStatusStorage"]="MONGO_URI MONGO_DATABASE" +) + +declare -Ag STORAGE_DB_TYPES=( + ["MongoKVStorage"]="mongodb" + ["MongoGraphStorage"]="mongodb" + ["MongoVectorDBStorage"]="mongodb" + ["MongoDocStatusStorage"]="mongodb" + ["RedisKVStorage"]="redis" + ["RedisDocStatusStorage"]="redis" + ["PGKVStorage"]="postgresql" + ["PGGraphStorage"]="postgresql" + ["PGVectorStorage"]="postgresql" + ["PGDocStatusStorage"]="postgresql" + ["Neo4JStorage"]="neo4j" + ["MemgraphStorage"]="memgraph" + ["MilvusVectorDBStorage"]="milvus" + ["QdrantVectorDBStorage"]="qdrant" +) diff --git a/scripts/setup/lib/validation.sh b/scripts/setup/lib/validation.sh new file mode 100644 index 0000000000..b6e7a63538 --- /dev/null +++ b/scripts/setup/lib/validation.sh @@ -0,0 +1,156 @@ +# Validation helpers for interactive setup. + +validate_uri() { + local uri="$1" + local db_type="$2" + + if [[ -z "$uri" ]]; then + return 1 + fi + + case "$db_type" in + postgresql) + [[ "$uri" =~ ^postgres(ql)?://.+ ]] + return $?; ;; + neo4j) + [[ "$uri" =~ ^(neo4j(\+s)?|bolt)://.+ ]] + return $?; ;; + mongodb) + [[ "$uri" =~ ^mongodb(\+srv)?://.+ ]] + return $?; ;; + redis) + [[ "$uri" =~ ^rediss?://.+ ]] + return $?; ;; + milvus|qdrant) + [[ "$uri" =~ ^https?://.+ ]] + return $?; ;; + memgraph) + [[ "$uri" =~ ^bolt://.+ ]] + return $?; ;; + *) + return 1 + ;; + esac +} + +validate_api_key() { + local key="$1" + local provider="$2" + + if [[ -z "$key" ]]; then + return 1 + fi + + case "$provider" in + openai|openrouter) + [[ "$key" == sk-* ]] + return $?; ;; + *) + [[ ${#key} -ge 8 ]] + return $?; ;; + esac +} + +validate_port() { + local port="$1" + + if [[ ! "$port" =~ ^[0-9]+$ ]]; then + return 1 + fi + + if (( port < 1 || port > 65535 )); then + return 1 + fi + + return 0 +} + +check_storage_compatibility() { + local kv_storage="$1" + local vector_storage="$2" + local graph_storage="$3" + local doc_status_storage="$4" + local warnings=() + + if [[ "$vector_storage" == "MongoVectorDBStorage" ]]; then + warnings+=("MongoDB vector storage requires Atlas (mongodb+srv:// URI).") + fi + + if [[ "$graph_storage" == "Neo4JStorage" && "$kv_storage" == "JsonKVStorage" ]]; then + warnings+=("Neo4j graph with JSON KV storage is fine for dev, but not ideal for production.") + fi + + if [[ "$graph_storage" == "NetworkXStorage" ]]; then + warnings+=("NetworkX graph storage is memory-bound and suited for small datasets only.") + fi + + if [[ "$vector_storage" == "FaissVectorDBStorage" ]]; then + warnings+=("Faiss vector storage is local-only and requires manual persistence management.") + fi + + if [[ "$kv_storage" == "JsonKVStorage" || "$doc_status_storage" == "JsonDocStatusStorage" ]]; then + warnings+=("JSON-based KV/doc status storage is recommended only for local development.") + fi + + if ((${#warnings[@]} > 0)); then + echo "${COLOR_YELLOW:-}Storage compatibility/performance warnings:${COLOR_RESET:-}" >&2 + for warning in "${warnings[@]}"; do + echo " - $warning" >&2 + done + return 1 + fi + + return 0 +} + +format_error() { + local message="$1" + local suggestion="${2:-}" + + echo "${COLOR_RED:-}Error:${COLOR_RESET:-} $message" >&2 + if [[ -n "$suggestion" ]]; then + echo "${COLOR_YELLOW:-}Hint:${COLOR_RESET:-} $suggestion" >&2 + fi +} + +validate_required_variables() { + local storages=("$@") + local missing=() + local storage required var + + for storage in "${storages[@]}"; do + if [[ -z "$storage" ]]; then + continue + fi + required="${STORAGE_ENV_REQUIREMENTS[$storage]}" + if [[ -z "$required" ]]; then + continue + fi + for var in $required; do + if [[ -z "${ENV_VALUES[$var]:-}" ]]; then + missing+=("$var") + fi + done + done + + if ((${#missing[@]} > 0)); then + format_error "Missing required variables: ${missing[*]}" "Fill them in .env or re-run setup." + return 1 + fi + + return 0 +} + +check_docker_availability() { + if ! command -v docker >/dev/null 2>&1; then + format_error "Docker is not installed or not in PATH." "Install Docker or disable docker service generation." + return 1 + fi + + if ! docker compose version >/dev/null 2>&1; then + format_error "Docker Compose is not available." "Install the Docker Compose plugin or use docker-compose." + return 1 + fi + + return 0 +} diff --git a/scripts/setup/presets/development.sh b/scripts/setup/presets/development.sh new file mode 100644 index 0000000000..943ee22416 --- /dev/null +++ b/scripts/setup/presets/development.sh @@ -0,0 +1,14 @@ +# shellcheck disable=SC2034 +PRESET_DEVELOPMENT=( + "LIGHTRAG_KV_STORAGE=JsonKVStorage" + "LIGHTRAG_VECTOR_STORAGE=NanoVectorDBStorage" + "LIGHTRAG_GRAPH_STORAGE=NetworkXStorage" + "LIGHTRAG_DOC_STATUS_STORAGE=JsonDocStatusStorage" + "LLM_BINDING=openai" + "LLM_MODEL=gpt-4o" + "LLM_BINDING_HOST=https://api.openai.com/v1" + "EMBEDDING_BINDING=openai" + "EMBEDDING_MODEL=text-embedding-3-large" + "EMBEDDING_DIM=3072" + "EMBEDDING_BINDING_HOST=https://api.openai.com/v1" +) diff --git a/scripts/setup/presets/local.sh b/scripts/setup/presets/local.sh new file mode 100644 index 0000000000..5454dc7883 --- /dev/null +++ b/scripts/setup/presets/local.sh @@ -0,0 +1,14 @@ +# shellcheck disable=SC2034 +PRESET_LOCAL=( + "LIGHTRAG_KV_STORAGE=RedisKVStorage" + "LIGHTRAG_VECTOR_STORAGE=QdrantVectorDBStorage" + "LIGHTRAG_GRAPH_STORAGE=Neo4JStorage" + "LIGHTRAG_DOC_STATUS_STORAGE=RedisDocStatusStorage" + "LLM_BINDING=openai" + "LLM_MODEL=gpt-4o" + "LLM_BINDING_HOST=https://api.openai.com/v1" + "EMBEDDING_BINDING=openai" + "EMBEDDING_MODEL=text-embedding-3-large" + "EMBEDDING_DIM=3072" + "EMBEDDING_BINDING_HOST=https://api.openai.com/v1" +) diff --git a/scripts/setup/presets/production.sh b/scripts/setup/presets/production.sh new file mode 100644 index 0000000000..76ddf69735 --- /dev/null +++ b/scripts/setup/presets/production.sh @@ -0,0 +1,14 @@ +# shellcheck disable=SC2034 +PRESET_PRODUCTION=( + "LIGHTRAG_KV_STORAGE=PGKVStorage" + "LIGHTRAG_VECTOR_STORAGE=MilvusVectorDBStorage" + "LIGHTRAG_GRAPH_STORAGE=Neo4JStorage" + "LIGHTRAG_DOC_STATUS_STORAGE=PGDocStatusStorage" + "LLM_BINDING=openai" + "LLM_MODEL=gpt-4o" + "LLM_BINDING_HOST=https://api.openai.com/v1" + "EMBEDDING_BINDING=openai" + "EMBEDDING_MODEL=text-embedding-3-large" + "EMBEDDING_DIM=3072" + "EMBEDDING_BINDING_HOST=https://api.openai.com/v1" +) diff --git a/scripts/setup/setup.sh b/scripts/setup/setup.sh new file mode 100644 index 0000000000..ab3bd4dbdb --- /dev/null +++ b/scripts/setup/setup.sh @@ -0,0 +1,1218 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LIB_DIR="$SCRIPT_DIR/lib" +PRESETS_DIR="$SCRIPT_DIR/presets" +# shellcheck disable=SC2034 +TEMPLATES_DIR="$SCRIPT_DIR/templates" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +declare -A ENV_VALUES +declare -A REQUIRED_DB_TYPES +declare -A DOCKER_SERVICE_SET +declare -a DOCKER_SERVICES +declare -A DOCKER_IMAGE_TAG_DEFAULTS=( + ["postgres"]="18" + ["neo4j"]="5.26.19-community" + ["mongodb"]="8.2.3" + ["redis"]="8.4" + ["milvus"]="2.6-20251227-44275071" + ["etcd"]="v3.5.16" + ["minio"]="RELEASE.2024-12-13T22-19-12Z" + ["qdrant"]="v1.16-gpu-nvidia" + ["memgraph"]="3.7.2" + ["vllm-rerank"]="latest" +) +declare -A DOCKER_IMAGE_TAG_ENV=( + ["postgres"]="POSTGRES_IMAGE_TAG" + ["neo4j"]="NEO4J_IMAGE_TAG" + ["mongodb"]="MONGODB_IMAGE_TAG" + ["redis"]="REDIS_IMAGE_TAG" + ["milvus"]="MILVUS_IMAGE_TAG" + ["etcd"]="ETCD_IMAGE_TAG" + ["minio"]="MINIO_IMAGE_TAG" + ["qdrant"]="QDRANT_IMAGE_TAG" + ["memgraph"]="MEMGRAPH_IMAGE_TAG" + ["vllm-rerank"]="VLLM_RERANK_IMAGE_TAG" +) +DEPLOYMENT_TYPE="" +DEBUG="${DEBUG:-false}" +WAIT_TIMEOUT="${SETUP_WAIT_TIMEOUT:-90}" +# shellcheck disable=SC2034 +COLOR_RESET="" +COLOR_BOLD="" +COLOR_BLUE="" +COLOR_GREEN="" +COLOR_YELLOW="" +# shellcheck disable=SC2034 +COLOR_RED="" + +# shellcheck disable=SC1091 +source "$LIB_DIR/storage_requirements.sh" +# shellcheck disable=SC1091 +source "$LIB_DIR/validation.sh" +# shellcheck disable=SC1091 +source "$LIB_DIR/prompts.sh" +# shellcheck disable=SC1091 +source "$LIB_DIR/file_ops.sh" +# shellcheck disable=SC1091 +source "$LIB_DIR/presets.sh" + +# shellcheck disable=SC1091 +source "$PRESETS_DIR/development.sh" +# shellcheck disable=SC1091 +source "$PRESETS_DIR/production.sh" +# shellcheck disable=SC1091 +source "$PRESETS_DIR/local.sh" + +init_colors() { + if [[ -t 1 && -z "${NO_COLOR:-}" ]]; then + COLOR_RESET=$'\033[0m' + COLOR_BOLD=$'\033[1m' + COLOR_BLUE=$'\033[34m' + COLOR_GREEN=$'\033[32m' + COLOR_YELLOW=$'\033[33m' + # shellcheck disable=SC2034 + COLOR_RED=$'\033[31m' + fi +} + +reset_state() { + ENV_VALUES=() + REQUIRED_DB_TYPES=() + DOCKER_SERVICE_SET=() + DOCKER_SERVICES=() + DEPLOYMENT_TYPE="" +} + +log_debug() { + if [[ "$DEBUG" == "true" ]]; then + echo "${COLOR_YELLOW}[debug]${COLOR_RESET} $*" + fi +} + +log_info() { + echo "${COLOR_BLUE}${COLOR_BOLD}$*${COLOR_RESET}" +} + +log_warn() { + echo "${COLOR_YELLOW}$*${COLOR_RESET}" +} + +log_success() { + echo "${COLOR_GREEN}$*${COLOR_RESET}" +} + +log_step() { + echo "${COLOR_BLUE}${COLOR_BOLD}$*${COLOR_RESET}" +} + +wait_for_port() { + local host="$1" + local port="$2" + local label="$3" + local timeout="${4:-$WAIT_TIMEOUT}" + local start_time=$SECONDS + + log_step "Waiting for ${label} on ${host}:${port} (timeout ${timeout}s)" + while true; do + if (echo > "/dev/tcp/${host}/${port}") >/dev/null 2>&1; then + log_success "${label} is ready." + return 0 + fi + if (( SECONDS - start_time >= timeout )); then + log_warn "Timed out waiting for ${label} (${host}:${port})." + return 1 + fi + sleep 2 + done +} + +wait_for_services() { + local service + local host="127.0.0.1" + local port="" + + for service in "${DOCKER_SERVICES[@]}"; do + case "$service" in + postgres) + port="${ENV_VALUES[POSTGRES_PORT]:-5432}" + ;; + neo4j) + port="7687" + ;; + mongodb) + port="27017" + ;; + redis) + port="6379" + ;; + milvus) + port="19530" + ;; + qdrant) + port="6333" + ;; + memgraph) + port="7687" + ;; + vllm-rerank) + port="${ENV_VALUES[VLLM_RERANK_PORT]:-8000}" + ;; + *) + port="" + ;; + esac + + if [[ -n "$port" ]]; then + wait_for_port "$host" "$port" "$service" || true + fi + done +} + +add_docker_service() { + local service="$1" + + if [[ -z "${DOCKER_SERVICE_SET[$service]+set}" ]]; then + DOCKER_SERVICE_SET["$service"]=1 + DOCKER_SERVICES+=("$service") + fi +} + +confirm_default_yes() { + local prompt="$1" + local response + + read -r -p "$prompt [Y/n]: " response + case "${response,,}" in + n|no) + return 1 + ;; + *) + return 0 + ;; + esac +} + +prompt_choice() { + local prompt="$1" + local default="$2" + shift 2 + local options=("$@") + local choice + local found + local index=1 + local default_index="" + local prompt_default="$default" + + while true; do + printf '%s\n' "${COLOR_BLUE}${prompt}${COLOR_RESET} options:" >&2 + index=1 + default_index="" + for option in "${options[@]}"; do + if [[ "$option" == "$default" ]]; then + default_index="$index" + fi + printf ' %s) %s\n' "${COLOR_GREEN}${index}${COLOR_RESET}" "$option" >&2 + index=$((index + 1)) + done + if [[ -n "$default_index" ]]; then + prompt_default="$default_index" + else + prompt_default="$default" + fi + printf '%s\n' "Enter a number or name (default: $prompt_default)." >&2 + + choice="$(prompt_with_default "$prompt" "$prompt_default")" + found="" + if [[ "$choice" =~ ^[0-9]+$ ]]; then + if ((choice >= 1 && choice <= ${#options[@]})); then + choice="${options[choice-1]}" + found="yes" + fi + else + for option in "${options[@]}"; do + if [[ "$choice" == "$option" ]]; then + found="yes" + break + fi + done + fi + + if [[ -n "$found" ]]; then + printf '%s' "$choice" + return 0 + fi + + echo "${COLOR_YELLOW}Invalid selection.${COLOR_RESET} Please choose one of the listed options." >&2 + done +} + +select_deployment_type() { + local options=("development" "production" "custom") + prompt_choice "Deployment type" "development" "${options[@]}" +} + +select_storage_backends() { + local deployment_type="$1" + local kv_default="JsonKVStorage" + local vector_default="NanoVectorDBStorage" + local graph_default="NetworkXStorage" + local doc_default="JsonDocStatusStorage" + local kv_storage vector_storage graph_storage doc_storage + + if [[ "$deployment_type" == "production" ]]; then + kv_default="PGKVStorage" + vector_default="MilvusVectorDBStorage" + graph_default="Neo4JStorage" + doc_default="PGDocStatusStorage" + fi + + while true; do + kv_storage="$(prompt_choice "KV storage" "$kv_default" "${KV_STORAGE_OPTIONS[@]}")" + vector_storage="$(prompt_choice "Vector storage" "$vector_default" "${VECTOR_STORAGE_OPTIONS[@]}")" + graph_storage="$(prompt_choice "Graph storage" "$graph_default" "${GRAPH_STORAGE_OPTIONS[@]}")" + doc_storage="$(prompt_choice "Doc status storage" "$doc_default" "${DOC_STATUS_STORAGE_OPTIONS[@]}")" + + if check_storage_compatibility "$kv_storage" "$vector_storage" "$graph_storage" "$doc_storage"; then + break + fi + + if confirm "Proceed with these storage selections anyway?"; then + break + fi + done + + ENV_VALUES["LIGHTRAG_KV_STORAGE"]="$kv_storage" + ENV_VALUES["LIGHTRAG_VECTOR_STORAGE"]="$vector_storage" + ENV_VALUES["LIGHTRAG_GRAPH_STORAGE"]="$graph_storage" + ENV_VALUES["LIGHTRAG_DOC_STATUS_STORAGE"]="$doc_storage" + + for storage in "$kv_storage" "$vector_storage" "$graph_storage" "$doc_storage"; do + if [[ -n "${STORAGE_DB_TYPES[$storage]:-}" ]]; then + REQUIRED_DB_TYPES["${STORAGE_DB_TYPES[$storage]}"]=1 + fi + done +} + +collect_database_config() { + local db_type="$1" + local default_docker="${2:-no}" + + case "$db_type" in + postgresql) + collect_postgres_config "$default_docker" + ;; + neo4j) + collect_neo4j_config "$default_docker" + ;; + mongodb) + collect_mongodb_config "$default_docker" + ;; + redis) + collect_redis_config "$default_docker" + ;; + milvus) + collect_milvus_config "$default_docker" + ;; + qdrant) + collect_qdrant_config "$default_docker" + ;; + memgraph) + collect_memgraph_config "$default_docker" + ;; + *) + echo "Unknown database type: $db_type" >&2 + return 1 + ;; + esac +} + +collect_postgres_config() { + local default_docker="${1:-no}" + local use_docker="no" + local host port user password database + + if [[ "$default_docker" == "yes" ]]; then + if confirm_default_yes "Add PostgreSQL service to docker-compose.yml?"; then + use_docker="yes" + fi + else + if confirm "Add PostgreSQL service to docker-compose.yml?"; then + use_docker="yes" + fi + fi + + if [[ "$use_docker" == "yes" ]]; then + add_docker_service "postgres" + host="postgres" + else + host="localhost" + fi + + host="$(prompt_with_default "PostgreSQL host" "$host")" + port="$(prompt_until_valid "PostgreSQL port" "5432" validate_port)" + user="$(prompt_with_default "PostgreSQL user" "lightrag")" + password="$(mask_sensitive_input "PostgreSQL password: ")" + database="$(prompt_with_default "PostgreSQL database" "lightrag")" + + ENV_VALUES["POSTGRES_HOST"]="$host" + ENV_VALUES["POSTGRES_PORT"]="$port" + ENV_VALUES["POSTGRES_USER"]="$user" + ENV_VALUES["POSTGRES_PASSWORD"]="$password" + ENV_VALUES["POSTGRES_DATABASE"]="$database" +} + +collect_neo4j_config() { + local default_docker="${1:-no}" + local use_docker="no" + local uri username password database + + if [[ "$default_docker" == "yes" ]]; then + if confirm_default_yes "Add Neo4j service to docker-compose.yml?"; then + use_docker="yes" + fi + else + if confirm "Add Neo4j service to docker-compose.yml?"; then + use_docker="yes" + fi + fi + + if [[ "$use_docker" == "yes" ]]; then + add_docker_service "neo4j" + uri="neo4j://neo4j:7687" + else + uri="neo4j://localhost:7687" + fi + + uri="$(prompt_until_valid "Neo4j URI" "$uri" validate_uri neo4j)" + username="$(prompt_with_default "Neo4j username" "neo4j")" + password="$(prompt_with_default "Neo4j password" "neo4j_password")" + database="$(prompt_with_default "Neo4j database" "neo4j")" + + ENV_VALUES["NEO4J_URI"]="$uri" + ENV_VALUES["NEO4J_USERNAME"]="$username" + ENV_VALUES["NEO4J_PASSWORD"]="$password" + ENV_VALUES["NEO4J_DATABASE"]="$database" +} + +collect_mongodb_config() { + local default_docker="${1:-no}" + local use_docker="no" + local uri database + + if [[ "$default_docker" == "yes" ]]; then + if confirm_default_yes "Add MongoDB service to docker-compose.yml?"; then + use_docker="yes" + fi + else + if confirm "Add MongoDB service to docker-compose.yml?"; then + use_docker="yes" + fi + fi + + if [[ "$use_docker" == "yes" ]]; then + add_docker_service "mongodb" + uri="mongodb://mongodb:27017/" + else + uri="mongodb://localhost:27017/" + fi + + uri="$(prompt_until_valid "MongoDB URI" "$uri" validate_uri mongodb)" + database="$(prompt_with_default "MongoDB database" "LightRAG")" + + ENV_VALUES["MONGO_URI"]="$uri" + ENV_VALUES["MONGO_DATABASE"]="$database" +} + +collect_redis_config() { + local default_docker="${1:-no}" + local use_docker="no" + local uri + + if [[ "$default_docker" == "yes" ]]; then + if confirm_default_yes "Add Redis service to docker-compose.yml?"; then + use_docker="yes" + fi + else + if confirm "Add Redis service to docker-compose.yml?"; then + use_docker="yes" + fi + fi + + if [[ "$use_docker" == "yes" ]]; then + add_docker_service "redis" + uri="redis://redis:6379" + else + uri="redis://localhost:6379" + fi + + uri="$(prompt_until_valid "Redis URI" "$uri" validate_uri redis)" + ENV_VALUES["REDIS_URI"]="$uri" +} + +collect_milvus_config() { + local default_docker="${1:-no}" + local use_docker="no" + local uri db_name + + if [[ "$default_docker" == "yes" ]]; then + if confirm_default_yes "Add Milvus service to docker-compose.yml?"; then + use_docker="yes" + fi + else + if confirm "Add Milvus service to docker-compose.yml?"; then + use_docker="yes" + fi + fi + + if [[ "$use_docker" == "yes" ]]; then + add_docker_service "milvus" + uri="http://milvus:19530" + else + uri="http://localhost:19530" + fi + + uri="$(prompt_until_valid "Milvus URI" "$uri" validate_uri milvus)" + db_name="$(prompt_with_default "Milvus database name" "default")" + + ENV_VALUES["MILVUS_URI"]="$uri" + ENV_VALUES["MILVUS_DB_NAME"]="$db_name" +} + +collect_qdrant_config() { + local default_docker="${1:-no}" + local use_docker="no" + local url + + if [[ "$default_docker" == "yes" ]]; then + if confirm_default_yes "Add Qdrant service to docker-compose.yml?"; then + use_docker="yes" + fi + else + if confirm "Add Qdrant service to docker-compose.yml?"; then + use_docker="yes" + fi + fi + + if [[ "$use_docker" == "yes" ]]; then + add_docker_service "qdrant" + url="http://qdrant:6333" + else + url="http://localhost:6333" + fi + + url="$(prompt_until_valid "Qdrant URL" "$url" validate_uri qdrant)" + ENV_VALUES["QDRANT_URL"]="$url" +} + +collect_memgraph_config() { + local default_docker="${1:-no}" + local use_docker="no" + local uri + + if [[ "$default_docker" == "yes" ]]; then + if confirm_default_yes "Add Memgraph service to docker-compose.yml?"; then + use_docker="yes" + fi + else + if confirm "Add Memgraph service to docker-compose.yml?"; then + use_docker="yes" + fi + fi + + if [[ "$use_docker" == "yes" ]]; then + add_docker_service "memgraph" + uri="bolt://memgraph:7687" + else + uri="bolt://localhost:7687" + fi + + uri="$(prompt_until_valid "Memgraph URI" "$uri" validate_uri memgraph)" + ENV_VALUES["MEMGRAPH_URI"]="$uri" +} + +collect_llm_config() { + local options=("openai" "azure_openai" "ollama" "gemini" "aws_bedrock") + local binding model host api_key + + binding="$(prompt_choice "LLM provider" "${ENV_VALUES[LLM_BINDING]:-openai}" "${options[@]}")" + model="$(prompt_with_default "LLM model" "${ENV_VALUES[LLM_MODEL]:-gpt-4o}")" + + case "$binding" in + ollama) + host="$(prompt_with_default "Ollama host" "${ENV_VALUES[LLM_BINDING_HOST]:-http://localhost:11434}")" + api_key="" + ;; + azure_openai) + host="$(prompt_with_default "Azure OpenAI endpoint" "${ENV_VALUES[LLM_BINDING_HOST]:-https://example.openai.azure.com/}")" + api_key="$(prompt_secret_until_valid "Azure OpenAI API key: " validate_api_key azure_openai)" + ;; + gemini) + host="$(prompt_with_default "Gemini endpoint" "${ENV_VALUES[LLM_BINDING_HOST]:-https://generativelanguage.googleapis.com}")" + api_key="$(prompt_secret_until_valid "Gemini API key: " validate_api_key gemini)" + ;; + aws_bedrock) + host="$(prompt_with_default "Bedrock endpoint" "${ENV_VALUES[LLM_BINDING_HOST]:-https://bedrock.amazonaws.com}")" + api_key="$(prompt_secret_until_valid "Bedrock API key: " validate_api_key aws_bedrock)" + ;; + *) + host="$(prompt_with_default "LLM endpoint" "${ENV_VALUES[LLM_BINDING_HOST]:-https://api.openai.com/v1}")" + api_key="$(prompt_secret_until_valid "LLM API key: " validate_api_key "$binding")" + ;; + esac + + ENV_VALUES["LLM_BINDING"]="$binding" + ENV_VALUES["LLM_MODEL"]="$model" + ENV_VALUES["LLM_BINDING_HOST"]="$host" + if [[ -n "$api_key" ]]; then + ENV_VALUES["LLM_BINDING_API_KEY"]="$api_key" + fi +} + +collect_embedding_config() { + local options=("openai" "azure_openai" "ollama" "jina" "gemini" "aws_bedrock") + local binding model host api_key dim + + binding="$(prompt_choice "Embedding provider" "${ENV_VALUES[EMBEDDING_BINDING]:-openai}" "${options[@]}")" + model="$(prompt_with_default "Embedding model" "${ENV_VALUES[EMBEDDING_MODEL]:-text-embedding-3-large}")" + dim="$(prompt_with_default "Embedding dimension" "${ENV_VALUES[EMBEDDING_DIM]:-3072}")" + + case "$binding" in + ollama) + host="$(prompt_with_default "Ollama embedding host" "${ENV_VALUES[EMBEDDING_BINDING_HOST]:-http://localhost:11434}")" + api_key="" + ;; + azure_openai) + host="$(prompt_with_default "Azure OpenAI endpoint" "${ENV_VALUES[EMBEDDING_BINDING_HOST]:-https://example.openai.azure.com/}")" + api_key="$(prompt_secret_until_valid "Azure OpenAI API key: " validate_api_key azure_openai)" + ;; + gemini) + host="$(prompt_with_default "Gemini endpoint" "${ENV_VALUES[EMBEDDING_BINDING_HOST]:-https://generativelanguage.googleapis.com}")" + api_key="$(prompt_secret_until_valid "Gemini API key: " validate_api_key gemini)" + ;; + aws_bedrock) + host="$(prompt_with_default "Bedrock endpoint" "${ENV_VALUES[EMBEDDING_BINDING_HOST]:-https://bedrock.amazonaws.com}")" + api_key="$(prompt_secret_until_valid "Bedrock API key: " validate_api_key aws_bedrock)" + ;; + jina) + host="$(prompt_with_default "Jina endpoint" "${ENV_VALUES[EMBEDDING_BINDING_HOST]:-https://api.jina.ai/v1/embeddings}")" + api_key="$(prompt_secret_until_valid "Jina API key: " validate_api_key jina)" + ;; + *) + host="$(prompt_with_default "Embedding endpoint" "${ENV_VALUES[EMBEDDING_BINDING_HOST]:-https://api.openai.com/v1}")" + api_key="$(prompt_secret_until_valid "Embedding API key: " validate_api_key "$binding")" + ;; + esac + + ENV_VALUES["EMBEDDING_BINDING"]="$binding" + ENV_VALUES["EMBEDDING_MODEL"]="$model" + ENV_VALUES["EMBEDDING_DIM"]="$dim" + ENV_VALUES["EMBEDDING_BINDING_HOST"]="$host" + if [[ -n "$api_key" ]]; then + ENV_VALUES["EMBEDDING_BINDING_API_KEY"]="$api_key" + fi +} + +collect_rerank_config() { + local options=("cohere" "jina" "aliyun" "vllm") + local binding_choice binding model host api_key + local vllm_model vllm_port vllm_device vllm_dtype vllm_extra + local default_dtype="" + local default_model="" default_host="" use_docker="no" + + if ! confirm "Enable reranking?"; then + ENV_VALUES["RERANK_BINDING"]="null" + return + fi + + binding_choice="$(prompt_choice "Rerank provider" "cohere" "${options[@]}")" + + if [[ "$binding_choice" == "vllm" ]]; then + log_info "vLLM uses the Cohere-compatible rerank API." + if confirm_default_yes "Add local vLLM rerank service to docker-compose.yml?"; then + add_docker_service "vllm-rerank" + use_docker="yes" + fi + vllm_model="$(prompt_with_default "vLLM rerank model" "${ENV_VALUES[VLLM_RERANK_MODEL]:-BAAI/bge-reranker-v2-m3}")" + vllm_port="$(prompt_until_valid "vLLM rerank port" "${ENV_VALUES[VLLM_RERANK_PORT]:-8000}" validate_port)" + vllm_device="$(prompt_choice "vLLM device" "${ENV_VALUES[VLLM_RERANK_DEVICE]:-cpu}" "cpu" "cuda")" + if [[ "$vllm_device" == "cuda" ]] && ! command -v nvidia-smi >/dev/null 2>&1; then + log_warn "CUDA device selected but no NVIDIA driver detected on host." + if confirm_default_yes "Use CPU instead?"; then + vllm_device="cpu" + fi + fi + default_dtype="${ENV_VALUES[VLLM_RERANK_DTYPE]:-}" + if [[ -z "$default_dtype" ]]; then + if [[ "$vllm_device" == "cpu" ]]; then + default_dtype="float32" + else + default_dtype="float16" + fi + fi + vllm_dtype="$(prompt_with_default "vLLM dtype" "$default_dtype")" + vllm_extra="$(prompt_with_default "vLLM extra args" "${ENV_VALUES[VLLM_RERANK_EXTRA_ARGS]:-}")" + + ENV_VALUES["VLLM_RERANK_MODEL"]="$vllm_model" + ENV_VALUES["VLLM_RERANK_PORT"]="$vllm_port" + ENV_VALUES["VLLM_RERANK_DEVICE"]="$vllm_device" + ENV_VALUES["VLLM_RERANK_DTYPE"]="$vllm_dtype" + if [[ -n "$vllm_extra" ]]; then + ENV_VALUES["VLLM_RERANK_EXTRA_ARGS"]="$vllm_extra" + fi + + default_model="$vllm_model" + if [[ "$use_docker" == "yes" ]]; then + default_host="http://vllm-rerank:${vllm_port}/v1/rerank" + else + default_host="http://localhost:${vllm_port}/v1/rerank" + fi + binding="cohere" + else + binding="$binding_choice" + fi + + model="$(prompt_with_default "Rerank model" "${ENV_VALUES[RERANK_MODEL]:-$default_model}")" + host="$(prompt_with_default "Rerank endpoint" "${ENV_VALUES[RERANK_BINDING_HOST]:-$default_host}")" + if [[ "$binding_choice" == "vllm" ]]; then + api_key="$(prompt_with_default "Rerank API key (optional)" "${ENV_VALUES[RERANK_BINDING_API_KEY]:-}")" + else + api_key="$(prompt_secret_until_valid "Rerank API key: " validate_api_key "$binding")" + fi + + ENV_VALUES["RERANK_BINDING"]="$binding" + if [[ -n "$model" ]]; then + ENV_VALUES["RERANK_MODEL"]="$model" + fi + if [[ -n "$host" ]]; then + ENV_VALUES["RERANK_BINDING_HOST"]="$host" + fi + if [[ -n "$api_key" ]]; then + ENV_VALUES["RERANK_BINDING_API_KEY"]="$api_key" + fi +} + +collect_server_config() { + local host port title description + + host="$(prompt_with_default "Server host" "${ENV_VALUES[HOST]:-0.0.0.0}")" + port="$(prompt_until_valid "Server port" "${ENV_VALUES[PORT]:-9621}" validate_port)" + title="$(prompt_with_default "WebUI title" "${ENV_VALUES[WEBUI_TITLE]:-My Graph KB}")" + description="$(prompt_with_default "WebUI description" "${ENV_VALUES[WEBUI_DESCRIPTION]:-Simple and Fast Graph Based RAG System}")" + + ENV_VALUES["HOST"]="$host" + ENV_VALUES["PORT"]="$port" + ENV_VALUES["WEBUI_TITLE"]="$title" + ENV_VALUES["WEBUI_DESCRIPTION"]="$description" +} + +collect_ssl_config() { + local cert key + + if ! confirm_default_yes "Enable SSL/TLS for the API server?"; then + return + fi + + cert="$(prompt_with_default "SSL certificate file" "")" + key="$(prompt_with_default "SSL key file" "")" + + ENV_VALUES["SSL"]="true" + if [[ -n "$cert" ]]; then + ENV_VALUES["SSL_CERTFILE"]="$cert" + fi + if [[ -n "$key" ]]; then + ENV_VALUES["SSL_KEYFILE"]="$key" + fi +} + +collect_security_config() { + local required="${1:-no}" + local default_yes="${2:-no}" + local auth_accounts token_secret token_expire api_key whitelist + local confirm_result=1 + + if [[ "$default_yes" == "yes" ]]; then + if confirm_default_yes "Configure authentication and API key settings?"; then + confirm_result=0 + fi + else + if confirm "Configure authentication and API key settings?"; then + confirm_result=0 + fi + fi + + if ((confirm_result != 0)); then + if [[ "$required" == "yes" ]]; then + echo "Warning: production deployments should set authentication and API keys." >&2 + fi + return + fi + + auth_accounts="$(prompt_with_default "Auth accounts (user:pass,comma-separated)" "")" + token_secret="$(mask_sensitive_input "JWT token secret: ")" + token_expire="$(prompt_with_default "Token expire hours" "48")" + api_key="$(mask_sensitive_input "LightRAG API key: ")" + whitelist="$(prompt_with_default "Whitelist paths (comma-separated)" "/health,/api/*")" + + if [[ -n "$auth_accounts" ]]; then + ENV_VALUES["AUTH_ACCOUNTS"]="$auth_accounts" + fi + if [[ -n "$token_secret" ]]; then + ENV_VALUES["TOKEN_SECRET"]="$token_secret" + fi + if [[ -n "$token_expire" ]]; then + ENV_VALUES["TOKEN_EXPIRE_HOURS"]="$token_expire" + fi + if [[ -n "$api_key" ]]; then + ENV_VALUES["LIGHTRAG_API_KEY"]="$api_key" + fi + if [[ -n "$whitelist" ]]; then + ENV_VALUES["WHITELIST_PATHS"]="$whitelist" + fi +} + +collect_observability_config() { + local secret_key public_key host + + if ! confirm "Enable Langfuse observability?"; then + return + fi + + secret_key="$(prompt_secret_until_valid "Langfuse secret key: " validate_api_key langfuse)" + public_key="$(prompt_secret_until_valid "Langfuse public key: " validate_api_key langfuse)" + host="$(prompt_with_default "Langfuse host" "https://cloud.langfuse.com")" + + if [[ -n "$secret_key" ]]; then + ENV_VALUES["LANGFUSE_SECRET_KEY"]="$secret_key" + fi + if [[ -n "$public_key" ]]; then + ENV_VALUES["LANGFUSE_PUBLIC_KEY"]="$public_key" + fi + if [[ -n "$host" ]]; then + ENV_VALUES["LANGFUSE_HOST"]="$host" + fi + ENV_VALUES["LANGFUSE_ENABLE_TRACE"]="true" +} + +collect_docker_image_tags() { + local service env_var default_tag selected_tag + local -a tag_services=() + + if ((${#DOCKER_SERVICES[@]} == 0)); then + return + fi + + tag_services=("${DOCKER_SERVICES[@]}") + if [[ -n "${DOCKER_SERVICE_SET[milvus]+set}" ]]; then + tag_services+=("etcd" "minio") + fi + + log_info "Docker image tags for selected services:" + for service in "${tag_services[@]}"; do + env_var="${DOCKER_IMAGE_TAG_ENV[$service]}" + default_tag="${DOCKER_IMAGE_TAG_DEFAULTS[$service]}" + if [[ -n "$env_var" && -n "$default_tag" ]]; then + ENV_VALUES["$env_var"]="${ENV_VALUES[$env_var]:-$default_tag}" + echo " - $service: ${ENV_VALUES[$env_var]} ($env_var)" + fi + done + + if confirm "Keep these image tags?"; then + return + fi + + for service in "${tag_services[@]}"; do + env_var="${DOCKER_IMAGE_TAG_ENV[$service]}" + default_tag="${ENV_VALUES[$env_var]:-${DOCKER_IMAGE_TAG_DEFAULTS[$service]}}" + if [[ -n "$env_var" ]]; then + selected_tag="$(prompt_with_default "Tag for $service ($env_var)" "$default_tag")" + ENV_VALUES["$env_var"]="$selected_tag" + fi + done +} + +show_summary() { + local key + local value + local compose_suffix="" + + echo + log_info "Configuration summary:" + for key in "${!ENV_VALUES[@]}"; do + value="${ENV_VALUES[$key]}" + if [[ "$key" =~ (KEY|PASSWORD|SECRET|TOKEN) ]]; then + value="***" + fi + printf ' %s=%s\n' "$key" "$value" + done + + if ((${#DOCKER_SERVICES[@]} > 0)); then + echo + log_info "Docker services to include:" + for service in "${DOCKER_SERVICES[@]}"; do + echo " - $service" + done + compose_suffix="${DEPLOYMENT_TYPE:-custom}" + echo " Compose file: docker-compose.${compose_suffix}.yml" + fi +} + +finalize_setup() { + local backup_path + local compose_suffix + local compose_file + local generate_compose="no" + + if [[ ! -f "${REPO_ROOT}/env.example" ]]; then + format_error "env.example is missing in $REPO_ROOT" "Restore env.example before running setup." + return 1 + fi + + if [[ ! -w "$REPO_ROOT" ]]; then + format_error "No write permission in $REPO_ROOT" "Run the setup from a writable directory." + return 1 + fi + + if [[ -n "${ENV_VALUES[LIGHTRAG_KV_STORAGE]:-}" ]]; then + if ! validate_required_variables \ + "${ENV_VALUES[LIGHTRAG_KV_STORAGE]}" \ + "${ENV_VALUES[LIGHTRAG_VECTOR_STORAGE]}" \ + "${ENV_VALUES[LIGHTRAG_GRAPH_STORAGE]}" \ + "${ENV_VALUES[LIGHTRAG_DOC_STATUS_STORAGE]}"; then + return 1 + fi + fi + + show_summary + + if ! confirm "Generate .env and docker-compose.yml now?"; then + log_warn "Setup cancelled." + return 1 + fi + + backup_path="$(backup_env_file)" + if [[ -n "$backup_path" ]]; then + log_success "Backed up existing .env to $backup_path" + fi + + log_debug "Writing .env to ${REPO_ROOT}/.env" + generate_env_file "${REPO_ROOT}/env.example" "${REPO_ROOT}/.env" + log_success "Wrote .env" + + if ((${#DOCKER_SERVICES[@]} > 0)); then + generate_compose="yes" + else + if confirm "Generate docker-compose for LightRAG only?"; then + generate_compose="yes" + fi + fi + + if [[ "$generate_compose" == "yes" ]]; then + compose_suffix="${DEPLOYMENT_TYPE:-custom}" + compose_file="${REPO_ROOT}/docker-compose.${compose_suffix}.yml" + if [[ -f "$compose_file" ]]; then + if ! confirm "Overwrite existing ${compose_file}?"; then + compose_file="${REPO_ROOT}/docker-compose.${compose_suffix}.$(date +%Y%m%d_%H%M%S).yml" + log_warn "Using new compose file: $compose_file" + fi + fi + generate_docker_compose "$compose_file" + log_success "Wrote ${compose_file}" + if confirm_default_yes "Start docker services now?"; then + if ! check_docker_availability; then + return 1 + fi + log_step "Starting docker services with ${compose_file}" + if ((${#DOCKER_SERVICES[@]} > 0)); then + docker compose -f "$compose_file" up -d "${DOCKER_SERVICES[@]}" + wait_for_services + fi + docker compose -f "$compose_file" up -d lightrag + log_success "Docker services are up." + fi + else + log_warn "No docker services selected." + fi +} + +interactive_flow() { + local deployment_type + local db_type + local db_order=("postgresql" "neo4j" "mongodb" "redis" "milvus" "qdrant" "memgraph") + + reset_state + + log_info "Interactive setup wizard" + log_step "Step 1: Deployment type" + echo " - development: local JSON/NetworkX defaults" + echo " - production: database-backed defaults with security prompts" + echo " - custom: pick each backend manually" + deployment_type="$(select_deployment_type)" + DEPLOYMENT_TYPE="$deployment_type" + + case "$deployment_type" in + development) + load_preset "development" + ;; + production) + load_preset "production" + ;; + custom) + ;; + esac + + log_step "Step 2: Storage backends" + select_storage_backends "$deployment_type" + log_debug "Storage selections: kv=${ENV_VALUES[LIGHTRAG_KV_STORAGE]:-} vector=${ENV_VALUES[LIGHTRAG_VECTOR_STORAGE]:-} graph=${ENV_VALUES[LIGHTRAG_GRAPH_STORAGE]:-} doc=${ENV_VALUES[LIGHTRAG_DOC_STATUS_STORAGE]:-}" + + log_step "Step 3: Database configuration" + for db_type in "${db_order[@]}"; do + if [[ -n "${REQUIRED_DB_TYPES[$db_type]+set}" ]]; then + collect_database_config "$db_type" "no" + fi + done + + collect_docker_image_tags + + log_step "Step 4: LLM configuration" + collect_llm_config + log_step "Step 5: Embedding configuration" + collect_embedding_config + log_step "Step 6: Reranking configuration" + collect_rerank_config + log_step "Step 7: Server configuration" + collect_server_config + log_step "Step 8: Security configuration" + collect_security_config "no" "no" + log_step "Step 9: Observability configuration" + collect_observability_config + + finalize_setup +} + +quick_start_flow() { + local api_key + + reset_state + load_preset "development" + DEPLOYMENT_TYPE="development" + + log_info "Quick start setup" + echo "Using development preset. Only OpenAI API key is required." + + ENV_VALUES["HOST"]="0.0.0.0" + ENV_VALUES["PORT"]="9621" + ENV_VALUES["WEBUI_TITLE"]="My Graph KB" + ENV_VALUES["WEBUI_DESCRIPTION"]="Simple and Fast Graph Based RAG System" + ENV_VALUES["RERANK_BINDING"]="null" + + api_key="$(prompt_secret_until_valid "OpenAI API key: " validate_api_key openai)" + ENV_VALUES["LLM_BINDING_API_KEY"]="$api_key" + ENV_VALUES["EMBEDDING_BINDING_API_KEY"]="$api_key" + + finalize_setup +} + +production_flow() { + local db_type + local db_order=("postgresql" "neo4j" "mongodb" "redis" "milvus" "qdrant" "memgraph") + + reset_state + load_preset "production" + DEPLOYMENT_TYPE="production" + + log_info "Production setup wizard" + echo "Recommended defaults are preselected. Customize as needed." + + select_storage_backends "production" + log_debug "Storage selections: kv=${ENV_VALUES[LIGHTRAG_KV_STORAGE]:-} vector=${ENV_VALUES[LIGHTRAG_VECTOR_STORAGE]:-} graph=${ENV_VALUES[LIGHTRAG_GRAPH_STORAGE]:-} doc=${ENV_VALUES[LIGHTRAG_DOC_STATUS_STORAGE]:-}" + + log_step "Configuring database services" + for db_type in "${db_order[@]}"; do + if [[ -n "${REQUIRED_DB_TYPES[$db_type]+set}" ]]; then + collect_database_config "$db_type" "yes" + fi + done + + collect_docker_image_tags + + log_step "Configuring LLM and embedding providers" + collect_llm_config + collect_embedding_config + collect_rerank_config + log_step "Configuring server and security settings" + collect_server_config + collect_ssl_config + collect_security_config "yes" "yes" + collect_observability_config + + finalize_setup +} + +load_env_file() { + local env_file="$1" + local line key value + + if [[ ! -f "$env_file" ]]; then + format_error ".env file not found at $env_file" "Run make setup to generate it." + return 1 + fi + + while IFS= read -r line || [[ -n "$line" ]]; do + if [[ "$line" =~ ^[A-Z0-9_]+= ]]; then + key="${line%%=*}" + value="${line#*=}" + if [[ "$value" =~ ^\".*\"$ ]]; then + value="${value:1:${#value}-2}" + elif [[ "$value" =~ ^\'.*\'$ ]]; then + value="${value:1:${#value}-2}" + fi + ENV_VALUES["$key"]="$value" + fi + done < "$env_file" +} + +validate_env_file() { + local env_file="${REPO_ROOT}/.env" + local errors=0 + local kv vector graph doc_status + + reset_state + + if ! load_env_file "$env_file"; then + return 1 + fi + + kv="${ENV_VALUES[LIGHTRAG_KV_STORAGE]:-}" + vector="${ENV_VALUES[LIGHTRAG_VECTOR_STORAGE]:-}" + graph="${ENV_VALUES[LIGHTRAG_GRAPH_STORAGE]:-}" + doc_status="${ENV_VALUES[LIGHTRAG_DOC_STATUS_STORAGE]:-}" + + if [[ -z "$kv" || -z "$vector" || -z "$graph" || -z "$doc_status" ]]; then + format_error "Storage selections are missing in .env" "Set LIGHTRAG_*_STORAGE variables." + return 1 + fi + + if ! validate_required_variables "$kv" "$vector" "$graph" "$doc_status"; then + errors=1 + fi + + if [[ -n "${ENV_VALUES[NEO4J_URI]:-}" ]] && ! validate_uri "${ENV_VALUES[NEO4J_URI]}" neo4j; then + format_error "Invalid NEO4J_URI" "Use neo4j:// or bolt:// format." + errors=1 + fi + if [[ -n "${ENV_VALUES[MONGO_URI]:-}" ]] && ! validate_uri "${ENV_VALUES[MONGO_URI]}" mongodb; then + format_error "Invalid MONGO_URI" "Use mongodb:// or mongodb+srv:// format." + errors=1 + fi + if [[ -n "${ENV_VALUES[REDIS_URI]:-}" ]] && ! validate_uri "${ENV_VALUES[REDIS_URI]}" redis; then + format_error "Invalid REDIS_URI" "Use redis:// or rediss:// format." + errors=1 + fi + if [[ -n "${ENV_VALUES[MILVUS_URI]:-}" ]] && ! validate_uri "${ENV_VALUES[MILVUS_URI]}" milvus; then + format_error "Invalid MILVUS_URI" "Use http://host:port format." + errors=1 + fi + if [[ -n "${ENV_VALUES[QDRANT_URL]:-}" ]] && ! validate_uri "${ENV_VALUES[QDRANT_URL]}" qdrant; then + format_error "Invalid QDRANT_URL" "Use http://host:port format." + errors=1 + fi + if [[ -n "${ENV_VALUES[MEMGRAPH_URI]:-}" ]] && ! validate_uri "${ENV_VALUES[MEMGRAPH_URI]}" memgraph; then + format_error "Invalid MEMGRAPH_URI" "Use bolt://host:port format." + errors=1 + fi + if [[ -n "${ENV_VALUES[POSTGRES_PORT]:-}" ]] && ! validate_port "${ENV_VALUES[POSTGRES_PORT]}"; then + format_error "Invalid POSTGRES_PORT" "Use a port between 1 and 65535." + errors=1 + fi + + if ((errors != 0)); then + return 1 + fi + + log_success "Validation passed." +} + +backup_only() { + local backup_path + + backup_path="$(backup_env_file)" + if [[ -z "$backup_path" ]]; then + format_error "No .env file found to back up." "Create one with make setup first." + return 1 + fi + echo "Backed up .env to $backup_path" +} + +print_help() { + cat <<'HELP' +Usage: scripts/setup/setup.sh [--quick|--production|--validate|--backup] + +Options: + --quick Run the quick start flow (development preset, minimal prompts) + --production Run the production preset flow (recommended defaults) + --validate Validate an existing .env file + --backup Backup the current .env file + --debug Enable debug logging + --help Show this help message +HELP +} + +main() { + init_colors + local mode="interactive" + + while [[ $# -gt 0 ]]; do + case "$1" in + --quick) + mode="quick" + ;; + --production) + mode="production" + ;; + --validate) + mode="validate" + ;; + --backup) + mode="backup" + ;; + --debug) + DEBUG="true" + ;; + --help|-h) + mode="help" + ;; + *) + echo "Unknown option: $1" >&2 + print_help + return 1 + ;; + esac + shift + done + + case "$mode" in + quick) + quick_start_flow + ;; + production) + production_flow + ;; + validate) + validate_env_file + ;; + backup) + backup_only + ;; + help) + print_help + ;; + *) + interactive_flow + ;; + esac +} + +main "$@" diff --git a/scripts/setup/templates/memgraph.yml b/scripts/setup/templates/memgraph.yml new file mode 100644 index 0000000000..cad54fecd1 --- /dev/null +++ b/scripts/setup/templates/memgraph.yml @@ -0,0 +1,7 @@ + memgraph: + image: memgraph/memgraph:${MEMGRAPH_IMAGE_TAG:-3.7.2} + ports: + - "7687:7687" + volumes: + - memgraph_data:/var/lib/memgraph + restart: unless-stopped diff --git a/scripts/setup/templates/milvus.yml b/scripts/setup/templates/milvus.yml new file mode 100644 index 0000000000..5973d87db5 --- /dev/null +++ b/scripts/setup/templates/milvus.yml @@ -0,0 +1,43 @@ + milvus: + image: milvusdb/milvus:${MILVUS_IMAGE_TAG:-2.6-20251227-44275071} + command: ["milvus", "run", "standalone"] + environment: + ETCD_ENDPOINTS: etcd:2379 + MINIO_ADDRESS: minio:9000 + MINIO_ACCESS_KEY_ID: ${MINIO_ACCESS_KEY_ID:-minioadmin} + MINIO_SECRET_ACCESS_KEY: ${MINIO_SECRET_ACCESS_KEY:-minioadmin} + ports: + - "19530:19530" + - "9091:9091" + volumes: + - milvus_data:/var/lib/milvus + depends_on: + - etcd + - minio + restart: unless-stopped + + etcd: + image: quay.io/coreos/etcd:${ETCD_IMAGE_TAG:-v3.5.16} + environment: + ETCD_AUTO_COMPACTION_MODE: revision + ETCD_AUTO_COMPACTION_RETENTION: "1000" + ETCD_QUOTA_BACKEND_BYTES: "4294967296" + ETCD_SNAPSHOT_COUNT: "50000" + volumes: + - etcd_data:/etcd + command: > + etcd + -advertise-client-urls=http://0.0.0.0:2379 + -listen-client-urls=http://0.0.0.0:2379 + -data-dir /etcd + restart: unless-stopped + + minio: + image: minio/minio:${MINIO_IMAGE_TAG:-RELEASE.2024-12-13T22-19-12Z} + environment: + MINIO_ROOT_USER: ${MINIO_ACCESS_KEY_ID:-minioadmin} + MINIO_ROOT_PASSWORD: ${MINIO_SECRET_ACCESS_KEY:-minioadmin} + volumes: + - minio_data:/minio_data + command: minio server /minio_data --console-address ":9001" + restart: unless-stopped diff --git a/scripts/setup/templates/mongodb.yml b/scripts/setup/templates/mongodb.yml new file mode 100644 index 0000000000..33004fc944 --- /dev/null +++ b/scripts/setup/templates/mongodb.yml @@ -0,0 +1,7 @@ + mongodb: + image: mongo:${MONGODB_IMAGE_TAG:-8.2.3} + ports: + - "27017:27017" + volumes: + - mongo_data:/data/db + restart: unless-stopped diff --git a/scripts/setup/templates/neo4j.yml b/scripts/setup/templates/neo4j.yml new file mode 100644 index 0000000000..edca2a890b --- /dev/null +++ b/scripts/setup/templates/neo4j.yml @@ -0,0 +1,11 @@ + neo4j: + image: neo4j:${NEO4J_IMAGE_TAG:-5.26.19-community} + environment: + NEO4J_AUTH: "${NEO4J_USERNAME}/${NEO4J_PASSWORD}" + NEO4J_dbms_default__database: "${NEO4J_DATABASE:-neo4j}" + ports: + - "7474:7474" + - "7687:7687" + volumes: + - neo4j_data:/data + restart: unless-stopped diff --git a/scripts/setup/templates/postgres.yml b/scripts/setup/templates/postgres.yml new file mode 100644 index 0000000000..445b12f4a8 --- /dev/null +++ b/scripts/setup/templates/postgres.yml @@ -0,0 +1,11 @@ + postgres: + image: postgres:${POSTGRES_IMAGE_TAG:-18} + environment: + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: ${POSTGRES_DATABASE} + ports: + - "${POSTGRES_PORT:-5432}:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + restart: unless-stopped diff --git a/scripts/setup/templates/qdrant.yml b/scripts/setup/templates/qdrant.yml new file mode 100644 index 0000000000..abe37cee30 --- /dev/null +++ b/scripts/setup/templates/qdrant.yml @@ -0,0 +1,7 @@ + qdrant: + image: qdrant/qdrant:${QDRANT_IMAGE_TAG:-v1.16-gpu-nvidia} + ports: + - "6333:6333" + volumes: + - qdrant_data:/qdrant/storage + restart: unless-stopped diff --git a/scripts/setup/templates/redis.yml b/scripts/setup/templates/redis.yml new file mode 100644 index 0000000000..ec152182c6 --- /dev/null +++ b/scripts/setup/templates/redis.yml @@ -0,0 +1,7 @@ + redis: + image: redis:${REDIS_IMAGE_TAG:-8.4} + ports: + - "6379:6379" + volumes: + - redis_data:/data + restart: unless-stopped diff --git a/scripts/setup/templates/vllm-rerank-gpu.yml b/scripts/setup/templates/vllm-rerank-gpu.yml new file mode 100644 index 0000000000..61bae6c743 --- /dev/null +++ b/scripts/setup/templates/vllm-rerank-gpu.yml @@ -0,0 +1,16 @@ + vllm-rerank: + image: vllm/vllm-openai:${VLLM_RERANK_IMAGE_TAG:-latest} + command: > + ${VLLM_RERANK_MODEL:-BAAI/bge-reranker-v2-m3} + --port ${VLLM_RERANK_PORT:-8000} + --dtype ${VLLM_RERANK_DTYPE:-float16} + ${VLLM_RERANK_EXTRA_ARGS:-} + environment: + NVIDIA_VISIBLE_DEVICES: ${NVIDIA_VISIBLE_DEVICES:-all} + NVIDIA_DRIVER_CAPABILITIES: ${NVIDIA_DRIVER_CAPABILITIES:-compute,utility} + ports: + - "${VLLM_RERANK_PORT:-8000}:${VLLM_RERANK_PORT:-8000}" + volumes: + - vllm_rerank_cache:/root/.cache/huggingface + gpus: all + restart: unless-stopped diff --git a/scripts/setup/templates/vllm-rerank.yml b/scripts/setup/templates/vllm-rerank.yml new file mode 100644 index 0000000000..a3852cb330 --- /dev/null +++ b/scripts/setup/templates/vllm-rerank.yml @@ -0,0 +1,12 @@ + vllm-rerank: + image: vllm/vllm-openai:${VLLM_RERANK_IMAGE_TAG:-latest} + command: > + ${VLLM_RERANK_MODEL:-BAAI/bge-reranker-v2-m3} + --port ${VLLM_RERANK_PORT:-8000} + --dtype ${VLLM_RERANK_DTYPE:-float32} + ${VLLM_RERANK_EXTRA_ARGS:-} + ports: + - "${VLLM_RERANK_PORT:-8000}:${VLLM_RERANK_PORT:-8000}" + volumes: + - vllm_rerank_cache:/root/.cache/huggingface + restart: unless-stopped