diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 6e613d4cd..048f2041d 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -3,7 +3,7 @@ "description": "OpenRL: a self-hosted, Kubernetes-native post-training API that serves the Tinker API.", "owner": { "name": "GKE Labs", - "url": "https://github.com/gke-labs/open-rl" + "url": "https://github.com/openrl-dev/openrl" }, "plugins": [ { diff --git a/.github/workflows/build-and-push.yml b/.github/workflows/build-and-push.yml index 38c163a1f..3fbdb5aeb 100644 --- a/.github/workflows/build-and-push.yml +++ b/.github/workflows/build-and-push.yml @@ -58,7 +58,7 @@ jobs: id: meta uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: - images: ghcr.io/gke-labs/open-rl/${{ matrix.image_name }} + images: ghcr.io/openrl-dev/openrl/${{ matrix.image_name }} # Tags every push `sha-`, the default branch `latest`, and a # `v*` tag push `v`. The literal `v` keeps the image tag equal # to the git tag, which the bundle pins to. The sha outranks `latest` diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml index dc4838dd0..0612a8724 100644 --- a/.github/workflows/site.yml +++ b/.github/workflows/site.yml @@ -52,7 +52,7 @@ jobs: # main deploys everywhere; a fork also deploys its website/* branches, for previews deploy: needs: build - if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.repository_owner != 'gke-labs') + if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.repository_owner != 'openrl-dev') runs-on: ubuntu-latest permissions: pages: write diff --git a/AGENTS.md b/AGENTS.md index 02971e994..8339b0ac6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -173,7 +173,7 @@ kubectl delete pods -l timeslice.io/group=samplers --ignore-not-found ### Kustomize Deployment & Base Manifest Best Practices (`Tip`) To prevent noisy container image tag diffs inside pull requests while ensuring clean deployments across Kubernetes environments, always follow this Kustomize pattern: 1. **Deploy via Kustomize (`-k`)**: Always apply directory manifests via `kubectl apply -k ` rather than `kubectl apply -f `. -2. **Keep Base YAMLs at `:latest` or Placeholder**: In all base/rendered YAML template files (`04-api-server.yaml`, `05-worker-pod-template.yaml`, `07-accel-timeslicer-daemonset.yaml`, `09-sampler-pod-template.yaml`, `04-deployment.yaml`, etc.), keep container image tags permanently set to a static placeholder (`e.g. image: ghcr.io/gke-labs/open-rl/server:latest` or `/API server:latest`). **Never bump image tags inside these base template files.** +2. **Keep Base YAMLs at `:latest` or Placeholder**: In all base/rendered YAML template files (`04-api-server.yaml`, `05-worker-pod-template.yaml`, `07-accel-timeslicer-daemonset.yaml`, `09-sampler-pod-template.yaml`, `04-deployment.yaml`, etc.), keep container image tags permanently set to a static placeholder (`e.g. image: ghcr.io/openrl-dev/openrl/server:latest` or `/API server:latest`). **Never bump image tags inside these base template files.** 3. **Single Source of Truth for Version Bumps**: When releasing or bumping image versions (`e.g. 0.1.75 -> 0.1.76`), modify **only**: - `VERSION` (`at repository root`) - The `newTag:` field inside the target environment's `kustomization.yaml` (`e.g. k8s/deploy/distributed-fft-timeslice/kustomization.yaml`) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 39d02e04e..e1452735e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,7 @@ that we need help with, including: * Bugs in our automation scripts If anything doesn't make sense, or doesn't work when you run it, please -[open an issue](https://github.com/gke-labs/open-rl/issues/new) and let us know. +[open an issue](https://github.com/openrl-dev/openrl/issues/new) and let us know. Please note that this project has a [Code of Conduct](CODE_OF_CONDUCT.md) that all contributors are expected to follow. @@ -36,7 +36,7 @@ We welcome many different types of contributions, including: * Release management Not everything happens through a GitHub pull request. If you would like to discuss an idea -before writing code, open a [GitHub issue](https://github.com/gke-labs/open-rl/issues) and +before writing code, open a [GitHub issue](https://github.com/openrl-dev/openrl/issues) and let's talk it through. -- **Questions and discussion**: [GitHub Issues](https://github.com/gke-labs/open-rl/issues) +- **Questions and discussion**: [GitHub Issues](https://github.com/openrl-dev/openrl/issues) - **Reporting a vulnerability**: see our [Security Policy](SECURITY.md) — please do not open a public issue for security reports - **How the project is run**: [GOVERNANCE.md](GOVERNANCE.md) diff --git a/RELEASING.md b/RELEASING.md index 2a9279a42..1e1fe55b4 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -15,10 +15,10 @@ produces a release; nothing else does. Images, published to GHCR by `.github/workflows/build-and-push.yml` and tagged with the git tag verbatim: -- `ghcr.io/gke-labs/open-rl/server:` -- `ghcr.io/gke-labs/open-rl/api-server:` -- `ghcr.io/gke-labs/open-rl/client:` (the e2e client, `src/server/Dockerfile.client`) -- `ghcr.io/gke-labs/open-rl/scheduler:` +- `ghcr.io/openrl-dev/openrl/server:` +- `ghcr.io/openrl-dev/openrl/api-server:` +- `ghcr.io/openrl-dev/openrl/client:` (the e2e client, `src/server/Dockerfile.client`) +- `ghcr.io/openrl-dev/openrl/scheduler:` Assets, attached to the GitHub Release: @@ -71,7 +71,7 @@ Every bundle has its images pinned to the release tag. The API server reports th 4. **Verify on a clean cluster.** ```bash - kubectl apply --server-side -f https://github.com/gke-labs/open-rl/releases/download/v0.0.2/openrl-lora.yaml + kubectl apply --server-side -f https://github.com/openrl-dev/openrl/releases/download/v0.0.2/openrl-lora.yaml kubectl -n openrl-system get pods -o jsonpath='{..image}' ``` diff --git a/SECURITY.md b/SECURITY.md index a842caf07..5d0391e3e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -7,7 +7,7 @@ If you discover a security vulnerability in OpenRL, please report it responsibly To report a vulnerability, use GitHub Private Vulnerability Reporting: -* **[Report a vulnerability](https://github.com/gke-labs/open-rl/security/advisories/new)** +* **[Report a vulnerability](https://github.com/openrl-dev/openrl/security/advisories/new)** @@ -1211,7 +1211,7 @@

Build it with us.

We have applied to donate OpenRL to the CNCF, for a vendor-neutral home.

- github.com/gke-labs/open-rl + github.com/openrl-dev/openrl

The roadmap and the issues are public. File one, or pick one up.

@@ -1232,7 +1232,7 @@

Try it

Thank you.

GPUs for work, not for people. Standard RL loops on shared Kubernetes accelerators.

OpenRL Authors

- github.com/gke-labs/open-rl + github.com/openrl-dev/openrl
@@ -1587,7 +1587,7 @@

A sweep an agent could launch tonight.

0.57 → 0.72 held-out reward, 30 steps

Harvey's Legal Agent Benchmark: documents in a sandbox, tools to read them, deliverables graded by a judge. Recipe in the repo, 32k-token turns in a 192k context.

- + diff --git a/docs/setup/gke-setup.md b/docs/setup/gke-setup.md index d53e354b3..1c574cb8f 100644 --- a/docs/setup/gke-setup.md +++ b/docs/setup/gke-setup.md @@ -118,12 +118,12 @@ Apply **only one** of the following release bundles. Both install the same API s * **Option A: LoRA.** Trainer and sampler workers each get a GPU of their own. ```bash - kubectl apply --server-side -f https://github.com/gke-labs/open-rl/releases/latest/download/openrl-lora.yaml + kubectl apply --server-side -f https://github.com/openrl-dev/openrl/releases/latest/download/openrl-lora.yaml ``` * **Option B: LoRA and full fine-tuning (FFT).** Adds FFT workers, which can share a GPU with other FFT workers, and two DaemonSets that coordinate that sharing on each GPU node: the accelerator time-slicer and the llm-d snapshot agent. ```bash - kubectl apply --server-side -f https://github.com/gke-labs/open-rl/releases/latest/download/openrl-fft.yaml + kubectl apply --server-side -f https://github.com/openrl-dev/openrl/releases/latest/download/openrl-fft.yaml ``` The DaemonSets run privileged, with host PID and host network, and schedule onto nodes labeled `nvidia.com/gpu.present=true` (set on the pool above). The snapshot agent checkpoints CUDA processes and needs NVIDIA driver r570 or newer, which the `latest` driver installer above provides. FFT workers never share a GPU with a LoRA worker. See [GKE FFT Time-Slice Setup](gke-fft-timeslice.md) for how the sharing works. diff --git a/docs/setup/local-setup.md b/docs/setup/local-setup.md index 177e438fd..a31c681c3 100644 --- a/docs/setup/local-setup.md +++ b/docs/setup/local-setup.md @@ -36,8 +36,8 @@ gcloud compute instances create openrl-vm \ Once you have accessed your VM, clone the repository and stay in the repository root for the following steps: ```bash -git clone https://github.com/gke-labs/open-rl.git -cd open-rl +git clone https://github.com/openrl-dev/openrl.git +cd openrl ``` ### 3. System Packages diff --git a/docs/setup/lora-dra.md b/docs/setup/lora-dra.md index 1d98fdcee..63711fe6c 100644 --- a/docs/setup/lora-dra.md +++ b/docs/setup/lora-dra.md @@ -55,7 +55,7 @@ Apply one bundle, for example LoRA only: ```bash kubectl --context my-cluster apply --server-side \ - -f https://github.com/gke-labs/open-rl/releases/latest/download/openrl-lora.yaml + -f https://github.com/openrl-dev/openrl/releases/latest/download/openrl-lora.yaml ``` From a checkout, render the overlay with the image tag to deploy. `latest` @@ -109,7 +109,7 @@ download the bundle and edit the `open-rl-shared-pvc` claim in place. Keep the name so the API server and workers find it; change the storage class and size: ```bash -curl -fsSLO https://github.com/gke-labs/open-rl/releases/latest/download/openrl-lora.yaml +curl -fsSLO https://github.com/openrl-dev/openrl/releases/latest/download/openrl-lora.yaml ``` ```yaml diff --git a/examples/autoresearch/k8s/base/resources.yaml b/examples/autoresearch/k8s/base/resources.yaml index 85c8310ee..4fb3d2679 100644 --- a/examples/autoresearch/k8s/base/resources.yaml +++ b/examples/autoresearch/k8s/base/resources.yaml @@ -57,7 +57,7 @@ spec: activeDeadlineSeconds: 21600 containers: - name: researcher - image: ghcr.io/gke-labs/open-rl/autoresearch:latest + image: ghcr.io/openrl-dev/openrl/autoresearch:latest imagePullPolicy: Always resources: requests: @@ -89,7 +89,7 @@ spec: # exits, so the run stays inspectable until the Sandbox is deleted or # the deadline passes. - name: ui - image: ghcr.io/gke-labs/open-rl/autoresearch:latest + image: ghcr.io/openrl-dev/openrl/autoresearch:latest imagePullPolicy: Always command: ["sh", "-c"] args: diff --git a/examples/sft/text-to-sql/texttosql_sft_notebook.ipynb b/examples/sft/text-to-sql/texttosql_sft_notebook.ipynb index 22e838659..beaa4da32 100644 --- a/examples/sft/text-to-sql/texttosql_sft_notebook.ipynb +++ b/examples/sft/text-to-sql/texttosql_sft_notebook.ipynb @@ -26,7 +26,7 @@ "| **Model** | `google/gemma-3-1b-pt` |\n", "| **Dataset** | [gretel-synthetic-text-to-sql](https://huggingface.co/datasets/philschmid/gretel-synthetic-text-to-sql) (100k examples) |\n", "| **Method** | LoRA SFT, attention + MLP adapters, base frozen |\n", - "| **Infra** | [Open-RL](https://github.com/gke-labs/open-rl) server + [Tinker SDK](https://pypi.org/project/tinker/) |\n" + "| **Infra** | [Open-RL](https://github.com/openrl-dev/openrl) server + [Tinker SDK](https://pypi.org/project/tinker/) |\n" ] }, { diff --git a/examples/tinker-cookbook/README.md b/examples/tinker-cookbook/README.md index 5644702a9..732ad2f0b 100644 --- a/examples/tinker-cookbook/README.md +++ b/examples/tinker-cookbook/README.md @@ -53,7 +53,7 @@ make server BASE_MODEL="Qwen/Qwen3-4B-Instruct-2507" ## Checkpointing Limitation -OpenRL does not yet implement full Tinker-compatible durable checkpoint management. For recipes that expose periodic checkpoint saves, set `save_every=0`; See [gke-labs/open-rl#83](https://github.com/gke-labs/open-rl/issues/83) for more details. +OpenRL does not yet implement full Tinker-compatible durable checkpoint management. For recipes that expose periodic checkpoint saves, set `save_every=0`; See [openrl-dev/openrl#83](https://github.com/openrl-dev/openrl/issues/83) for more details. ## Supervised Learning Loop diff --git a/k8s/deploy/base/api-server.yaml b/k8s/deploy/base/api-server.yaml index 49f4fbe36..b57004da8 100644 --- a/k8s/deploy/base/api-server.yaml +++ b/k8s/deploy/base/api-server.yaml @@ -32,7 +32,7 @@ spec: serviceAccountName: open-rl-sa containers: - name: api-server - image: ghcr.io/gke-labs/open-rl/api-server:latest + image: ghcr.io/openrl-dev/openrl/api-server:latest imagePullPolicy: IfNotPresent command: ["uv", "run", "uvicorn", "server.api_server:app", "--host", "0.0.0.0", "--port", "8000"] ports: diff --git a/k8s/deploy/base/kustomization.yaml b/k8s/deploy/base/kustomization.yaml index a5bbe7ea3..7f026b789 100644 --- a/k8s/deploy/base/kustomization.yaml +++ b/k8s/deploy/base/kustomization.yaml @@ -20,8 +20,8 @@ configMapGenerator: - ENABLE_GCP_TRACE=0 - name: open-rl-images literals: - - worker=ghcr.io/gke-labs/open-rl/server:latest - - dispatcher=ghcr.io/gke-labs/open-rl/api-server:latest + - worker=ghcr.io/openrl-dev/openrl/server:latest + - dispatcher=ghcr.io/openrl-dev/openrl/api-server:latest # Dynamic worker images receive the same image transformations as containers. configurations: diff --git a/k8s/deploy/demo/app.py b/k8s/deploy/demo/app.py index f26a05074..322bc465d 100644 --- a/k8s/deploy/demo/app.py +++ b/k8s/deploy/demo/app.py @@ -26,7 +26,7 @@ NAMESPACE = os.getenv("POD_NAMESPACE", "openrl-system") API_SERVER = os.getenv("API_SERVER_URL", "http://open-rl-api-server-service:8000").rstrip("/") -CLIENT_IMAGE = os.getenv("CLIENT_IMAGE", "ghcr.io/gke-labs/open-rl/client:latest") +CLIENT_IMAGE = os.getenv("CLIENT_IMAGE", "ghcr.io/openrl-dev/openrl/client:latest") CLUSTER_NAME = os.getenv("CLUSTER_NAME", "") # shown on the Fleet tab; the page falls back to the namespace PVC = os.getenv("SHARED_PVC", "open-rl-shared-pvc") # Each Job writes its client logs to RUNS_ROOT/. The app mounts the same volume read-only and reads only those diff --git a/k8s/deploy/demo/demo-app.yaml b/k8s/deploy/demo/demo-app.yaml index 8a14ef559..ca68abbb1 100644 --- a/k8s/deploy/demo/demo-app.yaml +++ b/k8s/deploy/demo/demo-app.yaml @@ -50,7 +50,7 @@ spec: terminationGracePeriodSeconds: 2 containers: - name: demo - image: ghcr.io/gke-labs/open-rl/api-server:latest + image: ghcr.io/openrl-dev/openrl/api-server:latest command: ["sh", "-c", "cd /app && uv run python /demo/app.py"] ports: - name: http @@ -64,7 +64,7 @@ spec: value: http://open-rl-api-server-service:8000 # The client image the sweep's Jobs run; an overlay points it at its own build. - name: CLIENT_IMAGE - value: ghcr.io/gke-labs/open-rl/client:latest + value: ghcr.io/openrl-dev/openrl/client:latest # Shown on the Fleet tab next to the namespace; optional. - name: CLUSTER_NAME value: "" diff --git a/k8s/deploy/distributed-fft-timeslice/kustomization.yaml b/k8s/deploy/distributed-fft-timeslice/kustomization.yaml index 563aa32ff..079f1083a 100644 --- a/k8s/deploy/distributed-fft-timeslice/kustomization.yaml +++ b/k8s/deploy/distributed-fft-timeslice/kustomization.yaml @@ -28,9 +28,9 @@ configMapGenerator: - OPEN_RL_WEIGHT_SYNC_STRATEGY="delta" images: - - name: ghcr.io/gke-labs/open-rl/server + - name: ghcr.io/openrl-dev/openrl/server newTag: latest - - name: ghcr.io/gke-labs/open-rl/api-server + - name: ghcr.io/openrl-dev/openrl/api-server newTag: latest # FFT remains an optional deployment with cooperative GPU sharing. diff --git a/k8s/deploy/fft-runtime/07-accel-timeslicer-daemonset.yaml b/k8s/deploy/fft-runtime/07-accel-timeslicer-daemonset.yaml index 38e369ca3..588776aa9 100644 --- a/k8s/deploy/fft-runtime/07-accel-timeslicer-daemonset.yaml +++ b/k8s/deploy/fft-runtime/07-accel-timeslicer-daemonset.yaml @@ -45,7 +45,7 @@ spec: effect: "NoSchedule" containers: - name: accel-timeslicer - image: ghcr.io/gke-labs/open-rl/server:latest + image: ghcr.io/openrl-dev/openrl/server:latest imagePullPolicy: IfNotPresent command: ["uv", "run", "python", "-m", "accel_timeslicer.serve"] args: ["--listen-host", "0.0.0.0", "--port", "9753", "--backend", "llmd", "--llmd-snapshot-endpoint", "127.0.0.1:9001", "--scheduling-policy", "lrs"] diff --git a/k8s/eval/vllm-eval-job.yaml b/k8s/eval/vllm-eval-job.yaml index edb2df430..b944d16f4 100644 --- a/k8s/eval/vllm-eval-job.yaml +++ b/k8s/eval/vllm-eval-job.yaml @@ -38,7 +38,7 @@ spec: restartPolicy: Never containers: - name: eval - image: ghcr.io/gke-labs/open-rl/server:latest + image: ghcr.io/openrl-dev/openrl/server:latest imagePullPolicy: Always command: ["uv", "run", "python", "-m", "server.scripts.run_vllm_eval"] env: diff --git a/scheduler/README.md b/scheduler/README.md index 6c3deee33..df4e584b4 100644 --- a/scheduler/README.md +++ b/scheduler/README.md @@ -21,7 +21,7 @@ spec: spec: containers: - name: worker - image: ghcr.io/gke-labs/open-rl/worker:latest + image: ghcr.io/openrl-dev/openrl/worker:latest ``` Everything else — device, tier, claim, node — is derived and reported back in diff --git a/scheduler/controller/Makefile b/scheduler/controller/Makefile index 3cbb651dd..01deca2fb 100644 --- a/scheduler/controller/Makefile +++ b/scheduler/controller/Makefile @@ -1,4 +1,4 @@ -IMG ?= ghcr.io/gke-labs/open-rl/scheduler:latest +IMG ?= ghcr.io/openrl-dev/openrl/scheduler:latest CONTROLLER_TOOLS_VERSION ?= v0.19.0 CRD_MANIFEST := ../deploy/base/00-workload-crd.yaml diff --git a/scheduler/controller/PROJECT b/scheduler/controller/PROJECT index d8a1b2a46..18c15a3f2 100644 --- a/scheduler/controller/PROJECT +++ b/scheduler/controller/PROJECT @@ -14,7 +14,7 @@ domain: openrl.io layout: - go.kubebuilder.io/v4 projectName: open-rl-scheduler -repo: github.com/gke-labs/open-rl/scheduler/controller +repo: github.com/openrl-dev/openrl/scheduler/controller resources: - api: crdVersion: v1 @@ -22,13 +22,13 @@ resources: controller: true domain: openrl.io kind: Workload - path: github.com/gke-labs/open-rl/scheduler/controller/api/v1alpha1 + path: github.com/openrl-dev/openrl/scheduler/controller/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 namespaced: true domain: openrl.io kind: ClaimLedger - path: github.com/gke-labs/open-rl/scheduler/controller/api/v1alpha1 + path: github.com/openrl-dev/openrl/scheduler/controller/api/v1alpha1 version: v1alpha1 version: "3" diff --git a/scheduler/controller/cmd/manager/main.go b/scheduler/controller/cmd/manager/main.go index 6b0e16715..282ef628b 100644 --- a/scheduler/controller/cmd/manager/main.go +++ b/scheduler/controller/cmd/manager/main.go @@ -24,9 +24,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log/zap" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" - openrlv1alpha1 "github.com/gke-labs/open-rl/scheduler/controller/api/v1alpha1" - "github.com/gke-labs/open-rl/scheduler/controller/internal/controller" - "github.com/gke-labs/open-rl/scheduler/controller/internal/placement" + openrlv1alpha1 "github.com/openrl-dev/openrl/scheduler/controller/api/v1alpha1" + "github.com/openrl-dev/openrl/scheduler/controller/internal/controller" + "github.com/openrl-dev/openrl/scheduler/controller/internal/placement" ) var scheme = runtime.NewScheme() diff --git a/scheduler/controller/go.mod b/scheduler/controller/go.mod index 1ba836367..adfb60e0f 100644 --- a/scheduler/controller/go.mod +++ b/scheduler/controller/go.mod @@ -1,4 +1,4 @@ -module github.com/gke-labs/open-rl/scheduler/controller +module github.com/openrl-dev/openrl/scheduler/controller go 1.26.0 diff --git a/scheduler/controller/internal/controller/fleet.go b/scheduler/controller/internal/controller/fleet.go index 0fd79919a..a40845276 100644 --- a/scheduler/controller/internal/controller/fleet.go +++ b/scheduler/controller/internal/controller/fleet.go @@ -14,8 +14,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - openrlv1alpha1 "github.com/gke-labs/open-rl/scheduler/controller/api/v1alpha1" - "github.com/gke-labs/open-rl/scheduler/controller/internal/placement" + openrlv1alpha1 "github.com/openrl-dev/openrl/scheduler/controller/api/v1alpha1" + "github.com/openrl-dev/openrl/scheduler/controller/internal/placement" ) // Labels the controller stamps on the objects it owns, and reads back to diff --git a/scheduler/controller/internal/controller/ledger.go b/scheduler/controller/internal/controller/ledger.go index a0657b684..801546f4a 100644 --- a/scheduler/controller/internal/controller/ledger.go +++ b/scheduler/controller/internal/controller/ledger.go @@ -13,8 +13,8 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "sigs.k8s.io/controller-runtime/pkg/client" - openrlv1alpha1 "github.com/gke-labs/open-rl/scheduler/controller/api/v1alpha1" - "github.com/gke-labs/open-rl/scheduler/controller/internal/placement" + openrlv1alpha1 "github.com/openrl-dev/openrl/scheduler/controller/api/v1alpha1" + "github.com/openrl-dev/openrl/scheduler/controller/internal/placement" ) // bookAttempts bounds the CAS retry loop; past it the reconcile requeues. diff --git a/scheduler/controller/internal/controller/ledger_test.go b/scheduler/controller/internal/controller/ledger_test.go index b31f3179b..26d5c5ea7 100644 --- a/scheduler/controller/internal/controller/ledger_test.go +++ b/scheduler/controller/internal/controller/ledger_test.go @@ -15,8 +15,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" - openrlv1alpha1 "github.com/gke-labs/open-rl/scheduler/controller/api/v1alpha1" - "github.com/gke-labs/open-rl/scheduler/controller/internal/placement" + openrlv1alpha1 "github.com/openrl-dev/openrl/scheduler/controller/api/v1alpha1" + "github.com/openrl-dev/openrl/scheduler/controller/internal/placement" ) func getLedger(t *testing.T, r *WorkloadReconciler, name string) *openrlv1alpha1.ClaimLedger { diff --git a/scheduler/controller/internal/controller/pod.go b/scheduler/controller/internal/controller/pod.go index 868010ad8..c0d40d056 100644 --- a/scheduler/controller/internal/controller/pod.go +++ b/scheduler/controller/internal/controller/pod.go @@ -13,8 +13,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - openrlv1alpha1 "github.com/gke-labs/open-rl/scheduler/controller/api/v1alpha1" - "github.com/gke-labs/open-rl/scheduler/controller/internal/placement" + openrlv1alpha1 "github.com/openrl-dev/openrl/scheduler/controller/api/v1alpha1" + "github.com/openrl-dev/openrl/scheduler/controller/internal/placement" ) // Time-slicer contract, mirrored from src/accel_timeslicer/workload.py. A pod diff --git a/scheduler/controller/internal/controller/stress_test.go b/scheduler/controller/internal/controller/stress_test.go index 2ab006ced..9c17b87bd 100644 --- a/scheduler/controller/internal/controller/stress_test.go +++ b/scheduler/controller/internal/controller/stress_test.go @@ -24,8 +24,8 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - openrlv1alpha1 "github.com/gke-labs/open-rl/scheduler/controller/api/v1alpha1" - "github.com/gke-labs/open-rl/scheduler/controller/internal/placement" + openrlv1alpha1 "github.com/openrl-dev/openrl/scheduler/controller/api/v1alpha1" + "github.com/openrl-dev/openrl/scheduler/controller/internal/placement" ) // The placement storm: random fleets, random workload churn, a random DRA, diff --git a/scheduler/controller/internal/controller/workload_controller.go b/scheduler/controller/internal/controller/workload_controller.go index 0ab9dcca6..29801cc5b 100644 --- a/scheduler/controller/internal/controller/workload_controller.go +++ b/scheduler/controller/internal/controller/workload_controller.go @@ -27,8 +27,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - openrlv1alpha1 "github.com/gke-labs/open-rl/scheduler/controller/api/v1alpha1" - "github.com/gke-labs/open-rl/scheduler/controller/internal/placement" + openrlv1alpha1 "github.com/openrl-dev/openrl/scheduler/controller/api/v1alpha1" + "github.com/openrl-dev/openrl/scheduler/controller/internal/placement" ) // WorkloadReconciler turns Workload requests into ResourceClaims diff --git a/scheduler/controller/internal/controller/workload_controller_test.go b/scheduler/controller/internal/controller/workload_controller_test.go index f35b5ec8b..38c82184e 100644 --- a/scheduler/controller/internal/controller/workload_controller_test.go +++ b/scheduler/controller/internal/controller/workload_controller_test.go @@ -19,8 +19,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - openrlv1alpha1 "github.com/gke-labs/open-rl/scheduler/controller/api/v1alpha1" - "github.com/gke-labs/open-rl/scheduler/controller/internal/placement" + openrlv1alpha1 "github.com/openrl-dev/openrl/scheduler/controller/api/v1alpha1" + "github.com/openrl-dev/openrl/scheduler/controller/internal/placement" ) const ( diff --git a/scheduler/deploy/base/01-scheduler.yaml b/scheduler/deploy/base/01-scheduler.yaml index 80c1e4d7b..f7dd59314 100644 --- a/scheduler/deploy/base/01-scheduler.yaml +++ b/scheduler/deploy/base/01-scheduler.yaml @@ -117,7 +117,7 @@ spec: containers: - name: manager # Built by `make docker-build docker-push` from controller/. - image: ghcr.io/gke-labs/open-rl/scheduler:latest + image: ghcr.io/openrl-dev/openrl/scheduler:latest args: - --leader-elect - --health-probe-bind-address=:8081 diff --git a/scheduler/deploy/overlays/smoke/kustomization.yaml b/scheduler/deploy/overlays/smoke/kustomization.yaml index 94ffd8988..02ed4050b 100644 --- a/scheduler/deploy/overlays/smoke/kustomization.yaml +++ b/scheduler/deploy/overlays/smoke/kustomization.yaml @@ -9,7 +9,7 @@ resources: - ../../base images: - - name: ghcr.io/gke-labs/open-rl/scheduler + - name: ghcr.io/openrl-dev/openrl/scheduler newName: open-rl/scheduler newTag: smoke diff --git a/scheduler/docs/design.md b/scheduler/docs/design.md index 8755f5d7f..ebfa264fb 100644 --- a/scheduler/docs/design.md +++ b/scheduler/docs/design.md @@ -306,7 +306,7 @@ spec: restartPolicy: OnFailure containers: - name: worker - image: ghcr.io/gke-labs/open-rl/trainer:latest + image: ghcr.io/openrl-dev/openrl/trainer:latest command: - uv - run diff --git a/scripts/perf_compare.py b/scripts/perf_compare.py index 35f0973b4..767c6e4b0 100644 --- a/scripts/perf_compare.py +++ b/scripts/perf_compare.py @@ -39,7 +39,7 @@ REPO_ROOT = Path(__file__).resolve().parents[1] WORKLOAD = REPO_ROOT / "k8s" / "perf" / "workload.conf" -CLIENT_IMAGE = "ghcr.io/gke-labs/open-rl/client:latest" +CLIENT_IMAGE = "ghcr.io/openrl-dev/openrl/client:latest" APP_LABEL = "open-rl-perf" RUN_LABEL = "openrl.io/perf-run" WORKER_SELECTOR = "app in (open-rl-trainer-worker,open-rl-sampler-worker)" diff --git a/scripts/run_cluster_e2e.py b/scripts/run_cluster_e2e.py index 29601d90c..c1615aa2a 100755 --- a/scripts/run_cluster_e2e.py +++ b/scripts/run_cluster_e2e.py @@ -5,7 +5,7 @@ applies it with kubectl, and streams the logs. Stdlib only - no uv needed: python3 scripts/run_cluster_e2e.py --scenario fft-gsm8k-rl-x2 \\ - --args "base_model=Qwen/Qwen3-8B steps=30 jitter_sec=5" --image ghcr.io/gke-labs/open-rl/client:latest + --args "base_model=Qwen/Qwen3-8B steps=30 jitter_sec=5" --image ghcr.io/openrl-dev/openrl/client:latest --print-only shows the rendered manifest and kubectl commands without running anything. """ diff --git a/site/content/blog/delta-weight-sync/index.md b/site/content/blog/delta-weight-sync/index.md index 45419e80c..36db6d854 100644 --- a/site/content/blog/delta-weight-sync/index.md +++ b/site/content/blog/delta-weight-sync/index.md @@ -58,7 +58,7 @@ On the sampler side, applying a delta means updating the changed parameters in p **1. Custom weight transfer backend.** - vLLM provides a pluggable [weight transfer engine](https://docs.vllm.ai/en/latest/training/weight_transfer/base/) [4] interface that receives weight updates while generation is paused, driven through start, update, and finish hooks. -- OpenRL registers a [`delta_snapshot` backend](https://github.com/gke-labs/open-rl/blob/5fae60a5213fd05fcaf17b955f25629bbc2c0fdb/src/server/delta_weight_transfer_engine.py) enabled via `WeightTransferConfig(backend="delta_snapshot")`, avoiding a custom vLLM fork. +- OpenRL registers a [`delta_snapshot` backend](https://github.com/openrl-dev/openrl/blob/5fae60a5213fd05fcaf17b955f25629bbc2c0fdb/src/server/delta_weight_transfer_engine.py) enabled via `WeightTransferConfig(backend="delta_snapshot")`, avoiding a custom vLLM fork. **2. In-place sparse patching.** - Inside that backend, we pass the changed positions and values to vLLM's [checkpoint weight patch loader](https://docs.vllm.ai/en/latest/api/vllm/model_executor/model_loader/checkpoint_weight_patch/), indexed by the original Hugging Face parameter names. diff --git a/site/content/blog/openrl-fall-update/index.md b/site/content/blog/openrl-fall-update/index.md index 8046657cd..4e33bb175 100644 --- a/site/content/blog/openrl-fall-update/index.md +++ b/site/content/blog/openrl-fall-update/index.md @@ -89,7 +89,7 @@ This makes it straightforward to test custom training loops, different framework Harvey's Legal Agent Benchmark (LAB) is a set of 1,251 long-horizon legal tasks across different practice areas. In each task, the model works inside a sandboxed environment containing source documents (contracts, board minutes, financial filings) and uses tools to inspect files and draft deliverables such as memos, letters, spreadsheets, and timelines, which are then graded against a rubric by an LLM judge. -The [Harvey LAB recipe](https://github.com/gke-labs/open-rl/tree/main/examples/harvey_labs) in our repository is a complete GRPO training loop built on `tinker-cookbook`. It uses [kubernetes-sigs/agent-sandbox](https://github.com/kubernetes-sigs/agent-sandbox) to isolate the per-task workspaces and includes a Kubernetes Job manifest to run the training loop inside the cluster. Over 30 steps, held-out reward improves from 0.57 to 0.72–0.74. We use this recipe to test OpenRL on realistic multi-turn workloads, and it serves as a working reference if you are building your own tool-using RL environments. +The [Harvey LAB recipe](https://github.com/openrl-dev/openrl/tree/main/examples/harvey_labs) in our repository is a complete GRPO training loop built on `tinker-cookbook`. It uses [kubernetes-sigs/agent-sandbox](https://github.com/kubernetes-sigs/agent-sandbox) to isolate the per-task workspaces and includes a Kubernetes Job manifest to run the training loop inside the cluster. Over 30 steps, held-out reward improves from 0.57 to 0.72–0.74. We use this recipe to test OpenRL on realistic multi-turn workloads, and it serves as a working reference if you are building your own tool-using RL environments. ## Configuring jobs through settings @@ -133,7 +133,7 @@ Next up on our roadmap: - **Multi-GPU full fine-tuning** on the Automodel trainer backend, followed by GPU time-slicing for multi-GPU workloads. - **Custom sampler images and prefix-aware routing** across sampler replicas. -We will share deeper posts on each of the capabilities above over the coming weeks. In the meantime, if you want to try them out, see the [getting-started guide](https://github.com/gke-labs/open-rl/blob/main/docs/getting-started.md) or browse the [v0.0.6](https://github.com/gke-labs/open-rl/releases/tag/v0.0.6) and [v0.0.7](https://github.com/gke-labs/open-rl/releases/tag/v0.0.7) release notes on GitHub. If you hit any issues, please [let us know](https://github.com/gke-labs/open-rl/issues). +We will share deeper posts on each of the capabilities above over the coming weeks. In the meantime, if you want to try them out, see the [getting-started guide](https://github.com/openrl-dev/openrl/blob/main/docs/getting-started.md) or browse the [v0.0.6](https://github.com/openrl-dev/openrl/releases/tag/v0.0.6) and [v0.0.7](https://github.com/openrl-dev/openrl/releases/tag/v0.0.7) release notes on GitHub. If you hit any issues, please [let us know](https://github.com/openrl-dev/openrl/issues). ## Acknowledgements diff --git a/site/hugo.toml b/site/hugo.toml index a6c34c0a1..20f66d74f 100644 --- a/site/hugo.toml +++ b/site/hugo.toml @@ -7,7 +7,7 @@ timeZone = "UTC" [params] description = "A self-hosted, Kubernetes-native post-training API for fine-tuning LLMs." - repo = "https://github.com/gke-labs/open-rl" + repo = "https://github.com/openrl-dev/openrl" ogImage = "img/og.jpg" [markup] diff --git a/site/static/llms.txt b/site/static/llms.txt index 7de08c5b9..c6f7f0c4e 100644 --- a/site/static/llms.txt +++ b/site/static/llms.txt @@ -2,18 +2,18 @@ > A self-hosted, Kubernetes-native post-training API for fine-tuning LLMs. It serves the Tinker API, so Tinker SDK clients and tinker-cookbook recipes run against your own GPUs unchanged. -Repository: https://github.com/gke-labs/open-rl +Repository: https://github.com/openrl-dev/openrl ## For AI coding agents -- [OpenRL skill](https://github.com/gke-labs/open-rl/blob/main/skills/openrl/SKILL.md): how to connect, the openrl.* settings, worker lifecycle, and a symptom-first runbook. Each release ships the same skill as `openrl-skill.tar.gz`; a running server reports the matching URL as `openrl.skill_url` in `GET /api/v1/get_server_capabilities`. -- [Getting started](https://github.com/gke-labs/open-rl/blob/main/docs/getting-started.md): deploy on a Kubernetes cluster, then run SFT and RL from a laptop. +- [OpenRL skill](https://github.com/openrl-dev/openrl/blob/main/skills/openrl/SKILL.md): how to connect, the openrl.* settings, worker lifecycle, and a symptom-first runbook. Each release ships the same skill as `openrl-skill.tar.gz`; a running server reports the matching URL as `openrl.skill_url` in `GET /api/v1/get_server_capabilities`. +- [Getting started](https://github.com/openrl-dev/openrl/blob/main/docs/getting-started.md): deploy on a Kubernetes cluster, then run SFT and RL from a laptop. - For how to train (recipes, hyperparameters, evaluation, SDK debugging) use the [tinker-cookbook skills](https://github.com/thinking-machines-lab/tinker-cookbook/tree/main/skills); the OpenRL skill covers only what differs on a self-hosted server and says when to load them. - A deployed server describes itself: `GET /api/v1/get_server_capabilities` (version, limits, where the settings schema is), `GET /openapi.json` (every `openrl.*` setting as `components.schemas.OpenRLSettings`), `GET /api/v1/openrl/models/` (one model's workers and their state), `GET /openapi.json`. ## Docs -- [Architecture](https://github.com/gke-labs/open-rl/blob/main/docs/architecture.md) -- [Tinker client compatibility](https://github.com/gke-labs/open-rl/blob/main/docs/tinker-client-compatibility.md) -- [Configuration](https://github.com/gke-labs/open-rl/blob/main/docs/configuration.md) -- [Releases](https://github.com/gke-labs/open-rl/releases) +- [Architecture](https://github.com/openrl-dev/openrl/blob/main/docs/architecture.md) +- [Tinker client compatibility](https://github.com/openrl-dev/openrl/blob/main/docs/tinker-client-compatibility.md) +- [Configuration](https://github.com/openrl-dev/openrl/blob/main/docs/configuration.md) +- [Releases](https://github.com/openrl-dev/openrl/releases) diff --git a/skills/openrl/SKILL.md b/skills/openrl/SKILL.md index 1a2053608..fb9eb7eae 100644 --- a/skills/openrl/SKILL.md +++ b/skills/openrl/SKILL.md @@ -8,7 +8,7 @@ description: >- OpenRL release: dev -OpenRL (github.com/gke-labs/open-rl) serves the Tinker API on a Kubernetes +OpenRL (github.com/openrl-dev/openrl) serves the Tinker API on a Kubernetes cluster your platform team runs. Any `tinker` SDK client or `tinker-cookbook` recipe works against it; your training loop runs on your machine and the GPUs do the work on the cluster. Facts here were verified on v0.0.6 plus the diff --git a/skills/openrl/references/lifecycle.md b/skills/openrl/references/lifecycle.md index c3b5171a3..35511595b 100644 --- a/skills/openrl/references/lifecycle.md +++ b/skills/openrl/references/lifecycle.md @@ -85,7 +85,7 @@ What changes when you choose Automodel: - The trainer runs a different image, the one the platform owner set as `OPEN_RL_AUTOMODEL_IMAGE`. The endpoint does not report which, and a deployment that - never set it runs `ghcr.io/gke-labs/open-rl/automodel:latest`. A first start pulls that + never set it runs `ghcr.io/openrl-dev/openrl/automodel:latest`. A first start pulls that image (several GiB) on top of the usual durations. - The job gets a trainer of its own, keyed `automodel-`, so it never shares with PyTorch LoRA jobs on the same base model and starts cold every time: expect the diff --git a/src/server/api_server.py b/src/server/api_server.py index a6f651ca4..2476a38db 100644 --- a/src/server/api_server.py +++ b/src/server/api_server.py @@ -862,7 +862,7 @@ async def lifespan(_: FastAPI): # The release tag, baked in at image build (OPEN_RL_VERSION build arg); the # VERSION file is an internal counter and does not name a release. OPEN_RL_VERSION = os.getenv("OPEN_RL_VERSION") or "dev" # an empty build arg must not become the version -RELEASES_URL = "https://github.com/gke-labs/open-rl/releases" +RELEASES_URL = "https://github.com/openrl-dev/openrl/releases" EXAMPLE_MODELS = ["Qwen/Qwen2.5-0.5B", "Qwen/Qwen3-0.6B", "google/gemma-4-e2b", "Qwen/Qwen3-8B"] app = FastAPI( @@ -872,7 +872,7 @@ async def lifespan(_: FastAPI): "A self-hosted, Kubernetes-native post-training API that serves the Tinker API. " "Tinker SDK clients use the /api/v1 paths. GET /api/v1/openrl/models/{model_id} is OpenRL's own: " "what the server knows about one model, its settings, its workers and whether its session is live. " - "Repository and docs: https://github.com/gke-labs/open-rl" + "Repository and docs: https://github.com/openrl-dev/openrl" ), lifespan=lifespan, ) @@ -989,7 +989,7 @@ def openrl_info() -> dict[str, Any]: "session_reap_interval_seconds": SESSION_REAP_INTERVAL_SEC, }, "skill_url": f"{RELEASES_URL}/download/{OPEN_RL_VERSION}/openrl-skill.tar.gz" if release else None, - "getting_started_url": "https://github.com/gke-labs/open-rl/blob/main/docs/getting-started.md", + "getting_started_url": "https://github.com/openrl-dev/openrl/blob/main/docs/getting-started.md", } diff --git a/src/server/scheduler_worker_manager.py b/src/server/scheduler_worker_manager.py index 14f219c3a..bc3e9ac77 100644 --- a/src/server/scheduler_worker_manager.py +++ b/src/server/scheduler_worker_manager.py @@ -182,12 +182,12 @@ def worker_container(worker: Worker) -> tuple[str, list[str]]: """The image and command. An Automodel trainer, or one from an image the job names, runs the python on its image's PATH.""" if worker.role == "trainer" and worker.meta.trainer_backend != "pytorch": - image = worker.meta.trainer_image() or os.getenv("OPEN_RL_AUTOMODEL_IMAGE", "ghcr.io/gke-labs/open-rl/automodel:latest") + image = worker.meta.trainer_image() or os.getenv("OPEN_RL_AUTOMODEL_IMAGE", "ghcr.io/openrl-dev/openrl/automodel:latest") if worker.devices > 1: torchrun = ["-m", "torch.distributed.run", "--standalone", f"--nproc-per-node={worker.devices}"] return image, ["python", "-u", *torchrun, "-m", TRAINER_MODULE] return image, ["python", "-u", "-m", TRAINER_MODULE] - image = os.getenv("OPEN_RL_WORKER_IMAGE", "ghcr.io/gke-labs/open-rl/server:latest") + image = os.getenv("OPEN_RL_WORKER_IMAGE", "ghcr.io/openrl-dev/openrl/server:latest") return image, ["uv", "run", "python", "-u", "-m", TRAINER_MODULE] @@ -273,7 +273,7 @@ def dispatcher_body(pool: str, owner: str) -> dict[str, Any]: dispatcher = { "name": "dispatcher", # The dispatcher is a small CPU process; the API-server image carries it without the GPU stack. - "image": os.getenv("OPEN_RL_DISPATCHER_IMAGE") or os.getenv("OPEN_RL_WORKER_IMAGE", "ghcr.io/gke-labs/open-rl/server:latest"), + "image": os.getenv("OPEN_RL_DISPATCHER_IMAGE") or os.getenv("OPEN_RL_WORKER_IMAGE", "ghcr.io/openrl-dev/openrl/server:latest"), "command": ["uv", "run", "python", "-u", "-m", "server.sampling_dispatcher"], "env": env, "volumeMounts": [{"name": "shared-storage", "mountPath": "/mnt/shared"}], diff --git a/tests/test_openrl_status.py b/tests/test_openrl_status.py index c5f70c122..7b11fa191 100644 --- a/tests/test_openrl_status.py +++ b/tests/test_openrl_status.py @@ -68,7 +68,7 @@ async def test_capabilities_describe_the_deployment_without_breaking_the_sdk_fie self.assertTrue(info["models"]["any_huggingface_model"]) self.assertEqual(info["limits"]["vllm_max_model_len"], 8192) self.assertEqual(info["limits"]["session_ttl_seconds"], 120) - self.assertEqual(info["skill_url"], "https://github.com/gke-labs/open-rl/releases/download/v9.9.9/openrl-skill.tar.gz") + self.assertEqual(info["skill_url"], "https://github.com/openrl-dev/openrl/releases/download/v9.9.9/openrl-skill.tar.gz") # Deployment facts only; nothing about other clients' models or the fleet. self.assertNotIn("endpoints", info) # The settings are described once, in the OpenAPI document; capabilities point there.