{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": "# Basic Distillation\n\nThis notebook demonstrates the full softs pipeline:\n- **Broker** routes orders between clients and suppliers\n- **Supplier** generates batches of soft labels\n- **Client** trains a student model on those labels\n\nWe use random data here to keep it fast. For real LLM distillation, see the `examples/distillation/` examples — e.g. `logit_topp/` (broker.py / supplier.py / client.py).", "id": "cell-0" }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import time\n", "import torch\n", "import torch.nn as nn\n", "\n", "from softs import (\n", " Broker, Supplier, Client, ShmMedium,\n", " BatchConfig, TensorSpec, EndpointConfig,\n", ")" ], "id": "cell-1" }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Define the batch layout\n", "\n", "Each slot holds one batch: `x` (inputs) and `y` (soft targets)." ], "id": "cell-2" }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "BATCH_SIZE = 8\n", "HIDDEN = 256\n", "NUM_CLASSES = 100\n", "\n", "config = BatchConfig([\n", " TensorSpec(\"x\", (BATCH_SIZE, HIDDEN), \"float32\"),\n", " TensorSpec(\"y\", (BATCH_SIZE, NUM_CLASSES), \"float32\"),\n", "])\n", "\n", "print(f\"Slot size: {config.nbytes() / 1e6:.1f} MB\")" ], "id": "cell-3" }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Start the broker" ], "id": "cell-4" }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "endpoints = EndpointConfig()\n", "broker = Broker(endpoints=endpoints)\n", "broker.start()\n", "time.sleep(0.2)" ], "id": "cell-5" }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Start a supplier\n", "\n", "The supplier generates random soft labels. In practice, this would run a teacher model." ], "id": "cell-6" }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def teacher_generator(product_id: str) -> bytes:\n", " \"\"\"Simulate teacher: random soft targets.\"\"\"\n", " x = torch.randn(BATCH_SIZE, HIDDEN)\n", " logits = torch.randn(BATCH_SIZE, NUM_CLASSES)\n", " y = torch.softmax(logits, dim=-1) # soft targets\n", " return config.encode(x=x, y=y)\n", "\n", "supplier = Supplier(\n", " generator_fn=teacher_generator,\n", " product_ids=[\"teacher_v1\"],\n", " endpoint=endpoints.backend,\n", " medium_cls=ShmMedium,\n", " slot_size=config.nbytes(),\n", ")\n", "supplier.start()\n", "time.sleep(0.2)" ], "id": "cell-7" }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Create a client and train\n", "\n", "The client orders batches by `product_id`, reads them from shared memory, and trains a small student." ], "id": "cell-8" }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "student = nn.Sequential(\n", " nn.Linear(HIDDEN, 128),\n", " nn.ReLU(),\n", " nn.Linear(128, NUM_CLASSES),\n", ")\n", "optimizer = torch.optim.Adam(student.parameters(), lr=1e-3)\n", "\n", "client = Client(\n", " endpoint=endpoints.frontend,\n", " medium_cls=ShmMedium,\n", " slot_size=config.nbytes(),\n", " num_slots=4,\n", ")\n", "client.hello()\n", "\n", "for step in range(10):\n", " slot = client.request_sample(\"teacher_v1\", timeout_ms=5000)\n", " assert slot is not None, f\"Timeout at step {step}\"\n", "\n", " batch = config.decode(client.medium.read(slot))\n", " client.release_slot(slot)\n", "\n", " x, y_teacher = batch[\"x\"], batch[\"y\"]\n", " y_student = torch.log_softmax(student(x), dim=-1)\n", " loss = -(y_teacher * y_student).sum(dim=-1).mean()\n", "\n", " optimizer.zero_grad()\n", " loss.backward()\n", " optimizer.step()\n", "\n", " print(f\"Step {step:2d}: loss={loss.item():.4f}\")" ], "id": "cell-9" }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Check broker stats" ], "id": "cell-10" }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "stats = broker.get_stats()\n", "print(f\"Suppliers: {stats.connected_suppliers}, Clients: {stats.connected_clients}, Completed: {stats.total_completed}\")" ], "id": "cell-11" }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6. Graceful shutdown\n", "\n", "Order matters: close the client first, then stop the supplier (sends GOODBYE), then stop the broker." ], "id": "cell-12" }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "client.close()\n", "supplier.stop()\n", "time.sleep(0.2)\n", "broker.stop()\n", "print(\"Shutdown complete.\")" ], "id": "cell-13" } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.11" } }, "nbformat": 4, "nbformat_minor": 5 }