Instructions to use briscoooe/tiny-cube-solver with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use briscoooe/tiny-cube-solver with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="briscoooe/tiny-cube-solver")# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("briscoooe/tiny-cube-solver") model = AutoModelForCausalLM.from_pretrained("briscoooe/tiny-cube-solver", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use briscoooe/tiny-cube-solver with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "briscoooe/tiny-cube-solver" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "briscoooe/tiny-cube-solver", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/briscoooe/tiny-cube-solver
- SGLang
How to use briscoooe/tiny-cube-solver with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "briscoooe/tiny-cube-solver" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "briscoooe/tiny-cube-solver", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "briscoooe/tiny-cube-solver" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "briscoooe/tiny-cube-solver", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use briscoooe/tiny-cube-solver with Docker Model Runner:
docker model run hf.co/briscoooe/tiny-cube-solver
| # Provisions a vast.ai instance and runs the full pipeline: generate -> verify -> | |
| # train -> push to the Hub. Written to be re-runnable: a reclaimed instance can be | |
| # replaced and this script started again from scratch. | |
| # | |
| # Expects, in the environment: | |
| # HF_TOKEN write token, for checkpoint pushes | |
| # HUB_REPO e.g. yourname/tiny-cube-solver | |
| # Optional: PAIRS (default 10000000), STEPS, HIDDEN, LAYERS | |
| set -euo pipefail | |
| PAIRS="${PAIRS:-10000000}" | |
| STEPS="${STEPS:-40000}" | |
| HIDDEN="${HIDDEN:-384}" | |
| LAYERS="${LAYERS:-8}" | |
| CORES="$(nproc)" | |
| echo "=== $CORES cores, $(nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null || echo 'no GPU') ===" | |
| # Build against SYSTEM python, not the image's conda python. kociemba ships a C | |
| # extension and a pure-Python fallback, and it falls back *silently* when the | |
| # extension cannot build -- which is what happens if the venv's interpreter has no | |
| # matching dev headers. python3-dev is therefore not optional here. | |
| apt-get update -qq | |
| # libffi-dev is the one that actually matters and is the least obvious: kociemba's | |
| # native extension is built through cffi, which needs ffi.h. Without it the | |
| # compile dies with "fatal error: ffi.h: No such file or directory", kociemba | |
| # installs its pure-Python fallback instead, and pip still exits 0. | |
| apt-get install -y -qq build-essential python3-dev python3-venv libffi-dev git | |
| # Prefer python3.11. kociemba 1.2.1 builds its C extension cleanly on 3.11 (the | |
| # version this repo is developed against) but silently produces no extension on | |
| # the 3.10 that ships as system python in the Ubuntu 22.04 based images -- pip | |
| # still reports success, so the only symptom is the fallback. The PyTorch images | |
| # carry a conda 3.11, so prefer that and fall back to system python. | |
| PYBIN="" | |
| for cand in /opt/conda/bin/python3.11 /opt/conda/bin/python "$(command -v python3.11 || true)" /usr/bin/python3; do | |
| [ -x "$cand" ] || continue | |
| if "$cand" -c 'import sys; sys.exit(0 if sys.version_info[:2] >= (3,11) else 1)' 2>/dev/null; then | |
| PYBIN="$cand"; break | |
| fi | |
| done | |
| [ -z "$PYBIN" ] && PYBIN=/usr/bin/python3 | |
| echo "building venv from $PYBIN ($($PYBIN -V 2>&1))" | |
| "$PYBIN" -m venv /opt/venv | |
| /opt/venv/bin/pip install -q --upgrade pip | |
| # kociemba's setup.py predates modern setuptools' removal of install_layout. | |
| /opt/venv/bin/pip install -q "setuptools<60" wheel | |
| # Full output, not a tail: when the C extension fails to build, kociemba still | |
| # installs successfully (as pure Python), so the compiler error is the only | |
| # evidence of what went wrong and it must not be truncated away. | |
| /opt/venv/bin/pip install --no-build-isolation kociemba 2>&1 | tail -40 | |
| # Last resort before giving up: build from the upstream git source, whose build | |
| # metadata is newer than the 2017 PyPI sdist. | |
| if ! /opt/venv/bin/python -c "import kociemba.ckociembawrapper" 2>/dev/null; then | |
| echo "=== sdist build produced no extension; trying upstream git ===" | |
| /opt/venv/bin/pip install --force-reinstall --no-build-isolation \ | |
| "git+https://github.com/muodov/kociemba.git" 2>&1 | tail -15 || true | |
| fi | |
| if ! /opt/venv/bin/python -c "import kociemba.ckociembawrapper" 2>/dev/null; then | |
| echo "=== NATIVE BUILD FAILED -- diagnostics ===" | |
| echo "python: $(/opt/venv/bin/python -V 2>&1) at $(/opt/venv/bin/python -c 'import sys;print(sys.executable)')" | |
| echo "gcc: $(gcc --version 2>&1 | head -1)" | |
| echo "includes: $(/opt/venv/bin/python -c 'import sysconfig;print(sysconfig.get_paths()["include"])')" | |
| ls -l "$(/opt/venv/bin/python -c 'import sysconfig;print(sysconfig.get_paths()["include"])')/Python.h" 2>&1 || echo " Python.h MISSING" | |
| dpkg -l | grep -E "python3.*dev|build-essential" || echo " no dev packages found" | |
| echo "=== retrying verbosely ===" | |
| /opt/venv/bin/pip install --force-reinstall --no-build-isolation -v kociemba 2>&1 | grep -iE "error|gcc|Python.h|fatal" | head -30 | |
| fi | |
| /opt/venv/bin/pip install -q torch --index-url https://download.pytorch.org/whl/cu128 | |
| /opt/venv/bin/pip install -q transformers huggingface_hub | |
| # Hard gate. The pure-Python fallback is ~50x slower, so generating this dataset | |
| # with it would take days rather than hours -- and the only symptom is a warning | |
| # buried in the log while the meter runs. Fail here instead. | |
| echo "=== verifying native kociemba ===" | |
| /opt/venv/bin/python - <<'PYCHECK' | |
| import sys, time | |
| import kociemba | |
| from kociemba import ckociembawrapper # absent entirely when the C build failed | |
| SOLVED = "".join("URFDLB"[i // 9] for i in range(54)) | |
| kociemba.solve("DRLUUBFBRBLURRLRUBLRDDFDLFUFUFFDBRDUBRUFLLFDDBFLUBLRBD") | |
| t = time.time() | |
| for _ in range(20): | |
| kociemba.solve("DRLUUBFBRBLURRLRUBLRDDFDLFUFUFFDBRDUBRUFLLFDDBFLUBLRBD") | |
| ms = (time.time() - t) / 20 * 1000 | |
| print(f"kociemba: {ms:.1f} ms/solve (native)") | |
| if ms > 200: | |
| sys.exit(f"ABORT: {ms:.0f} ms/solve is fallback-speed; refusing to generate") | |
| PYCHECK | |
| cd "${CODE_DIR:-/workspace/code}" | |
| mkdir -p data checkpoints | |
| # Smoke-test the GPU *before* generating anything. A torch build without kernels | |
| # for this GPU fails only when the first tensor op runs, which used to be training | |
| # -- so an unusable GPU was discovered an hour and a full dataset later. This | |
| # runs the real model for one forward and backward pass, so it catches missing | |
| # kernels rather than merely that a device is visible. | |
| echo "=== verifying GPU can run the model ===" | |
| /opt/venv/bin/python - <<PYCHECK | |
| import sys, torch | |
| if not torch.cuda.is_available(): | |
| sys.exit("ABORT: no CUDA device visible") | |
| name = torch.cuda.get_device_name(0) | |
| cap = torch.cuda.get_device_capability(0) | |
| vram = torch.cuda.get_device_properties(0).total_memory / 1e9 | |
| print(f"gpu: {name} sm_{cap[0]}{cap[1]} {vram:.0f}GB | torch {torch.__version__} | arch {torch.cuda.get_arch_list()}") | |
| try: | |
| from transformers import LlamaConfig, LlamaForCausalLM | |
| # The REAL config and batch size. A scaled-down probe is worse than useless | |
| # here: it passes on a GPU that cannot hold the actual model, so the OOM | |
| # surfaces only after data generation has already been paid for. | |
| cfg = LlamaConfig(vocab_size=28, hidden_size=$HIDDEN, intermediate_size=$HIDDEN * 4, | |
| num_hidden_layers=$LAYERS, num_attention_heads=8, | |
| num_key_value_heads=8, max_position_embeddings=83, | |
| tie_word_embeddings=True) | |
| m = LlamaForCausalLM(cfg).cuda() | |
| opt = torch.optim.AdamW(m.parameters(), lr=1e-4) | |
| ids = torch.randint(0, 28, ($BATCH, 83), device="cuda") | |
| with torch.autocast("cuda", dtype=torch.bfloat16 if torch.cuda.is_bf16_supported() else torch.float16): | |
| loss = m(input_ids=ids, labels=ids).loss | |
| loss.backward() | |
| opt.step() # optimizer state is where the memory actually peaks | |
| torch.cuda.synchronize() | |
| peak = torch.cuda.max_memory_allocated() / 1e9 | |
| print(f"gpu smoke test: full step at batch $BATCH OK, peak {peak:.1f}GB of {vram:.0f}GB") | |
| except torch.OutOfMemoryError: | |
| sys.exit(f"ABORT: batch $BATCH of a $LAYERS-layer/$HIDDEN-wide model does not fit in {vram:.0f}GB") | |
| except Exception as e: | |
| sys.exit(f"ABORT: GPU cannot run the model ({type(e).__name__}: {e})") | |
| PYCHECK | |
| cd "${CODE_DIR:-/workspace/code}" | |
| mkdir -p data checkpoints | |
| # Generation is the wall-clock bottleneck, not training -- use every core. | |
| echo "=== generating $PAIRS pairs on $CORES cores ===" | |
| # --workers 0 detects the cgroup quota. --augment takes several states from each | |
| # solution path, so one Kociemba solve yields several pairs: an ~8x cut in solves, | |
| # which is the actual bottleneck. It also samples distance-to-solved far more | |
| # evenly than uniform states do (those are ~95% distance-18-to-20), which happens | |
| # to match a benchmark whose buckets run from depth 3 upward. | |
| /opt/venv/bin/python gen_data.py --count "$PAIRS" --workers 0 --augment 8 --out data/train.jsonl | |
| # A separate seed, and canonical labels only: the holdout must reflect the real | |
| # task, not the augmented training mix, or the reported solve rate is inflated. | |
| echo "=== generating canonical holdout ===" | |
| # Holdout stays unaugmented and uniform: the hard case. Scoring against the | |
| # augmented mix would flatter the model, since those states sit partway along a | |
| # solution path and are nearer to solved. | |
| # --shards 32 fixes the shard count so the holdout is byte-identical on every | |
| # machine. Without it the per-shard seeds follow the core count, so two boxes | |
| # comparing two models evaluate them against merely similar holdouts rather than | |
| # the same one -- silently downgrading a paired comparison to an unpaired one, | |
| # exactly where the pairing matters most. | |
| /opt/venv/bin/python gen_data.py --count 20000 --workers 0 --shards 32 --seed 999999 \ | |
| --augment 0 --out data/val.jsonl | |
| # DAgger phase: if ROLLOUT_FROM names a checkpoint, roll that policy out, label | |
| # the states it actually reaches, and append them to the training set. | |
| # | |
| # The model is otherwise trained only on states from the sampler and never on the | |
| # ones its own attempts produce -- which is where it measurably fails, walking | |
| # from 10 moves out to 18 and staying there. Behaviour cloning alone compounds | |
| # error quadratically in horizon; training on the policy's own state | |
| # distribution is the standard fix. | |
| if [ -n "${ROLLOUT_FROM:-}" ]; then | |
| echo "=== rolling out ${ROLLOUT_FROM} for ${ROLLOUT_PAIRS:-2000000} states ===" | |
| /opt/venv/bin/python gen_rollout_data.py --checkpoint "$ROLLOUT_FROM" \ | |
| --count "${ROLLOUT_PAIRS:-2000000}" --batch-size 512 --rounds 4 \ | |
| --out data/rollout.jsonl | |
| /opt/venv/bin/python verify_data.py data/rollout.jsonl --limit 20000 | |
| cat data/rollout.jsonl >> data/train.jsonl | |
| echo "=== training set is now $(wc -l < data/train.jsonl) pairs ===" | |
| fi | |
| echo "=== verifying (must report 0 FAILED) ===" | |
| /opt/venv/bin/python verify_data.py data/train.jsonl --limit 100000 | |
| /opt/venv/bin/python verify_data.py data/val.jsonl | |
| echo "=== training ===" | |
| /opt/venv/bin/python train.py \ | |
| --data data/train.jsonl --val-data data/val.jsonl \ | |
| --hidden "$HIDDEN" --layers "$LAYERS" --heads 8 \ | |
| --batch-size "${BATCH:-1024}" --lr 6e-4 --max-steps "$STEPS" \ | |
| --eval-every 1000 --eval-n 512 \ | |
| --out checkpoints/cube --hub-repo "${HUB_REPO:-}" ${RESUME:+--resume "$RESUME"} | |
| echo "=== done ===" | |