Skip to content
This repository was archived by the owner on May 23, 2025. It is now read-only.
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
25 changes: 25 additions & 0 deletions .docker/app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Use an official Python image
FROM python:3.11

# Set environment variables
ENV PYTHONUNBUFFERED=1
ENV POETRY_HOME="/opt/poetry"
ENV PATH="$POETRY_HOME/bin:$PATH"

# Install Poetry
RUN curl -sSL https://install.python-poetry.org | python3 -

# Set up the working directory
WORKDIR /app
ENV PYTHONPATH="/app"

# Copy project files
COPY pyproject.toml poetry.lock ./
RUN poetry install --no-root --no-interaction --no-ansi

# Copy the entire application
COPY config.yml main.py ./
COPY src ./src

# Run the application
ENTRYPOINT ["poetry", "run", "python", "main.py"]
Empty file.
Empty file added .docker/ollama/.gitkeep
Empty file.

This file was deleted.

Empty file.
99 changes: 99 additions & 0 deletions .docker/vector_storage_loader/add_snapshots.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/bin/bash
set -e # Exit on error

# Install curl if not present
apk add --no-cache curl || echo "Warning: Unable to install curl, assuming it's already present"

echo "Waiting for vector storage to be ready..."
BASEURL="http://${VECTOR_STORAGE_HOST:-localhost}:6333"
echo "Using BASEURL: $BASEURL"

# Wait for Qdrant to be ready
until curl -sSf "$BASEURL/healthz" > /dev/null; do
echo "Waiting for Qdrant health check..."
sleep 5
done
echo "Vector storage is ready!"

# Check and handle PROJECT_COLLECTION
if [ -n "$PROJECT_COLLECTION" ]; then
echo "Verifying PROJECT_COLLECTION: $PROJECT_COLLECTION"

# Validate vector size and distance if provided
VECTOR_SIZE="${PROJECT_COLLECTION_VECTOR_SIZE:-1536}"
VECTOR_DISTANCE="${PROJECT_COLLECTION_VECTOR_DISTANCE:-Cosine}"

# Validate vector size is a positive integer
if ! [[ "$VECTOR_SIZE" =~ ^[0-9]+$ ]] || [ "$VECTOR_SIZE" -le 0 ]; then
echo "Error: PROJECT_COLLECTION_VECTOR_SIZE must be a positive integer, got: $VECTOR_SIZE"
VECTOR_SIZE=1536
echo "Falling back to default size: $VECTOR_SIZE"
fi

# Validate vector distance
case "$VECTOR_DISTANCE" in
"Cosine"|"Euclid"|"Dot")
echo "Using vector distance: $VECTOR_DISTANCE"
;;
*)
echo "Error: PROJECT_COLLECTION_VECTOR_DISTANCE must be 'Cosine', 'Euclid', or 'Dot', got: $VECTOR_DISTANCE"
VECTOR_DISTANCE="Cosine"
echo "Falling back to default distance: $VECTOR_DISTANCE"
;;
esac

# Check if collection exists
EXISTS_RESPONSE=$(curl -s -X GET "$BASEURL/collections/$PROJECT_COLLECTION/exists")
echo "Exists response: $EXISTS_RESPONSE"

if echo "$EXISTS_RESPONSE" | grep -q '"exists":true'; then
echo "Collection '$PROJECT_COLLECTION' already exists. Continuing with existing collection."
else
echo "Collection '$PROJECT_COLLECTION' does not exist. Creating empty collection..."
CREATE_RESPONSE=$(curl -s -X PUT "$BASEURL/collections/$PROJECT_COLLECTION" \
-H "Content-Type: application/json" \
-d "{\"vectors\": {\"size\": $VECTOR_SIZE, \"distance\": \"$VECTOR_DISTANCE\"}}")
echo "Create response: $CREATE_RESPONSE"
if echo "$CREATE_RESPONSE" | grep -q '"status":"ok"'; then
echo "Empty collection '$PROJECT_COLLECTION' created successfully with size $VECTOR_SIZE and distance $VECTOR_DISTANCE."
else
echo "Error creating collection. Continuing anyway..."
fi
fi
else
echo "PROJECT_COLLECTION not specified. Continuing with snapshot restoration only."
fi

# Set the snapshot directory path
SNAPSHOT_DIR="/snapshots"
echo "Looking for snapshots in: $SNAPSHOT_DIR"

