# Deploying OpenSOC to Hugging Face Spaces This is the one-time deployment recipe. The same Space serves both the OpenEnv API (consumed by judge bots and `OpenSOCClient`) **and** a Gradio "before vs after" UI at `/demo` for human reviewers. ## 1. Local sanity check ```bash python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt python server.py & sleep 2 curl -s http://localhost:7860/health | jq . curl -s -X POST 'http://localhost:7860/reset?task=stage1_basic&mode=defender_only' | jq . curl -s -I http://localhost:7860/demo | head -1 # should be 200 OK kill %1 ``` ## 2. Build the Docker image locally ```bash docker build -t opensoc:latest . docker run -p 7860:7860 opensoc:latest # in another shell: curl -s http://localhost:7860/tasks | jq . open http://localhost:7860/demo ``` ## 3. Push to Hugging Face The simplest path is via `huggingface-cli`; the second is a one-shot script that does the same thing. ### One-shot ```bash export HF_USER= huggingface-cli login # browser-based PAT login bash scripts/deploy_to_hf.sh ``` ### Manual (equivalent) ```bash huggingface-cli login huggingface-cli repo create opensoc-env --type space --space-sdk docker # Use SPACE_README.md as the Space's README so HF picks up the docker SDK config: cp SPACE_README.md /tmp/SPACE_README.md # save a copy git checkout -b space-deploy cp SPACE_README.md README.md # or prepend SPACE_README front-matter to README git add README.md && git commit -m "Space metadata header" git remote add space https://huggingface.co/spaces/$HF_USER/opensoc-env git push space space-deploy:main git checkout main && git checkout README.md ``` ## 4. Verify the deployed Space ```bash export OPENSOC_URL=https://-opensoc-env.hf.space python -c " from client import OpenSOCClient c = OpenSOCClient(base_url='$OPENSOC_URL') print(c.health()) print(c.tasks()) obs = c.reset(task='stage1_basic', mode='defender_only', seed=1) print('first log id:', obs['log_window'][0]['log_id']) " # And visually: open $OPENSOC_URL/demo ``` `/demo` reads `data/demo_examples.json`. If you deployed before running the GPU pipeline, the file holds the *placeholder* before-vs-after pairs (always-dismiss vs verifier-oracle). Re-run `python -m eval.bake_demo` on a GPU host (no `--placeholder`) and re-push to overwrite with real trained-model outputs. ## 5. (Optional) Run the eval harness against the live Space ```bash # Pure-CPU smoke run (no Unsloth required): python -m eval.eval --smoke-only --holdout data/holdout.jsonl ``` ## OpenEnv hackathon checklist - [x] `openenv.yaml` manifest with `endpoints.demo: GET /demo` - [x] gym-style API: `reset` / `step` / `state` (+ `grade`, `tasks`, `health`) - [x] non-reserved tool names (`craft_incident`, `submit_triage`) - [x] FastAPI app exposed on port 7860 inside the container - [x] Gradio UI mounted at `/demo` for the storytelling deliverable - [x] Dockerfile suitable for Hugging Face Spaces (`sdk: docker`) - [x] Client / server separation (`client/opensoc_client.py` is HTTP-only) - [x] Frozen 200-incident eval set committed (`data/holdout.jsonl`) - [x] 600-example SFT dataset committed (`data/sft_train.jsonl`) - [x] 50 pre-baked demo pairs committed (`data/demo_examples.json`) - [x] GRPO Colab/HF Jupyter notebook (`train_grpo.ipynb`) + one-shot `scripts/run_full_pipeline.sh` - [x] Pytest suite — 93 tests, all green