CoolFace
Apppublic

s123hree/green-code-optimizer-a100

sourceHugging Faceupdated 5mo agoView on Hugging Face
0likes
Dockerfile146 linesDownload Raw Back to root
1# ── Green-Code Optimizer — Environment Image ────────────────────────────────2# OpenEnv-compatible RL env that trains a code agent to refactor Python for3# energy efficiency (CPU + memory). Includes graphlet analyzer, runtime4# profiler, and CO2-savings dashboard. The trained LoRA adapter is downloaded5# from HuggingFace Hub at startup.6# ─────────────────────────────────────────────────────────────────────────────7FROM pytorch/pytorch:2.6.0-cuda12.4-cudnn9-runtime AS base8 9# System deps for building wheels10RUN apt-get update && apt-get install -y --no-install-recommends \11    build-essential git curl \12    && rm -rf /var/lib/apt/lists/*13 14WORKDIR /app15 16# ── Install Python dependencies (two layers for caching) ─────────────────────17COPY requirements.txt .18RUN pip install --no-cache-dir -r requirements.txt19 20# ── CUDA library discovery for bitsandbytes ──────────────────────────────────21# bitsandbytes loads libbitsandbytes_cuda<version>.so via ctypes.CDLL, which in22# turn depends on libcudart.so.12 from CUDA 12.4. On HF Spaces the container23# runs as UID 1000, so unsloth's runtime fallback `ldconfig /usr/lib64-nvidia`24# fails with "Permission denied" → bnb fails to import → unsloth then dies on25# `name 'bnb' is not defined`. Populate the loader cache at build time (where26# we ARE root) and set LD_LIBRARY_PATH explicitly so bnb can dlopen its libs27# without needing root at runtime.28ENV LD_LIBRARY_PATH=/opt/conda/lib:/usr/local/cuda/lib64:/usr/lib64-nvidia29# Force bitsandbytes to pick the CUDA 12.4 library that ships in the wheel,30# matching the pytorch:2.6.0-cuda12.4 base image. Without this it tries to31# auto-detect from `nvidia-smi`, which is flaky in non-interactive containers.32ENV BNB_CUDA_VERSION=12433RUN ldconfig34 35# Smoke-test bitsandbytes during build. HF Spaces builders are CPU-only, so36# `torch.cuda.is_available()` is False and bnb's auto-loader picks the CPU37# library — that won't tell us whether the CUDA shim works on the GPU node.38# Instead, dlopen libbitsandbytes_cuda124.so directly via ctypes: that does39# NOT require a live GPU (no kernel launch happens), only that libcudart.so.1240# and friends are reachable on LD_LIBRARY_PATH. If they're not, the build41# fails here with the real error instead of producing the cryptic runtime42# `name 'bnb' is not defined` we hit before.43RUN python -c "import bitsandbytes, ctypes, pathlib; \44pkg = pathlib.Path(bitsandbytes.__file__).parent; \45so = pkg / 'libbitsandbytes_cuda124.so'; \46print('dlopen', so); \47ctypes.CDLL(str(so)); \48print('bnb', bitsandbytes.__version__, 'CUDA shim loads OK')"49 50# ── Patch unsloth's bnb fallback path ────────────────────────────────────────51# unsloth/__init__.py has a footgun: if `import bitsandbytes as bnb` raises,52# the bare `except:` swallows it but `bnb` is never bound, and the *very next*53# except block calls `importlib.reload(bnb)` — which raises `NameError: name54# 'bnb' is not defined` and propagates out of `import unsloth` entirely.55# Wrap that single reload call so unsloth can finish importing in 16-bit mode56# even when bnb has any runtime issue, instead of taking the whole trainer57# (and our diagnostic logging) down with a cryptic NameError.58RUN python -c "import pathlib; \59p = pathlib.Path('/opt/conda/lib/python3.11/site-packages/unsloth/__init__.py'); \60src = p.read_text(); \61old = '        importlib.reload(bnb)\n        importlib.reload(triton)'; \62new = '        try: importlib.reload(bnb)\n        except NameError: pass  # bnb undefined if its import failed earlier\n        importlib.reload(triton)'; \63assert old in src, 'unsloth bnb-reload pattern not found — wheel changed shape'; \64p.write_text(src.replace(old, new, 1)); \65print('Patched unsloth __init__.py: guarded importlib.reload(bnb)')"66 67# ── Copy application code ────────────────────────────────────────────────────68COPY environment/ ./environment/69COPY server.py .70COPY inference.py .71COPY openenv.yaml .72COPY training/ ./training/73 74# ── Environment variables ────────────────────────────────────────────────────75# HF_TOKEN must be set at runtime for adapter download76ENV PYTHONUNBUFFERED=177ENV PORT=786078ENV HF_HUB_ENABLE_HF_TRANSFER=179# Avoid CUDA fragmentation OOM when bnb 4-bit loads the base model right80# next to a peft + LoRA training graph. Set in env (not just Python) so it81# applies to every subprocess train_grpo.py spawns.82ENV PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True83# Keep HF caches on /tmp so the read-only HF Spaces home doesn't bite us.84ENV HF_HOME=/tmp/hf_home85ENV TRANSFORMERS_CACHE=/tmp/hf_home86ENV WANDB_DISABLED=true87# Training checkpoints + plots: /app is not writable for UID 1000 on HF Spaces.88ENV GRPO_OUTPUT_DIR=/tmp/grpo_output89# unsloth_zoo defaults to cwd-relative "unsloth_compiled_cache" → PermissionError90# when cwd is /app. Point compile artifacts at /tmp instead.91ENV UNSLOTH_COMPILE_LOCATION=/tmp/unsloth_compiled_cache92# Note: GREEN_PROFILE_MODE is intentionally NOT set here. Training picks93# "compile" via os.environ.setdefault in train_grpo.py; the live API server94# keeps the default "runtime" so /step and /dashboard/co2 do real profiling.95 96# Fix for KeyError: 'getpwuid(): uid not found: 1000'97# Hugging Face Spaces runs as UID 1000 without a corresponding /etc/passwd entry.98# Create a dummy passwd entry AND a writable home dir. Without the home dir,99# triton's autotune cache (/home/huggingface/.triton/cache) blows up at100# `os.makedirs(...)` time during `import bitsandbytes` → which trips101# `from .nn.triton_based_modules import ...` → which trips102# `@triton.autotune(...)` → PermissionError. That cascades into103# `import unsloth` failing through transformers.integrations.bitsandbytes.104RUN echo "huggingface:x:1000:1000:HuggingFace user:/home/huggingface:/bin/sh" >> /etc/passwd \105    && mkdir -p /home/huggingface/.triton/cache /home/huggingface/.cache \106    && chmod -R 1777 /home/huggingface107# Make every cache-bearing tool point at a writable place explicitly. We can't108# rely on `~` resolution alone because `pwd.getpwuid()` and `expanduser('~')`109# both still return `/home/huggingface` on HF Spaces; setting HOME wins over110# both, and individual *_CACHE_DIR vars override even that.111ENV HOME=/home/huggingface112ENV XDG_CACHE_HOME=/tmp/xdg_cache113ENV TRITON_CACHE_DIR=/tmp/triton_cache114ENV TORCHINDUCTOR_CACHE_DIR=/tmp/torch_inductor115ENV TORCHINDUCTOR_DISABLE=1116ENV USER=huggingface117ENV LOGNAME=huggingface118 119# ── Entrypoint that survives a training crash ────────────────────────────────120# - Starts uvicorn in the foreground so SIGTERM reaches it cleanly.121# - Tees training logs to /tmp/train.log AND stdout, prefixed for clarity.122# - If training crashes (OOM, import error, …) we log it but keep the API up123#   so judges can still hit /demo, /reset, /step, /docs, etc.124RUN printf '%s\n' \125    '#!/usr/bin/env bash' \126    'set -u' \127    'mkdir -p /tmp/torch_inductor /tmp/hf_home /tmp/triton_cache /tmp/xdg_cache /tmp/grpo_output /tmp/unsloth_compiled_cache' \128    'echo "[entrypoint] starting GRPO training in background"' \129    '(' \130    '  python -u training/train_grpo.py 2>&1 | sed -u "s/^/[train] /"' \131    '  ec=${PIPESTATUS[0]}' \132    '  if [ "$ec" != "0" ]; then echo "[entrypoint] training exited with code $ec — API will keep running"; fi' \133    ') &' \134    'echo "[entrypoint] starting uvicorn on :7860"' \135    'exec uvicorn server:app --host 0.0.0.0 --port 7860 --log-level info' \136    > /usr/local/bin/start.sh \137    && chmod +x /usr/local/bin/start.sh138 139EXPOSE 7860140 141# Health check for container orchestrators / HF Spaces142HEALTHCHECK --interval=30s --timeout=5s --retries=3 \143    CMD curl -f http://localhost:7860/health || exit 1144 145CMD ["/usr/local/bin/start.sh"]146