生成AIの自作
ChatGPTのような生成AIを自作する方法
① OpenAIやAnthropic等のクラウドAPIへプロンプトを投げる
【長所】すぐにつくれる
【短所】お金がかかる、カスタマイズできない
② オープンモデル(LIama系・Mistral系)に対して微調整(LoRA)を行い、特定の文体やキャラに合わせる
【長所】カスタマイズできる、クラウドAPIより安くつくれる
【短所】GPUが必要、学習コスト必要(※7B~13B程度の軽量モデルならGPU12GB前後で実用可能)
③ オープンモデルに対してRAG(追加学習データ)を読み込ませる
【長所】
④ 大規模モデルを時前で運用
【長所】
【短所】数十〜数百GBモデルを自前GPU群でホスト
ーーーーー
②、③にした
全体の流れ
① モデル選定(ベースとなる大規模言語モデルを選ぶ)
② データセット準備(学習データをJSON形式で整える)
③ LoRAで微調整(小さなGPUでも学習できるように軽量化する)
④ 推論環境構築(Python+Transformers / Text Generation WebUIといったモデルを読み込んで推論っせる)
⑤ ウェブアプリ化(ElectronなどでUIをつくる)
モデル選定
| モデル名 | パラメータ数 | 会社 | 特徴 |
| LIAMA 3 8B | 8B | Meta製 | 日本語性能も良く、LoRA対応が容易 |
| Mistral 7B | 7B | 軽量で高速。GPU24GBでLoRA可能 | |
| Gemma 2B / 7B | 2~7B | Google製 | ライセンスが緩い |
| Phi-3 Mini | 3.8B | Microsoft製 | 低VRAMでLoRA可能 |
開発PCがVRAM12~24GBならLiamaかMistralが現実的
インストール
# GPU/CPUでのモデル計算
pip install torch torchvision torchaudio
# Hugging Faceのモデル読み込み
pip install transformers
# JSONファイルの読み込み
pip install datasets
# LoRA微調整用
pip install peft
# GPU/CPU切り替え用
pip install accelerate
# LLaMA系で必要
pip install sentencepieceデータセット準備
LoRAに学習させるデータセットを準備する
# r18_dataset.json
[
{"prompt": "女の子が図書館で...", "completion": "彼女はそっと本をめくった..."},
{"prompt": "男子高校生が教室で...", "completion": "その瞬間、心臓がドキドキした..."}
]のようなJSONL形式もしくは、純粋なテキストファイルを用意
彼女は冷たい金属の指を握った。
「痛くないの?」と彼が聞いた。
「もう慣れたの」と少女は微笑んだ。LoRAによる微調整
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model, TaskType, PeftTrainer
model_name = "meta-llama/Llama-7B-hf"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto", load_in_8bit=True)
# LoRA設定
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj","v_proj"],
lora_dropout=0.05,
bias="none",
task_type=TaskType.CAUSAL_LM
)
model = get_peft_model(model, lora_config)
# 学習データ読み込み
# datasetsライブラリでJSON読み込み可能
from datasets import load_dataset
dataset = load_dataset("json", data_files="r18_dataset.json")["train"]
# 学習の準備
# CPUのみの場合はfp16=Trueをfp32にする
from transformers import TrainingArguments
training_args = TrainingArguments(
output_dir="./r18_lora",
per_device_train_batch_size=2,
num_train_epochs=3,
learning_rate=1e-4,
save_total_limit=2,
logging_steps=10,
fp16=True,
save_strategy="steps",
save_steps=100
)
trainer = PeftTrainer(
model=model,
train_dataset=dataset,
args=training_args,
tokenizer=tokenizer
)
trainer.train()
RAG(任意)
LoRAで微調整したモデルに加えて、外部R18テキストデータを参照させることにより、モデル自体を大きくせずに多様なシナリオ生成が可能
推論させてみる
# =========================
# 学習後にそのまま推論する
# =========================
# 推論用関数
def generate_r18_text(prompt, max_length=200, temperature=0.8, top_p=0.9):
"""
prompt: 生成したい文章の指示
max_length: 生成トークン数の最大値
temperature: 創造性
top_p: nucleus sampling
"""
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(
**inputs,
max_new_tokens=max_length,
temperature=temperature,
top_p=top_p,
do_sample=True,
pad_token_id=tokenizer.eos_token_id
)
text = tokenizer.decode(outputs[0], skip_special_tokens=True)
if text.startswith(prompt):
text = text[len(prompt):].strip()
return text
# =========================
# 学習後テスト生成
# =========================
if __name__ == "__main__":
test_prompt = "図書館でひとりの少女が本を読んでいる場面を描写してください。"
generated_text = generate_r18_text(test_prompt)
print("=== 生成結果 ===")
print(generated_text)