diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0e1fd49ee..3c6384321 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,3 @@ * @sr-remsha @PolinaGurinovich97 /dial-cookbook/ @adubovik -/dial-docker-compose/ @adubovik /.github/ @nepalevov @alexey-ban diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 0a7639e24..5eaf08aeb 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -65,6 +65,26 @@ jobs: cd ./dial-docker-compose/ci/ollama docker compose up --abort-on-container-exit --exit-code-from test --timeout 300 + run-advanced-v1-smoke-test: + name: Docker compose advanced v1 smoke test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: isbang/compose-action@d2bee4f07e8ca410d6b196d00f90c12e7d48c33a # v2.6.0 + with: + cwd: "./dial-docker-compose-advanced-v1/ci" + up-flags: "--abort-on-container-exit --exit-code-from test --timeout 300" + + run-advanced-v2-smoke-test: + name: Docker compose advanced v2 smoke test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: isbang/compose-action@d2bee4f07e8ca410d6b196d00f90c12e7d48c33a # v2.6.0 + with: + cwd: "./dial-docker-compose-advanced-v2/ci" + up-flags: "--abort-on-container-exit --exit-code-from test --timeout 300" + build: needs: - run-notebooks @@ -72,6 +92,8 @@ jobs: - run-quickstart-application - run-quickstart-addon - run-quickstart-self-hosted-model + - run-advanced-v1-smoke-test + - run-advanced-v2-smoke-test runs-on: ubuntu-latest steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e8670472f..ad9118609 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,6 +66,26 @@ jobs: cd ./dial-docker-compose/ci/ollama docker compose up --abort-on-container-exit --exit-code-from test --timeout 300 + run-advanced-v1-smoke-test: + name: Docker compose advanced v1 smoke test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: isbang/compose-action@d2bee4f07e8ca410d6b196d00f90c12e7d48c33a # v2.6.0 + with: + cwd: "./dial-docker-compose-advanced-v1/ci" + up-flags: "--abort-on-container-exit --exit-code-from test --timeout 300" + + run-advanced-v2-smoke-test: + name: Docker compose advanced v2 smoke test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: isbang/compose-action@d2bee4f07e8ca410d6b196d00f90c12e7d48c33a # v2.6.0 + with: + cwd: "./dial-docker-compose-advanced-v2/ci" + up-flags: "--abort-on-container-exit --exit-code-from test --timeout 300" + build-and-deploy: needs: - run-notebooks @@ -73,6 +93,8 @@ jobs: - run-quickstart-application - run-quickstart-addon - run-quickstart-self-hosted-model-ollama + - run-advanced-v1-smoke-test + - run-advanced-v2-smoke-test runs-on: ubuntu-latest steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 diff --git a/dial-docker-compose-advanced/.env b/dial-docker-compose-advanced-v1/.env similarity index 100% rename from dial-docker-compose-advanced/.env rename to dial-docker-compose-advanced-v1/.env diff --git a/dial-docker-compose-advanced-v1/.gitignore b/dial-docker-compose-advanced-v1/.gitignore new file mode 100644 index 000000000..6a94c2c4d --- /dev/null +++ b/dial-docker-compose-advanced-v1/.gitignore @@ -0,0 +1,7 @@ +# admin-backend runtime data (H2 db, etc.) +admin/ + +core-data/ +core-logs/ + +keycloak/data/ diff --git a/dial-docker-compose-advanced/README.md b/dial-docker-compose-advanced-v1/README.md similarity index 100% rename from dial-docker-compose-advanced/README.md rename to dial-docker-compose-advanced-v1/README.md diff --git a/dial-docker-compose-advanced-v1/ci/docker-compose.yml b/dial-docker-compose-advanced-v1/ci/docker-compose.yml new file mode 100644 index 000000000..3cfdff88a --- /dev/null +++ b/dial-docker-compose-advanced-v1/ci/docker-compose.yml @@ -0,0 +1,15 @@ +include: + - path: ../docker-compose-base.yml + env_file: ../.env + +services: + test: + build: test + environment: + CORE_URL: "http://core:8080" + KEYCLOAK_URL: "http://keycloak:${KC_PORT:-8900}" + depends_on: + core: + condition: service_started + keycloak: + condition: service_started diff --git a/dial-docker-compose-advanced-v1/ci/test/Dockerfile b/dial-docker-compose-advanced-v1/ci/test/Dockerfile new file mode 100644 index 000000000..32b33adfa --- /dev/null +++ b/dial-docker-compose-advanced-v1/ci/test/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.11-alpine + +WORKDIR /app +COPY * /app +RUN pip install -r requirements.txt + +CMD ["python", "app.py"] diff --git a/dial-docker-compose-advanced-v1/ci/test/app.py b/dial-docker-compose-advanced-v1/ci/test/app.py new file mode 100644 index 000000000..67c38ff8d --- /dev/null +++ b/dial-docker-compose-advanced-v1/ci/test/app.py @@ -0,0 +1,42 @@ +import asyncio +import logging +import os + +import aiohttp +import backoff + + +def get_env(name: str) -> str: + value = os.environ.get(name) + if value is None: + raise ValueError(f"'{name}' environment variable must be defined") + return value + + +CORE_URL = get_env("CORE_URL") +KEYCLOAK_URL = get_env("KEYCLOAK_URL") + +logging.basicConfig(level=logging.INFO) + + +@backoff.on_exception( + backoff.expo, + (aiohttp.ClientError, asyncio.TimeoutError), + max_time=120, +) +async def check_reachable(url: str): + timeout = aiohttp.ClientTimeout(total=10) + async with aiohttp.ClientSession(timeout=timeout) as session: + async with session.get(url) as response: + logging.info("%s -> %s", url, response.status) + if response.status >= 500: + raise RuntimeError(f"{url} responded with {response.status}") + + +async def tests(): + await check_reachable(f"{KEYCLOAK_URL}/realms/master") + await check_reachable(f"{CORE_URL}/health") + + +if __name__ == "__main__": + asyncio.run(tests()) diff --git a/dial-docker-compose-advanced-v1/ci/test/requirements.txt b/dial-docker-compose-advanced-v1/ci/test/requirements.txt new file mode 100644 index 000000000..38bbda2ba --- /dev/null +++ b/dial-docker-compose-advanced-v1/ci/test/requirements.txt @@ -0,0 +1,2 @@ +aiohttp==3.14.3 +backoff==2.2.1 diff --git a/dial-docker-compose-advanced/core/config.json b/dial-docker-compose-advanced-v1/core/config.json similarity index 100% rename from dial-docker-compose-advanced/core/config.json rename to dial-docker-compose-advanced-v1/core/config.json diff --git a/dial-docker-compose-advanced/docker-compose-base.yml b/dial-docker-compose-advanced-v1/docker-compose-base.yml similarity index 95% rename from dial-docker-compose-advanced/docker-compose-base.yml rename to dial-docker-compose-advanced-v1/docker-compose-base.yml index b895c21f8..072ee914c 100644 --- a/dial-docker-compose-advanced/docker-compose-base.yml +++ b/dial-docker-compose-advanced-v1/docker-compose-base.yml @@ -1,7 +1,7 @@ services: themes: - image: epam/ai-dial-chat-themes:0.10.0 + image: epam/ai-dial-chat-themes:0.19.1 platform: linux/amd64 ports: - "3101:8080" @@ -21,7 +21,7 @@ services: mem_limit: 2200M chat: - image: epam/ai-dial-chat:0.41.7 + image: epam/ai-dial-chat:0.49.3 platform: linux/amd64 environment: AUTH_KEYCLOAK_CLIENT_ID: "dial-chat" @@ -47,7 +47,7 @@ services: restart: always core: - image: epam/ai-dial-core:0.39.2 + image: epam/ai-dial-core:0.47.1 platform: linux/amd64 environment: 'JAVA_OPTS': '-Dgflog.config=/opt/settings/gflog.xml' @@ -78,7 +78,7 @@ services: restart: always adapter-openai: - image: epam/ai-dial-adapter-openai:0.36.1 + image: epam/ai-dial-adapter-openai:0.43.2 platform: linux/amd64 environment: DALLE3_DEPLOYMENTS: "dall-e-3" @@ -111,7 +111,7 @@ services: restart: always admin-backend: - image: epam/ai-dial-admin-backend:0.13.0 + image: epam/ai-dial-admin-backend:0.20.0 platform: linux/amd64 user: root environment: @@ -142,7 +142,7 @@ services: restart: always admin-frontend: - image: epam/ai-dial-admin-frontend:0.13.0 + image: epam/ai-dial-admin-frontend:0.20.0 platform: linux/amd64 environment: DIAL_ADMIN_API_URL: "http://admin-backend:8080/" diff --git a/dial-docker-compose-advanced/docker-compose-full.yml b/dial-docker-compose-advanced-v1/docker-compose-full.yml similarity index 91% rename from dial-docker-compose-advanced/docker-compose-full.yml rename to dial-docker-compose-advanced-v1/docker-compose-full.yml index b46e7bcc2..714b5fde1 100644 --- a/dial-docker-compose-advanced/docker-compose-full.yml +++ b/dial-docker-compose-advanced-v1/docker-compose-full.yml @@ -4,7 +4,7 @@ include: services: dial-rag: - image: ghcr.io/epam/ai-dial-rag:0.32.0 + image: ghcr.io/epam/ai-dial-rag:0.43.0 platform: linux/amd64 env_file: .env environment: diff --git a/dial-docker-compose-advanced/keycloak/import/realm-config.json b/dial-docker-compose-advanced-v1/keycloak/import/realm-config.json similarity index 100% rename from dial-docker-compose-advanced/keycloak/import/realm-config.json rename to dial-docker-compose-advanced-v1/keycloak/import/realm-config.json diff --git a/dial-docker-compose-advanced/settings/gflog.xml b/dial-docker-compose-advanced-v1/settings/gflog.xml similarity index 100% rename from dial-docker-compose-advanced/settings/gflog.xml rename to dial-docker-compose-advanced-v1/settings/gflog.xml diff --git a/dial-docker-compose-advanced/settings/settings.json b/dial-docker-compose-advanced-v1/settings/settings.json similarity index 100% rename from dial-docker-compose-advanced/settings/settings.json rename to dial-docker-compose-advanced-v1/settings/settings.json diff --git a/dial-docker-compose-advanced-v2/.env b/dial-docker-compose-advanced-v2/.env new file mode 100644 index 000000000..ad4d55c4f --- /dev/null +++ b/dial-docker-compose-advanced-v2/.env @@ -0,0 +1,23 @@ +COMMON_HOST=localhost + +# Core +DIAL_CORE_HOST_PORT=8081 +DIAL_CORE_ENCRYPTION_SECRET=core_encryption_secret +DIAL_CORE_ENCRYPTION_KEY=core_encryption_key + +# Chat +DIAL_CHAT_HOST_PORT=3100 +AUTH_SESSION_SECRET=f48bbcf155737c653c87b307b3fa84d49e2038c835415c3bfa16c9cc68a9406e +AUTH_KEYCLOAK_SECRET=keycloak_secret + +# Keycloak +KC_ADMIN_PASSWORD=admin +KC_PORT=8900 +KC_HTTPS_PORT=8901 + +# Admin +DIAL_ADMIN_FRONTEND_HOST_PORT=3102 +NEXTAUTH_SECRET=JujxVSQV/VsqvE6qi92YwelW6FX/wXtGDpTmyVlyoEA= +H2_DATASOURCE_MASTER_KEY=t8+npcgNMiipR+kHMb8zXAjgA3IedCXC +H2_DATASOURCE_ENCRYPTED_FILE_KEY=9vW1l/Eg+1J3YXpCsyR6AUI4ptMtI6pjkktePuUQts+wKVAauoP5CG21z5WTzp91xBcEww== +H2_DATASOURCE_PASSWORD=password diff --git a/dial-docker-compose-advanced-v2/.gitignore b/dial-docker-compose-advanced-v2/.gitignore new file mode 100644 index 000000000..708139b00 --- /dev/null +++ b/dial-docker-compose-advanced-v2/.gitignore @@ -0,0 +1,7 @@ +# admin-backend runtime data (H2 db, etc.) +admin/ + +core-data/ +core-logs/ + +keycloak/data/ \ No newline at end of file diff --git a/dial-docker-compose-advanced-v2/README.md b/dial-docker-compose-advanced-v2/README.md new file mode 100644 index 000000000..21c8c4eb6 --- /dev/null +++ b/dial-docker-compose-advanced-v2/README.md @@ -0,0 +1,36 @@ +# DIAL Docker Compose (DIAL 2.0) + +### 1. Setup model endpoints and keys + +Update `./core/config.json` with real upstream model endpoints and keys. + +### 2. Run the Docker Compose file + +``` +docker compose -f up +``` + +Choose one of the Compose files depending on your needs: + +|File|Description| +|---|---| +|docker-compose-base.yml|Runs Core, Chat, Admin, Keycloak and required underlying services| +|docker-compose-full.yml|Runs RAG in addition to the base services from above| + +### 3. Start using DIAL + +|URL|Description| +|---|---| +|http://localhost:3100|DIAL Chat| +|http://localhost:3102|DIAL Admin| +|http://localhost:8900|Keycloak| + +There are three default DIAL users pre-defined in Keycloak: + +|Username|Password|Description| +|---|---|---| +|user|dial|Has only basic access to DIAL Chat| +|dial|dial|Has admin access to DIAL Chat| +|dial-admin|dial|Has access to DIAL Admin console| + +Use `admin` as a user and a password to login to Keycloak as administrator. diff --git a/dial-docker-compose-advanced-v2/ci/docker-compose.yml b/dial-docker-compose-advanced-v2/ci/docker-compose.yml new file mode 100644 index 000000000..2b07c201b --- /dev/null +++ b/dial-docker-compose-advanced-v2/ci/docker-compose.yml @@ -0,0 +1,15 @@ +include: + - path: ../docker-compose-base.yml + env_file: ../.env + +services: + test: + build: test + environment: + CORE_URL: "http://core:8080" + KEYCLOAK_URL: "http://keycloak:${KC_PORT:-8900}" + depends_on: + core: + condition: service_started + keycloak: + condition: service_healthy diff --git a/dial-docker-compose-advanced-v2/ci/test/Dockerfile b/dial-docker-compose-advanced-v2/ci/test/Dockerfile new file mode 100644 index 000000000..32b33adfa --- /dev/null +++ b/dial-docker-compose-advanced-v2/ci/test/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.11-alpine + +WORKDIR /app +COPY * /app +RUN pip install -r requirements.txt + +CMD ["python", "app.py"] diff --git a/dial-docker-compose-advanced-v2/ci/test/app.py b/dial-docker-compose-advanced-v2/ci/test/app.py new file mode 100644 index 000000000..67c38ff8d --- /dev/null +++ b/dial-docker-compose-advanced-v2/ci/test/app.py @@ -0,0 +1,42 @@ +import asyncio +import logging +import os + +import aiohttp +import backoff + + +def get_env(name: str) -> str: + value = os.environ.get(name) + if value is None: + raise ValueError(f"'{name}' environment variable must be defined") + return value + + +CORE_URL = get_env("CORE_URL") +KEYCLOAK_URL = get_env("KEYCLOAK_URL") + +logging.basicConfig(level=logging.INFO) + + +@backoff.on_exception( + backoff.expo, + (aiohttp.ClientError, asyncio.TimeoutError), + max_time=120, +) +async def check_reachable(url: str): + timeout = aiohttp.ClientTimeout(total=10) + async with aiohttp.ClientSession(timeout=timeout) as session: + async with session.get(url) as response: + logging.info("%s -> %s", url, response.status) + if response.status >= 500: + raise RuntimeError(f"{url} responded with {response.status}") + + +async def tests(): + await check_reachable(f"{KEYCLOAK_URL}/realms/master") + await check_reachable(f"{CORE_URL}/health") + + +if __name__ == "__main__": + asyncio.run(tests()) diff --git a/dial-docker-compose-advanced-v2/ci/test/requirements.txt b/dial-docker-compose-advanced-v2/ci/test/requirements.txt new file mode 100644 index 000000000..38bbda2ba --- /dev/null +++ b/dial-docker-compose-advanced-v2/ci/test/requirements.txt @@ -0,0 +1,2 @@ +aiohttp==3.14.3 +backoff==2.2.1 diff --git a/dial-docker-compose-advanced-v2/core/config.json b/dial-docker-compose-advanced-v2/core/config.json new file mode 100644 index 000000000..3034643ea --- /dev/null +++ b/dial-docker-compose-advanced-v2/core/config.json @@ -0,0 +1,86 @@ +{ + "routes": {}, + "applications": { + "dial-rag" : { + "displayName": "Dial RAG", + "description": "RAG (Retrieval Augmented Generation)", + "endpoint": "http://dial-rag:5000/openai/deployments/dial-rag/chat/completions", + "inputAttachmentTypes": [ + "*/*" + ] + } + }, + "models": { + "gpt-5": { + "type": "chat", + "displayName": "GPT-5", + "endpoint": "http://adapter-openai:5000/openai/deployments/gpt-5/chat/completions", + "features": { + "toolsSupported": true + }, + "upstreams": [ + { + "endpoint": "http://azure_or_dial_deployment_host/openai/deployments/gpt-5/chat/completions", + "key": "AZURE_MODEL_OR_DIAL_API_KEY" + } + ], + "inputAttachmentTypes": [ "*/*" ] + }, + "claude-sonnet-4-5-20250929": { + "type": "chat", + "displayName": "Claude Sonnet 4.5", + "overrideName": "claude-sonnet-4-5-20250929", + "endpoint": "http://adapter-openai:5000/openai/deployments/claude-sonnet-4-5-20250929/chat/completions", + "interfaces": { + "anthropicMessages": { + "base_url": "http://adapter-openai:5000" + } + }, + "defaults": { + "max_tokens": 4096 + }, + "upstreams": [ + { + "endpoint": "https://api.anthropic.com/v1/messages", + "key": "ANTHROPIC_API_KEY" + } + ], + "inputAttachmentTypes": [ "*/*" ] + }, + "dall-e-3": { + "type": "chat", + "displayName": "DALL-E 3", + "features": { + "systemPromptSupported": false + }, + "pricing": { + "unit": "token", + "prompt": "0", + "completion": "0.04" + }, + "endpoint": "http://adapter-openai:5000/openai/deployments/dall-e-3/chat/completions", + "upstreams": [ + { + "endpoint": "http://azure_or_dial_deployment_host/openai/deployments/dall-e-3/images/generations", + "key": "AZURE_MODEL_OR_DIAL_API_KEY" + } + ] + } + }, + "keys": { + "dial_api_key": { + "project": "TEST-PROJECT", + "role": "default" + } + }, + "roles": { + "default": { + "limits": { + "gpt-5": {}, + "claude-sonnet-4-5-20250929": {}, + "dall-e-3": {}, + "dial-rag": {} + } + } + } +} diff --git a/dial-docker-compose-advanced-v2/docker-compose-base.yml b/dial-docker-compose-advanced-v2/docker-compose-base.yml new file mode 100644 index 000000000..260a27bec --- /dev/null +++ b/dial-docker-compose-advanced-v2/docker-compose-base.yml @@ -0,0 +1,177 @@ +services: + + # ----------------- # + # DIAL Components + # ----------------- # + + themes: + image: epam/ai-dial-chat-themes:0.19.1 + platform: linux/amd64 + ports: + - "3101:8080" + + chat: + image: epam/ai-dial-chat:1.0.15 + platform: linux/amd64 + environment: + PORT: ${DIAL_CHAT_HOST_PORT} + API_PREFIX: "api" + AUTH_SESSION_SECRET: "${AUTH_SESSION_SECRET}" + AUTH_CALLBACK_BASE_URL: "http://${COMMON_HOST}:${DIAL_CHAT_HOST_PORT}" + AUTH_POST_LOGOUT_REDIRECT_URI: "http://${COMMON_HOST}:${DIAL_CHAT_HOST_PORT}" + AUTH_KEYCLOAK_CLIENT_ID: "dial-chat" + AUTH_KEYCLOAK_SECRET: "${AUTH_KEYCLOAK_SECRET}" + AUTH_KEYCLOAK_HOST: "http://${COMMON_HOST}:${KC_PORT}/realms/dial" + AUTH_KEYCLOAK_DIAL_ROLES_FIELD: "resource_access.dial-chat.roles" + AUTH_COOKIE_SECURE: "false" + DIAL_CORE_URL: "http://core:8080" + THEMES_CONFIG_URL: "http://themes:8080" + ENABLED_UI_FEATURES: "code-apps,schema-apps,custom-apps,chat-settings,dislike-comment,input-files,likes,live-chat-interaction,attachments-manager,conversations-panel-toggle,conversations-section,header,showConversationsSectionByDefault,catalog,catalog-table-view,file-manager,conversations-publishing,applications-sharing,conversations-sharing,toolsets-sharing,toolsets,prompts,skills,voice-input" + LIVE_CHAT_INTERACTION_ENABLED: "true" + RESPONSES_API_ENABLED: "true" + network_mode: "service:keycloak" + depends_on: + themes: + condition: service_started + core: + condition: service_started + keycloak: + condition: service_healthy + restart: always + + core: + image: epam/ai-dial-core:0.47.1 + platform: linux/amd64 + environment: + 'JAVA_OPTS': '-Dgflog.config=/opt/settings/gflog.xml' + 'aidial.config.files': '["/app/config/config.json"]' + 'aidial.identityProviders.keycloak.jwksUrl': 'http://keycloak:${KC_PORT}/realms/dial/protocol/openid-connect/certs' + 'aidial.identityProviders.keycloak.rolePath': 'roles' + 'aidial.access.admin.rules': '[{"source": "roles", "function": "CONTAIN", "targets": ["admin"]}]' + 'aidial.identityProviders.keycloak.loggingKey': 'email' + 'aidial.identityProviders.keycloak.loggingSalt': 'loggingSalt' + 'aidial.encryption.secret': '${DIAL_CORE_ENCRYPTION_SECRET}' + 'aidial.encryption.key': '${DIAL_CORE_ENCRYPTION_KEY}' + 'aidial.redis.singleServerConfig.address': 'redis://redis:6379' + 'aidial.storage.provider': 'filesystem' + 'aidial.storage.prefix': 'core' + 'aidial.storage.bucket': 'dial' + 'aidial.storage.createBucket': 'true' + 'aidial.storage.overrides': '{"jclouds.filesystem.basedir": "data"}' + 'aidial.applications.includeCustomApps': 'true' + ports: + - "${DIAL_CORE_HOST_PORT}:8080" + volumes: + - ${DIAL_DIR:-.}/core:/app/config + - ${DIAL_DIR:-.}/core-logs:/app/log + - ${DIAL_DIR:-.}/core-data:/app/data + - ./settings:/opt/settings + depends_on: + - redis + restart: always + + adapter-openai: + image: epam/ai-dial-adapter-openai:0.43.2 + platform: linux/amd64 + environment: + DIAL_URL: "http://core:8080" + WEB_CONCURRENCY: "3" + DALLE3_DEPLOYMENTS: "dall-e-3" + + admin-backend: + image: epam/ai-dial-admin-backend:0.20.1 + platform: linux/amd64 + user: root + environment: + ENABLE_CORE_CONFIG_VERSION_AUTO_DETECT: "true" + CONFIG_EXPORT_OUTPUTFILE_PATH: /app/config/config.json + CONFIG_REST_SECURITY_MODE: "oidc" + CORE_CLIENT_URL: "http://core:8080" + DEBUG_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5006" + DISABLE_SWAGGER_AUTHORIZATION: true + ENABLE_CONFIG_AUTO_IMPORT_ON_BOOTSTRAP: "true" + H2_DATASOURCE_ENCRYPTED_FILE_KEY: ${H2_DATASOURCE_ENCRYPTED_FILE_KEY} + H2_DATASOURCE_MASTER_KEY: ${H2_DATASOURCE_MASTER_KEY} + H2_DATASOURCE_PASSWORD: ${H2_DATASOURCE_PASSWORD} + H2_FILE: ./data/testdb + METRICS_ENABLED: "false" + 'providers.keycloak.audiences': 'dial-admin-console' + 'providers.keycloak.issuer': "http://${COMMON_HOST}:${KC_PORT}/realms/dial" + 'providers.keycloak.jwk-set-uri': "http://keycloak:${KC_PORT}/realms/dial/protocol/openid-connect/certs" + 'providers.keycloak.role-claims': roles + volumes: + - ${DIAL_DIR:-.}/admin/data:/app/data + - ${DIAL_DIR:-.}/core:/app/config + depends_on: + core: + condition: service_started + restart: always + + admin-frontend: + image: epam/ai-dial-admin-frontend:0.20.2 + platform: linux/amd64 + environment: + DIAL_ADMIN_API_URL: "http://admin-backend:8080/" + DIAL_CORE_API_URL: "http://core:8080/" + THEMES_CONFIG_URL: "http://themes:8080/" + NEXTAUTH_URL: "http://${COMMON_HOST}:${DIAL_ADMIN_FRONTEND_HOST_PORT}" + NEXTAUTH_SECRET: "${NEXTAUTH_SECRET}" + NEXTAUTH_COOKIE_PREFIX: "admin" + AUTH_KEYCLOAK_HOST: "http://${COMMON_HOST}:${KC_PORT}/realms/dial" + AUTH_KEYCLOAK_CLIENT_ID: "dial-admin-console" + AUTH_KEYCLOAK_SECRET: "${AUTH_KEYCLOAK_SECRET}" + AUTH_KEYCLOAK_DIAL_ROLES_FIELD: "roles" + ADMIN_ROLE_NAMES: 'ConfigAdmin,admin' + network_mode: "service:keycloak" + depends_on: + keycloak: + condition: service_healthy + admin-backend: + condition: service_started + restart: always + + # ----------------- # + # Dependencies + # ----------------- # + redis: + image: redis:7.2.4-alpine3.19 + restart: always + ports: + - "6600:6379" + command: > + redis-server + --maxmemory 2000mb + --maxmemory-policy volatile-lfu + --save "" + --appendonly no + --loglevel warning + mem_limit: 2200M + + keycloak: + image: keycloak/keycloak:26.7 + user: root + command: ["start-dev", "--import-realm", "--http-port=${KC_PORT}"] + environment: + KC_BOOTSTRAP_ADMIN_USERNAME: admin + KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD} + KC_HOSTNAME: http://${COMMON_HOST}:${KC_PORT} + KC_HOSTNAME_STRICT: true + KC_HTTP_ENABLED: true + QUARKUS_HTTP_LIMITS_MAX_HEADER_SIZE: 64k + KC_INITIALIZE_EMPTY: 'true' + KC_CACHE: local + KC_HEALTH_ENABLED: 'true' + ports: + - "${KC_PORT}:${KC_PORT}" + - "${DIAL_CHAT_HOST_PORT}:${DIAL_CHAT_HOST_PORT}" + - "${DIAL_ADMIN_FRONTEND_HOST_PORT}:3000" + volumes: + - ./keycloak/data:/opt/keycloak/data + - ./keycloak/import/realm-config.json:/opt/keycloak/data/import/realm-config.json + restart: always + healthcheck: + test: ["CMD-SHELL", "bash -c 'exec 3<>/dev/tcp/127.0.0.1/${KC_PORT}'"] + interval: 5s + timeout: 5s + retries: 30 + start_period: 20s \ No newline at end of file diff --git a/dial-docker-compose-advanced-v2/docker-compose-full.yml b/dial-docker-compose-advanced-v2/docker-compose-full.yml new file mode 100644 index 000000000..1a9bde645 --- /dev/null +++ b/dial-docker-compose-advanced-v2/docker-compose-full.yml @@ -0,0 +1,18 @@ +include: + - path: ./docker-compose-base.yml + +services: + + dial-rag: + image: ghcr.io/epam/ai-dial-rag:0.43.0 + platform: linux/amd64 + env_file: .env + environment: + DIAL_URL: "http://core:8080" + DIAL_RAG__INDEX_STORAGE__USE_DIAL_FILE_STORAGE: "true" + DIAL_RAG__REQUEST__INDEXING__DESCRIPTION_INDEX__LLM__DEPLOYMENT_NAME: "gpt-5" + DIAL_RAG__REQUEST__QA_CHAIN__CHAT_CHAIN__LLM__DEPLOYMENT_NAME: "gpt-5" + DIAL_RAG__REQUEST__QA_CHAIN__QUERY_CHAIN__LLM__DEPLOYMENT_NAME: "gpt-5" + restart: always + +#TODO: add other DIAL services and/or observability \ No newline at end of file diff --git a/dial-docker-compose-advanced-v2/keycloak/import/realm-config.json b/dial-docker-compose-advanced-v2/keycloak/import/realm-config.json new file mode 100644 index 000000000..13f977d02 --- /dev/null +++ b/dial-docker-compose-advanced-v2/keycloak/import/realm-config.json @@ -0,0 +1,852 @@ +{ + "realm": "dial", + "displayName": "DIAL Keycloak Sign-In", + "displayNameHtml": "

