From fc64f9b06fb991d66aba314d5923bac358ea584f Mon Sep 17 00:00:00 2001 From: Artem Astapenko <3767150+jamakase@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:10:04 +0300 Subject: [PATCH] Add ollama docker (#40) * Add ollama docker support * Remove ollama from core docker --- .gitignore | 3 +- docker-compose.ollama.yaml | 144 +++++++++++++++++++++++++++++++ docker-compose.yaml | 4 + services/ml/.gitignore | 1 + services/ml/Dockerfile | 4 +- services/ml/app/config/config.py | 1 + services/ml/app/server.py | 9 +- 7 files changed, 160 insertions(+), 6 deletions(-) create mode 100644 docker-compose.ollama.yaml diff --git a/.gitignore b/.gitignore index 5e7b373..042b2b2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .env instance/ -.pyc \ No newline at end of file +.pyc +.model_cache diff --git a/docker-compose.ollama.yaml b/docker-compose.ollama.yaml new file mode 100644 index 0000000..ee4b4af --- /dev/null +++ b/docker-compose.ollama.yaml @@ -0,0 +1,144 @@ +version: '3.8' + +services: + traefik: + image: traefik:v2.11 + container_name: traefik + command: + - "--api.insecure=true" + - "--providers.docker=true" + - "--entrypoints.web.address=:80" + - "--entrypoints.websecure.address=:443" + ports: + - "80:80" + - "443:443" + - "8080:8080" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./data/ssl:/letsencrypt + restart: always + + frontend_app: + image: cr.yandex/crpc50gkvq2bp251sfgb/app + container_name: frontend_app + build: + context: ./frontend + dockerfile: Dockerfile + environment: + - API_URL=http://api.${HOST} + labels: + - "traefik.enable=true" + - "traefik.http.routers.app.rule=Host(`${HOST}`)" + - "traefik.http.routers.app.entrypoints=web" + - "traefik.http.services.app.loadbalancer.server.port=3000" + + backend_app: + restart: unless-stopped + image: cr.yandex/crpc50gkvq2bp251sfgb/backend + build: + context: ./services/backend + dockerfile: Dockerfile + env_file: + - .env + volumes: + - ./services/backend:/app + environment: + - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} + - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 + - CELERY_RESULT_BACKEND=redis://:${REDIS_PASSWORD}@redis:6379/0 + depends_on: + - db + - redis + ports: + - 5001:5000 + labels: + - "traefik.enable=true" + - "traefik.http.routers.api.rule=Host(`api.${HOST}`)" + - "traefik.http.routers.api.entrypoints=web" + - "traefik.http.services.api.loadbalancer.server.port=5000" + + db: + container_name: db + image: postgres:15 + volumes: + - postgres_data:/var/lib/postgresql/data + environment: + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: ${POSTGRES_DB} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] + interval: 5s + timeout: 10s + retries: 5 + start_period: 10s + ports: + - "5432:5432" + + redis: + container_name: redis + image: redis:6 + ports: + - "6379:6379" + environment: + REDIS_PASSWORD: ${REDIS_PASSWORD} + command: redis-server --requirepass ${REDIS_PASSWORD} + + celery_worker: + image: cr.yandex/crpc50gkvq2bp251sfgb/backend + build: + context: ./services/backend + dockerfile: Dockerfile + command: celery -A celery_worker.celery worker --loglevel=info + volumes: + - ./services/backend:/app + environment: + - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} + - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 + - CELERY_RESULT_BACKEND=redis://:${REDIS_PASSWORD}@redis:6379/0 + depends_on: + - db + - redis + - backend_app + + ml: + restart: unless-stopped + image: cr.yandex/crpc50gkvq2bp251sfgb/ml + build: + context: ./services/ml + dockerfile: Dockerfile + environment: + FAISS_INDEX_PATH: /data/faiss_index + OLLAMA_HOST: http://ollama:11434 + USE_OPENROUTER: false + MODEL: llama3.1 + volumes: + - ./services/ml:/app + - ./services/ml/data:/data + - ./.model_cache:/app/model_cache + depends_on: + - redis + - ollama # Add this line + ports: + - "3001:8000" + + ollama: # Add this new service + image: ollama/ollama:latest + container_name: ollama + ports: + - "7869:11434" + environment: + - OLLAMA_HOST=0.0.0.0 + volumes: + - ollama_data:/root/.ollama + entrypoint: > + sh -c " + ollama serve & + sleep 10 && + ollama run llama3.1 & + wait + " + +volumes: + postgres_data: + ollama_data: diff --git a/docker-compose.yaml b/docker-compose.yaml index 3160d7c..17fe471 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -85,6 +85,7 @@ services: command: redis-server --requirepass ${REDIS_PASSWORD} celery_worker: + image: cr.yandex/crpc50gkvq2bp251sfgb/backend build: context: ./services/backend dockerfile: Dockerfile @@ -101,6 +102,7 @@ services: - backend_app ml: + restart: unless-stopped image: cr.yandex/crpc50gkvq2bp251sfgb/ml build: context: ./services/ml @@ -110,8 +112,10 @@ services: volumes: - ./services/ml:/app - ./services/ml/data:/data + - ./.model_cache:/app/model_cache depends_on: - redis + - ollama # Add this line ports: - "3001:8000" diff --git a/services/ml/.gitignore b/services/ml/.gitignore index bee8a64..af97ac7 100644 --- a/services/ml/.gitignore +++ b/services/ml/.gitignore @@ -1 +1,2 @@ __pycache__ +model_cache \ No newline at end of file diff --git a/services/ml/Dockerfile b/services/ml/Dockerfile index 0b9a799..ce45807 100644 --- a/services/ml/Dockerfile +++ b/services/ml/Dockerfile @@ -8,7 +8,7 @@ RUN apt-get update && apt-get install -y \ && rm -rf /var/lib/apt/lists/* # Install Poetry -RUN curl -sSL https://install.python-poetry.org | python3 - +RUN curl -sSL https://install.python-poetry.org | python3.11 - # Add Poetry to PATH ENV PATH="/root/.local/bin:$PATH" @@ -21,7 +21,7 @@ COPY pyproject.toml poetry.lock* /app/ # Configure Poetry RUN poetry config virtualenvs.create false \ - && poetry install --no-interaction --no-ansi + && poetry install --no-interaction --no-ansi --only main # Runtime stage FROM python:3.11-slim diff --git a/services/ml/app/config/config.py b/services/ml/app/config/config.py index d3d2fb3..25a842b 100644 --- a/services/ml/app/config/config.py +++ b/services/ml/app/config/config.py @@ -7,3 +7,4 @@ class Config: USE_OPENROUTER: bool = os.environ.get("USE_OPENROUTER", "true").lower() == "true" OPENROUTER_API_KEY: str = os.environ.get("OPENROUTER_API_KEY", "placeholder") EMBEDDING_MODEL: str = os.environ.get("EMBEDDING_MODEL", "intfloat/multilingual-e5-base") + OLLAMA_HOST: str = os.environ.get("OLLAMA_HOST", "http://localhost:11434") diff --git a/services/ml/app/server.py b/services/ml/app/server.py index 797a49e..a4b39ab 100644 --- a/services/ml/app/server.py +++ b/services/ml/app/server.py @@ -7,6 +7,8 @@ from packages.retriever import Retriever from packages.prompts import prompt +import os + faiss_index_path = config.FAISS_INDEX_PATH # Create a ChatOllama instance with the llama2 model @@ -20,13 +22,14 @@ base_url="https://openrouter.ai/api/v1", max_tokens=1000, ) - embeddings = HuggingFaceEmbeddings(model_name=config.EMBEDDING_MODEL) + cache_folder = os.path.join(os.getcwd(), "model_cache") + embeddings = HuggingFaceEmbeddings(model_name=config.EMBEDDING_MODEL, cache_folder=cache_folder) else: from langchain_community.chat_models import ChatOllama from langchain_community.embeddings import OllamaEmbeddings - llm = ChatOllama(model=config.MODEL) - embeddings = OllamaEmbeddings(model=config.MODEL) + llm = ChatOllama(model=config.MODEL, base_url=config.OLLAMA_HOST) + embeddings = OllamaEmbeddings(model=config.MODEL, base_url=config.OLLAMA_HOST) retriever_instance = Retriever(embeddings, faiss_index_path)