Skip to content

Conversation

jacksonjacobs1
Copy link
Collaborator

@jacksonjacobs1 jacksonjacobs1 commented Sep 25, 2025

[#149] FEATURE: restructure qa as a uv project with package locks

https://jacksonjjacobs.com/openproject/work_packages/149

- note, this facilitates live development with a ray cluster. However, note that it's not perfect. If you add new files, make sure to set the ownership to user 1013, or else only add files from the host machine to control ownership.
…tainer configuration; add interactive terminal options to devcontainer service in docker-compose.
…ion instructions and adjust file mount settings.
@jacksonjacobs1
Copy link
Collaborator Author

This PR makes the following changes

Use ray for base docker image: rayproject/ray-ml:2.49.1.3fe06a-py310-cu121

  • This base image already includes CUDA and pytorch python packages
  • Includes packages and configuration required for ray's autoscaler

uv manages base environment

  • All packages in pyproject.toml are versioned.
  • a uv.lock file contains the exact environment state for additional precision
  • adding packages with uv add automatically updates the above files.

Adds three distinct installation methods

  1. quickstart: deploys quickannotator reliably in 1 command
  2. multi-node: deploys quickannotator on a configurable multi-node cluster
  3. for developers: installs quickannotator on local machine.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR restructures QuickAnnotator as a UV project with package locks, focusing on containerized deployment and dependency management. The changes include migrating from a single Dockerfile to a Docker Compose setup, updating the build system to use UV for Python package management, and integrating Grafana for monitoring.

  • Replaced single Dockerfile with multi-service Docker Compose setup including PostgreSQL and Grafana
  • Updated pyproject.toml to use UV with locked dependency versions and removed dynamic versioning
  • Added Grafana integration with automatic dashboard and datasource setup

Reviewed Changes

Copilot reviewed 16 out of 19 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pyproject.toml Updated to use UV with fixed version and reorganized dependencies
quickannotator/config/init.py Added PostgreSQL and Grafana configuration functions
quickannotator/config/config.ini Updated database configuration to use PostgreSQL with separate parameters
quickannotator/grafana/utils.py Added Grafana client for automatic datasource and dashboard setup
quickannotator/main.py Added Grafana initialization call
deployment/ New deployment configuration files for Docker Compose and Ray cluster
.devcontainer/devcontainer.json Updated to use Docker Compose instead of single Dockerfile

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.


def add_postgres_datasource(self, host, port, db, username, password) -> str:
name = "PostgreSQL"
try: # NOTE: api client does not have a datasource search method, so we just have to try getting the datasource by name.
Copy link
Preview

Copilot AI Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra spaces before the comment. There should be only one space after the colon.

Copilot uses AI. Check for mistakes.

self.logger.info(f"Grafana datasource '{name}' already exists. Skipping creation.")
return existing_datasource["uid"]
except Exception as e:
self.logger.error(f"Datasource does not exist. Creating datasource...")
Copy link
Preview

Copilot AI Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message is misleading. This is not an error condition but expected behavior when the datasource doesn't exist. Consider changing to info level and rephrasing as 'Datasource not found. Creating new datasource...'

Suggested change
self.logger.error(f"Datasource does not exist. Creating datasource...")
self.logger.info("Datasource not found. Creating new datasource...")

Copilot uses AI. Check for mistakes.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this suggestion seems...corret?

Copy link
Owner

@choosehappy choosehappy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks great - nice job- 1 or 2 minor questions

```
- **Pre-existing cluster**: If you would like QA to connect to an existing Ray cluster, use the `--cluster_address` argument.
2. Configure the `deployment/multi_node_cluster_config.yaml` file to specify the head and worker nodes of your ray cluster. See the [ray cluster launcher documentation](https://docs.ray.io/en/latest/cluster/vms/user-guides/launching.html) for more details.
> All lines with the comment `CHANGE ME` should be configured.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should or must?

# --chown is needed because USER ray only affects run commands, not copy commands.
# --mount is a feature that allows caching of pip downloads between builds.
COPY --chown=ray:users ../pyproject.toml /opt/QuickAnnotator/
RUN --mount=type=cache,target=/root/.cache/uv \
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow- super cool. didn't know that this was a feature!


; NOTE: Use this URI for PostgreSQL. Replace with your credentials
database_uri = postgresql+psycopg2://admin:admin@postgis:5432/gisdb
postgres_username = admin
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so these values need to match the ones which are in docker-compose?

self.logger.info(f"Grafana datasource '{name}' already exists. Skipping creation.")
return existing_datasource["uid"]
except Exception as e:
self.logger.error(f"Datasource does not exist. Creating datasource...")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this suggestion seems...corret?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants