littlefig-bench / fix_colab_cloudflared.py
ticketguy's picture
Fix Colab: embed UI inline + use cloudflared tunnel (no auth needed)
9f8d4a1 verified
#!/usr/bin/env python3
"""Fix Colab โ€” use cloudflared for tunnel (free, no auth) + verify server starts."""
import subprocess, os, json
TOKEN = "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"
subprocess.run(["git", "clone", f"https://{TOKEN}@github.com/ticketguy/littlefig.git", "/app/littlefig"], check=True)
os.chdir("/app/littlefig")
subprocess.run(["git", "config", "user.name", "0xticketguy"], check=True)
subprocess.run(["git", "config", "user.email", "0xticketguy@harboria.dev"], check=True)
colab = {
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {"provenance": [], "gpuType": "T4"},
"kernelspec": {"name": "python3", "display_name": "Python 3"},
"accelerator": "GPU"
},
"cells": [
{"cell_type": "markdown", "metadata": {}, "source": [
"# ๐Ÿ Little Fig Studio\n",
"\n",
"**Train any LLM on any hardware.** Select your model, configure, launch.\n",
"\n",
"| Feature | Result |\n",
"|---|---|\n",
"| Quantization | Beats NF4 on 156/156 layers |\n",
"| GPU Speed | 7ร— faster than BnB NF4 |\n",
"| CPU Training | 1.1B model in 400MB RAM |\n",
"| Optimizer | FigMeZO (โˆ’18.6%, original research) |\n",
"\n",
"**Run all cells below โ†“**"
]},
{"cell_type": "code", "metadata": {}, "source": [
"# Step 1: Install\n",
"!git clone https://github.com/ticketguy/littlefig.git /content/littlefig --quiet 2>/dev/null || (cd /content/littlefig && git pull --quiet)\n",
"!cd /content/littlefig && pip install -q -e \".[train]\"\n",
"!pip install -q uvicorn fastapi python-multipart websockets\n",
"\n",
"# Download cloudflared (free tunnel, no signup)\n",
"!wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -O /usr/local/bin/cloudflared\n",
"!chmod +x /usr/local/bin/cloudflared\n",
"\n",
"import torch, sys\n",
"sys.path.insert(0, '/content/littlefig/src')\n",
"print(f'\\nโœ… Installed | PyTorch {torch.__version__} | GPU: {torch.cuda.get_device_name() if torch.cuda.is_available() else \"CPU\"}')"
], "execution_count": None, "outputs": []},
{"cell_type": "code", "metadata": {}, "source": [
"# Step 2: Launch Little Fig Studio\n",
"import subprocess, time, threading, re\n",
"\n",
"# Start the web server\n",
"server = subprocess.Popen(\n",
" ['python', '-m', 'uvicorn', 'little_fig.web.server:app',\n",
" '--host', '0.0.0.0', '--port', '8888'],\n",
" cwd='/content/littlefig/src',\n",
" stdout=subprocess.PIPE, stderr=subprocess.PIPE\n",
")\n",
"time.sleep(3)\n",
"\n",
"# Check if server is running\n",
"import urllib.request\n",
"try:\n",
" urllib.request.urlopen('http://localhost:8888', timeout=2)\n",
" print('โœ… Server running on port 8888')\n",
"except:\n",
" # Server might return non-200 but still be alive\n",
" print('โš ๏ธ Server may not have started correctly. Check errors below:')\n",
" try:\n",
" err = server.stderr.read(1000).decode()\n",
" print(err[:500])\n",
" except:\n",
" pass\n",
"\n",
"# Start cloudflared tunnel (free, no account needed)\n",
"tunnel = subprocess.Popen(\n",
" ['cloudflared', 'tunnel', '--url', 'http://localhost:8888'],\n",
" stdout=subprocess.PIPE, stderr=subprocess.PIPE\n",
")\n",
"time.sleep(5)\n",
"\n",
"# Read tunnel URL from stderr\n",
"tunnel_url = None\n",
"try:\n",
" output = tunnel.stderr.read(4096).decode()\n",
" urls = re.findall(r'https://[a-z0-9-]+\\.trycloudflare\\.com', output)\n",
" if urls:\n",
" tunnel_url = urls[0]\n",
"except:\n",
" pass\n",
"\n",
"if tunnel_url:\n",
" print(f'\\n๐Ÿ Little Fig Studio is LIVE!')\n",
" print(f'\\n ๐Ÿ‘‰ {tunnel_url}')\n",
" print(f'\\n Open the link above in your browser.')\n",
" print(f' Select model โ†’ Configure โ†’ Train')\n",
"else:\n",
" print('\\nโš ๏ธ Tunnel failed. Using iframe fallback...')\n",
" from IPython.display import IFrame, display\n",
" # Try Colab proxy\n",
" from google.colab.output import eval_js\n",
" proxy_url = eval_js(\"google.colab.kernel.proxyPort(8888)\")\n",
" print(f' Try: {proxy_url}')\n",
" display(IFrame(src=str(proxy_url), width='100%', height=700))\n",
"\n",
"print('\\n Keep this cell running to keep the server alive.')"
], "execution_count": None, "outputs": []},
{"cell_type": "markdown", "metadata": {}, "source": [
"---\n",
"## Alternative: Python API (no UI)\n",
"\n",
"Change `MODEL` to any HuggingFace model."
]},
{"cell_type": "code", "metadata": {}, "source": [
"from little_fig.engine import FigModel, FigTrainer, FigTrainingConfig\n",
"\n",
"# === YOUR MODEL HERE ===\n",
"MODEL = 'TinyLlama/TinyLlama-1.1B-Chat-v1.0'\n",
"# MODEL = 'google/gemma-3-4b-it'\n",
"# MODEL = 'Qwen/Qwen2.5-1.5B'\n",
"# MODEL = 'microsoft/phi-2'\n",
"\n",
"model = FigModel.from_pretrained(MODEL, lora_r=16, lora_alpha=32, shared_codebook=True)\n",
"print(f'โœ… {MODEL} loaded | Trainable: {sum(p.numel() for p in model.parameters() if p.requires_grad):,}')"
], "execution_count": None, "outputs": []},
{"cell_type": "code", "metadata": {}, "source": [
"# Train\n",
"config = FigTrainingConfig(\n",
" num_epochs=1,\n",
" learning_rate=2e-4,\n",
" max_seq_length=256,\n",
" batch_size=2,\n",
" gradient_accumulation_steps=4,\n",
" logging_steps=5,\n",
" use_packing=True,\n",
")\n",
"trainer = FigTrainer(model, config)\n",
"trainer.load_dataset('tatsu-lab/alpaca', max_samples=200)\n",
"trainer.train()\n",
"model.save_adapter('./my_adapter')\n",
"print('\\nโœ… Training complete! Adapter saved.')"
], "execution_count": None, "outputs": []},
{"cell_type": "markdown", "metadata": {}, "source": [
"---\n",
"*0xticketguy / Harboria Labs | AGPL-3.0*"
]}
]
}
with open("Little_Fig_Colab.ipynb", "w") as f:
json.dump(colab, f, indent=2)
subprocess.run(["git", "add", "-A"], check=True)
subprocess.run(["git", "commit", "-m",
"Fix Colab: cloudflared tunnel (free, no signup) + fallback to Colab proxy\n\n"
"- Uses cloudflared (Cloudflare's free tunnel) instead of ngrok\n"
"- No account needed, no auth token\n"
"- Falls back to google.colab.output.eval_js proxy if tunnel fails\n"
"- Checks if server is actually running before tunneling\n"
"- Shows errors if server fails to start"], check=True)
subprocess.run(["git", "push", "origin", "main"], check=True)
print("โœ… Colab fixed with cloudflared tunnel")