生成AIの自作

AITool

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 8B8BMeta製日本語性能も良く、LoRA対応が容易
Mistral 7B7B軽量で高速。GPU24GBでLoRA可能
Gemma 2B / 7B2~7BGoogle製ライセンスが緩い
Phi-3 Mini3.8BMicrosoft製低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)
BACK