Qwen3 を NeMo で単一 GPU 学習するチュートリアル
MarkTechPost は、NVIDIA NeMo AutoModel を用いて Qwen3 モデルを単一 GPU で効率的にファインチューニングする Google Colab の完全なワークフロー教程を提供している。
キーポイント
NeMo AutoModel の Colab 統合とインストール
公式リポジトリから NeMo AutoModel を直接インストールし、Colab 環境での CUDA ハードウェア検証と bfloat16 サポート確認を含むセットアップ手順を詳述している。
Qwen3 の LoRA ファインチューニング実行
公式レシピに基づき、精度、バッチサイズ、チェックポイント設定を Colab のリソース制約に合わせてプログラム的に調整し、パラメータ効率的なファインチューニングを実行する。
生成結果の比較と API 統合デモ
ファインチューニング後のモデル出力を元モデルと比較検証し、NeMo AutoModelForCausalLM を通じて Hugging Face インターフェースを維持しつつ NVIDIA 最適化実行パスを利用する方法を示す。
Colab環境へのレシピ適応
単一GPUの制約に合わせて、bfloat16対応状況を確認し非対応時はfloat32へ自動変換、バッチサイズを最小化して実行可能に調整します。
トレーニング設定のカスタマイズ
学習ステップ数を40回、エポック数を1回に制限し、チェックポイントの保存ディレクトリを明示的に設定してリソース効率を高めます。
NeMo AutoModel のフォールバック処理
トレーニング実行時に主要なコマンドが失敗した場合、レガシー CLI 構文 (`automodel finetune llm`) を自動的に試すエラーハンドリングを実装しています。
LoRA アダプターの実行時読み込み
評価ステップでは `peft` ライブラリを使用して、トレーニング済みの LoRA アダプターをベースモデルに動的に結合し、比較可能な状態で推論を行います。
重要な引用
In this tutorial, we build an end-to-end NVIDIA NeMo AutoModel workflow in Google Colab and use a single GPU to explore the same configuration-driven training architecture that scales to distributed multi-GPU environments.
We verify the available CUDA hardware and precision support, install NeMo AutoModel directly from its source repository, load an official Qwen3-0.6B LoRA fine-tuning recipe...
Finally, we use NeMoAutoModelForCausalLM through the Python API to demonstrate how NeMo AutoModel integrates NVIDIA-optimized execution paths while preserving the familiar Hugging Face model interface.
"We recursively adapt the precision and batch size parameters to fit the recipe on a single Colab GPU while preserving its original structure."
"limit the training duration, configure checkpoint output..."
"We turn off unnecessary Hugging Face transfer and tokenizer parallelism features to keep the Colab run more predictable."
影響分析・編集コメントを表示
影響分析
本記事は、大規模モデルのファインチューニングを専門的なオンプレミス環境や高価なマルチ GPU クラスタに依存せず、個人開発者や研究者が手軽に試せる Colab 上で実現可能であることを示しています。NVIDIA の NeMo AutoModel が Hugging Face エコシステムとシームレスに連携することで、開発のハードルを下げつつ、高性能な推論・学習基盤への移行を容易にする重要な実践例となっています。
編集コメント
Qwen3 のような最新モデルを、NVIDIA の強力なツールチェーンと組み合わせることで、リソース制約のある環境でも高品質なカスタマイズが可能になる点は、実務開発において非常に価値が高いです。特に Hugging Face との互換性を保ちつつ NVIDIA 最適化を活用できる点は、技術選定における重要な選択肢となります。
本チュートリアルでは、Google Colab で NVIDIA NeMo AutoModel のエンドツーエンド・ワークフローを構築し、単一の GPU を用いて、分散マルチ GPU 環境へもスケーリング可能な設定駆動型のトレーニングアーキテクチャを探求します。利用可能な CUDA ハードウェアと精度サポートを確認した後、ソースリポジトリから直接 NeMo AutoModel をインストールします。続いて、公式の Qwen3-0.6B LoRA 微調整レシピを読み込み、Colab の制約されたランタイムに合わせて、精度やバッチサイズ、チェックポイント設定、スケジューラーのパラメータをプログラムで動的に調整します。
その後、automodel コマンドラインインターフェースを通じてパラメータ効率の高い微調整(LoRA)を実行し、生成された LoRA チェックポイントの場所を確認して再読み込みします。さらに、元のモデルと微調整後のモデルから出力される結果を比較検証します。最後に、Python API を通じて NeMoAutoModelForCausalLM を使用し、NeMo AutoModel が NVIDIA 最適化の実行パスを取り入れつつも、馴染み深い Hugging Face のモデルインターフェースを維持している仕組みを実演します。
Colab ワークスペースとシェルヘルパーのセットアップ
コードをコピーして実行してください(ブラウザを変更することも可能です)。
import os, sys, glob, json, subprocess, shutil, textwrap
REPO_DIR = "/content/Automodel"
WORK_DIR = "/content/automodel_demo"
CKPT_DIR = os.path.join(WORK_DIR, "checkpoints")
os.makedirs(WORK_DIR, exist_ok=True)
def sh(cmd, check=True):
print(f"\n$ {cmd}\n" + "-" * 78)
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, text=True, bufsize=1)
for line in p.stdout:
print(line, end="")
p.wait()
if check and p.returncode != 0:
raise RuntimeError(f"Command failed ({p.returncode}): {cmd}")
return p.returncode
ファイル操作、プロセス実行、パス管理、そして整形された出力のために必要な Python ライブラリを読み込みます。また、本ワークフロー全体で使用するリポジトリディレクトリ、作業用ディレクトリ、チェックポイント保存先のディレクトリを定義しています。さらに、コマンドの実行結果をストリーミング表示し、実行に失敗した場合はエラーを抛出する再利用可能なシェルコマンド関数 sh も用意しました。
GPU の確認と NeMo AutoModel のインストール
コピーコード(Copied)
別のブラウザを使用
print("=" * 78)
print("STEP 0 — GPU ランタイムの確認")
print("=" * 78)
import torch
assert torch.cuda.is_available(), (
"GPU が検出されません!Colab の場合:ランタイム -> ランタイムタイプの変更 -> GPU を選択してください。"
)
GPU_NAME = torch.cuda.get_device_name(0)
BF16_OK = torch.cuda.is_bf16_supported()
VRAM_GB = torch.cuda.get_device_properties(0).total_memory / 1e9
print(f"GPU: {GPU_NAME} | VRAM: {VRAM_GB:.1f} GB | bf16 サポート:{BF16_OK}")
print("\n" + "=" * 78)
print("STEP 1 — NeMo AutoModel のインストール(数分かかります)")
print("=" * 78)
if not os.path.isdir(REPO_DIR):
sh(f"git clone --depth 1 https://github.com/NVIDIA-NeMo/Automodel.git {REPO_DIR}")
sh(f"pip -q install -e {REPO_DIR}")
sh("pip -q install pyyaml peft")
sh('python -c "import nemo_automodel; print(\'NeMo AutoModel version:\', '
'getattr(nemo_automodel, \'__version__', \'source\'))"')
Colab のランタイムに CUDA 対応の GPU が用意されているか確認し、その機種名やメモリ容量、bfloat16 のサポート状況を確認します。NVIDIA NeMo AutoModel のリポジトリが存在しない場合はクローンして取得し、ソースコードからパッケージを直接インストールします。その後、依存ライブラリの YAML と PEFT をインストールし、NeMo AutoModel が正常にインポートできるか確認します。
Qwen3 の LoRA レシピの読み込みとパッチ適用
コピー コピー済み
別のブラウザを使用する
print("\n" + "=" * 78)
print("STEP 2 — レシピの準備")
print("=" * 78)
import yaml
candidates = sorted(glob.glob(
os.path.join(REPO_DIR, "examples", "llm_finetune", "qwen", "*0p6b*peft*.yaml")
)) or sorted(glob.glob(
os.path.join(REPO_DIR, "examples", "llm_finetune", "**", "*peft*.yaml"),
recursive=True,
))
assert candidates, "クローンしたリポジトリ内に PEFT のレシピが見つかりません。"
BASE_RECIPE = candidates[0]
print(f"基本レシピ:{os.path.relpath(BASE_RECIPE, REPO_DIR)}")
with open(BASE_RECIPE) as f:
cfg = yaml.safe_load(f)
print("\n--- 元のレシピ(そのままの状態) ---")
print(yaml.dump(cfg, sort_keys=False)[:2500])
def patch(node):
if isinstance(node, dict):
for k, v in list(node.items()):
if isinstance(v, str) and not BF16_OK and v.lower() in (
"bf16", "bfloat16", "torch.bfloat16"):
node[k] = "float32"
elif k in ("batch_size", "local_batch_size") and isinstance(v, int):
node[k] = min(v, 4)
elif k == "global_batch_size" and isinstance(v, int):
node[k] = min(v, 8)
else:
patch(v)
elif isinstance(node, list):
for item in node:
patch(item)
patch(cfg)
cfg.setdefault("step_scheduler", {})
cfg["step_scheduler"]["max_steps"] = 40
cfg["step_scheduler"]["ckpt_every_steps"] = 40
cfg["step_scheduler"]["num_epochs"] = 1
if isinstance(cfg.get("checkpoint"), dict):
cfg["checkpoint"]["enabled"] = True
cfg["checkpoint"]["checkpoint_dir"] = CKPT_DIR
DEMO_RECIPE = os.path.join(WORK_DIR, "qwen3_0p6b_colab_lora.yaml")
with open(DEMO_RECIPE, "w") as f:
yaml.dump(cfg, f, sort_keys=False)
print("\n--- 修正後のレシピ(実際に実行する内容) ---")
print(yaml.dump(cfg, sort_keys=False)[:2500])
MODEL_ID = "Qwen/Qwen3-0.6B"
try:
MODEL_ID = cfg["model"]["pretrained_model_name_or_path"]
except Exception:
pass
print(f"\n基本モデル:{MODEL_ID}")
公式の PEFT レシピを見つけて YAML 設定を読み込み、元のトレーニング設定を確認します。その後、Colab の単一 GPU で実行できるように精度やバッチサイズのパラメータを再帰的に調整しつつ、レシピの構造自体は維持します。さらに、トレーニング時間の制限を設定し、チェックポイントの出力先を指定して修正済みのレシピを保存、Hugging Face 上のモデル ID を抽出します。
HellaSwag データセットでの LoRA 微調整の実行
print("\n" + "=" * 78)
print("STEP 3 — Training (LoRA fine-tune of Qwen3-0.6B on HellaSwag)")
print("=" * 78)
env_prefix = "HF_HUB_ENABLE_HF_TRANSFER=0 TOKENIZERS_PARALLELISM=false"
rc = sh(f"cd {WORK_DIR} && {env_prefix} automodel {DEMO_RECIPE}", check=False)
if rc != 0:
print("\nRetrying with legacy CLI syntax...")
sh(f"cd {WORK_DIR} && {env_prefix} automodel finetune llm -c {DEMO_RECIPE}")NeMo AutoModel のコマンドラインインターフェースを通じて、HellaSwag データセット上で Qwen3-0.6B の LoRA 微調整を開始します。Colab での実行をより予測可能にするため、不要な Hugging Face の転送機能やトークナイザーの並列処理機能をオフにしています。また、メインのコマンドが失敗した場合に備えて、古い NeMo AutoModel CLI 構文に対応するフォールバックコマンドも用意されています。
ベースモデルと微調整済みモデルの出力比較
print("\n" + "=" * 78)
print("STEP 4 — Evaluating: base model vs LoRA fine-tuned model")
print("=" * 78)
from transformers import AutoModelForCausalLM, AutoTokenizer
DTYPE = torch.bfloat16 if BF16_OK else torch.float32
PROMPT = ("A man is sitting on a roof. He starts pulling up roofing shingles. "
"What happens next?")
def generate(model, tok, prompt, max_new_tokens=60):
inputs = tok(prompt, return_tensors="pt").to(model.device)
with torch.no_grad():
out = model.generate(**inputs, max_new_tokens=max_new_tokens,
do_sample=False, temperature=None, top_p=None,
pad_token_id=tok.eos_token_id)
return tok.decode(out[0][inputs["input_ids"].shape[1]:],
skip_special_tokens=True)
tok = AutoTokenizer.from_pretrained(MODEL_ID)
base = AutoModelForCausalLM.from_pretrained(
MODEL_ID, torch_dtype=DTYPE, device_map="cuda")
print("\n[BASE MODEL]")
print(textwrap.fill(generate(base, tok, PROMPT), 90))
ckpt_glob = sorted(glob.glob(os.path.join(CKPT_DIR, "**", "model"),
recursive=True))
if not ckpt_glob:
ckpt_glob = sorted(glob.glob(os.path.join(WORK_DIR, "**",
"adapter_model.safetensors"),
recursive=True))
ckpt_glob = [os.path.dirname(p) for p in ckpt_glob]
if ckpt_glob:
ADAPTER_DIR = ckpt_glob[-1]
print(f"\nFound checkpoint: {ADAPTER_DIR}")
try:
from peft import PeftModel
tuned = PeftModel.from_pretrained(base, ADAPTER_DIR)
print("\n[FINE-TUNED MODEL (base + LoRA adapter)]")
print(textwrap.fill(generate(tuned, tok, PROMPT), 90))
except Exception as e:
print(f"\nCould not auto-load the adapter with peft ({e}).")
print("Inspect the checkpoint contents manually:")
for p in glob.glob(os.path.join(ADAPTER_DIR, "*"))[:20]:
print(" ", p)
else:
print("\nNo checkpoint found — check the training logs above.")
del base
torch.cuda.empty_cache()
まず、トークナイザーとベースとなる因果言語モデルを読み込み、決定論的な応答を生成して比較の基準(ベンチマーク)を設定します。次に、微調整中に作成された最新の LoRA チェックポイントまたはアダプターファイルを検索し、PEFT を用いてこれらをモデルに適用します。その後、微調整後の応答を生成して評価を行い、GPU メモリを解放します。
NeMo AutoModel Python API の使用
print("\n" + "=" * 78)
print("STEP 5 — Bonus: drop-in Python API")
print("=" * 78)
try:
from nemo_automodel import NeMoAutoModelForCausalLM
nm = NeMoAutoModelForCausalLM.from_pretrained(
MODEL_ID, torch_dtype=DTYPE).to("cuda")
print("[NeMoAutoModelForCausalLM]")
print(textwrap.fill(generate(nm, tok, "The key idea of LoRA is"), 90))
del nm
torch.cuda.empty_cache()
except Exception as e:
print(f"Python-API demo skipped on this version/GPU: {e}")
print("\n" + "=" * 78)
print("DONE! Where to go next:")
print("=" * 78)
print(f"""
- Recipes を探索する (REPO_DIR/examples/内):
llm_finetune/ — Llama, Qwen, Gemma, Phi, GPT-OSS などへの SFT + LoRA
llm_pretrain/ — FineWeb での nanoGPT や DeepSeek-V3 の事前学習など
vlm_finetune/ — Qwen-VL, Gemma-3-VL、その他のビジョン・ランゲージモデル向け
diffusion/ — FLUX / Wan / Qwen-Image の LoRA 微調整
- モデルの差し替え: 1 つのフィールドをオーバーライドする
automodel recipe.yaml --model.pretrained_model_name_or_path
- スケーリング: 同じレシピで 8 GPU で実行可能(
--nproc-per-node 8)。
または、同梱された slurm.sub / SkyPilot / Kubernetes ランチャーを使ってマルチノード展開も可能です。
- ドキュメント: https://docs.nvidia.com/nemo/automodel/latest/index.html
""")
NeMoAutoModelForCausalLM を通じてモデルを読み込み、追加の生成例を実行することで、Python インターフェースの直接使用をデモンストレーションします。バージョンやハードウェアに依存するエラーが発生しても柔軟に対応し、ノートブックが正常に完了できるよう設計しています。最後に、利用可能なレシピのカテゴリ、モデル上書き構文、分散スケーリングオプション、および公式ドキュメントへのアクセス経路について解説します。
結論として、環境検証からソースコードのインストール、レシピの確認、設定パッチ適用、LoRA によるトレーニング、チェックポイントの復元、モデル評価、そして Python API を介した直接推論までを網羅する、実用的な NeMo AutoModel パイプラインを構築しました。NeMo AutoModel では、モデル、データセット、オプティマイザ、精度設定、並列処理、チェックポイント動作などを再利用可能な YAML レシピで指定することで、分散トレーニング戦略とアプリケーションコードを明確に分離しています。
今回は単一の Colab GPU 上でワークフローを実行しましたが、大規模な FSDP2、テンソル並列、コンテキスト並列、シーケンス並列、パイプライン並列の各展開でも採用されている SPMD(Single Program Multiple Data)指向の構造をそのまま維持しています。これにより、言語モデルやビジョン・ランゲージモデル、事前学習、拡散モデルなど他のレシピへの適応や、実験段階からマルチノードの NVIDIA インフラへスケールする際にも、技術的に根拠のある出発点を提供します。
詳細なコードは、こちらからご確認ください。また、Twitter でフォローしていただくと幸いです。15 万人以上の ML エンジニアが集まる Reddit サブコミュニティにもぜひご参加ください。さらに、ニュースレターへの購読も忘れずに。
あ、Telegram も利用されていますか?今なら Telegram でも私たちに参加いただけます。
GitHub リポジトリや Hugging Face ページの宣伝、製品発表、ウェビナーなどのご提携をご検討の場合は、お気軽にご連絡ください。
本記事「Fine-Tuning Qwen3 with LoRA Using NVIDIA NeMo AutoModel: A Complete Single-GPU Google Colab Workflow Tutorial」は、MarkTechPost で公開されたものです。
原文を表示
In this tutorial, we build an end-to-end NVIDIA NeMo AutoModel workflow in Google Colab and use a single GPU to explore the same configuration-driven training architecture that scales to distributed multi-GPU environments. We verify the available CUDA hardware and precision support, install NeMo AutoModel directly from its source repository, load an official Qwen3-0.6B LoRA fine-tuning recipe, and programmatically adapt its precision, batch-size, checkpointing, and scheduler settings for a constrained Colab runtime. We then launch parameter-efficient fine-tuning through the automodel command-line interface, locate and reload the generated LoRA checkpoint, and compare outputs from the original and fine-tuned models. Finally, we use NeMoAutoModelForCausalLM through the Python API to demonstrate how NeMo AutoModel integrates NVIDIA-optimized execution paths while preserving the familiar Hugging Face model interface.
Setting Up the Colab Workspace and Shell Helper
Copy CodeCopiedUse a different Browser
import os, sys, glob, json, subprocess, shutil, textwrap
REPO_DIR = "/content/Automodel"
WORK_DIR = "/content/automodel_demo"
CKPT_DIR = os.path.join(WORK_DIR, "checkpoints")
os.makedirs(WORK_DIR, exist_ok=True)
def sh(cmd, check=True):
print(f"\n$ {cmd}\n" + "-" * 78)
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, text=True, bufsize=1)
for line in p.stdout:
print(line, end="")
p.wait()
if check and p.returncode != 0:
raise RuntimeError(f"Command failed ({p.returncode}): {cmd}")
return p.returncode
We import the core Python libraries required for file handling, process execution, path management, and formatted output. We define the repository, working, and checkpoint directories used throughout the workflow. We also create a reusable shell-command function that streams command output and raises errors when execution fails.
Verifying the GPU and Installing NeMo AutoModel
Copy CodeCopiedUse a different Browser
print("=" * 78)
print("STEP 0 — Checking GPU runtime")
print("=" * 78)
import torch
assert torch.cuda.is_available(), (
"No GPU found! In Colab: Runtime -> Change runtime type -> select a GPU."
)
GPU_NAME = torch.cuda.get_device_name(0)
BF16_OK = torch.cuda.is_bf16_supported()
VRAM_GB = torch.cuda.get_device_properties(0).total_memory / 1e9
print(f"GPU: {GPU_NAME} | VRAM: {VRAM_GB:.1f} GB | bf16 supported: {BF16_OK}")
print("\n" + "=" * 78)
print("STEP 1 — Installing NeMo AutoModel (takes a few minutes)")
print("=" * 78)
if not os.path.isdir(REPO_DIR):
sh(f"git clone --depth 1 https://github.com/NVIDIA-NeMo/Automodel.git {REPO_DIR}")
sh(f"pip -q install -e {REPO_DIR}")
sh("pip -q install pyyaml peft")
sh('python -c "import nemo_automodel; print(\'NeMo AutoModel version:\', '
'getattr(nemo_automodel, \'__version__\', \'source\'))"')
We verify that the Colab runtime provides a CUDA-enabled GPU and inspect its name, memory capacity, and bfloat16 support. We clone the NVIDIA NeMo AutoModel repository when it is not already available and install the package directly from source. We then install the supporting YAML and PEFT libraries and confirm that the NeMo AutoModel package imports correctly.
Loading and Patching the Qwen3 LoRA Recipe
Copy CodeCopiedUse a different Browser
print("\n" + "=" * 78)
print("STEP 2 — Preparing the recipe")
print("=" * 78)
import yaml
candidates = sorted(glob.glob(
os.path.join(REPO_DIR, "examples", "llm_finetune", "qwen", "*0p6b*peft*.yaml")
)) or sorted(glob.glob(
os.path.join(REPO_DIR, "examples", "llm_finetune", "**", "*peft*.yaml"),
recursive=True,
))
assert candidates, "Could not find a PEFT recipe in the cloned repo."
BASE_RECIPE = candidates[0]
print(f"Base recipe: {os.path.relpath(BASE_RECIPE, REPO_DIR)}")
with open(BASE_RECIPE) as f:
cfg = yaml.safe_load(f)
print("\n--- Original recipe (as shipped) ---")
print(yaml.dump(cfg, sort_keys=False)[:2500])
def patch(node):
if isinstance(node, dict):
for k, v in list(node.items()):
if isinstance(v, str) and not BF16_OK and v.lower() in (
"bf16", "bfloat16", "torch.bfloat16"):
node[k] = "float32"
elif k in ("batch_size", "local_batch_size") and isinstance(v, int):
node[k] = min(v, 4)
elif k == "global_batch_size" and isinstance(v, int):
node[k] = min(v, 8)
else:
patch(v)
elif isinstance(node, list):
for item in node:
patch(item)
patch(cfg)
cfg.setdefault("step_scheduler", {})
cfg["step_scheduler"]["max_steps"] = 40
cfg["step_scheduler"]["ckpt_every_steps"] = 40
cfg["step_scheduler"]["num_epochs"] = 1
if isinstance(cfg.get("checkpoint"), dict):
cfg["checkpoint"]["enabled"] = True
cfg["checkpoint"]["checkpoint_dir"] = CKPT_DIR
DEMO_RECIPE = os.path.join(WORK_DIR, "qwen3_0p6b_colab_lora.yaml")
with open(DEMO_RECIPE, "w") as f:
yaml.dump(cfg, f, sort_keys=False)
print("\n--- Patched recipe (what we will actually run) ---")
print(yaml.dump(cfg, sort_keys=False)[:2500])
MODEL_ID = "Qwen/Qwen3-0.6B"
try:
MODEL_ID = cfg["model"]["pretrained_model_name_or_path"]
except Exception:
pass
print(f"\nBase model: {MODEL_ID}")
We locate an official PEFT recipe, load its YAML configuration, and inspect the original training settings. We recursively adapt the precision and batch size parameters to fit the recipe on a single Colab GPU while preserving its original structure. We also limit the training duration, configure checkpoint output, save the patched recipe, and extract the Hugging Face model identifier.
Running LoRA Fine-Tuning on HellaSwag
Copy CodeCopiedUse a different Browser
print("\n" + "=" * 78)
print("STEP 3 — Training (LoRA fine-tune of Qwen3-0.6B on HellaSwag)")
print("=" * 78)
env_prefix = "HF_HUB_ENABLE_HF_TRANSFER=0 TOKENIZERS_PARALLELISM=false"
rc = sh(f"cd {WORK_DIR} && {env_prefix} automodel {DEMO_RECIPE}", check=False)
if rc != 0:
print("\nRetrying with legacy CLI syntax...")
sh(f"cd {WORK_DIR} && {env_prefix} automodel finetune llm -c {DEMO_RECIPE}")
We launch Qwen3-0.6B LoRA fine-tuning on the HellaSwag dataset through the NeMo AutoModel command-line interface. We turn off unnecessary Hugging Face transfer and tokenizer parallelism features to keep the Colab run more predictable. We also include a fallback command that supports older NeMo AutoModel CLI syntax when the primary invocation fails.
Comparing Base and Fine-Tuned Model Outputs
Copy CodeCopiedUse a different Browser
print("\n" + "=" * 78)
print("STEP 4 — Evaluating: base model vs LoRA fine-tuned model")
print("=" * 78)
from transformers import AutoModelForCausalLM, AutoTokenizer
DTYPE = torch.bfloat16 if BF16_OK else torch.float32
PROMPT = ("A man is sitting on a roof. He starts pulling up roofing shingles. "
"What happens next?")
def generate(model, tok, prompt, max_new_tokens=60):
inputs = tok(prompt, return_tensors="pt").to(model.device)
with torch.no_grad():
out = model.generate(**inputs, max_new_tokens=max_new_tokens,
do_sample=False, temperature=None, top_p=None,
pad_token_id=tok.eos_token_id)
return tok.decode(out[0][inputs["input_ids"].shape[1]:],
skip_special_tokens=True)
tok = AutoTokenizer.from_pretrained(MODEL_ID)
base = AutoModelForCausalLM.from_pretrained(
MODEL_ID, torch_dtype=DTYPE, device_map="cuda")
print("\n[BASE MODEL]")
print(textwrap.fill(generate(base, tok, PROMPT), 90))
ckpt_glob = sorted(glob.glob(os.path.join(CKPT_DIR, "**", "model"),
recursive=True))
if not ckpt_glob:
ckpt_glob = sorted(glob.glob(os.path.join(WORK_DIR, "**",
"adapter_model.safetensors"),
recursive=True))
ckpt_glob = [os.path.dirname(p) for p in ckpt_glob]
if ckpt_glob:
ADAPTER_DIR = ckpt_glob[-1]
print(f"\nFound checkpoint: {ADAPTER_DIR}")
try:
from peft import PeftModel
tuned = PeftModel.from_pretrained(base, ADAPTER_DIR)
print("\n[FINE-TUNED MODEL (base + LoRA adapter)]")
print(textwrap.fill(generate(tuned, tok, PROMPT), 90))
except Exception as e:
print(f"\nCould not auto-load the adapter with peft ({e}).")
print("Inspect the checkpoint contents manually:")
for p in glob.glob(os.path.join(ADAPTER_DIR, "*"))[:20]:
print(" ", p)
else:
print("\nNo checkpoint found — check the training logs above.")
del base
torch.cuda.empty_cache()
We load the tokenizer and base causal language model, generate a deterministic response, and establish a baseline for comparison. We search the training output directories for the latest LoRA checkpoint or adapter files created during fine-tuning. We then attach the adapter with PEFT, generate the fine-tuned response, and release GPU memory after evaluation.
Using the NeMo AutoModel Python API
Copy CodeCopiedUse a different Browser
print("\n" + "=" * 78)
print("STEP 5 — Bonus: drop-in Python API")
print("=" * 78)
try:
from nemo_automodel import NeMoAutoModelForCausalLM
nm = NeMoAutoModelForCausalLM.from_pretrained(
MODEL_ID, torch_dtype=DTYPE).to("cuda")
print("[NeMoAutoModelForCausalLM]")
print(textwrap.fill(generate(nm, tok, "The key idea of LoRA is"), 90))
del nm
torch.cuda.empty_cache()
except Exception as e:
print(f"Python-API demo skipped on this version/GPU: {e}")
print("\n" + "=" * 78)
print("DONE! Where to go next:")
print("=" * 78)
print(f"""
- Recipes to explore (in {REPO_DIR}/examples/):
llm_finetune/ — SFT + LoRA for Llama, Qwen, Gemma, Phi, GPT-OSS, ...
llm_pretrain/ — e.g. nanoGPT on FineWeb, DeepSeek-V3 pre-training
vlm_finetune/ — Qwen-VL, Gemma-3-VL, and other vision-language models
diffusion/ — FLUX / Wan / Qwen-Image LoRA fine-tuning
- Swap the model: override one field —
automodel recipe.yaml --model.pretrained_model_name_or_path <any-HF-LM>
- Scale out: the SAME recipe runs on 8 GPUs with
--nproc-per-node 8,
or multi-node via the shipped slurm.sub / SkyPilot / Kubernetes launchers.
- Docs: https://docs.nvidia.com/nemo/automodel/latest/index.html
""")
We demonstrate the direct Python interface by loading the model through NeMoAutoModelForCausalLM and running an additional generation example. We handle version-specific or hardware-specific failures gracefully so the notebook can still complete successfully. We conclude by presenting the available recipe categories, model-override syntax, distributed scaling options, and official documentation path.
Conclusion
In conclusion, we established a practical NeMo AutoModel pipeline that covers environment validation, source installation, recipe inspection, configuration patching, LoRA training, checkpoint recovery, model evaluation, and direct Python API inference. We saw how NeMo AutoModel separates the distributed training strategy from the application code by specifying model, dataset, optimizer, precision, parallelism, and checkpoint behavior through reusable YAML recipes. Although we ran the workflow on a single Colab GPU, we retained the same SPMD-oriented structure used for larger FSDP2, tensor-parallel, context-parallel, sequence-parallel, and pipeline-parallel deployments. It gives us a technically grounded starting point for adapting additional language-model, vision-language, pre-training, and diffusion recipes while scaling the same workflow from experimentation to multi-node NVIDIA infrastructure.
Check out the Full Code here. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.? Connect with us
The post Fine-Tuning Qwen3 with LoRA Using NVIDIA NeMo AutoModel: A Complete Single-GPU Google Colab Workflow Tutorial appeared first on MarkTechPost.
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み