#!/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")