AIStudio Server supports two workload types. Each runs as a Docker container on the GPU node, managed by the Celery worker over SSH.
Image: us-docker.pkg.dev/aimlworkbench/aistudio/llminference:1.0.0-nvidia
Source: aistudio-workloads/llm-inference
Benchmarks LLM inference throughput and latency using vLLM. The container owns the entire workflow — it starts its own vLLM server, sweeps the requested concurrency levels, collects metrics, and writes results.
| Metric | Description |
|---|---|
total_token_throughput |
Total output tokens per second across all concurrent requests |
per_gpu_throughput_tok_s |
total_token_throughput ÷ gpu_count — for cross-GPU comparison |
mean_ttft_ms |
Mean time to first token (ms) |
mean_tpot_ms |
Mean time per output token (ms) |
mean_e2el_ms |
Mean end-to-end latency per request (ms) |
- The Celery worker calls
ManifestBuilder.build_llm_benchmark_command()to produce adocker runshell command. - The command is executed on the GPU node via SSH.
- Inside the container,
benchmark.py:- Starts a vLLM server on port
9123(internal to the container) - Runs
vllm bench servefor each concurrency level - Prints
BENCH_RESULT:{json}lines to stdout for each level - Writes
benchmark_result.jsonandsummary.jsonto/results/<run_id>/
- Starts a vLLM server on port
- The worker parses the
BENCH_RESULT:lines and inserts aBenchmarkResultrow per concurrency level.
| Host path | Container path | Purpose |
|---|---|---|
~/.cache/huggingface |
/root/.cache/huggingface |
Model weight cache — shared across runs |
NODE_RESULTS_PATH/<run_id> |
/results/<run_id> |
Benchmark output persistence |
dataset_path |
dataset_path (same path) |
User-supplied dataset file |
The benchmark requires a ShareGPT-format JSON file. No dataset is bundled or downloaded automatically. The operator provides an absolute path via dataset_path in the benchmark config.
"config": {
"dataset_path": "/home/ubuntu/datasets/sharegpt.json"
}The path is bind-mounted into the container at the same location — benchmark.py reads it directly.
| Parameter | Default | Description |
|---|---|---|
precision |
fp16 |
Model precision |
concurrency |
4 |
Number of simultaneous requests |
input_tokens |
512 |
Prompt length |
output_tokens |
256 |
Generated tokens per request |
gpu_count |
1 |
Number of GPUs (tensor parallelism) |
max_model_len |
(model default) | Max sequence length override |
dataset_path |
(required) | Absolute path to dataset on GPU node |
Image: us-docker.pkg.dev/aimlworkbench/aistudio/jupyternotebook:1.0.0-nvidia
Source: aistudio-workloads/jupyter-notebook
Launches a JupyterLab environment on the GPU node with pre-installed GPU profiling utilities and MLPerf microbenchmarks.
- JupyterLab with GPU access (
--gpus all) jupyter-ai— AI-assisted coding inside notebooks- PyTorch + torchvision + CUDA
- vLLM for in-notebook inference experiments
- onnxruntime-gpu, accelerate, datasets, pycocotools (MLPerf dependencies)
- The Celery worker calls
ManifestBuilder.build_jupyter_command(). - The container starts in detached mode (
-d) — unlike benchmarks, it runs until explicitly stopped. script.shcopies notebooks to/data/<workload_id>/and starts JupyterLab from that directory.- The worker polls the Jupyter API endpoint until it responds (up to 5 minutes).
- The UI shows the Jupyter URL once the health check passes.
When NGINX_ENABLED=false (default), the Jupyter URL is the GPU node's direct IP and port. This exposes the node's internal IP to the client.
When NGINX_ENABLED=true, the server writes an nginx location config for the instance and the URL becomes a public path-based route:
{PROXY_BASE_URL}/jupyter/{gpu_type}/{task_id}/lab
The nginx container auto-reloads when new location configs are written (via inotifywait) — no manual restart needed.
| Host path | Container path | Purpose |
|---|---|---|
NODE_JUPYTER_DATA_PATH |
/data |
Notebook storage — persists across container restarts |
DELETE /api/v1/jupyter/instances/{task_id}Or from the UI — click the delete button on the instance row.
JupyterLab ships with jupyter-ai built in — write, execute, and visualize code with LLM assistance inside the notebook.
Prerequisites:
- GPUs with CUDA compute capability ≥ 7
- Docker installed with the NVIDIA Container Toolkit
1. Run a vLLM inference server (or point at one already running):
sudo docker run --restart=always --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
--network host -p 8000:8000 --ipc=host \
vllm/<vllm_docker_image> \
--model <model_name> \
--dtype half \
--gpu-memory-utilization 0.95 \
--trust-remote-code \
--tensor-parallel-size <NUMBER_OF_GPUS> \
--max-model-len 131072 \
--max-num-seqs 8 \
--host 0.0.0.0Replace <NUMBER_OF_GPUS> with the number of GPUs available on the machine.
2. Point JupyterLab at it:
- Open the Settings tab in JupyterLab.
- Go to AI Settings → click Add Secret.
- Set Secret Name to
HOSTED_VLLM_API_BASEand Value to your vLLM server URL:http://<MACHINE_IP>:8000/v1/ - Update the Chat Model to
hosted_vllm/Qwen/Qwen2.5-7B-Instruct-1M.
The AI assistant is now ready to use inside notebooks.
New workload types require changes in both repositories:
aistudio-workloads — create a new directory with:
Dockerfile— base image + dependenciesscript.sh— entrypointrequirements.txtversion.py
aistudio-server — three changes:
- Add the workload type to
catalog.jsonunderworkload_types - Add a
build_<workload>_command()method toManifestBuilder - Add a route and Celery task to handle the new type
Re-seed the catalog after updating catalog.json:
docker compose exec api python -m app.services.catalog_seederSee CONTRIBUTING.md for the full contribution workflow.