JoyCaptionの使い方|Beta Oneを4bit量子化で8GB VRAMから動かす手順
JoyCaptionは、画像から説明文やタグを生成する無検閲の画像キャプショニングVLMです。学習用データセットのタグ付けや画像からのプロンプト復元に使われますが、素の状態では約17GBのVRAMを要求するため「手元のGPUで動くのか」「どのモードを指定すれば狙った出力になるのか」でつまずきやすいモデルでもあります。この記事では、2026年7月31日時点の公式リポジトリとモデルカードの記述をもとに、必要スペック・4bit量子化の正しい設定・12種類のキャプションモード・ComfyUIやGGUFでの動かし方を整理します。
まとめ
- 最新版はBeta One:2025年5月11日にHugging Faceで公開されて以降、Beta TwoやJoyCaption 3は公開されていません(2026年7月31日時点)。
- VRAMはbf16で約17GB、nf4なら8GB:公式は24GB以上のGPUを推奨し、公式GUIのREADMEはnf4モード時の下限を8GBと明記しています。
- 4bit化は
llm_int8_skip_modulesが必須:視覚エンコーダ(SigLIP)まで量子化するとdtype不一致で落ちるため、vision_towerとmulti_modal_projectorを除外します。 - 出力の作り分けはモード指定で行う:公式GUIは12種類のキャプションタイプを持ち、Stable Diffusion用プロンプトやDanbooruタグも同じモデルで生成できます。
- GGUFで動かすならmmprojが要る:本体GGUFだけでは画像を読めず、Ollamaの公式インポート手順にはプロジェクタの指定がありません。
最短経路は、Beta Oneの重みをnf4で読み込み、llm_int8_skip_modules で視覚エンコーダを量子化から外す2点に集約されます。
JoyCaptionの最新版と開発の現在地
モデル構成:Llama 3.1 8BとSigLIP2を組み合わせたLLaVA型VLM
JoyCaptionはLLaVA形式のVisual Language Modelで、Hugging Faceのモデルカードには基盤モデルとして meta-llama/Llama-3.1-8B-Instruct と google/siglip2-so400m-patch14-384 の2つが記載されています。言語側がLlama 3.1の8Bモデル、視覚側がSigLIP2という構成です。パイプラインは image-text-to-text、ライブラリは transformers なので、Hugging Faceの標準的なコードでそのまま読み込めます。
開発者(fpgaminer氏)がREADMEに掲げる方針は、無料・オープンな重み配布、SFWとNSFWを等しく扱う無検閲設計、アニメからファーリーまでを含む多様性、学習データのフィルタリング最小化の4点です。画像生成モデルの学習用キャプションを作る目的から、表現を選ばずに記述できることが優先されています。
Beta Two・JoyCaption 3の公開状況(2026年7月31日時点)
検索では「joycaption beta two」「joycaption 3」といったクエリが出ますが、Hugging Faceのモデル一覧APIで作者アカウントを確認すると、JoyCaption系で最も新しいのは2025年5月11日作成の fancyfeast/llama-joycaption-beta-one-hf-llava(最終更新2025年5月16日、累計ダウンロード1,586,824件・直近30日で223,735件)です。それ以降に同アカウントから公開されているのは bigASP v3 や FLUX向けテキストエンコーダなど別系統のモデルで、JoyCaptionの新バージョンは存在しません。
GitHubリポジトリの最終コミットも2026年2月24日のデータセットリンク追加で、モデル更新を伴う動きは止まっています。新版を待つのではなく、Beta Oneを前提に環境を組むのが2026年7月時点の判断です。2024年10月公開のalpha twoは精度・モード数ともに旧版なので、選ぶ理由はありません。
ライセンスの読み方:コードはApache-2.0、重みはLlama 3.1の派生
GitHubリポジトリのLICENSEファイルはApache License 2.0です。一方、Hugging Faceのモデルカードにはライセンス欄の記載がなく、代わりに基盤モデルとして Llama-3.1-8B-Instruct が宣言されています。READMEの「no restrictions(制限なし)」という表現は開発者の配布方針を述べたもので、Llamaの派生物に課される条件まで消すものではありません。商用利用を検討する場合は、コード側のApache-2.0と、基盤モデル側のライセンス条件を分けて確認してください。
必要VRAMと精度の選び方
公式READMEは「bfloat16のネイティブ精度では約17GBのVRAMを必要とし、24GB以上のGPUで快適に動作する。軽量版が必要なら8bitまたは4bitに量子化できる」と明記しています。さらに公式GUIのREADMEでは、必要要件を「bf16精度で最低24GB VRAM(nf4量子化モードなら8GB)」と数値で示しています。8GBという下限はモデル本体の話であり、高解像度画像や大きなバッチサイズを扱えばこれを超えます。
| 精度 | VRAMの目安 | 追加要件 | 想定用途 |
|---|---|---|---|
| bf16(既定) | 約17GB・24GB以上を推奨 | なし | 品質最優先・バッチ処理 |
| 8bit | 公式に数値記載なし | bitsandbytes | 16GB級GPUでの妥協点 |
| nf4(4bit) | 8GBから | bitsandbytes | コンシューマGPUでの実行 |
| GGUF+mmproj | 量子化レベル次第 | mmproj対応ランタイム | 8GB未満・CPU併用 |
4bit量子化は精度と引き換えにメモリを削る手法で、公式ComfyUIノードのREADMEも「省メモリが必要なら8bitまたは4bit量子化を使えるが品質は劣化する」と断っています。数千枚を一括処理する前に、bf16で数十枚を処理した出力を基準に置き、nf4の劣化を許容できるか判断してください。低精度フォーマットの設計思想はFP8とは?8ビット浮動小数点フォーマットの基本とその仕組みで扱っており、量子化形式ごとの前提を押さえておくと選択の判断が速くなります。
4bit(NF4)でローカル実行する手順
前提となる環境とPythonバージョンの注意
必要なのはCUDA対応のNVIDIA GPU、PyTorch、transformers、そして量子化を使う場合の bitsandbytes です。公式GUIのREADMEでは bitsandbytes は「4bitおよび8bit量子化のためのオプション」として pip install bitsandbytes の一行で案内されています。同じくオプション扱いの Liger Kernel を入れると推論が速くなります。
注意したいのがPythonのバージョンです。公式GUIのREADMEは「Python 3.8+」と記載していますが、bitsandbytesの公式インストールドキュメントは要件を Python >= 3.10(Windows ARM64は3.12以上)としています。3.8系の環境を用意すると量子化まわりで詰まるため、3.10以上で組んでください。
Windowsについては、bitsandbytesがx86-64向けのホイールをpipで配布しているため、WSL2を用意しなくてもネイティブに動きます。同ドキュメントは対応環境を「NVIDIA GPU、AMD GPU、Intel XPU、Apple Silicon、Intel Gaudi」と明記しており、macOS arm64向けにもCPUバックエンドのビルドが提供されています。ただしApple Siliconでは実用的な生成速度を期待しにくく、後述するGGUF+mmprojのルートのほうが現実的です。
量子化設定:視覚エンコーダの除外指定
JoyCaptionをそのまま4bit化しようとすると RuntimeError: self and mat2 must have the same dtype, but got BFloat16 and Byte で停止します。これはSigLIP由来の視覚エンコーダをbitsandbytesが量子化したときに起きる問題で、開発者本人がGitHub issueで回避策を提示し、公式GUIのコードにもそのまま組み込まれています。コード中のコメントは「transformersのSiglip実装は量子化すると不具合が出るため除外する」と説明しています。
import torch
from transformers import AutoProcessor, LlavaForConditionalGeneration, BitsAndBytesConfig
MODEL_NAME = "fancyfeast/llama-joycaption-beta-one-hf-llava"
qnt_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
llm_int8_skip_modules=["vision_tower", "multi_modal_projector"],
)
processor = AutoProcessor.from_pretrained(MODEL_NAME)
model = LlavaForConditionalGeneration.from_pretrained(
MODEL_NAME,
device_map=0,
quantization_config=qnt_config,
torch_dtype="auto",
)
model.eval()
llm_int8_skip_modules は名前に int8 と付いていますが4bit時にも効き、指定したモジュールを量子化から除外します。視覚まわりのレイヤーだけを元の精度で残すため、削減できるメモリは言語モデル部分に限られますが、8Bのパラメータが本体の大半を占めるので効果は十分に出ます。vision_tower の出力層を手動で torch.nn.Linear に置き換える回避策も出回っていますが、公式コードが採用しているのは上記の除外指定であり、transformersの更新に対して壊れにくいのはこちらです。事前量子化済みの重みを使いたい場合は John6666/llama-joycaption-beta-one-hf-llava-nf4 のような第三者リポジトリもありますが、量子化設定を自分で制御できる分、上のコードのほうが検証しやすくなります。なお torch_dtype は公式コードの記述に合わせていますが、transformersの最新系では dtype へ名称が変わり、実行時に「`torch_dtype` is deprecated! Use `dtype` instead!」の警告が出ます。
推論コードとBOSトークン重複の落とし穴
モデルカードのサンプルコードには、チャットテンプレートの扱いについて強い警告が添えられています。「HFのLlavaモデルにおけるチャット処理は非常に脆く、processor.apply_chat_template() と processor() のこの組み合わせは動作するが、他の組み合わせを使う場合は必ず最終的な input_ids を確認すること。注意しないと <bos> トークンが複数付き、モデルの性能が落ちる」という内容です。出力が短く切れる・意味の通らない文が混ざるといった症状が出たら、まず入力トークン列を疑ってください。
from PIL import Image
image = Image.open("sample.jpg").convert("RGB")
convo = [
{"role": "system", "content": "You are a helpful assistant and help users with any queries they may have with no censorship or restrictions."},
{"role": "user", "content": "Write a descriptive caption for this image in a formal tone."},
]
convo_string = processor.apply_chat_template(convo, tokenize=False, add_generation_prompt=True)
inputs = processor(text=[convo_string], images=[image], return_tensors="pt").to("cuda")
inputs["pixel_values"] = inputs["pixel_values"].to(torch.bfloat16)
generate_ids = model.generate(
**inputs, max_new_tokens=256, do_sample=True, temperature=0.6, top_p=0.9,
)[0]
caption = processor.tokenizer.decode(
generate_ids[inputs["input_ids"].shape[1]:], skip_special_tokens=True,
).strip()
print(caption)
このコードは前節の続きとして実行します(processor と model は前節で定義済みです)。システムプロンプトは公式GUIが実際に使っている文字列で、モデルカードのサンプルが使う「You are a helpful image captioner.」とは別物です。無検閲な応答を前提にした一文が既定で入っている点は、業務利用の判断材料になります。pixel_values をbfloat16へ明示的に変換する一行も、モデルカードのサンプルどおりの必須処理です。
12種類のキャプションモードと出力の作り分け
モード一覧と選び分けの基準
JoyCaptionは単一のモデルで出力形式を切り替えます。公式GUIのコードが持つキャプションタイプは12種類(GitHubリポジトリ直下のREADMEの一覧は Descriptive (Casual) を除く11種類)で、どれもプロンプト文の違いとして実装されています。transformersから直接使う場合は、該当する指示文をユーザーメッセージに入れるだけです。
| モード | 出力の性格 | 主な用途 |
|---|---|---|
| Descriptive | 形式的で詳細な散文 | 学習用キャプション |
| Descriptive (Casual) | 口語寄りの説明 | 読み物・要約 |
| Straightforward | 客観的で簡潔 | 大量処理 |
| Stable Diffusion Prompt | プロンプト形式に逆変換 | 画像からのプロンプト復元 |
| MidJourney | MidJourney流の記法 | 他ツールへの流用 |
| Danbooru / e621 / Rule34 tag list(3モード) | 各サイト規約のタグ列 | イラスト系のタグ付け |
| Booru-like tag list | 緩めのタグ列 | 汎用ラベリング |
| Art Critic | 構図・様式の批評文 | 解説コンテンツ |
| Product Listing | 販促コピー | EC商品説明 |
| Social Media Post | 短い訴求文 | SNS投稿 |
Booru系のタグモードはアニメ・イラストを対象に調整されており、公式GUIのREADMEも実写や抽象画では精度が落ちると注意しています。写真素材にタグを付けたい場合はStraightforwardで説明文を得てから、別途タグ化する構成のほうが破綻しません。
画像からプロンプトを復元する場合の指定
「画像からプロンプトを抽出したい」という用途では Stable Diffusion Prompt モードを使います。生成された文字列はそのまま拡散モデルへ渡せる語順・記法になりますが、元画像を再現する保証はなく、あくまで構図・被写体・様式を言語化した近似です。生成側のモデルによって効くプロンプトの書式は変わるため、たとえば動画生成で使う場合はLTX-2.3の使い方・プロンプト設計・日本語対応とComfyUI導入をまとめた実践ガイドで扱っている記法に寄せる調整が要ります。
大量画像の一括処理:batch-caption.py
公式リポジトリの scripts/batch-caption.py は、フォルダ内の画像をまとめて処理して同じ場所に .txt として書き出すスクリプトです。すでにキャプションファイルがある画像は自動でスキップするため、中断・再開が前提の運用に向いています。既定モデルはBeta Oneが指定済みです。
./batch-caption.py \
--glob "path/to/images/*.jpg" \
--prompt "Write a descriptive caption for this image in a formal tone." \
--batch-size 4 --num-workers 4 --max-new-tokens 256
主要な既定値は --batch-size 1、--temperature 0.6、--top-p 0.9、--max-new-tokens 256、--num-workers 4 です。出力のぶれを抑えたい場合は --greedy でサンプリングを止めます。複数の指示文を重み付きで振り分けるJSONも指定でき、同じ画像群から表現の異なるキャプションを混在させられます。
実行環境の選択肢:ComfyUI・Gradio・GGUF・vLLM
公式ComfyUIノード:2ノード構成と量子化オプション
ComfyUIから使う場合は、開発者本人が公開している fpgaminer/joycaption_comfyui が第一候補です。JoyCaption(プリセット指定)とJoyCaption (Custom)(システムプロンプトとクエリを自由記述)の2ノードで構成され、画像を入力するとキャプションタイプ・長さ・追加オプションを選んで生成できます。モデルは LLavacheckpoints ディレクトリへ自動ダウンロードされ、8bit・4bit量子化のオプションも用意されています。GGUF対応やバッチ処理に強い第三者製ノードも複数ありますが、こちらは作者本人がメンテナンスしている実装です。Wan2.2とは?使い方・VRAM要件・ComfyUI導入を解説【2026年最新・後継Wan2.7まで】のような動画生成モデルと同一ワークフローに置く場合は、VRAMの配分を先に決めておく必要があります。
公式Gradioアプリ:精度切り替えとバッチZIP出力
単体で試すなら gradio-app/app.py が最短です。pip install -r requirements.txt 後に python app.py を実行し、表示されたURL(既定は127.0.0.1:7860)を開きます。画面上でbf16・8bit・nf4を切り替えられるので、量子化による出力差を同じ画像で比較できます。バッチ処理タブでは複数画像をまとめて処理し、結果をZIPで受け取れます。
GGUF+mmprojでの軽量実行
GGUF形式のJoyCaptionはコミュニティが公開しており、画像を扱うには本体GGUFに加えてmmproj(マルチモーダルプロジェクタ)のファイルが必要です。KoboldCpp向けの配布物は「KoboldCpp 1.91以降での利用を想定」と明記し、本体をText Model欄、mmprojをVision mmproj欄に指定する手順を示しています。llama.cppでは llama-mtmd-cli や llama-server が対応し、-m model.gguf --mmproj mmproj.gguf のように両方を渡します。本体GGUFだけを読み込むと画像入力の経路が存在しない、ただのテキストモデルになる点が最大の落とし穴です。
OllamaとLM Studioの対応状況
Ollamaの公式インポート手順では、GGUFの取り込みは FROM /path/to/file.gguf を書いた Modelfile を ollama create でビルドするだけの記述で、mmprojやビジョンプロジェクタを指定する項目がありません(アーキテクチャの列挙があるのはSafetensorsインポートの節で、こちらもLlama・Mistral・Gemma・Phi3のみです)。したがってJoyCaptionのGGUFを取り込んでも、画像を渡す経路は用意されません。Ollamaを軸にした構成についてはOllama Web Searchとは?使い方・APIの設定・料金とPython実装をわかりやすく解説で扱っていますが、画像キャプショニングに限ってはllama.cpp系のランタイムを直接使うか、transformersで動かすほうが確実です。LM Studioを使う場合も、本体GGUFと同じ場所にmmprojを置いてビジョンモデルとして認識させる構成になります。公式ドキュメントに手順の記載は見当たらず、ファイル名の付け方まで含めて認識条件が変わる報告もあるため、動作するモデルフォルダの構成を実機で確認してから運用に乗せてください。
スループット重視ならvLLM
大量の画像を継続的に処理するなら、OpenAI互換APIとして立てられるvLLMが選択肢になります。モデルカードが示すコマンドは次のとおりです。
vllm serve fancyfeast/llama-joycaption-beta-one-hf-llava \
--max-model-len 4096 --enable-prefix-caching
ただしモデルカード自身が「VLMはvLLM上で少々気難しく、vLLMはメモリを大量に消費するため、環境によってはeagerモードの強制、max-model-lenやgpu_memory_utilizationの調整が必要になる」と注意しています。起動しない場合はまず --max-model-len を下げ、それでも解決しなければeagerモードを試す順序で切り分けてください。
無検閲モデルを業務で使うときの線引き
JoyCaptionの無検閲設計は、学習用データセットを作る現場では利点になります。商用VLMは水着や暴力描写を含む画像で応答を拒否したり曖昧な表現に逃げたりするため、そうした画像が混ざるデータセットではキャプションの品質が場所によって崩れます。JoyCaptionはこの偏りが小さく、フィルタで抜けた分を人手で埋める作業が減ります。
一方で、そのまま顧客向けの機能に組み込むのは避けるべきです。既定のシステムプロンプトが「検閲や制限なしに回答する」という指示を含んでいる以上、入力画像しだいでは公開できない文言がそのまま返ります。エンドユーザーが任意の画像をアップロードできる導線に直結させると、出力の責任をモデル側の設計に負わせられません。社内のデータセット構築やカタログ整備のように、出力を人が確認してから次工程へ渡すバッチ処理に用途を限定するのが現実的な線引きです。
運用では、キャプション本文と一緒に生成条件を残しておくと、後から差し替えが要るときに再生成の範囲を特定できます。最低限、次の5項目をファイル単位で記録してください。
- モデルID(例:
fancyfeast/llama-joycaption-beta-one-hf-llava)とリビジョン - 精度・量子化設定(bf16/8bit/nf4、
llm_int8_skip_modulesの有無) - キャプションタイプと、実際に投げた指示文の全文
- 生成パラメータ(
temperature・top_p・max_new_tokens、または--greedy) - 生成日と、人による確認の有無
指示文の全文まで残す理由は、モード名だけでは再現できないためです。プリセット名は同じでもGUIとスクリプトでプロンプトが異なる場合があり、後日の追加分と表現が揃わなくなります。ローカル完結型の構成そのものの利点と制約はローカルLLMの活用事例|個人・業務での使い方とELYZAでの始め方で整理しています。
よくある質問
JoyCaptionのBeta TwoやJoyCaption 3は公開されていますか
2026年7月31日時点では公開されていません。検索候補に「beta two」「joycaption 3」が出るのは需要の表れであって、リリースの根拠ではありません。
手持ちのGPUではどの精度を選べばよいですか
24GB以上ならbf16をそのまま使えます。16GBはbf16の約17GBに届かないため8bit、12GBや8GBはnf4が基準です。8GBは公式GUIのREADMEが示すnf4モードの下限なので、画像解像度やバッチサイズを上げると超えます。6GB以下はnf4でも余裕がなく、GGUF+mmprojでより低いビット数を選びCPUオフロードを併用する構成に切り替えてください。
NSFW画像もキャプションできますか
できます。SFWとNSFWを等しく学習対象に含め、婉曲表現に置き換えずに記述することが設計目標に挙げられています。ただし出力の取り扱いは利用者側の責任です。業務で使う場合は前掲の線引きに従い、人の確認を挟む工程に限定するのが前提になります。
Ollamaで使えますか
公式のインポート手順に沿う限り、画像入力はできません。Ollamaのドキュメントが挙げるインポート対応アーキテクチャにビジョンプロジェクタの指定が含まれておらず、本体GGUFのみではテキストモデルとして読み込まれるためです。llama.cppの llama-server や llama-mtmd-cli、あるいはKoboldCpp 1.91以降であればmmprojを指定して画像を渡せます。
Hugging Face上のどのリポジトリを使えばよいですか
基準は fancyfeast/llama-joycaption-beta-one-hf-llava です。4bit化済みの重みやGGUF、FP8など派生リポジトリは多数ありますが、いずれも第三者による変換物で更新時期も作者とは無関係です。transformersで動かすなら、本家を読み込んで量子化設定を自分で与えるほうが再現性を保てます。量子化形式ごとの選び方はGemma 4とは|モデル一覧・必要スペック(VRAM)・量子化(GGUF/AWQ)・ローカル実行を解説【2026年版】でも整理しています。