Skip to content

Commit 3df2b6a

Browse files
authored
chore: make src the server package root (#117)
* Restructure server packages under src * Add training e2e checks
1 parent bc91e08 commit 3df2b6a

52 files changed

Lines changed: 2036 additions & 1151 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.git
2+
**/.venv
3+
**/__pycache__
4+
**/*.pyc
5+
.ruff_cache
6+
.pytest_cache

.github/workflows/build-and-push.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ jobs:
1313
matrix:
1414
include:
1515
- image_name: gateway
16-
context: src/server
16+
context: .
1717
dockerfile: src/server/Dockerfile.gateway
1818
- image_name: server
19-
context: src/server
19+
context: .
2020
dockerfile: src/server/Dockerfile
2121
- image_name: client
22-
context: examples
22+
context: .
2323
dockerfile: examples/autoresearch/Dockerfile
2424
permissions:
2525
contents: read

.github/workflows/build-pr.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ jobs:
1010
matrix:
1111
include:
1212
- image_name: gateway
13-
context: src/server
13+
context: .
1414
dockerfile: src/server/Dockerfile.gateway
1515
- image_name: server
16-
context: src/server
16+
context: .
1717
dockerfile: src/server/Dockerfile
1818
- image_name: client
19-
context: examples
19+
context: .
2020
dockerfile: examples/autoresearch/Dockerfile
2121
permissions:
2222
contents: read

Makefile

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,45 @@ HOST ?= 127.0.0.1
1313
PORT ?= 9003
1414
# The fully qualified base URL used by local CLI tools and clients
1515
BASE_URL ?= http://$(HOST):$(PORT)
16-
TEST_PYTHONPATH ?= examples/sft/pig-latin
16+
UNIT_TESTS ?= tests.test_gateway_paths tests.test_snapshot_agent tests.test_trainer_optimizer_correctness tests.test_worker_launch_processor
17+
# Only forward BASE_URL to e2e when the user supplied it. The Makefile default
18+
# is for local CLI usage; e2e should start its own backend by default.
19+
TRAINING_TEST_BASE_URL ?= $(if $(filter environment command line,$(origin BASE_URL)),$(BASE_URL),)
20+
TRAINING_TEST_EXTRA ?= gpu
21+
TRAINING_TEST_ARGS ?=
22+
PIGLATIN_TEST_PYTHONPATH ?= examples/sft/pig-latin
23+
24+
# CUDA_VISIBLE_DEVICES can be provided either as an environment variable or as a
25+
# Make variable, and is inherited by the backend/eval subprocesses.
26+
ifneq ($(origin CUDA_VISIBLE_DEVICES),undefined)
27+
export CUDA_VISIBLE_DEVICES
28+
endif
1729

1830
help:
1931
@echo "make server # $(BASE_MODEL), SAMPLING_BACKEND=$(SAMPLING_BACKEND), port $(PORT)"
2032
@echo "make server BASE_MODEL=google/gemma-4-e2b SAMPLING_BACKEND=vllm"
2133
@echo "VLLM_ARCHITECTURE_OVERRIDE=Gemma4ForCausalLM make vllm BASE_MODEL=google/gemma-4-e2b"
22-
@echo "make test | lint | fmt"
34+
@echo "make test # fast unit tests"
35+
@echo "make test e2e tiny-lora|tiny-fft|tiny-rl|lora-textsql|fft-gsm8k|fft-gsm8k-x2 # tiny-* = fast overfit smoke tests"
36+
@echo "make test e2e tiny-lora BASE_URL=http://host:9003"
37+
@echo "CUDA_VISIBLE_DEVICES=0 make test e2e tiny-fft"
38+
@echo "make test e2e tiny-fft TRAINING_TEST_ARGS='steps=20'"
39+
@echo "make test e2e fft-gsm8k TRAINING_TEST_ARGS='steps=10 eval_examples=8 extra=\"batch=2\"'"
40+
@echo "make test piglatin # pig-latin example end-to-end tests"
41+
@echo "make lint | fmt"
2342

2443
# ---------------------------------------------------------------------------
2544
# Server
2645
# ---------------------------------------------------------------------------
2746
server:
2847
@-kill -9 $$(lsof -ti:$(PORT)) 2>/dev/null || true
29-
cd src/server && BASE_MODEL="$(BASE_MODEL)" SAMPLING_BACKEND="$(SAMPLING_BACKEND)" \
48+
BASE_MODEL="$(BASE_MODEL)" SAMPLING_BACKEND="$(SAMPLING_BACKEND)" \
3049
uv run --extra $(if $(filter vllm,$(SAMPLING_BACKEND)),gpu,cpu) \
31-
python -m uvicorn gateway:app --host $(HOST) --port $(PORT)
50+
python -m uvicorn server.gateway:app --host $(HOST) --port $(PORT)
3251

3352
vllm:
34-
cd src/server && BASE_MODEL="$(BASE_MODEL)" \
35-
uv run --extra vllm python -m vllm_sampler
53+
BASE_MODEL="$(BASE_MODEL)" \
54+
uv run --extra vllm python -m server.vllm_sampler
3655

3756
# ---------------------------------------------------------------------------
3857
# CLI
@@ -42,14 +61,40 @@ ifeq (cli,$(firstword $(MAKECMDGOALS)))
4261
$(eval $(CLI_ARGS):;@:)
4362
endif
4463

64+
ifeq (test,$(firstword $(MAKECMDGOALS)))
65+
TEST_MODE := $(word 2,$(MAKECMDGOALS))
66+
TEST_SCENARIO := $(word 3,$(MAKECMDGOALS))
67+
TEST_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
68+
ifneq ($(TEST_ARGS),)
69+
$(eval $(TEST_ARGS):;@:)
70+
endif
71+
endif
72+
4573
cli:
4674
@cd dev/tools && BASE_URL="$(BASE_URL)" uv run python cli.py $(CLI_ARGS)
4775

4876
# ---------------------------------------------------------------------------
4977
# Dev
5078
# ---------------------------------------------------------------------------
5179
test:
52-
PYTHONPATH="$(TEST_PYTHONPATH)" uv --project examples run python -m unittest discover -s tests
80+
@mode="$(TEST_MODE)"; \
81+
scenario="$(TEST_SCENARIO)"; \
82+
if [ -z "$$mode" ] || [ "$$mode" = "unit" ]; then \
83+
uv run --frozen --exact --extra cpu python -m unittest $(UNIT_TESTS); \
84+
elif [ "$$mode" = "e2e" ]; then \
85+
if [ -z "$$scenario" ]; then \
86+
echo "Missing e2e scenario. Expected tiny-lora, tiny-fft, tiny-rl, lora-textsql, fft-gsm8k, or fft-gsm8k-x2."; \
87+
exit 2; \
88+
fi; \
89+
set -- "scenario=$$scenario" "uv_extra=$(TRAINING_TEST_EXTRA)"; \
90+
if [ -n "$(TRAINING_TEST_BASE_URL)" ]; then set -- "$$@" "base_url=$(TRAINING_TEST_BASE_URL)"; fi; \
91+
uv run --extra "$(TRAINING_TEST_EXTRA)" python scripts/run_training_e2e.py "$$@" $(TRAINING_TEST_ARGS); \
92+
elif [ "$$mode" = "piglatin" ]; then \
93+
PYTHONPATH="$(PIGLATIN_TEST_PYTHONPATH)" uv --project examples run python -m unittest discover -s tests; \
94+
else \
95+
echo "Unknown test mode '$$mode'. Expected unit, e2e, or piglatin."; \
96+
exit 2; \
97+
fi
5398

5499
lint:
55100
uvx ruff check .
@@ -66,8 +111,8 @@ GCP_PROJECT ?= cdrollouts-sunilarora
66111
IMAGE_TAG ?= latest
67112

68113
build-images:
69-
cd src/server && DOCKER_BUILDKIT=1 docker build -t gcr.io/$(GCP_PROJECT)/open-rl-server:$(IMAGE_TAG) -f Dockerfile .
70-
cd src/server && DOCKER_BUILDKIT=1 docker build -t gcr.io/$(GCP_PROJECT)/open-rl-gateway:$(IMAGE_TAG) -f Dockerfile.gateway .
114+
DOCKER_BUILDKIT=1 docker build -t gcr.io/$(GCP_PROJECT)/open-rl-server:$(IMAGE_TAG) -f src/server/Dockerfile .
115+
DOCKER_BUILDKIT=1 docker build -t gcr.io/$(GCP_PROJECT)/open-rl-gateway:$(IMAGE_TAG) -f src/server/Dockerfile.gateway .
71116

72117
push-images:
73118
docker push gcr.io/$(GCP_PROJECT)/open-rl-server:$(IMAGE_TAG)
@@ -106,4 +151,3 @@ push-vm:
106151
# Pull changes from the remote VM back to the local workspace
107152
pull-vm:
108153
rsync -avz --exclude '.git' --exclude '.venv' --exclude '__pycache__' --exclude '*.pyc' --exclude '.DS_Store' $(REMOTE_HOST):~/open-rl/ ./
109-

dev/tools/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def list_adapters(args):
4444
# Format timestamp if possible
4545
try:
4646
# If it's a float timestamp
47-
if isinstance(created_at, (int, float)):
47+
if isinstance(created_at, int | float):
4848
dt = datetime.fromtimestamp(created_at)
4949
created_at = dt.strftime("%Y-%m-%d %H:%M:%S")
5050
# If it's an ISO string (from metadata.json)

docs/blog/assets/local-to-cloud.svg

Lines changed: 2 additions & 2 deletions
Loading

docs/blog/from-mac-to-gke.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Start the server:
1616

1717
```bash
1818
BASE_MODEL="google/gemma-3-1b-pt" \
19-
uv run uvicorn src.gateway:app --host 0.0.0.0 --port 9003
19+
uv run uvicorn server.gateway:app --host 0.0.0.0 --port 9003
2020
```
2121

2222
Then write your training loop with the Tinker SDK — 4 API primitives are all you need:

docs/configuration.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ curl -LsSf https://astral.sh/uv/install.sh | sh
1515
Start the API server and trainer with the default torch sampling backend:
1616

1717
```bash
18-
cd src/server
1918
BASE_MODEL=google/gemma-4-e2b \
2019
SAMPLING_BACKEND=torch \
21-
uv run --extra cpu python -m uvicorn gateway:app --host 127.0.0.1 --port 9003
20+
uv run --extra cpu python -m uvicorn server.gateway:app --host 127.0.0.1 --port 9003
2221
```
2322

2423
Because `REDIS_URL` is unset, this starts the API server and trainer loop in one
@@ -28,20 +27,18 @@ For a separate vLLM sampler, use two terminals:
2827

2928
```bash
3029
# Terminal 1: vLLM sampler
31-
cd src/server
3230
BASE_MODEL=google/gemma-4-e2b \
3331
VLLM_ARCHITECTURE_OVERRIDE=Gemma4ForCausalLM \
3432
CUDA_VISIBLE_DEVICES=0 \
35-
uv run --extra vllm python -m vllm_sampler
33+
uv run --extra vllm python -m server.vllm_sampler
3634
```
3735

3836
```bash
3937
# Terminal 2: API server and trainer
40-
cd src/server
4138
BASE_MODEL=google/gemma-4-e2b \
4239
SAMPLING_BACKEND=vllm \
4340
CUDA_VISIBLE_DEVICES=1 \
44-
uv run --extra gpu python -m uvicorn gateway:app --host 127.0.0.1 --port 9003
41+
uv run --extra gpu python -m uvicorn server.gateway:app --host 127.0.0.1 --port 9003
4542
```
4643

4744
The equivalent Makefile shortcuts are:
@@ -95,18 +92,18 @@ Kubernetes deployment manifests set these variables in pod specs. The important
9592
REDIS_URL=redis://redis-service:6379 \
9693
VLLM_URL=http://vllm-service:8001 \
9794
BASE_MODEL=google/gemma-4-e2b \
98-
uv run uvicorn src.gateway:app --host 0.0.0.0 --port 8000
95+
uv run uvicorn server.gateway:app --host 0.0.0.0 --port 8000
9996
```
10097

10198
```bash
10299
# Trainer worker pod
103100
REDIS_URL=redis://redis-service:6379 \
104101
BASE_MODEL=google/gemma-4-e2b \
105-
uv run python -m src.clock_cycle
102+
uv run python -m server.training_requests_processor
106103
```
107104

108105
```bash
109106
# vLLM worker pod
110107
BASE_MODEL=google/gemma-4-e2b \
111-
uv run uvicorn src.vllm_sampler:app --host 0.0.0.0 --port 8001
108+
uv run uvicorn server.vllm_sampler:app --host 0.0.0.0 --port 8001
112109
```

docs/setup/local-setup.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ All commands below assume you are in the **repository root** directory.
6767
Patch vLLM `0.20.0` for Gemma 4 LoRA support.
6868

6969
```bash
70-
(cd src/server && \
71-
uv run --extra vllm python scripts/patch_vllm_lora_dedup.py)
70+
uv run --extra vllm python src/server/scripts/patch_vllm_lora_dedup.py
7271
```
7372

7473
### 2. Start the vLLM Sampler

examples/autoresearch/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ RUN npm install -g @google/gemini-cli
2121

2222
WORKDIR /app
2323

24-
COPY pyproject.toml uv.lock README.md ./
25-
COPY autoresearch ./autoresearch
24+
COPY examples/pyproject.toml examples/uv.lock examples/README.md ./
25+
COPY examples/autoresearch ./autoresearch
2626

2727
RUN --mount=type=cache,target=/root/.cache/uv \
2828
uv sync --frozen

0 commit comments

Comments
 (0)