DIAL Keycloak Sign-In

", + "rememberMe": false, + "accessTokenLifespan": 86400, + "ssoSessionIdleTimeout": 86400, + "ssoSessionMaxLifespan": 86400, + "sslRequired": "none", + "browserSecurityHeaders": { + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "referrerPolicy": "no-referrer", + "strictTransportSecurity": "" + }, + "enabled": true, + "roles": { + "client": { + "dial-chat": [ + { + "name": "admin", + "description": "AI DIAL chat admin role", + "composite": false, + "clientRole": true + }, + { + "name": "user", + "description": "AI DIAL chat user role", + "composite": false, + "clientRole": true + } + ], + "dial-admin-console": [ + { + "name": "admin", + "description": "AI DIAL web-console admin user role", + "composite": false, + "clientRole": true + }, + { + "name": "ConfigAdmin", + "description": "AI DIAL web-console admin user role", + "composite": false, + "clientRole": true + } + ] + } + }, + "users": [ + { + "username": "dial", + "enabled": true, + "emailVerified": true, + "requiredActions": [], + "email": "no-reply-dial@example.com", + "firstName": "Chat", + "lastName": "Power User", + "credentials": [ + { + "type": "password", + "value": "dial" + } + ], + "clientRoles": { + "dial-chat": [ + "admin" + ] + }, + "realmRoles": [ + "offline_access" + ] + }, + { + "username": "user", + "enabled": true, + "emailVerified": true, + "requiredActions": [], + "email": "no-reply-user@example.com", + "firstName": "Chat", + "lastName": "Regular User", + "credentials": [ + { + "type": "password", + "value": "dial" + } + ], + "clientRoles": { + "dial-chat": [ + "user" + ] + }, + "realmRoles": [ + "offline_access" + ] + }, + { + "username": "dial-admin", + "enabled": true, + "emailVerified": true, + "requiredActions": [], + "email": "no-reply-dial-admin@example.com", + "firstName": "Console", + "lastName": "Admin User", + "credentials": [ + { + "type": "password", + "value": "dial" + } + ], + "clientRoles": { + "dial-admin-console": [ + "ConfigAdmin", + "admin" + ] + }, + "realmRoles": [ + "offline_access" + ] + } + ], + "clientScopes": [ + { + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${profileScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + }, + { + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + } + ] + }, + { + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "consent.screen.text": "", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "name": "basic", + "description": "OpenID Connect scope for add all basic claims to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "name": "sub", + "protocol": "openid-connect", + "protocolMapper": "oidc-sub-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "name": "auth_time", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "AUTH_TIME", + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "auth_time", + "jsonType.label": "long" + } + } + ] + }, + { + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${addressScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "introspection.token.claim": "true", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${phoneScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + }, + { + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + } + ] + }, + { + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${emailScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "consent.screen.text": "${rolesScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "name": "organization", + "description": "Additional claims about the organization a subject belongs to", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${organizationScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "name": "organization", + "protocol": "openid-connect", + "protocolMapper": "oidc-organization-membership-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "organization", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + } + ], + "clients": [ + { + "clientId": "dial-chat", + "name": "dial-chat", + "description": "AI DIAL chat client", + "rootUrl": "http://localhost:3100/", + "adminUrl": "http://localhost:3100/", + "baseUrl": "http://localhost:3100/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "keycloak_secret", + "redirectUris": [ + "http://localhost:3100/*" + ], + "webOrigins": [ + "http://localhost:3100/" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "standard.token.exchange.enabled": "false", + "post.logout.redirect.uris": "+", + "frontchannel.logout.session.required": "true", + "display.on.consent.screen": "false", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "35a3fb79-6361-4af3-a1f7-c5644da542e4", + "name": "Audience", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "included.client.audience": "dial-chat", + "id.token.claim": "false", + "lightweight.claim": "false", + "access.token.claim": "true", + "introspection.token.claim": "true" + } + }, + { + "id": "02e3982f-4be9-4168-b1a4-34ec22fe8586", + "name": "Client Role", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "roles", + "jsonType.label": "String", + "usermodel.clientRoleMapping.clientId": "dial-chat" + } + } + ], + "defaultClientScopes": [ + "basic", + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "clientId": "dial-admin-console", + "name": "dial-admin-console", + "description": "AI DIAL WebConsole admin", + "rootUrl": "http://localhost:3102/", + "adminUrl": "http://localhost:3102/", + "baseUrl": "http://localhost:3102/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "keycloak_secret", + "redirectUris": [ + "http://localhost:3102/*" + ], + "webOrigins": [ + "http://localhost:3102/" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "standard.token.exchange.enabled": "false", + "post.logout.redirect.uris": "+", + "frontchannel.logout.session.required": "true", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false", + "use.refresh.tokens": "true", + "realm_client": "false", + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "client_credentials.use_refresh_token": "false", + "tls.client.certificate.bound.access.tokens": "false", + "acr.loa.map": "{}", + "display.on.consent.screen": "false", + "token.response.type.bearer.lower-case": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "aee57d45-cdbd-45c3-ab65-082088758d99", + "name": "Client Roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "roles", + "jsonType.label": "String", + "usermodel.clientRoleMapping.clientId": "dial-admin-console" + } + }, + { + "id": "61f26395-a34c-4d44-a338-cfac35b39e8a", + "name": "Audience", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-mapper", + "consentRequired": false, + "config": { + "included.client.audience": "dial-admin-console", + "id.token.claim": "false", + "lightweight.claim": "false", + "access.token.claim": "true", + "introspection.token.claim": "true" + } + } + ], + "defaultClientScopes": [ + "basic", + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ] +} \ No newline at end of file diff --git a/dial-docker-compose-advanced-v2/settings/gflog.xml b/dial-docker-compose-advanced-v2/settings/gflog.xml new file mode 100644 index 000000000..496e97acf --- /dev/null +++ b/dial-docker-compose-advanced-v2/settings/gflog.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dial-docker-compose/addon/.env b/dial-docker-compose/addon/.env index a012d445d..49d6b7f76 100644 --- a/dial-docker-compose/addon/.env +++ b/dial-docker-compose/addon/.env @@ -1 +1,5 @@ -DIAL_DIR="./addon" \ No newline at end of file +DIAL_DIR="./addon" + +# DIAL Core dropped the legacy top-level "assistant" config block (used by the +# todo-assistant deployment below) in 0.38.0 - pin below the common.yml default. +CORE_VERSION=0.37.0 \ No newline at end of file diff --git a/dial-docker-compose/addon/docker-compose.yml b/dial-docker-compose/addon/docker-compose.yml index c5e91ade8..2d9a13e87 100644 --- a/dial-docker-compose/addon/docker-compose.yml +++ b/dial-docker-compose/addon/docker-compose.yml @@ -4,7 +4,7 @@ include: services: adapter-openai: - image: epam/ai-dial-adapter-openai:0.22.0 + image: epam/ai-dial-adapter-openai:0.43.2 environment: WEB_CONCURRENCY: "3" diff --git a/dial-docker-compose/common.yml b/dial-docker-compose/common.yml index cfc93d472..9cda3f768 100644 --- a/dial-docker-compose/common.yml +++ b/dial-docker-compose/common.yml @@ -1,13 +1,13 @@ services: themes: - image: epam/ai-dial-chat-themes:0.9.1 + image: epam/ai-dial-chat-themes:0.19.1 ports: - "3001:8080" chat: ports: - "3000:3000" - image: epam/ai-dial-chat:0.26.0 + image: epam/ai-dial-chat:0.49.3 depends_on: - themes - core @@ -37,7 +37,7 @@ services: user: ${UID:-root} ports: - "8080:8080" - image: epam/ai-dial-core:0.25.1 + image: epam/ai-dial-core:${CORE_VERSION:-0.47.1} environment: 'AIDIAL_SETTINGS': '/opt/settings/settings.json' 'JAVA_OPTS': '-Dgflog.config=/opt/settings/gflog.xml' diff --git a/dial-docker-compose/model/docker-compose.yml b/dial-docker-compose/model/docker-compose.yml index 59b949a28..beaad009a 100644 --- a/dial-docker-compose/model/docker-compose.yml +++ b/dial-docker-compose/model/docker-compose.yml @@ -4,6 +4,6 @@ include: services: adapter-openai: - image: epam/ai-dial-adapter-openai:0.22.0 + image: epam/ai-dial-adapter-openai:0.43.2 environment: WEB_CONCURRENCY: "3" \ No newline at end of file diff --git a/dial-docker-compose/ollama/docker-compose.yml b/dial-docker-compose/ollama/docker-compose.yml index 31bad0b82..172b47dbd 100644 --- a/dial-docker-compose/ollama/docker-compose.yml +++ b/dial-docker-compose/ollama/docker-compose.yml @@ -22,7 +22,7 @@ services: - OLLAMA_EMBEDDING_MODEL=${OLLAMA_EMBEDDING_MODEL} adapter-openai: - image: epam/ai-dial-adapter-openai:0.22.0 + image: epam/ai-dial-adapter-openai:0.43.2 environment: WEB_CONCURRENCY: "3" DIAL_URL: "http://core:8080" diff --git a/docs/quick-start.md b/docs/quick-start.md index 549d2bbc6..ed0719c63 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -5,6 +5,7 @@ Follow this tutorial to launch DIAL Chat locally with Echo application. As a res > * **Follow this link to [Try DIAL SaaS](https://chat.dialx.ai/) edition**. > * To learn more, watch a [demo video](/docs/video%20demos/3.Developers/Deployment/4.deploy-ollama.md) to see how to deploy a chat application with a self-hosted model. > * Refer to other quick start instructions in [Tutorials](/docs/tutorials/1.developers/0.local-run\0.quick-start-with-application.md). +> * Need the full stack with Admin and Keycloak instead? See [Launch the Full DIAL Stack](/docs/tutorials/1.developers/0.local-run/2.quick-start-full-stack-advanced.md). ## Prerequisites diff --git a/docs/tutorials/1.developers/0.local-run/2.quick-start-full-stack-advanced.md b/docs/tutorials/1.developers/0.local-run/2.quick-start-full-stack-advanced.md new file mode 100644 index 000000000..d8430c3d6 --- /dev/null +++ b/docs/tutorials/1.developers/0.local-run/2.quick-start-full-stack-advanced.md @@ -0,0 +1,41 @@ +# Launch the Full DIAL Stack + +## Introduction + +In this tutorial, you will learn how to quickly launch the full DIAL stack: Core, Chat, the Admin Panel and Keycloak for authentication, all pre-wired together with Docker Compose. + +Two folders are available depending on the DIAL version line you need: + + +- [1.x (legacy)](https://github.com/epam/ai-dial/tree/main/dial-docker-compose-advanced-v1/) +- [**2.x (current)**](https://github.com/epam/ai-dial/tree/main/dial-docker-compose-advanced-v2/) + +> If you only need Chat with a single sample application or model, see the lighter [quick starts](/docs/tutorials/1.developers/0.local-run/0.quick-start-with-application.md) instead. + +## Prerequisites + +1. Docker engine (Docker Compose Version 2.20.0 +) installed on your machine. Refer to [Docker](https://docs.docker.com/desktop/) documentation. + +## Step 1: Get DIAL + +[Download](https://github.com/epam/ai-dial/tree/main/dial-docker-compose-advanced-v1/) the `dial-docker-compose-advanced-v1` folder (legacy), or [download](https://github.com/epam/ai-dial/tree/main/dial-docker-compose-advanced-v2/) the `dial-docker-compose-advanced-v2` folder (current) — whichever version line you need. + +## Step 2: Configuration + +Update `./core/config.json` with your upstream model endpoints and keys. + +## Step 3: Launch DIAL + +Follow the steps in the folder's README ([v1](https://github.com/epam/ai-dial/blob/main/dial-docker-compose-advanced-v1/README.md) / [v2](https://github.com/epam/ai-dial/blob/main/dial-docker-compose-advanced-v2/README.md)) to choose between `docker-compose-base.yml` (Core, Chat, Admin, Keycloak) and `docker-compose-full.yml` (adds RAG), then run: + +```sh +docker compose -f up +``` + +Once running, + +- DIAL Chat is available at http://localhost:3100 +- DIAL Admin console at http://localhost:3102 +- Keycloak at http://localhost:8900 + +Default users and credentials are listed in the same README.