Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker Compose Enhancements for LocalGPT Deployment #707

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
23 changes: 23 additions & 0 deletions Dockerfile.api
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/moby/buildkit/issues/1436>.
# 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
57 changes: 57 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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=<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
34 changes: 34 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -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
88 changes: 88 additions & 0 deletions docs/docker-compose-makefile.md
Original file line number Diff line number Diff line change
@@ -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=<dir> - Sets the SOURCE_DOCUMENTS directory"
@echo " make help - Displays this help"
```

To set the source documents directory:
```
make set-source-docs dir=MyDocuments
```
64 changes: 64 additions & 0 deletions docs/docker-compose.md
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions localGPTUI/Dockerfile
Original file line number Diff line number Diff line change
@@ -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"]
3 changes: 3 additions & 0 deletions localGPTUI/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Flask==2.0.1
Werkzeug==2.0.1
requests==2.25.1
80 changes: 80 additions & 0 deletions run_inject.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/bin/bash

# Check if enough arguments are passed
if [ $# -lt 3 ]; then
echo "Usage: $0 <device_type> <exec_env> <action>"
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