Skip to content

Instantly share code, notes, and snippets.

@kishida
Last active December 3, 2025 12:11
Show Gist options
  • Select an option

  • Save kishida/3174865b6bbf2d9d790a1cb5b5a594b7 to your computer and use it in GitHub Desktop.

Select an option

Save kishida/3174865b6bbf2d9d790a1cb5b5a594b7 to your computer and use it in GitHub Desktop.
Javaのエラーを明るく説明するMinistral 3 3B
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "471f7cfe-b52f-402a-85dc-5fe7fe76639e",
"metadata": {},
"outputs": [],
"source": [
"%%capture\n",
"import os, re\n",
"if \"COLAB_\" not in \"\".join(os.environ.keys()):\n",
" !pip install unsloth\n",
"else:\n",
" # Do this only in Colab notebooks! Otherwise use pip install unsloth\n",
" import torch; v = re.match(r\"[0-9]{1,}\\.[0-9]{1,}\", str(torch.__version__)).group(0)\n",
" xformers = \"xformers==\" + (\"0.0.33.post1\" if v==\"2.9\" else \"0.0.32.post2\" if v==\"2.8\" else \"0.0.29.post3\")\n",
" !pip install --no-deps bitsandbytes accelerate {xformers} peft trl triton cut_cross_entropy unsloth_zoo\n",
" !pip install sentencepiece protobuf \"datasets==4.3.0\" \"huggingface_hub>=0.34.0\" hf_transfer\n",
" !pip install --no-deps unsloth\n",
"# Install transformers branch for Ministral\n",
"!pip install git+https://github.com/huggingface/transformers.git@bf3f0ae70d0e902efab4b8517fce88f6697636ce\n",
"!pip install --no-deps trl==0.22.2"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "df7c3391-e202-41a9-b206-2985f80b8e57",
"metadata": {},
"outputs": [],
"source": [
"max_seq_length = 2048\n",
"model_name = \"unsloth/Ministral-3-3B-Instruct-2512\"\n",
"max_steps = 30\n",
"output_dir = \"ministral3-cheerful\"\n",
"use_wandb = False"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "11312f48-22fe-4464-aa40-2888c4ea2541",
"metadata": {},
"outputs": [],
"source": [
"report_to = \"none\"\n",
"if use_wandb:\n",
" import wandb\n",
" report_to = \"wandb\"\n",
" wandb.login()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6296d8ac-dbca-4c9c-bbd0-41ebb075e467",
"metadata": {},
"outputs": [],
"source": [
"from unsloth import FastVisionModel\n",
"model, tokenizer = FastVisionModel.from_pretrained(\n",
" model_name = model_name,\n",
" max_seq_length = max_seq_length, # Choose any for long context!\n",
" load_in_4bit = False, # 4 bit quantization to reduce memory\n",
" load_in_8bit = False, # [NEW!] A bit more accurate, uses 2x memory\n",
" full_finetuning = False, # [NEW!] We have full finetuning now!\n",
" # token = \"hf_...\", # use one if using gated models\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "73711cac-2230-4ec5-95c7-4fc4c791769d",
"metadata": {},
"outputs": [],
"source": [
"model = FastVisionModel.get_peft_model(\n",
" model,\n",
" target_modules = [\n",
" \"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\",\n",
" \"gate_proj\", \"up_proj\", \"down_proj\",\n",
" ],\n",
" r = 32, # Larger = higher accuracy, but might overfit\n",
" lora_alpha = 64, # Recommended alpha == r at least\n",
" random_state = 3407,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "9b30812f-5fb4-4202-b035-a9bbed0a3758",
"metadata": {},
"source": [
"## データの準備"
]
},
{
"cell_type": "markdown",
"id": "e40e7dda-5640-4853-bc15-e5f1602379b5",
"metadata": {},
"source": [
"### 読み込み"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3bdef308-62a8-4e8b-822b-4808254d8bda",
"metadata": {},
"outputs": [],
"source": [
"from datasets import load_dataset\n",
"dataset = load_dataset(\"kishida/CompileError-Java-JP-cheerful\", split = \"train\")\n",
"filtered = dataset.filter(lambda x: x[\"description\"] is not None)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8f0457e5-51f0-48a1-b2cd-6ce663de4251",
"metadata": {},
"outputs": [],
"source": [
"print(len(dataset))\n",
"print(len(filtered))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b8e8dfeb-fe34-4dd1-8972-2c26ed02a1f0",
"metadata": {},
"outputs": [],
"source": [
"filtered[3]"
]
},
{
"cell_type": "markdown",
"id": "4530e85c-c9af-4110-bdac-0dc1fa29b84e",
"metadata": {},
"source": [
"### 変換"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1bca54d4-85fe-4fc3-98e1-7dbe780c179b",
"metadata": {},
"outputs": [],
"source": [
"template = \"\"\"filename: {}\n",
"## source\n",
"{}\n",
"\n",
"## error message\n",
"{}\n",
"\"\"\"\n",
"system_prompt = \"\"\"You are a good Java error explainer.\n",
"Please provide a concise explanation of the compilation error that occurred in the given source code.\n",
"Do not provide the complete code you have fixed.\n",
"\"\"\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "696095de-afba-4e85-bcaa-5d23366e6b89",
"metadata": {},
"outputs": [],
"source": [
"def make_conv(example):\n",
" prompt = template.format(example[\"filename\"], example[\"code\"], example[\"compile_message\"])\n",
" return {\"conversations\": [\n",
" {\"content\": system_prompt, \"role\": \"system\"},\n",
" {\"content\": prompt, \"role\": \"user\"},\n",
" {\"content\": example[\"description\"], \"role\": \"assistant\"}]}\n",
"dataset = filtered.map(make_conv, batched = False,)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3b6836d5-a354-49f2-8c77-00fc2e3faa26",
"metadata": {},
"outputs": [],
"source": [
"def formatting_prompts_func(examples):\n",
" convos = examples[\"conversations\"]\n",
" texts = [tokenizer.apply_chat_template(conv, tokenize = False, add_generation_prompt = False) for conv in convos]\n",
" return {\"text\": texts, }\n",
"dataset = dataset.map(formatting_prompts_func, batched = True,)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b7093231-40ef-4235-9bbb-1441e03d6b2c",
"metadata": {},
"outputs": [],
"source": [
"dataset[3][\"text\"]"
]
},
{
"cell_type": "markdown",
"id": "d38304a8-b44f-42f8-aa23-caccf3523a11",
"metadata": {},
"source": [
"## 学習"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3c9db459-f107-4dd7-9697-d29ab64d9453",
"metadata": {},
"outputs": [],
"source": [
"import wandb\n",
"if use_wandb: wandb.login()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b78eeff9-1c3a-4cd9-bf8a-6837a14f338d",
"metadata": {},
"outputs": [],
"source": [
"from trl import SFTConfig, SFTTrainer\n",
"from transformers import DataCollatorForSeq2Seq\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",
" packing = False, # Can make training 5x faster for short sequences.\n",
" args = SFTConfig(\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 = max_steps,\n",
" learning_rate = 2e-4,\n",
" logging_steps = 1,\n",
" optim = \"adamw_8bit\",\n",
" weight_decay = 0.001,\n",
" lr_scheduler_type = \"linear\",\n",
" seed = 3407,\n",
" output_dir = output_dir,\n",
" report_to = report_to, # Use TrackIO/WandB etc\n",
" ),\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ed5c3d82-1a7e-4b66-96b1-74fb8ee808e0",
"metadata": {},
"outputs": [],
"source": [
"tokenizer.decode(trainer.train_dataset[5][\"input_ids\"])"
]
},
{
"cell_type": "markdown",
"id": "9e78cf40-fb12-42dd-8059-2b3b3f0bb488",
"metadata": {},
"source": [
"### 学習開始"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "764f3e5d-72be-4367-8c99-d30712ff12fc",
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"# @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.\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3632ac67-9699-48c9-b8af-b1337de64d08",
"metadata": {},
"outputs": [],
"source": [
"trainer_stats = trainer.train()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3ae3de7d-b8bf-4b8a-bac5-c6bdb41ddf6e",
"metadata": {},
"outputs": [],
"source": [
"if use_wandb: wandb.finish()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0d87c1e1-6e42-4e84-8e5e-600ef6fafad5",
"metadata": {},
"outputs": [],
"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} %.\")"
]
},
{
"cell_type": "markdown",
"id": "d659802f-6623-4899-9335-fd44db303421",
"metadata": {},
"source": [
"## 推論"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fdfa15af-b13c-4789-a1f1-e84c8fb39ac3",
"metadata": {},
"outputs": [],
"source": [
"sample = filtered[5]\n",
"messages = [\n",
" {\"role\": \"system\", \"content\": [{\"type\":\"text\", \"text\": system_prompt}]},\n",
" {\"role\": \"user\", \"content\": [{\"type\":\"text\", \"text\" : template.format(sample[\"filename\"], sample[\"code\"], sample[\"compile_message\"])}]}]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5e12a6af-79a7-4c83-aede-abc1a8a93b94",
"metadata": {},
"outputs": [],
"source": [
"sample[\"description\"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "936d1ff9-fbed-4682-9ed7-60703daacec0",
"metadata": {},
"outputs": [],
"source": [
"# FastModel.for_inference(model) # Enable native 2x faster inference\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",
"from transformers import TextStreamer\n",
"text_streamer = TextStreamer(tokenizer, skip_prompt = True)\n",
"_ = model.generate(input_ids = inputs, streamer = text_streamer, max_new_tokens = 128,\n",
" use_cache = True, temperature = 1.5, min_p = 0.1)"
]
},
{
"cell_type": "markdown",
"id": "2ccf3578-8fdf-4fb0-8893-5244ca92949b",
"metadata": {},
"source": [
"## 保存"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ed39e906-d48f-401f-bc62-c5c1a83edadc",
"metadata": {},
"outputs": [],
"source": [
"# model.save_pretrained_merged(output_dir + \"_merged\", tokenizer)\n",
"# model.save_pretrained_gguf(output_dir + \"_gguf\", tokenizer, quantization_method = \"q8_0\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "10aebcd2-183e-4811-8286-ac51cb2facbd",
"metadata": {},
"outputs": [],
"source": [
"# %run llama.cpp/convert_hf_to_gguf.py --outfile Ministral-3-3B-Instruct-2512.q8.gguf --outtype q8_0 --split-max-size 50G ministral3-cheerful_gguf"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fc4eb5bf-4868-4134-9e6f-5aa0f7e8e12f",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment