lyffseba commited on
Commit ·
28bf38c
0
Parent(s):
Initial commit: AI Cloud Lab setup for Gemma-4-31B
Browse files- README.md +54 -0
- labs/01_inference_test.ipynb +62 -0
- labs/02_qlora_finetuning.ipynb +93 -0
- scripts/01_setup_inference.sh +27 -0
- scripts/02_start_server.sh +15 -0
README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# AI Cloud Lab 🚀
|
| 2 |
+
|
| 3 |
+
This repository contains everything needed to spin up, run, and fine-tune Large Language Models (like `google/gemma-4-31B`) on cheap, high-performance cloud GPUs.
|
| 4 |
+
|
| 5 |
+
## 🌟 The Best Platform: RunPod
|
| 6 |
+
|
| 7 |
+
For cost-to-performance, **RunPod.io** is currently the best platform. You can rent an RTX 3090 (24GB) or RTX 4090 (24GB) for ~$0.20 to $0.40 per hour, which is perfect for running the 31B model in 4-bit, or an A6000 (48GB) to run it in 8-bit.
|
| 8 |
+
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
## 🛠️ Getting Started on RunPod
|
| 12 |
+
|
| 13 |
+
### 1. Account Setup
|
| 14 |
+
1. Go to [RunPod.io](https://www.runpod.io) and create an account.
|
| 15 |
+
2. Add a few dollars in billing credits (e.g., $10).
|
| 16 |
+
3. Go to **Deploy -> Secure Cloud**.
|
| 17 |
+
|
| 18 |
+
### 2. Spinning up the Instance
|
| 19 |
+
1. Select a GPU:
|
| 20 |
+
- **1x RTX 3090 / 4090 (24GB VRAM)** (Good for 4-bit)
|
| 21 |
+
- **1x A6000 / RTX 6000 Ada (48GB VRAM)** (Best for 8-bit / Fine-tuning)
|
| 22 |
+
2. Select Template: `RunPod PyTorch 2.x` (or type "PyTorch" in the search bar).
|
| 23 |
+
3. Ensure you allocate at least **60 GB of Volume Disk** to hold the model weights.
|
| 24 |
+
4. Click **Deploy**.
|
| 25 |
+
|
| 26 |
+
### 3. Accessing the Workspace
|
| 27 |
+
Once deployed, click **Connect**. You will have access to a Jupyter Lab environment.
|
| 28 |
+
Open a Terminal inside Jupyter Lab and clone this repository (or just copy the setup scripts).
|
| 29 |
+
|
| 30 |
+
---
|
| 31 |
+
|
| 32 |
+
## 🚀 Running Gemma-4-31B (Inference)
|
| 33 |
+
|
| 34 |
+
Inside your RunPod terminal, run the setup script:
|
| 35 |
+
|
| 36 |
+
```bash
|
| 37 |
+
bash scripts/01_setup_inference.sh
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
Then start the OpenAI-compatible server using vLLM:
|
| 41 |
+
|
| 42 |
+
```bash
|
| 43 |
+
bash scripts/02_start_server.sh
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
Now you can interact with the model via Python or using a UI!
|
| 47 |
+
|
| 48 |
+
---
|
| 49 |
+
|
| 50 |
+
## 🔬 Tinkering & Fine-Tuning Labs
|
| 51 |
+
|
| 52 |
+
Check the `labs/` directory for Jupyter Notebooks designed to let you play with the model.
|
| 53 |
+
- `labs/01_inference_test.ipynb`: Test prompting and generating text.
|
| 54 |
+
- `labs/02_qlora_finetuning.ipynb`: Learn how to fine-tune Gemma-4-31B on your own custom data using LoRA.
|
labs/01_inference_test.ipynb
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"metadata": {},
|
| 6 |
+
"source": [
|
| 7 |
+
"# 🧪 Lab 1: Querying your Local Gemma API\n",
|
| 8 |
+
"\n",
|
| 9 |
+
"First, make sure you ran `bash scripts/02_start_server.sh` in a terminal so the server is running on port 8000."
|
| 10 |
+
]
|
| 11 |
+
},
|
| 12 |
+
{
|
| 13 |
+
"cell_type": "code",
|
| 14 |
+
"execution_count": null,
|
| 15 |
+
"metadata": {},
|
| 16 |
+
"outputs": [],
|
| 17 |
+
"source": [
|
| 18 |
+
"!pip install openai"
|
| 19 |
+
]
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
"cell_type": "code",
|
| 23 |
+
"execution_count": null,
|
| 24 |
+
"metadata": {},
|
| 25 |
+
"outputs": [],
|
| 26 |
+
"source": [
|
| 27 |
+
"from openai import OpenAI\n",
|
| 28 |
+
"\n",
|
| 29 |
+
"# Point the OpenAI client to your local vLLM server\n",
|
| 30 |
+
"client = OpenAI(\n",
|
| 31 |
+
" base_url=\"http://localhost:8000/v1\",\n",
|
| 32 |
+
" api_key=\"not-needed\" # Not required for local hosting\n",
|
| 33 |
+
")\n",
|
| 34 |
+
"\n",
|
| 35 |
+
"response = client.chat.completions.create(\n",
|
| 36 |
+
" model=\"./gemma-4-31B\",\n",
|
| 37 |
+
" messages=[\n",
|
| 38 |
+
" {\"role\": \"system\", \"content\": \"You are a helpful coding assistant.\"},\n",
|
| 39 |
+
" {\"role\": \"user\", \"content\": \"Write a python function to calculate the Fibonacci sequence.\"}\n",
|
| 40 |
+
" ],\n",
|
| 41 |
+
" temperature=0.7,\n",
|
| 42 |
+
" max_tokens=200\n",
|
| 43 |
+
")\n",
|
| 44 |
+
"\n",
|
| 45 |
+
"print(response.choices[0].message.content)"
|
| 46 |
+
]
|
| 47 |
+
}
|
| 48 |
+
],
|
| 49 |
+
"metadata": {
|
| 50 |
+
"kernelspec": {
|
| 51 |
+
"display_name": "Python 3",
|
| 52 |
+
"language": "python",
|
| 53 |
+
"name": "python3"
|
| 54 |
+
},
|
| 55 |
+
"language_info": {
|
| 56 |
+
"name": "python",
|
| 57 |
+
"version": "3.10.12"
|
| 58 |
+
}
|
| 59 |
+
},
|
| 60 |
+
"nbformat": 4,
|
| 61 |
+
"nbformat_minor": 4
|
| 62 |
+
}
|
labs/02_qlora_finetuning.ipynb
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"metadata": {},
|
| 6 |
+
"source": [
|
| 7 |
+
"# 🧪 Lab 2: Fine-Tuning Gemma-4-31B (QLoRA)\n",
|
| 8 |
+
"\n",
|
| 9 |
+
"In this lab, we will load the massive 31B model in 4-bit memory and attach small trainable \"adapters\" (LoRA) to teach it new things without needing a supercomputer."
|
| 10 |
+
]
|
| 11 |
+
},
|
| 12 |
+
{
|
| 13 |
+
"cell_type": "code",
|
| 14 |
+
"execution_count": null,
|
| 15 |
+
"metadata": {},
|
| 16 |
+
"outputs": [],
|
| 17 |
+
"source": [
|
| 18 |
+
"!pip install transformers accelerate bitsandbytes peft trl datasets"
|
| 19 |
+
]
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
"cell_type": "code",
|
| 23 |
+
"execution_count": null,
|
| 24 |
+
"metadata": {},
|
| 25 |
+
"outputs": [],
|
| 26 |
+
"source": [
|
| 27 |
+
"import torch\n",
|
| 28 |
+
"from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig\n",
|
| 29 |
+
"from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training\n",
|
| 30 |
+
"\n",
|
| 31 |
+
"model_id = \"../gemma-4-31B\"\n",
|
| 32 |
+
"\n",
|
| 33 |
+
"# 1. Load in 4-bit\n",
|
| 34 |
+
"bnb_config = BitsAndBytesConfig(\n",
|
| 35 |
+
" load_in_4bit=True,\n",
|
| 36 |
+
" bnb_4bit_use_double_quant=True,\n",
|
| 37 |
+
" bnb_4bit_quant_type=\"nf4\",\n",
|
| 38 |
+
" bnb_4bit_compute_dtype=torch.bfloat16\n",
|
| 39 |
+
")\n",
|
| 40 |
+
"\n",
|
| 41 |
+
"tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
|
| 42 |
+
"model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=bnb_config, device_map=\"auto\")\n",
|
| 43 |
+
"\n",
|
| 44 |
+
"model = prepare_model_for_kbit_training(model)"
|
| 45 |
+
]
|
| 46 |
+
},
|
| 47 |
+
{
|
| 48 |
+
"cell_type": "code",
|
| 49 |
+
"execution_count": null,
|
| 50 |
+
"metadata": {},
|
| 51 |
+
"outputs": [],
|
| 52 |
+
"source": [
|
| 53 |
+
"# 2. Setup LoRA Adapters\n",
|
| 54 |
+
"config = LoraConfig(\n",
|
| 55 |
+
" r=8, \n",
|
| 56 |
+
" lora_alpha=32, \n",
|
| 57 |
+
" target_modules=[\"q_proj\", \"v_proj\"], \n",
|
| 58 |
+
" lora_dropout=0.05,\n",
|
| 59 |
+
" bias=\"none\",\n",
|
| 60 |
+
" task_type=\"CAUSAL_LM\"\n",
|
| 61 |
+
")\n",
|
| 62 |
+
"\n",
|
| 63 |
+
"model = get_peft_model(model, config)\n",
|
| 64 |
+
"model.print_trainable_parameters() \n",
|
| 65 |
+
"# You will see we only train ~0.1% of the model!"
|
| 66 |
+
]
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
"cell_type": "code",
|
| 70 |
+
"execution_count": null,
|
| 71 |
+
"metadata": {},
|
| 72 |
+
"outputs": [],
|
| 73 |
+
"source": [
|
| 74 |
+
"# 3. From here, you would pass 'model' to the SFTTrainer from the 'trl' library \n",
|
| 75 |
+
"# along with a HuggingFace dataset to begin fine-tuning!\n",
|
| 76 |
+
"print(\"Model is ready for training!\")"
|
| 77 |
+
]
|
| 78 |
+
}
|
| 79 |
+
],
|
| 80 |
+
"metadata": {
|
| 81 |
+
"kernelspec": {
|
| 82 |
+
"display_name": "Python 3",
|
| 83 |
+
"language": "python",
|
| 84 |
+
"name": "python3"
|
| 85 |
+
},
|
| 86 |
+
"language_info": {
|
| 87 |
+
"name": "python",
|
| 88 |
+
"version": "3.10.12"
|
| 89 |
+
}
|
| 90 |
+
},
|
| 91 |
+
"nbformat": 4,
|
| 92 |
+
"nbformat_minor": 4
|
| 93 |
+
}
|
scripts/01_setup_inference.sh
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
set -e
|
| 3 |
+
|
| 4 |
+
echo "🚀 Setting up Inference Environment for Gemma-4-31B..."
|
| 5 |
+
|
| 6 |
+
# Update pip
|
| 7 |
+
pip install --upgrade pip
|
| 8 |
+
|
| 9 |
+
# Install huggingface hub for downloading
|
| 10 |
+
pip install "huggingface_hub[cli]"
|
| 11 |
+
|
| 12 |
+
# Install vLLM for ultra-fast serving and memory management
|
| 13 |
+
pip install vllm
|
| 14 |
+
|
| 15 |
+
# Login to HuggingFace (Requires HF_TOKEN environment variable)
|
| 16 |
+
if [ -z "$HF_TOKEN" ]; then
|
| 17 |
+
echo "⚠️ Warning: HF_TOKEN is not set. You might need it if the model requires accepting a license."
|
| 18 |
+
echo "Run: export HF_TOKEN='your_token_here'"
|
| 19 |
+
else
|
| 20 |
+
huggingface-cli login --token $HF_TOKEN
|
| 21 |
+
fi
|
| 22 |
+
|
| 23 |
+
# Download the model (we download it directly on the cloud instance because uploading 60GB takes too long)
|
| 24 |
+
echo "Downloading google/gemma-4-31B..."
|
| 25 |
+
huggingface-cli download google/gemma-4-31B --local-dir ./gemma-4-31B
|
| 26 |
+
|
| 27 |
+
echo "✅ Setup Complete!"
|
scripts/02_start_server.sh
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
echo "🚀 Starting vLLM Server with Gemma-4-31B in 4-bit mode..."
|
| 4 |
+
|
| 5 |
+
# We use vLLM with AWQ or GPTQ if pre-quantized, but for raw weights on a 24GB card we use bitsandbytes 4-bit via load-format
|
| 6 |
+
# If you are on an A6000 (48GB), you can remove the --quantization flag.
|
| 7 |
+
|
| 8 |
+
python -m vllm.entrypoints.openai.api_server \
|
| 9 |
+
--model ./gemma-4-31B \
|
| 10 |
+
--quantization bitsandbytes \
|
| 11 |
+
--load-format bitsandbytes \
|
| 12 |
+
--max-model-len 4096 \
|
| 13 |
+
--port 8000
|
| 14 |
+
|
| 15 |
+
# Note: Once this is running, your model acts exactly like the OpenAI API!
|