{ "metadata": { "kernelspec": { "name": "python3", "display_name": "Python 3", "language": "python" }, "language_info": { "name": "python", "version": "3.10.12", "mimetype": "text/x-python", "codemirror_mode": { "name": "ipython", "version": 3 }, "pygments_lexer": "ipython3", "nbconvert_exporter": "python", "file_extension": ".py" }, "accelerator": "GPU", "colab": { "gpuType": "T4", "provenance": [], "name": "Phi-4 Unsloth notebook", "include_colab_link": true }, "kaggle": { "accelerator": "nvidiaTeslaT4", "dataSources": [], "isInternetEnabled": true, "language": "python", "sourceType": "notebook", "isGpuEnabled": true } }, "nbformat_minor": 0, "nbformat": 4, "cells": [ { "cell_type": "markdown", "metadata": { "id": "view-in-github", "colab_type": "text" }, "source": [ "\"Open" ] }, { "cell_type": "markdown", "source": [ "To run this, press \"*Runtime*\" and press \"*Run all*\" on a **free** Tesla T4 Google Colab instance!\n", "
\n", "\n", "\n", " Join Discord if you need help + ⭐ Star us on Github ⭐\n", "
\n", "\n", "To install Unsloth on your own computer, follow the installation instructions [here](https://docs.unsloth.ai/get-started/installing-+-updating).\n", "\n", "You will learn how to do [data prep](#Data), how to [train](#Train), how to [run the model](#Inference), & [how to save it](#Save).\n", "\n", "Visit our docs for all our [model uploads](https://docs.unsloth.ai/get-started/all-our-models) and [notebooks](https://docs.unsloth.ai/get-started/unsloth-notebooks).\n", "\n" ], "metadata": { "id": "hwuDO656rQM4" } }, { "cell_type": "markdown", "source": [ "**[NEW] We've fixed many bugs in Phi-4** which greatly increases Phi-4's accuracy. See our [blogpost](https://unsloth.ai/blog/phi4)\n", "\n", "[NEW] You can view all Phi-4 model uploads with our bug fixes including [dynamic 4-bit quants](https://unsloth.ai/blog/dynamic-4bit), GGUF & more [here](https://huggingface.co/collections/unsloth/phi-4-all-versions-677eecf93784e61afe762afa)\n", "\n", "[NEW] As of Novemeber 2024, Unsloth now supports [vision finetuning](https://unsloth.ai/blog/vision)!\n" ], "metadata": { "id": "-EbJ7cIVrQM8" } }, { "cell_type": "code", "source": [ "%%capture\n", "!pip install unsloth\n", "# Also get the latest nightly Unsloth if you want!\n", "# !pip install --force-reinstall --no-cache-dir --no-deps git+https://github.com/unslothai/unsloth.git" ], "metadata": { "id": "oakVJTAArQM-" }, "outputs": [], "execution_count": null }, { "cell_type": "code", "source": [ "from unsloth import FastLanguageModel # FastVisionModel for LLMs\n", "import torch\n", "max_seq_length = 2048 # Choose any! We auto support RoPE Scaling internally!\n", "load_in_4bit = True # Use 4bit quantization to reduce memory usage. Can be False.\n", "\n", "# 4bit pre quantized models we support for 4x faster downloading + no OOMs.\n", "fourbit_models = [\n", " \"unsloth/Meta-Llama-3.1-8B-bnb-4bit\", # Llama-3.1 2x faster\n", " \"unsloth/Mistral-Small-Instruct-2409\", # Mistral 22b 2x faster!\n", " \"unsloth/Phi-4\", # Phi-4 2x faster!\n", " \"unsloth/Phi-4-unsloth-bnb-4bit\", # Phi-4 Unsloth Dynamic 4-bit Quant\n", " \"unsloth/gemma-2-9b-bnb-4bit\", # Gemma 2x faster!\n", " \"unsloth/Qwen2.5-7B-Instruct-bnb-4bit\" # Qwen 2.5 2x faster!\n", " \"unsloth/Llama-3.2-1B-bnb-4bit\", # NEW! Llama 3.2 models\n", " \"unsloth/Llama-3.2-1B-Instruct-bnb-4bit\",\n", " \"unsloth/Llama-3.2-3B-bnb-4bit\",\n", " \"unsloth/Llama-3.2-3B-Instruct-bnb-4bit\",\n", "] # More models at https://docs.unsloth.ai/get-started/all-our-models\n", "\n", "model, tokenizer = FastLanguageModel.from_pretrained(\n", " model_name = \"unsloth/Phi-4\",\n", " max_seq_length = max_seq_length,\n", " load_in_4bit = load_in_4bit,\n", " # token = \"hf_...\", # use one if using gated models like meta-llama/Llama-2-7b-hf\n", ")" ], "metadata": { "id": "QmUBVEnvCDJv" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "We now add LoRA adapters for parameter efficient finetuning - this allows us to only efficiently train 1% of all parameters." ], "metadata": { "id": "SXd9bTZd1aaL" } }, { "cell_type": "code", "source": [ "model = FastLanguageModel.get_peft_model(\n", " model,\n", " r = 16, # Choose any number > 0 ! Suggested 8, 16, 32, 64, 128\n", " target_modules = [\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\",\n", " \"gate_proj\", \"up_proj\", \"down_proj\",],\n", " lora_alpha = 16,\n", " lora_dropout = 0, # Supports any, but = 0 is optimized\n", " bias = \"none\", # Supports any, but = \"none\" is optimized\n", " # [NEW] \"unsloth\" uses 30% less VRAM, fits 2x larger batch sizes!\n", " use_gradient_checkpointing = \"unsloth\", # True or \"unsloth\" for very long context\n", " random_state = 3407,\n", " use_rslora = False, # We support rank stabilized LoRA\n", " loftq_config = None, # And LoftQ\n", ")" ], "metadata": { "id": "6bZsfBuZDeCL" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "\n", "### Data Prep\n", "We now use the `Phi-4` format for conversation style finetunes. We use [Maxime Labonne's FineTome-100k](https://huggingface.co/datasets/mlabonne/FineTome-100k) dataset in ShareGPT style. But we convert it to HuggingFace's normal multiturn format `(\"role\", \"content\")` instead of `(\"from\", \"value\")`/ Phi-4 renders multi turn conversations like below:\n", "\n", "```\n", "<|im_start|>user<|im_sep|>Hello!<|im_end|>\n", "<|im_start|>assistant<|im_sep|>Hi! How can I help?<|im_end|>\n", "<|im_start|>user<|im_sep|>What is 2+2?<|im_end|>\n", "```\n", "\n", "We use our `get_chat_template` function to get the correct chat template. We support `zephyr, chatml, mistral, llama, alpaca, vicuna, vicuna_old, phi3, phi4, llama3` and more." ], "metadata": { "id": "vITh0KVJ10qX" } }, { "cell_type": "code", "source": [ "from unsloth.chat_templates import get_chat_template\n", "\n", "tokenizer = get_chat_template(\n", " tokenizer,\n", " chat_template = \"phi-4\",\n", ")\n", "\n", "def formatting_prompts_func(examples):\n", " convos = examples[\"conversations\"]\n", " texts = [\n", " tokenizer.apply_chat_template(\n", " convo, tokenize = False, add_generation_prompt = False\n", " )\n", " for convo in convos\n", " ]\n", " return { \"text\" : texts, }\n", "pass\n", "\n", "from datasets import load_dataset\n", "dataset = load_dataset(\"mlabonne/FineTome-100k\", split = \"train\")" ], "metadata": { "id": "LjY75GoYUCB8" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "We now use `standardize_sharegpt` to convert ShareGPT style datasets into HuggingFace's generic format. This changes the dataset from looking like:\n", "```\n", "{\"from\": \"system\", \"value\": \"You are an assistant\"}\n", "{\"from\": \"human\", \"value\": \"What is 2+2?\"}\n", "{\"from\": \"gpt\", \"value\": \"It's 4.\"}\n", "```\n", "to\n", "```\n", "{\"role\": \"system\", \"content\": \"You are an assistant\"}\n", "{\"role\": \"user\", \"content\": \"What is 2+2?\"}\n", "{\"role\": \"assistant\", \"content\": \"It's 4.\"}\n", "```" ], "metadata": { "id": "K9CBpiISFa6C" } }, { "cell_type": "code", "source": [ "from unsloth.chat_templates import standardize_sharegpt\n", "\n", "dataset = standardize_sharegpt(dataset)\n", "dataset = dataset.map(\n", " formatting_prompts_func,\n", " batched=True,\n", ")" ], "metadata": { "id": "oPXzJZzHEgXe" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "We look at how the conversations are structured for item 5:" ], "metadata": { "id": "ndDUB23CGAC5" } }, { "cell_type": "code", "source": [ "dataset[5][\"conversations\"]" ], "metadata": { "id": "gGFzmplrEy9I" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "And we see how the chat template transformed these conversations." ], "metadata": { "id": "GfzTdMtvGE6w" } }, { "cell_type": "code", "source": [ "dataset[5][\"text\"]" ], "metadata": { "id": "vhXv0xFMGNKE" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "\n", "### Train the model\n", "Now let's use Huggingface TRL's `SFTTrainer`! More docs here: [TRL SFT docs](https://huggingface.co/docs/trl/sft_trainer). We do 60 steps to speed things up, but you can set `num_train_epochs=1` for a full run, and turn off `max_steps=None`. We also support TRL's `DPOTrainer`!" ], "metadata": { "id": "idAEIeSQ3xdS" } }, { "cell_type": "code", "source": [ "from trl import SFTTrainer\n", "from transformers import TrainingArguments, DataCollatorForSeq2Seq\n", "from unsloth import is_bfloat16_supported\n", "\n", "trainer = SFTTrainer(\n", " model = model,\n", " tokenizer = tokenizer,\n", " train_dataset = dataset,\n", " dataset_text_field = \"text\",\n", " max_seq_length = max_seq_length,\n", " data_collator = DataCollatorForSeq2Seq(tokenizer = tokenizer),\n", " dataset_num_proc = 2,\n", " packing = False, # Can make training 5x faster for short sequences.\n", " args = TrainingArguments(\n", " per_device_train_batch_size = 2,\n", " gradient_accumulation_steps = 4,\n", " warmup_steps = 5,\n", " # num_train_epochs = 1, # Set this for 1 full training run.\n", " max_steps = 30,\n", " learning_rate = 2e-4,\n", " fp16 = not is_bfloat16_supported(),\n", " bf16 = is_bfloat16_supported(),\n", " logging_steps = 1,\n", " optim = \"adamw_8bit\",\n", " weight_decay = 0.01,\n", " lr_scheduler_type = \"linear\",\n", " seed = 3407,\n", " output_dir = \"outputs\",\n", " report_to = \"none\", # Use this for WandB etc\n", " ),\n", ")" ], "metadata": { "id": "95_Nn-89DhsL" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "We also use Unsloth's `train_on_completions` method to only train on the assistant outputs and ignore the loss on the user's inputs." ], "metadata": { "id": "C_sGp5XlG6dq" } }, { "cell_type": "code", "source": [ "from unsloth.chat_templates import train_on_responses_only\n", "\n", "trainer = train_on_responses_only(\n", " trainer,\n", " instruction_part=\"<|im_start|>user<|im_sep|>\",\n", " response_part=\"<|im_start|>assistant<|im_sep|>\",\n", ")" ], "metadata": { "id": "juQiExuBG5Bt" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "We verify masking is actually done:" ], "metadata": { "id": "Dv1NBUozV78l" } }, { "cell_type": "code", "source": [ "tokenizer.decode(trainer.train_dataset[5][\"input_ids\"])" ], "metadata": { "id": "LtsMVtlkUhja" }, "outputs": [], "execution_count": null }, { "cell_type": "code", "source": [ "space = tokenizer(\" \", add_special_tokens = False).input_ids[0]\n", "tokenizer.decode([space if x == -100 else x for x in trainer.train_dataset[5][\"labels\"]])" ], "metadata": { "id": "_rD6fl8EUxnG" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "We can see the System and Instruction prompts are successfully masked!" ], "metadata": { "id": "3enWUM0jV-jV" } }, { "cell_type": "code", "source": [ "# @title Show current memory stats\n", "gpu_stats = torch.cuda.get_device_properties(0)\n", "start_gpu_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3)\n", "max_memory = round(gpu_stats.total_memory / 1024 / 1024 / 1024, 3)\n", "print(f\"GPU = {gpu_stats.name}. Max memory = {max_memory} GB.\")\n", "print(f\"{start_gpu_memory} GB of memory reserved.\")" ], "metadata": { "cellView": "form", "id": "2ejIt2xSNKKp" }, "outputs": [], "execution_count": null }, { "cell_type": "code", "source": [ "trainer_stats = trainer.train()" ], "metadata": { "id": "yqxqAZ7KJ4oL" }, "outputs": [], "execution_count": null }, { "cell_type": "code", "source": [ "# @title Show final memory and time stats\n", "used_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3)\n", "used_memory_for_lora = round(used_memory - start_gpu_memory, 3)\n", "used_percentage = round(used_memory / max_memory * 100, 3)\n", "lora_percentage = round(used_memory_for_lora / max_memory * 100, 3)\n", "print(f\"{trainer_stats.metrics['train_runtime']} seconds used for training.\")\n", "print(\n", " f\"{round(trainer_stats.metrics['train_runtime']/60, 2)} minutes used for training.\"\n", ")\n", "print(f\"Peak reserved memory = {used_memory} GB.\")\n", "print(f\"Peak reserved memory for training = {used_memory_for_lora} GB.\")\n", "print(f\"Peak reserved memory % of max memory = {used_percentage} %.\")\n", "print(f\"Peak reserved memory for training % of max memory = {lora_percentage} %.\")" ], "metadata": { "cellView": "form", "id": "pCqnaKmlO1U9" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "\n", "### Inference\n", "Let's run the model! You can change the instruction and input - leave the output blank!\n", "\n", "**[NEW] Try 2x faster inference in a free Colab for Llama-3.1 8b Instruct [here](https://colab.research.google.com/drive/1T-YBVfnphoVc8E2E854qF3jdia2Ll2W2?usp=sharing)**\n", "\n", "We use `min_p = 0.1` and `temperature = 1.5`." ], "metadata": { "id": "ekOmTR1hSNcr" } }, { "cell_type": "code", "source": [ "from unsloth.chat_templates import get_chat_template\n", "\n", "tokenizer = get_chat_template(\n", " tokenizer,\n", " chat_template = \"phi-4\",\n", ")\n", "FastLanguageModel.for_inference(model) # Enable native 2x faster inference\n", "\n", "messages = [\n", " {\"role\": \"user\", \"content\": \"Continue the fibonnaci sequence: 1, 1, 2, 3, 5, 8,\"},\n", "]\n", "inputs = tokenizer.apply_chat_template(\n", " messages,\n", " tokenize = True,\n", " add_generation_prompt = True, # Must add for generation\n", " return_tensors = \"pt\",\n", ").to(\"cuda\")\n", "\n", "outputs = model.generate(\n", " input_ids = inputs, max_new_tokens = 64, use_cache = True, temperature = 1.5, min_p = 0.1\n", ")\n", "tokenizer.batch_decode(outputs)" ], "metadata": { "id": "kR3gIAX-SM2q" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ " You can also use a `TextStreamer` for continuous inference - so you can see the generation token by token, instead of waiting the whole time!" ], "metadata": { "id": "CrSvZObor0lY" } }, { "cell_type": "code", "source": [ "FastLanguageModel.for_inference(model) # Enable native 2x faster inference\n", "\n", "messages = [\n", " {\"role\": \"user\", \"content\": \"Continue the fibonnaci sequence: 1, 1, 2, 3, 5, 8,\"},\n", "]\n", "inputs = tokenizer.apply_chat_template(\n", " messages,\n", " tokenize = True,\n", " add_generation_prompt = True, # Must add for generation\n", " return_tensors = \"pt\",\n", ").to(\"cuda\")\n", "\n", "from transformers import TextStreamer\n", "text_streamer = TextStreamer(tokenizer, skip_prompt = True)\n", "_ = model.generate(\n", " input_ids = inputs, streamer = text_streamer, max_new_tokens = 128,\n", " use_cache = True, temperature = 1.5, min_p = 0.1\n", ")" ], "metadata": { "id": "e2pEuRb1r2Vg" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "\n", "### Saving, loading finetuned models\n", "To save the final model as LoRA adapters, either use Huggingface's `push_to_hub` for an online save or `save_pretrained` for a local save.\n", "\n", "**[NOTE]** This ONLY saves the LoRA adapters, and not the full model. To save to 16bit or GGUF, scroll down!" ], "metadata": { "id": "uMuVrWbjAzhc" } }, { "cell_type": "code", "source": [ "model.save_pretrained(\"lora_model\") # Local saving\n", "tokenizer.save_pretrained(\"lora_model\")\n", "# model.push_to_hub(\"your_name/lora_model\", token = \"...\") # Online saving\n", "# tokenizer.push_to_hub(\"your_name/lora_model\", token = \"...\") # Online saving" ], "metadata": { "id": "upcOlWe7A1vc" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "Now if you want to load the LoRA adapters we just saved for inference, set `False` to `True`:" ], "metadata": { "id": "AEEcJ4qfC7Lp" } }, { "cell_type": "code", "source": [ "if False:\n", " from unsloth import FastLanguageModel\n", " model, tokenizer = FastLanguageModel.from_pretrained(\n", " model_name = \"lora_model\", # YOUR MODEL YOU USED FOR TRAINING\n", " max_seq_length = max_seq_length,\n", " dtype = dtype,\n", " load_in_4bit = load_in_4bit,\n", " )\n", " FastLanguageModel.for_inference(model) # Enable native 2x faster inference\n", "\n", "messages = [\n", " {\"role\": \"user\", \"content\": \"Describe a tall tower in the capital of France.\"},\n", "]\n", "inputs = tokenizer.apply_chat_template(\n", " messages,\n", " tokenize = True,\n", " add_generation_prompt = True, # Must add for generation\n", " return_tensors = \"pt\",\n", ").to(\"cuda\")\n", "\n", "from transformers import TextStreamer\n", "text_streamer = TextStreamer(tokenizer, skip_prompt = True)\n", "_ = model.generate(\n", " input_ids = inputs, streamer = text_streamer, max_new_tokens = 128,\n", " use_cache = True, temperature = 1.5, min_p = 0.1\n", ")" ], "metadata": { "id": "MKX_XKs_BNZR" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "You can also use Hugging Face's `AutoModelForPeftCausalLM`. Only use this if you do not have `unsloth` installed. It can be hopelessly slow, since `4bit` model downloading is not supported, and Unsloth's **inference is 2x faster**." ], "metadata": { "id": "QQMjaNrjsU5_" } }, { "cell_type": "code", "source": [ "if False:\n", " # I highly do NOT suggest - use Unsloth if possible\n", " from peft import AutoPeftModelForCausalLM\n", " from transformers import AutoTokenizer\n", "\n", " model = AutoPeftModelForCausalLM.from_pretrained(\n", " \"lora_model\", # YOUR MODEL YOU USED FOR TRAINING\n", " load_in_4bit=load_in_4bit,\n", " )\n", " tokenizer = AutoTokenizer.from_pretrained(\"lora_model\")" ], "metadata": { "id": "yFfaXG0WsQuE" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "### Saving to float16 for VLLM\n", "\n", "We also support saving to `float16` directly. Select `merged_16bit` for float16 or `merged_4bit` for int4. We also allow `lora` adapters as a fallback. Use `push_to_hub_merged` to upload to your Hugging Face account! You can go to https://huggingface.co/settings/tokens for your personal tokens." ], "metadata": { "id": "f422JgM9sdVT" } }, { "cell_type": "code", "source": [ "# Merge to 16bit\n", "if False: model.save_pretrained_merged(\"model\", tokenizer, save_method = \"merged_16bit\",)\n", "if False: model.push_to_hub_merged(\"hf/model\", tokenizer, save_method = \"merged_16bit\", token = \"\")\n", "\n", "# Merge to 4bit\n", "if False: model.save_pretrained_merged(\"model\", tokenizer, save_method = \"merged_4bit\",)\n", "if False: model.push_to_hub_merged(\"hf/model\", tokenizer, save_method = \"merged_4bit\", token = \"\")\n", "\n", "# Just LoRA adapters\n", "if False: model.save_pretrained_merged(\"model\", tokenizer, save_method = \"lora\",)\n", "if False: model.push_to_hub_merged(\"hf/model\", tokenizer, save_method = \"lora\", token = \"\")" ], "metadata": { "id": "iHjt_SMYsd3P" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "### GGUF / llama.cpp Conversion\n", "To save to `GGUF` / `llama.cpp`, we support it natively now! We clone `llama.cpp` and we default save it to `q8_0`. We allow all methods like `q4_k_m`. Use `save_pretrained_gguf` for local saving and `push_to_hub_gguf` for uploading to HF.\n", "\n", "Some supported quant methods (full list in our [Docs](https://docs.unsloth.ai/basics/saving-and-using-models/saving-to-gguf)):\n", "* `q8_0` - Fast conversion. High resource use, but generally acceptable.\n", "* `q4_k_m` - Recommended. Uses Q6_K for half of the attention.wv and feed_forward.w2 tensors, else Q4_K.\n", "* `q5_k_m` - Recommended. Uses Q6_K for half of the attention.wv and feed_forward.w2 tensors, else Q5_K.\n", "\n", "[**NEW**] To finetune and auto export to Ollama, try our [Ollama notebook](https://colab.research.google.com/drive/1WZDi7APtQ9VsvOrQSSC5DDtxq159j8iZ?usp=sharing)" ], "metadata": { "id": "TCv4vXHd61i7" } }, { "cell_type": "code", "source": [ "# Save to 8bit Q8_0\n", "if False: model.save_pretrained_gguf(\"model\", tokenizer,)\n", "# Remember to go to https://huggingface.co/settings/tokens for a token!\n", "# And change hf to your username!\n", "if False: model.push_to_hub_gguf(\"hf/model\", tokenizer, token = \"\")\n", "\n", "# Save to 16bit GGUF\n", "if False: model.save_pretrained_gguf(\"model\", tokenizer, quantization_method = \"f16\")\n", "if False: model.push_to_hub_gguf(\"hf/model\", tokenizer, quantization_method = \"f16\", token = \"\")\n", "\n", "# Save to q4_k_m GGUF\n", "if False: model.save_pretrained_gguf(\"model\", tokenizer, quantization_method = \"q4_k_m\")\n", "if False: model.push_to_hub_gguf(\"hf/model\", tokenizer, quantization_method = \"q4_k_m\", token = \"\")\n", "\n", "# Save to multiple GGUF options - much faster if you want multiple!\n", "if False:\n", " model.push_to_hub_gguf(\n", " \"hf/model\", # Change hf to your username!\n", " tokenizer,\n", " quantization_method = [\"q4_k_m\", \"q8_0\", \"q5_k_m\",],\n", " token = \"\", # Get a token at https://huggingface.co/settings/tokens\n", " )" ], "metadata": { "id": "FqfebeAdT073" }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "Now, use the `model-unsloth.gguf` file or `model-unsloth-Q4_K_M.gguf` file in llama.cpp or a UI based system like Jan or Open WebUI. You can install Jan [here](https://github.com/janhq/jan) and Open WebUI [here](https://github.com/open-webui/open-webui)\n", "\n", "And we're done! If you have any questions on Unsloth, we have a [Discord](https://discord.gg/unsloth) channel! If you find any bugs or want to keep updated with the latest LLM stuff, or need help, join projects etc, feel free to join our Discord!\n", "\n", "Some other links:\n", "1. Llama 3.2 Conversational notebook. [Free Colab](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.2_(1B_and_3B)-Conversational.ipynb)\n", "2. Saving finetunes to Ollama. [Free notebook](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3_(8B)-Ollama.ipynb)\n", "3. Llama 3.2 Vision finetuning - Radiography use case. [Free Colab](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.2_(11B)-Vision.ipynb)\n", "6. See notebooks for DPO, ORPO, Continued pretraining, conversational finetuning and more on our [documentation](https://docs.unsloth.ai/get-started/unsloth-notebooks)!\n", "\n", "
\n", " \n", " \n", " \n", "\n", " Join Discord if you need help + ⭐️ Star us on Github ⭐️\n", "
\n" ], "metadata": { "id": "Y69v-icGrQNY" } } ] }