diff --git a/Dockerfile b/Dockerfile index f6517151..a47871ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,4 +18,4 @@ ARG device_type=cpu RUN --mount=type=cache,target=/root/.cache python ingest.py --device_type $device_type COPY . . ENV device_type=cuda -CMD python run_localGPT.py --device_type $device_type +CMD python run_localGPT.py --device_type $device_type \ No newline at end of file diff --git a/Dockerfile.api b/Dockerfile.api new file mode 100644 index 00000000..9ef60ae4 --- /dev/null +++ b/Dockerfile.api @@ -0,0 +1,23 @@ +# syntax=docker/dockerfile:1 +# Build as `docker build . -t localgpt`, requires BuildKit. +# Run as `docker run -it --mount src="$HOME/.cache",target=/root/.cache,type=bind --gpus=all localgpt`, requires Nvidia container toolkit. + +FROM nvidia/cuda:11.7.1-runtime-ubuntu22.04 +RUN apt-get update && apt-get install -y software-properties-common +RUN apt-get install -y g++-11 make python3 python-is-python3 pip +# only copy what's needed at every step to optimize layer cache +COPY ./requirements.txt . +# use BuildKit cache mount to drastically reduce redownloading from pip on repeated builds +RUN --mount=type=cache,target=/root/.cache CMAKE_ARGS="-DLLAMA_CUBLAS=on" FORCE_CMAKE=1 pip install --timeout 100 -r requirements.txt llama-cpp-python==0.1.83 +#COPY SOURCE_DOCUMENTS ./SOURCE_DOCUMENTS +#RUN ls -lath . +RUN mkdir -p ./SOURCE_DOCUMENTS +COPY ingest.py constants.py ./ +# Docker BuildKit does not support GPU during *docker build* time right now, only during *docker run*. +# See . +# If this changes in the future you can `docker build --build-arg device_type=cuda . -t localgpt` (+GPU argument to be determined). +#ARG device_type=cpu +#RUN --mount=type=cache,target=/root/.cache python ingest.py --device_type $device_type +COPY . . +#ENV device_type=cuda +#CMD python run_localGPT.py --device_type $device_type \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..bb158cda --- /dev/null +++ b/Makefile @@ -0,0 +1,57 @@ +# Makefile for Docker Compose operations + +# Default values for environment variables +DEVICE_TYPE := cpu +SOURCE_DOCUMENTS := SOURCE_DOCUMENTS # Replace with your default source documents directory + +# Default target executed when no arguments are given to make. +.PHONY: all +all: build + +# Target for building the Docker image using Docker Compose +.PHONY: build +build: + @echo "Building Docker image with DEVICE_TYPE=$(DEVICE_TYPE) and SOURCE_DOCUMENTS=$(SOURCE_DOCUMENTS)..." + @DEVICE_TYPE=$(DEVICE_TYPE) SOURCE_DOCUMENTS=$(SOURCE_DOCUMENTS) docker-compose build + +# Target for running the Docker container using Docker Compose +.PHONY: run +run: + @echo "Running Docker container with DEVICE_TYPE=$(DEVICE_TYPE) and SOURCE_DOCUMENTS=$(SOURCE_DOCUMENTS)..." + @DEVICE_TYPE=$(DEVICE_TYPE) SOURCE_DOCUMENTS=$(SOURCE_DOCUMENTS) docker-compose up + +# Target to stop the running container using Docker Compose +.PHONY: stop +stop: + @echo "Stopping Docker container..." + @docker-compose down + +# Target for setting the device type to GPU (CUDA) +.PHONY: use-gpu +use-gpu: + $(eval DEVICE_TYPE := cuda) + +# Target for setting the device type to CPU +.PHONY: use-cpu +use-cpu: + $(eval DEVICE_TYPE := cpu) + +# Target to set the source documents directory +.PHONY: set-source-docs +set-source-docs: + $(eval SOURCE_DOCUMENTS := $(dir)) + +# Help target describing how to use the Makefile +.PHONY: help +help: + @echo "Makefile for Docker Compose operations" + @echo " make build - Builds the Docker image with the current DEVICE_TYPE and SOURCE_DOCUMENTS" + @echo " make run - Runs the Docker container with the current DEVICE_TYPE and SOURCE_DOCUMENTS" + @echo " make stop - Stops the running Docker container" + @echo " make use-gpu - Sets the DEVICE_TYPE to cuda (GPU)" + @echo " make use-cpu - Sets the DEVICE_TYPE to cpu" + @echo " make set-source-docs dir= - Sets the SOURCE_DOCUMENTS directory" + @echo " make help - Displays this help" + +# Use this command to set the source documents directory +# Example usage: make set-source-docs dir=MyDocuments diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000..2c921fd0 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,34 @@ +version: '3.8' + +services: + localgpt: + build: + context: . + dockerfile: Dockerfile.api + image: localgpt + environment: + - device_type=${DEVICE_TYPE} + - source_documents=${SOURCE_DOCUMENTS} + volumes: + - "$HOME/.cache:/root/.cache" + - "$HOME/${SOURCE_DOCUMENTS}:/SOURCE_DOCUMENTS" + command: python run_localGPT_API.py --port 8080 --host 0.0.0.0 + networks: + - localgpt-network + + localgpt-ui: + build: + context: localGPTUI/ + dockerfile: Dockerfile + ports: + - "5111:5111" # Map port 5111 inside the container to port 5111 on the Docker host + environment: + API_HOST: http://localgpt:8080/api + depends_on: + - localgpt + networks: + - localgpt-network + +networks: + localgpt-network: + driver: bridge diff --git a/docs/docker-compose-makefile.md b/docs/docker-compose-makefile.md new file mode 100644 index 00000000..0fb7bca7 --- /dev/null +++ b/docs/docker-compose-makefile.md @@ -0,0 +1,88 @@ +Here is the Markdown documentation for the Makefile: + +# Makefile for Docker Compose operations + +## Default values for environment variables +```makefile +DEVICE_TYPE := cpu +SOURCE_DOCUMENTS := SOURCE_DOCUMENTS +``` +Replace `SOURCE_DOCUMENTS` with your default source documents directory + +## Default target +Executed when no arguments are given to make. +```makefile +.PHONY: all +all: build +``` + +## Build target +Builds the Docker image using Docker Compose +```makefile +.PHONY: build +build: + @echo "Building Docker image with DEVICE_TYPE=$(DEVICE_TYPE) and SOURCE_DOCUMENTS=$(SOURCE_DOCUMENTS)..." + @DEVICE_TYPE=$(DEVICE_TYPE) SOURCE_DOCUMENTS=$(SOURCE_DOCUMENTS) docker-compose build +``` + +## Run target +Runs the Docker container using Docker Compose +```makefile +.PHONY: run +run: + @echo "Running Docker container with DEVICE_TYPE=$(DEVICE_TYPE) and SOURCE_DOCUMENTS=$(SOURCE_DOCUMENTS)..." + @DEVICE_TYPE=$(DEVICE_TYPE) SOURCE_DOCUMENTS=$(SOURCE_DOCUMENTS) docker-compose up +``` + +## Stop target +Stops the running container using Docker Compose +```makefile +.PHONY: stop +stop: + @echo "Stopping Docker container..." + @docker-compose down +``` + +## GPU target +Sets the device type to GPU (CUDA) +```makefile +.PHONY: use-gpu +use-gpu: + $(eval DEVICE_TYPE := cuda) +``` + +## CPU target +Sets the device type to CPU +```makefile +.PHONY: use-cpu +use-cpu: + $(eval DEVICE_TYPE := cpu) +``` + +## Set source docs target +Sets the source documents directory +```makefile +.PHONY: set-source-docs +set-source-docs: + $(eval SOURCE_DOCUMENTS := $(dir)) +``` + +## Help target +Describes how to use the Makefile +```makefile +.PHONY: help +help: + @echo "Makefile for Docker Compose operations" + @echo " make build - Builds the Docker image with the current DEVICE_TYPE and SOURCE_DOCUMENTS" + @echo " make run - Runs the Docker container with the current DEVICE_TYPE and SOURCE_DOCUMENTS" + @echo " make stop - Stops the running Docker container" + @echo " make use-gpu - Sets the DEVICE_TYPE to cuda (GPU)" + @echo " make use-cpu - Sets the DEVICE_TYPE to cpu" + @echo " make set-source-docs dir= - Sets the SOURCE_DOCUMENTS directory" + @echo " make help - Displays this help" +``` + +To set the source documents directory: +``` +make set-source-docs dir=MyDocuments +``` diff --git a/docs/docker-compose.md b/docs/docker-compose.md new file mode 100644 index 00000000..37692c1b --- /dev/null +++ b/docs/docker-compose.md @@ -0,0 +1,64 @@ +# Docker Compose file + +This Docker Compose file defines two services: + +## localgpt service + +This service builds the localgpt image and runs the localGPT API server. + +```yaml +services: + localgpt: + build: + context: . + dockerfile: Dockerfile.api + image: localgpt + environment: + - device_type=${DEVICE_TYPE} + - source_documents=${SOURCE_DOCUMENTS} + volumes: + - "$HOME/.cache:/root/.cache" + - "$HOME/${SOURCE_DOCUMENTS}:/SOURCE_DOCUMENTS" + command: python run_localGPT_API.py --port 8080 --host 0.0.0.0 + networks: + - localgpt-network +``` + +- Builds Dockerfile.api +- Sets device_type and source_documents environment variables +- Mounts host cache and source documents +- Runs the API server on port 8080 + +## localgpt-ui service + +This service runs the localGPT UI frontend. + +```yaml + localgpt-ui: + build: + context: localGPTUI/ + dockerfile: Dockerfile + ports: + - "5111:5111" + environment: + API_HOST: http://localgpt:8080/api + depends_on: + - localgpt + networks: + - localgpt-network +``` + +- Builds the localGPTUI Dockerfile +- Exposes port 5111 +- Sets API_HOST env var pointing to localgpt API +- Depends on localgpt service + +## Network + +```yaml +networks: + localgpt-network: + driver: bridge +``` + +- Single network for communication between containers diff --git a/localGPTUI/Dockerfile b/localGPTUI/Dockerfile new file mode 100644 index 00000000..18d84068 --- /dev/null +++ b/localGPTUI/Dockerfile @@ -0,0 +1,18 @@ +# Use an official Python runtime as a parent image +FROM python:3.9-slim + +# Set the working directory in the container +WORKDIR /usr/src/app + +# Install any needed packages specified in requirements.txt +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy the current directory contents into the container at /usr/src/app +COPY . . + +# Make port 5111 available to the world outside this container +EXPOSE 5111 + +# Run localGPTUI.py when the container launches +CMD ["python", "localGPTUI.py", "--host=0.0.0.0", "--port=5111"] diff --git a/localGPTUI/requirements.txt b/localGPTUI/requirements.txt new file mode 100644 index 00000000..3d80603b --- /dev/null +++ b/localGPTUI/requirements.txt @@ -0,0 +1,3 @@ +Flask==2.0.1 +Werkzeug==2.0.1 +requests==2.25.1 \ No newline at end of file diff --git a/run_inject.sh b/run_inject.sh new file mode 100755 index 00000000..ebdb391e --- /dev/null +++ b/run_inject.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# Check if enough arguments are passed +if [ $# -lt 3 ]; then + echo "Usage: $0 " + echo "device_type: cpu | mps" + echo "exec_env: machine | container" + echo "action: download | copy" + exit 1 +fi + +# Name of the Docker container +CONTAINER_NAME="localgpt_localgpt_1" + +# Set the device type (cpu or mps) +DEVICE_TYPE="$1" + +# Execution environment: "container" or "machine" +EXEC_ENV="$2" + +# Action: "download" or "copy" +ACTION="$3" + + +# PDF source - URL or local path +PDF_SOURCE="https://github.com/TatevKaren/free-resources-books-papers/blob/main/DataEngineering_HandBook.pdf" # URL of the PDF to download +LOCAL_PDF_PATH="$HOME/localGPT/SOURCE_DOCUMENTS/" # Local path of the PDF (if not downloading) + +# Destination path for the PDF +DESTINATION_PATH="$HOME/SOURCE_DOCUMENTS/" # Directory to save the PDF + +# Create destination directory if it doesn't exist +mkdir -p "$DESTINATION_PATH" + +# Function to download PDF +download_pdf() { + echo "Downloading PDF from $PDF_SOURCE..." + curl -o "$DESTINATION_PATH/downloaded_document.pdf" "$PDF_SOURCE" +} + +# Function to copy PDF +# Function to copy PDF files +copy_pdfs() { + echo "Copying PDF files from $LOCAL_PDF_PATH to $DESTINATION_PATH..." + for pdf_file in "$LOCAL_PDF_PATH"/*.pdf; do + if [ -f "$pdf_file" ]; then + pdf_filename=$(basename "$pdf_file") + cp "$pdf_file" "$DESTINATION_PATH/$pdf_filename" + echo "Copied: $pdf_filename" + fi + done +} + +# Run python script with device type +run_ingest() { + echo "Running ingest.py with device type $DEVICE_TYPE..." + if [ "$EXEC_ENV" = "container" ]; then + # Run in Docker container + docker exec "$CONTAINER_NAME" python ingest.py --device_type "$DEVICE_TYPE" + else + # Run on local machine + python ingest.py --device_type "$DEVICE_TYPE" + fi +} + +# Choose action based on the argument +case $ACTION in + download) + download_pdf + ;; + copy) + copy_pdfs + ;; + *) + echo "Invalid action: $ACTION" + exit 2 + ;; +esac + +run_ingest