From 78ebf4d075367051a33a046af003f4b2cc70ac51 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Mon, 22 Sep 2025 11:14:50 +0200 Subject: [PATCH] Added draft base for AI assistant --- roles/web-app-ai-assistant/config/main.yml | 42 +++++++ .../templates/docker-compose.yml.j2 | 106 ++++++++++++++++++ .../templates/litellm.config.yaml.j2 | 15 +++ roles/web-app-ai-assistant/vars/main.yml | 28 +++++ 4 files changed, 191 insertions(+) create mode 100644 roles/web-app-ai-assistant/config/main.yml create mode 100644 roles/web-app-ai-assistant/templates/docker-compose.yml.j2 create mode 100644 roles/web-app-ai-assistant/templates/litellm.config.yaml.j2 create mode 100644 roles/web-app-ai-assistant/vars/main.yml diff --git a/roles/web-app-ai-assistant/config/main.yml b/roles/web-app-ai-assistant/config/main.yml new file mode 100644 index 00000000..1529a2b4 --- /dev/null +++ b/roles/web-app-ai-assistant/config/main.yml @@ -0,0 +1,42 @@ +features: + matomo: true + css: true + desktop: true + central_database: true + logout: true + javascript: true +server: + domains: + canonical: + - "ai.{{ PRIMARY_DOMAIN }}" + aliases: [] + csp: + flags: [] + #script-src-elem: + # unsafe-inline: true + #script-src: + # unsafe-inline: true + # unsafe-eval: true + #style-src: + # unsafe-inline: true + whitelist: + font-src: [] + connect-src: [] +docker: + services: + akaunting: + backup: + no_stop_required: true + image: docker.io/akaunting/akaunting + version: latest + name: akaunting + redis: + enabled: false + volumes: + ollama_models: ai_ollama_models + openwebui_data: ai_openwebui_data + qdrant_data: ai_qdrant_data + flowise_data: ai_flowise_data + minio_data: ai_minio_data +credentials: {} + diff --git a/roles/web-app-ai-assistant/templates/docker-compose.yml.j2 b/roles/web-app-ai-assistant/templates/docker-compose.yml.j2 new file mode 100644 index 00000000..33092754 --- /dev/null +++ b/roles/web-app-ai-assistant/templates/docker-compose.yml.j2 @@ -0,0 +1,106 @@ +{% include 'roles/docker-compose/templates/base.yml.j2' %} + + # ===== LLM / Modelle ===== + ollama: + image: ollama/ollama:latest + container_name: ollama + restart: unless-stopped + ports: + - "11434:11434" # Ollama API + volumes: + - ollama_models:/root/.ollama +{% include 'roles/docker-container/templates/networks.yml.j2' %} + + openwebui: + image: ghcr.io/open-webui/open-webui:main + container_name: openwebui + restart: unless-stopped + depends_on: [ollama] + ports: + - "3001:8080" + environment: + - OLLAMA_BASE_URL=http://ollama:11434 + - OFFLINE_MODE=1 # blockt Netz-Zugriffe der App + - HF_HUB_OFFLINE=1 # zwingt HF-Client in Offline-Mode + - ENABLE_PERSISTENT_CONFIG=False # nimm ENV 1:1, ignoriere persistente Defaults + volumes: + - openwebui_data:/app/backend/data +{% include 'roles/docker-container/templates/networks.yml.j2' %} + + # ===== Model/Tool Proxy (OpenAI-kompatibel) ===== + litellm: + image: ghcr.io/berriai/litellm:main-v1.77.3.dynamic_rates + container_name: litellm + restart: unless-stopped + depends_on: [ollama] + ports: ["4000:4000"] + environment: + - LITELLM_MASTER_KEY=dummy-key + - LITELLM_CONFIG=/etc/litellm/config.yaml + volumes: + - ./litellm.config.yaml:/etc/litellm/config.yaml:ro + command: > + --host 0.0.0.0 + --port 4000 + --config /etc/litellm/config.yaml +{% include 'roles/docker-container/templates/networks.yml.j2' %} + + # ===== VectorDB ===== + qdrant: + image: qdrant/qdrant:latest + container_name: qdrant + restart: unless-stopped + ports: + - "6333:6333" # HTTP + - "6334:6334" # gRPC + volumes: + - qdrant_data:/qdrant/storage +{% include 'roles/docker-container/templates/networks.yml.j2' %} + + # ===== Flow/Orchestrator ===== + flowise: + image: flowiseai/flowise:latest + container_name: flowise + restart: unless-stopped + depends_on: [qdrant, litellm] + ports: + - "3000:3000" + environment: + - PORT=3000 + - FLOWISE_USERNAME=admin + - FLOWISE_PASSWORD=admin + - DATABASE_PATH=/root/.flowise + - FLOWISE_FILE_STORAGE_PATH=/root/.flowise/storage + # Qdrant + LiteLLM/Ollama: + - QDRANT_URL=http://qdrant:6333 + - OPENAI_API_BASE=http://litellm:4000/v1 + - OPENAI_API_KEY=dummy-key + volumes: + - flowise_data:/root/.flowise +{% include 'roles/docker-container/templates/networks.yml.j2' %} + + # ===== Knowledge (Optional: DMS/Bucket für Dokumente) ===== + minio: + image: quay.io/minio/minio:latest + container_name: minio + restart: unless-stopped + networks: [ai] + ports: + - "9000:9000" # S3 API + - "9001:9001" # Console + environment: + - MINIO_ROOT_USER=admin + - MINIO_ROOT_PASSWORD=adminadmin + command: server /data --console-address ":9001" + volumes: + - minio_data:/data +{% include 'roles/docker-container/templates/networks.yml.j2' %} + +{% include 'roles/docker-compose/templates/networks.yml.j2' %} + +{% include 'roles/docker-compose/templates/volumes.yml.j2' %} + ollama_models: + openwebui_data: + qdrant_data: + flowise_data: + minio_data: diff --git a/roles/web-app-ai-assistant/templates/litellm.config.yaml.j2 b/roles/web-app-ai-assistant/templates/litellm.config.yaml.j2 new file mode 100644 index 00000000..11471f99 --- /dev/null +++ b/roles/web-app-ai-assistant/templates/litellm.config.yaml.j2 @@ -0,0 +1,15 @@ +model_list: + - model_name: ollama/llama3 + litellm_params: + model: ollama/llama3 + api_base: http://ollama:11434 + rpm: 1000 + - model_name: ollama/nomic-embed-text + litellm_params: + model: ollama/nomic-embed-text + api_base: http://ollama:11434 + rpm: 1000 + +litellm_settings: + drop_params: true + set_verbose: true diff --git a/roles/web-app-ai-assistant/vars/main.yml b/roles/web-app-ai-assistant/vars/main.yml new file mode 100644 index 00000000..a9f2d8c5 --- /dev/null +++ b/roles/web-app-ai-assistant/vars/main.yml @@ -0,0 +1,28 @@ + +# General +application_id: "web-app-akaunting" +js_application_name: "Akaunting" + +# Database +database_type: "mariadb" +database_password: "{{ applications | get_app_conf(application_id, 'credentials.database_password') }}" + +# Docker +docker_repository_address: "https://github.com/akaunting/docker.git" +docker_pull_git_repository: true +docker_repository_branch: "master" +docker_compose_skipp_file_creation: false + +# Akaunting +AKAUNTING_URL: "{{ domains | get_url(application_id, WEB_PROTOCOL) }}" +AKAUNTING_VERSION: "{{ applications | get_app_conf(application_id, 'docker.services.akaunting.version') }}" +AKAUNTING_IMAGE: "{{ applications | get_app_conf(application_id, 'docker.services.akaunting.image') }}" +AKAUNTING_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.akaunting.name') }}" +AKAUNTING_VOLUME: "{{ applications | get_app_conf(application_id, 'docker.volumes.data') }}" +AKAUNTING_COMPANY_NAME: "{{ applications | get_app_conf(application_id, 'company.name') }}" +AKAUNTING_COMPANY_EMAIL: "{{ applications | get_app_conf(application_id, 'company.email') }}" +AKAUNTING_ADMIN_EMAIL: "{{ applications | get_app_conf(application_id, 'setup_admin_email') }}" +AKAUNTING_ADMIN_PASSWORD: "{{ applications | get_app_conf(application_id, 'credentials.setup_admin_password') }}" +AKAUNTING_SETUP_MARKER: "{{ [ (AKAUNTING_VOLUME | docker_volume_path), '.akaunting_installed' ] | path_join }}" +AKAUNTING_APP_KEY: "{{ applications | get_app_conf(application_id, 'credentials.app_key') }}" +AKAUNTING_CACHE_DRIVER: "{{ 'redis' if applications | get_app_conf(application_id, 'docker.services.redis.enabled') else 'file' }}" \ No newline at end of file