# Loop over snapshot files
for snapshot in "$SNAPSHOT_DIR"/*.snapshot; do
if [ -e "$snapshot" ]; then
COLLECTION_NAME=$(basename "$snapshot" .snapshot)
echo "Processing snapshot for collection: $COLLECTION_NAME"

EXISTS_RESPONSE=$(curl -s -X GET "$BASEURL/collections/$COLLECTION_NAME/exists")
echo "Exists response: $EXISTS_RESPONSE"

if echo "$EXISTS_RESPONSE" | grep -q '"exists":true'; then
echo "Collection '$COLLECTION_NAME' already exists. Skipping upload."
else
echo "Restoring snapshot for collection '$COLLECTION_NAME'..."
UPLOAD_RESPONSE=$(curl -s -X POST "$BASEURL/collections/$COLLECTION_NAME/snapshots/upload" \
-F "snapshot=@$snapshot")
echo "Upload response: $UPLOAD_RESPONSE"
if echo "$UPLOAD_RESPONSE" | grep -q '"status":"ok"'; then
echo "Snapshot restored successfully."
else
echo "Error uploading snapshot."
fi
fi
else
echo "No snapshots found in $SNAPSHOT_DIR"
break
fi
done

echo "Snapshots restoration finished successfully."
Empty file.
13 changes: 12 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,15 @@ pyrightconfig.json

.assets/
!.assets/.gitkeep
.localstorage
.localstorage
pandoc*

/.docker/vector_storage/storage/
/.docker/memory_storage/db/
/.docker/vector_storage_loader/
/.docker/ollama/
!/.docker/ollama/.gitkeep
!/.docker/vector_storage_loader/storage/.gitkeep
!/.docker/memory_storage/db/.gitkeep


8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions .idea/dataSources.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/docgpt.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.11
9 changes: 7 additions & 2 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,23 @@ core:

ai:
openai:
embedding_model_name: ${AI_OPENAI_EMBEDDING_MODEL:text-embedding-3-small}
model_name: ${AI_OPENAI_MODEL:gpt-3.5-turbo}
api_key: ${AI_OPENAI_APIKEY}
ollama:
base_url: ${AI_OLLAMA_BASE_URL:http://localhost:11434}

assistant:
k: ${ASSISTANT_K:100}
tokens_limit: ${ASSISTANT_TOKENS_LIMIT:2000}
score_threshold: ${ASSISTANT_SCORE_THRESHOLD:0.9}
score_threshold: ${ASSISTANT_SCORE_THRESHOLD:0.01}
distance_threshold: ${DISTANCE_THRESHOLD:null}

storage:
vector:
url: ${STORAGE_VECTOR_URL:postgresql://root:example@localhost:5432/postgres}
url: ${STORAGE_VECTOR_URL:http://localhost:6333}
collection_name: ${STORAGE_VECTOR_COLLECTION_NAME:my_collection}
timeout: ${STORAGE_VECTOR_TIMEOUT:60}
pre_delete_collection: false
memory:
url: ${STORAGE_MEMORY_URL:mongodb://root:example@localhost:27017}
Expand Down
89 changes: 75 additions & 14 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,26 +1,87 @@
version: '3'

services:
vector_storage:
image: ankane/pgvector
vector-storage:
image: qdrant/qdrant:latest
container_name: vector_storage
restart: always
restart: unless-stopped
ports:
- 5432:5432
environment:
- POSTGRES_USER=root
- POSTGRES_PASSWORD=example
- POSTGRES_DB=postgres
- "6333:6333"
- "6334:6334"
volumes:
- ./.docker/vector_storage/storage:/qdrant/storage

vector-storage-loader:
image: alpine:latest
profiles:
- loader
container_name: vector_storage_loader
volumes:
- .docker/postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
- ./.docker/vector_storage_loader/snapshots:/snapshots # Mount snapshot folder
- ./.docker/vector_storage_loader/add_snapshots.sh:/app/add_snapshots.sh:ro # Mount script
environment:
VECTOR_STORAGE_HOST: vector_storage
PROJECT_COLLECTION: jabref
PROJECT_COLLECTION_VECTOR_SIZE: 768 # nomic dimension, for openai use 1536
PROJECT_COLLECTION_VECTOR_DISTANCE: Cosine
depends_on:
- vector-storage
entrypoint: ["/bin/sh", "/app/add_snapshots.sh"]

memory_storage:
memory-storage:
image: mongo
container_name: memory_storage
restart: always
restart: unless-stopped
ports:
- 27017:27017
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
volumes:
- ./.docker/memory_storage/db:/data/db

ollama:
image: ollama/ollama:latest
container_name: docgpt_ollama
restart: unless-stopped
ports:
- "11434:11434"
volumes:
- ./.docker/ollama:/root/.ollama # Persist Ollama models and data
entrypoint: ["/bin/sh", "-c"]
environment:
OLLAMA_NUM_PARALLEL: 16
command:
- |
ollama serve & # Start the Ollama server in the background
sleep 5 && # Give the server a moment to start
ollama pull nomic-embed-text && # Pull the nomic-embed-text model
ollama pull llama2 && # Pull the llama2 model
wait # Keep the container running

app:
container_name: app
profiles:
- self
depends_on:
- memory-storage
- vector-storage
- ollama
restart: unless-stopped
build:
context: .
dockerfile: ./.docker/app/Dockerfile
env_file: .env
ports:
- "8000:8000"
environment:
API_PORT: 8000
STORAGE_VECTOR_COLLECTION_NAME: ${STORAGE_VECTOR_COLLECTION_NAME:-mozilla}
STORAGE_VECTOR_URL: http://vector_storage:6333
STORAGE_MEMORY_URL: mongodb://root:example@memory_storage:27017
AI_OLLAMA_BASE_URL: http://docgpt_ollama:11434
volumes:
- ./.assets:/app/.assets


networks:
default:
name: docgpt-network
Loading