diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0969b6b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +models/* diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..53013c0 --- /dev/null +++ b/Containerfile @@ -0,0 +1,16 @@ +# Use UBI Micro base image +FROM registry.access.redhat.com/ubi8/ubi-minimal + +WORKDIR /app/spilot +ENV SHELL_PILOT_CONFIG_PATH=/app/spilot + +RUN microdnf install -y findutils ncurses curl jq && \ + microdnf clean all + +COPY . . + +RUN chgrp -R 0 /app/spilot && chmod -R g=u /app/spilot && chmod +x /app/spilot/* + +# Set default command +USER 1001 +CMD ["sleep", "infinity"] diff --git a/README.md b/README.md index e841b1d..997f5b9 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ This script relies on curl for the requests to the api and jq to parse the json - Set your local `Ollama` server ip in configuration file `spilot_common.sh` if not set during the installation ```sh - OLLAMA_SERVER_IP= + OLLAMA_SERVER_HOST= ``` - You can also set the other parameters in `spilot_common.sh` before using. @@ -89,10 +89,76 @@ This script relies on curl for the requests to the api and jq to parse the json - Add the path of `s-pilot` to your `$PATH`. You do that by adding this line to your shell profile: `export PATH=$PATH:/path/to/s-pilot` - Reset the `SHELL_PILOT_CONFIG_PATH` in `s-pilot` if the `spilot_common.sh` path changed - Add the OpenAI API key to your shell profile by adding this line `export OPENAI_KEY=your_key_here` - - Add Ollama server ip address in `spilot_common.sh` for `OLLAMA_SERVER_IP` variable + - Add Ollama server ip address in `spilot_common.sh` for `OLLAMA_SERVER_HOST` variable -## Usage +### Running the service as a container + + +# Ollama Server and S-Pilot Podman Compose Configuration + +This Podman Compose configuration file defines two services: `ollama-server` and `s-pilot`. The `ollama-server` service hosts the Ollama application, while the `s-pilot` service runs the S-Pilot application. The services are configured to work together in a machine learning model serving environment. + +## Getting Started for Developers + +### Prerequisites + +Before you begin, ensure you have the following installed on your system: + +- Podman: [Install Podman](https://podman.io/getting-started/installation) +- Podman Compose: [Install Podman Compose](https://github.com/containers/podman-compose#installation) + +### Clone the Repository + +```bash +git clone https://github.com/reid41/shell-pilot +cd shell-pilot +``` + +##### Step 1: Start ollama and s-pilot + +Execute the below commands from the project root: + + ```bash +mkdir models #cache directory for downloaded models :) +podman compose up -d +``` +> If we need to interact with local volumes, enable the volume sections in the compose.ym file as required + +This step will build the required containers and bring up all the services +### Publishing individual images + + +#### Build ollama-server and s-pilot images + +##### To build the ollama-server without any model + +```bash +cd ollama-server +podman build -t ollama-server . +``` + +> Note: Model will be downloaded at during the container is started if the model is not available. Convinient option to distribute ollama binary as containers and pull the lastest version of the model during startup. + +##### Step 1: Build the ollama-server with embedded models + + ```bash +cd ollama-server +podman build -t ollama-server . --build-arg PULL_MODEL_BY_DEFAULT=true --build-arg MODEL=llama2 +``` + +Above will pull the model and embed inside the container for faster startup. + +##### Build the s-pilot container + +Execute the below commands from the project root: + + ```bash +podman build -t spilot:latest . +``` +> Use podman tag and podman push to push the image to the registry. + +## Usage ### Start #### Chat Mode @@ -104,7 +170,6 @@ This script relies on curl for the requests to the api and jq to parse the json <> ``` - #### Pipe Mode - You can also use it in pipe mode: ```shell diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..3ee1499 --- /dev/null +++ b/compose.yml @@ -0,0 +1,51 @@ +version: '3.8' + +services: + ollama-server: + image: ollama-server:latest + build: + context : ./ollama/ + dockerfile: Containerfile + args: + - PULL_MODEL_BY_DEFAULT= true + - MODEL=llama2 #Model should be a valid model + environment: + - MODEL=llama2 # Set this if we want to download the models during runtime. Change to mistral or any other model. + ports: + - 11434:11434 + + volumes: + #to cache the models to that we don't need to reload + - ./models:/app/ollama/.ollama/ + # Add any additional configuration for your ollama-server service here + # For example, environment variables, etc. + deploy: + resources: + reservations: + devices: + - driver: nvidia # change this to appropriatedrive + count: 1 + capabilities: [gpu] + #volumes: + #Mount any host volume as required. + # - ./data:/data + s-pilot: + image: spilot:latest + build: + context : . + dockerfile: Containerfile + depends_on: + - ollama-server + environment: + - OLLAMA_SERVER_HOST=ollama-server + healthcheck: + test: ["CMD", "curl ollama-server:11434"] + interval: 10s + timeout: 5s + retries: 3 + #volumes: + #Mount any host volume as required. + # - ./data:/data + + # Add any additional configuration for your s-pilot service here + # For example, ports, volumes, etc. diff --git a/ollama/Containerfile b/ollama/Containerfile new file mode 100644 index 0000000..74edfcf --- /dev/null +++ b/ollama/Containerfile @@ -0,0 +1,25 @@ +# Use UBI Micro base image +FROM registry.access.redhat.com/ubi8/ubi-minimal + +WORKDIR /app/ollama +# Install necessary packages +RUN microdnf --noplugins install -y findutils curl jq && \ + microdnf --noplugins clean all && \ + curl -fsSL https://ollama.com/install.sh | sh && \ + chmod +x /usr/local/bin/ollama +ADD ollama-entrypoint.sh /app/ollama +#RUN ollama pull llama2 +RUN mkdir -p /var/lib/ollama/.ollama/.ollama && \ + chgrp -R 0 /var/lib/ollama/.ollama && chmod -R g=u /var/lib/ollama/.ollama && \ + chmod +x /app/ollama/ollama-entrypoint.sh && \ + chgrp -R 0 /app/ollama && chmod -R g=u /app/ollama + +# Conditionally pull model if PULL_MODEL_BY_DEFAULT is set to true +ARG PULL_MODEL_BY_DEFAULT=false +ARG MODEL=llama2 +RUN if [ "$PULL_MODEL_BY_DEFAULT" = "true" ]; then ollama serve & sleep 50 && ollama pull $MODEL; fi +# Set default command +EXPOSE 11434 +USER 1001 +ENTRYPOINT ["/app/ollama/ollama-entrypoint.sh"] + diff --git a/ollama/README.md b/ollama/README.md new file mode 100644 index 0000000..db45a84 --- /dev/null +++ b/ollama/README.md @@ -0,0 +1,30 @@ +# Ollama Server Docker Image + +This Dockerfile is for building an Ollama Server container image. The container includes the Ollama application, which is a part of the Ollama system for managing and serving machine learning models. The Ollama Server provides an API for accessing machine learning models hosted on the server. + +## Usage + +### Building the Docker Image + +To build the Docker image, use the following command: + +```bash +podman build -t ollama-server . +``` +## Environment Variables + + PULL_MODEL_BY_DEFAULT (default: false): Controls whether to automatically pull the llama2 model at startup. + > MODEL (default: llama2): Specifies the name of the Ollama model to pull (if PULL_MODEL_BY_DEFAULT is true). + +## Ports + +The container exposes port 11434 (configurable) for Ollama communication. + +## User + +The container runs as user ID 1001 (non-root) for security reasons. + +## Entrypoint + +The container's entrypoint script is /app/ollama/ollama-entrypoint.sh. This script tries to download the given model during startup of the th e MODEL is not available. + diff --git a/ollama/ollama-entrypoint.sh b/ollama/ollama-entrypoint.sh new file mode 100644 index 0000000..f6249e3 --- /dev/null +++ b/ollama/ollama-entrypoint.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +# Start ollama serve in the background +export OLLAMA_HOST=0.0.0.0 + +ollama serve & + +# Sleep for 50 seconds (adjust as needed) +sleep 30 + +# Check if the specified model is present +MODEL="${MODEL:-llama2}" # Default to "llama2" if MODEL is not set +MODEL_PRESENT=$(ollama list | grep "$MODEL" | wc -l) +if [ $MODEL_PRESENT -lt 1 ]; then + #Ensure the model is pulled by default when the container starts up + echo "Model not available already. Pulling $MODEL now!" + ollama pull "$MODEL" +else + echo "Model $MODEL already available" +fi + +# Sleep indefinitely +echo "$MODEL ready to be served" +sleep infinity diff --git a/s-pilot b/s-pilot index a0b60af..3f6ed9e 100644 --- a/s-pilot +++ b/s-pilot @@ -1,6 +1,7 @@ # !/bin/bash # set -x -SHELL_PILOT_CONFIG_PATH="/usr/local/bin" +[ -z "${SHELL_PILOT_CONFIG_PATH}" ] && export SHELL_PILOT_CONFIG_PATH="/usr/local/bin" +#SHELL_PILOT_CONFIG_PATH="/usr/local/bin" COMMON_CONFIG_FILE="${SHELL_PILOT_CONFIG_PATH}/spilot_common.sh" source $COMMON_CONFIG_FILE @@ -13,14 +14,14 @@ fi # check if the OLLAMA host is set if [[ "$USE_API" == "ollama" ]]; then - if [[ -z "$OLLAMA_SERVER_IP" ]]; then - echo "Error: OLLAMA_SERVER_IP is not set in the configuration file." - exit 1 - fi - if ! [[ $OLLAMA_SERVER_IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Error: OLLAMA_SERVER_IP is not a valid IP address." + if [[ -z "$OLLAMA_SERVER_HOST" ]]; then + echo "Error: OLLAMA_SERVER_HOST is not set in the configuration file." exit 1 fi + # if ! [[ $OLLAMA_SERVER_HOST =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + # echo "Error: OLLAMA_SERVER_HOST is not a valid IP address." + # exit 1 + # fi fi usage() { @@ -113,7 +114,7 @@ list_models() { if [[ "$USE_API" == "ollama" ]] then # get the list of models - curl -s http://${OLLAMA_SERVER_IP}:11434/api/tags | jq -c '.models[]' | while read -r model; do + curl -s http://${OLLAMA_SERVER_HOST}:11434/api/tags | jq -c '.models[]' | while read -r model; do # show processing label echo -ne "$OVERWRITE_PROCESSING_LINE" @@ -170,7 +171,7 @@ request_to_completions() { if [[ "$USE_API" == "ollama" ]] then - curl http://${OLLAMA_SERVER_IP}:11434/api/generate \ + curl http://${OLLAMA_SERVER_HOST}:11434/api/generate \ -sS \ -d '{ "model": "'"$MODEL_OLLAMA"'", @@ -205,7 +206,7 @@ request_to_chat() { if [[ "$USE_API" == "ollama" ]] then - curl http://${OLLAMA_SERVER_IP}:11434/api/chat \ + curl http://${OLLAMA_SERVER_HOST}:11434/api/chat \ -sS \ -d '{ "model": "'"$MODEL_OLLAMA"'", @@ -553,7 +554,7 @@ while $running; do escaped_prompt=${escaped_prompt#model:} escaped_prompt=$(echo "$escaped_prompt" | sed 's/\\n//g' | sed 's/\.//g') echo -e "$OVERWRITE_PROCESSING_LINE" - curl -s http://${OLLAMA_SERVER_IP}:11434/api/show -d '{ + curl -s http://${OLLAMA_SERVER_HOST}:11434/api/show -d '{ "name": "'"$escaped_prompt"'" }' | jq -r '[ "License: \(.license)", @@ -681,4 +682,4 @@ while $running; do timestamp=$(date +"%Y-%m-%d %H:%M") echo -e "$timestamp $prompt \n$response_data \n" >>~/.chatgpt_history fi -done \ No newline at end of file +done diff --git a/spilot_install.sh b/spilot_install.sh index d00b254..a5ecdfa 100644 --- a/spilot_install.sh +++ b/spilot_install.sh @@ -152,18 +152,18 @@ else echo "https://github.com/reid41/shell-pilot/tree/main#manual-installation" fi -# Function to check and append OLLAMA_SERVER_IP to the specified configuration file +# Function to check and append OLLAMA_SERVER_HOST to the specified configuration file add_ollama_ip() { local config_file=$1 - # Check if the OLLAMA_SERVER_IP variable already exists in the configuration file - if grep -q "OLLAMA_SERVER_IP=" "$config_file"; then - local existing_ip=$(grep "OLLAMA_SERVER_IP=" "$config_file" | cut -d'=' -f2) + # Check if the OLLAMA_SERVER_HOST variable already exists in the configuration file + if grep -q "OLLAMA_SERVER_HOST=" "$config_file"; then + local existing_ip=$(grep "OLLAMA_SERVER_HOST=" "$config_file" | cut -d'=' -f2) if [[ $existing_ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "OLLAMA_SERVER_IP is already set to a valid IP address: $existing_ip" + echo "OLLAMA_SERVER_HOST is already set to a valid IP address: $existing_ip" return 0 else - echo "Error: OLLAMA_SERVER_IP is set but not valid: $existing_ip" + echo "Error: OLLAMA_SERVER_HOST is set but not valid: $existing_ip" return 1 fi else @@ -171,8 +171,8 @@ add_ollama_ip() { while true; do read -p "Enter the OLLAMA server IP address: " ip_address if [[ $ip_address =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "OLLAMA_SERVER_IP=$ip_address" >> "$config_file" - echo "OLLAMA_SERVER_IP added to $config_file" + echo "OLLAMA_SERVER_HOST=$ip_address" >> "$config_file" + echo "OLLAMA_SERVER_HOST added to $config_file" break else echo "Error: Invalid IP address entered. Please enter a valid IP address." @@ -184,7 +184,7 @@ add_ollama_ip() { # Specify the configuration file path CONFIG_FILE="${INSTALL_PATH}/spilot_common.sh" -# Check and append OLLAMA_SERVER_IP +# Check and append OLLAMA_SERVER_HOST if add_ollama_ip "$CONFIG_FILE"; then echo "Operation successful." else