Skip to main content
This page applies to direct object-storage and local-filesystem connections only. On LanceDB Enterprise (db://) connections, distributed job execution is fully managed: the cluster and manifest are configured at deployment time (see Helm deployment) and can be overridden per job with cluster= / manifest= (see Advanced Job Configuration). You do not define execution contexts there.When you connect Geneva directly to object storage (s3://, gs://, …) or a local path, there is no managed control plane, so you configure the execution backend yourself using the contexts below. The APIs on this page require Geneva v0.10.0 or later.
Geneva’s distributed execution backend is Ray. There are 3 ways to connect to a Ray cluster:
  1. Local Ray
  2. KubeRay: create a cluster on demand in your Kubernetes cluster.
  3. Existing Ray Cluster

Ray Clusters

Local Ray

To execute jobs without an external Ray cluster, you can use LocalRayContext. This will auto-create a Ray cluster on your machine. Because it’s on your laptop/desktop, this is only suitable for prototyping on small datasets. But it is the easiest way to get started. Simply define the UDF, add a column, call Connection.local_ray_context(), and trigger the job:
Geneva will package up your local environment and send it to each worker process, so they’ll have access to all the same dependencies as if you ran a simple Python script yourself.

KubeRay

If you have a Kubernetes cluster with kuberay-operator, you can use Geneva to automatically provision RayClusters. To do so, define a Geneva cluster, representing the resource needs, Docker images, and other Ray configurations necessary to run your job. Make sure your cluster has adequate compute resources to provision the RayCluster. Here is an example Geneva cluster definition:

Exit Modes

When you launch multiple async jobs in a single context, the exit mode controls whether the cluster waits for all of them to finish and how it handles failures. You can customize this behavior with the on_exit parameter:
Python

External Ray cluster

If you already have a Ray cluster, Geneva can execute jobs against it too. You do so by defining a Geneva cluster with GenevaCluster.create_external() which has the address of the cluster. Here’s an example:
If you need to send environment variables to your workers, in either a KubeRay or External Ray cluster, you can use ray_init_kwargs, like so:
Python

Dependencies and Manifests

Most UDFs require some dependencies: helper libraries like pillow for image processing, pre-trained models like open-clip to calculate embeddings, or even small config files. We have three ways to get them to workers:
  1. Define dependencies explicitly in a manifest
  2. Bake dependencies into an image
  3. Auto-upload local dependencies

Define dependencies explicitly in a manifest

We recommend defining dependencies explicitly: it’s the easiest way to understand exactly what’s running, and the least error-prone. To do so, define a Manifest, like so:
After workers start up, this will run pip install lancedb numpy on them. You can also use .requirements_path(path) to point to a local requirements.txt file instead of listing packages inline. Note that attempting to use both .pip() and .requirements_path() will raise an exception. For conda-based dependencies, use GenevaManifest.create_conda() instead:
Python
You can also use .conda_environment_path(path) to point to a local environment.yml file. Note that attempting to use both .conda() and .conda_environment_path() will raise an exception.

Bake dependencies into an image

Because the pip or conda methods involve installing packages, they will incur some startup costs. When your jobs are stable in production, therefore, it will be faster to build all your dependencies into the workers’ images, then specify them like so:
You can also define images in a cluster via the head_group method and cpu_worker/gpu_worker methods, e.g.:
Python
However, if an image is defined in both a Cluster and a Manifest, the definition in the Manifest will take priority.

Auto-upload local dependencies

Geneva can package your local environment and send it to Ray workers. This includes the current workspace root (if you’re in a python repo) or the current working directory (if you’re not). GenevaManifest.create_site() additionally uploads your Python site-packages (defined by site.getsitepackages()) to workers. This is not recommended for production use, as it is prone to issues like architecture mismatches of built dependencies, but it can be a good way to iterate quickly during development. To upload site packages:
Python

What’s in a manifest?

Here’s a summary of what’s in a manifest and how you can define it across the three manifest builder types. If you want to see exactly what is being uploaded to the cluster, set .delete_local_zips(False) and .local_zip_output_dir(path) then examine the zip files in path.

Putting it all together: Execution Contexts

An execution context represents the concrete execution environment (Cluster and Manifest) used to execute a distributed job. Calling context will enter a context manager that will provision an execution cluster and execute the Job using the Cluster and Manifest definitions provided. Because you’ve already defined the cluster and manifest, you can just reference them by name. Note that providing a manifest is optional. Once completed, the context manager will automatically de-provision the cluster.
In a notebook environment, you can manually enter and exit the context manager in multiple steps like so:

API Reference

  • Connectioncontext(), local_ray_context(), list_clusters(), list_manifests()
  • ClusterKubeRayClusterBuilder, LocalRayClusterBuilder, ExternalRayClusterBuilder, and worker configuration classes
  • ManifestPipManifestBuilder, CondaManifestBuilder, SiteManifestBuilder