👱‍♀️

生成AIモデルrinnaをFineTuningしてデモを公開するまでやってみた

2023/10/10に公開

はじめに

生成AIパスポートの試験が無事終わりました!結果は2ヶ月後なのでゆっくりと結果を待つことにします。
https://zenn.dev/yasuna/articles/8bfd5d680bfa78

せっかく生成AIや機械学習を勉強をしたので、実際にローカルでモデルを動かしてみたり、公開されているモデルをデータセットでトレーニングして自作モデルを作ってみたくなりました。

しかし手持ちのiMacは生成AIを開発することに向いておらず、あまり大規模なことはできません。
でもどうしてもやってみたいので、モデルをファインチューニングして自作モデルを作り公開するまでの流れをやってみることにしました!

実行環境

やってみた感想としては、

・最小サイズのモデルを選んだのは大正解だった
・選んだテキスト生成モデルに合う形でデータセットを作ってファインチューニングをするのが難しかった
・自作モデルを公開してデモを作るのは本当に一瞬でできて驚き!

って感じでした。

では、公開されているモデルをファインチューニングしてデモを公開するまでの流れをご紹介していきます!

ゴールはビジネス向けのテキスト生成AIを作ってデモアプリを公開する!

まずは何を作りたいのかゴールを設定します。今回はテキスト生成のモデルのRinnaの最小サイズをビジネス向けにチューニングしたBotを作ってみます。

今回使ったrinnaモデルはこちら
https://huggingface.co/rinna/japanese-gpt2-xsmall
rinnaはMITライセンスなので商用利用も可能です!

モデルをローカルでファインチューニング

csvファイルに用意した100個程度のビジネスについてのQAデータセットをモデルに読み込ませてファインチューニングをしていきます。
最小でやってみるためデータ数は少ないですが、自作モデルを作る流れを知るためこのまま進めていきます。

コードは全てChatGPTに書いてもらいました。
トライアンドエラーを繰り返していい感じのコードが出来上がりました。

training.py
from transformers import Trainer, TrainingArguments
from transformers import AutoTokenizer, AutoModelForCausalLM
import pandas as pd
from datasets import Dataset

# まず、トークナイザーをロードします。この例では "rinna/japanese-gpt2-xsmall"を使用します
tokenizer = AutoTokenizer.from_pretrained("rinna/japanese-gpt2-xsmall")

# CSVファイルからデータを読み込みます。
data = pd.read_csv('data.csv')

# pandasのDataFrameからHugging Faceのデータセットに変換します。
dataset = Dataset.from_pandas(data)

def add_prompt_and_format(example):
    example = f"入力:\n{example['input']}\n\n出力:\n{example['output']}"
    example = example.replace("\n", "<NL>")
    # input and output tokens need to match for causal language models
    encoded_example = tokenizer.encode_plus(
                            example,
                            truncation=True,
                            max_length=512,  # ここで最大長を指定します。必要に応じて調整してください
                            padding='max_length',
                            )
    return {"input_ids": encoded_example['input_ids'], 
            "attention_mask": encoded_example['attention_mask'], 
            "labels": encoded_example['input_ids']}  # MLMモデルのため、入力のIDをそのままラベルとして利用します

# 固定プロンプトを追加する
fixed_prompt = "あなたは優秀なビジネスマンです。以下、部下にアドバイスを送ってください。: \n\n"     
dataset = dataset.map(lambda example: {"input": fixed_prompt + ''.join(example["input"])})
tokenized_dataset = dataset.map(add_prompt_and_format)

# "rinna/japanese-gpt2-xsmall"モデルを読み込みます。
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt2-xsmall")

# トレーナーを設定します。
training_args = TrainingArguments(output_dir="trainer", num_train_epochs=1, per_device_train_batch_size=1, gradient_accumulation_steps=2)
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset,
)

# 学習を開始します。
trainer.train()

# 学習したモデルを保存します。
trainer.save_model("my_model_directory")

実行が終わったらディレクトリの中に「my_model_directory」という自作モデルが誕生します!

できた自作モデルをローカルで試してみる

自作モデルができたらinputから推論してもらいましょう!
以下もChatGPTでいい感じにコードを書いてもらいました。

inference.py
from transformers import AutoTokenizer, AutoModelForCausalLM

# モデルとトークナイザーをロードします
model = AutoModelForCausalLM.from_pretrained("my_model_directory")
tokenizer = AutoTokenizer.from_pretrained("my_model_directory")

# 入力テキスト
text = "どうしたら仕事が早くできるようになりますか?"

# 入力テキストをトークナイズします
inputs = tokenizer.encode(text, return_tensors='pt')

# 予測を生成します
outputs = model.generate(inputs, max_length=300, temperature=0.9, do_sample=True)

# 予測をデコード(トークンをテキストに戻す)します
predicted_text = tokenizer.decode(outputs[0], skip_special_tokens=True)

print(predicted_text)

HuggingFaceにモデルを公開

モデルのテストが終わったら、HuggingFaceHub上にモデルをアップロードして公開します。

以下にドキュメントがあります
https://huggingface.co/docs/hub/index

ローカルで自作モデルをコミットしてHuggingFaceにプッシュしていきます。
Gitの基本知識があれば、めちゃくちゃ簡単にできます。
以下にくわしい手順がありますのでよろしければどうぞ!
https://huggingface.co/learn/nlp-course/ja/chapter4/3?fw=tf
あっという間にモデルのアップロードが完了しました!
今回作ったモデルはこちらです。
https://huggingface.co/yasunamiura/mr-ja

次に、アップロードしたモデルを使ってデモアプリを作っていきます。

HuggingFaceSpacesでモデルのデモを公開

HuggingFaceにあるモデルを使って簡単にデモ作って公開することができます。
以下、さまざまなアプリを試すことができるのでぜひ覗いてみてくださいね。
https://huggingface.co/spaces

さて、先ほど作った自作モデルを使って、Spaces上にデモページを簡単に作っていきましょう。
作るファイルはアプリの元となるapp.pyとライブラリをまとめたrequirements.txt2つです。

app.py
# transformersとtorch、Gradioをインポート
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import gradio as gr

# トークナイザーとモデルをロードする
tokenizer = AutoTokenizer.from_pretrained("yasunamiura/mr-ja")
model = AutoModelForCausalLM.from_pretrained("yasunamiura/mr-ja")

# txt入力を受け取り、それを使用して新しいtxtを生成する関数
def generate(prompt):
    # 入力テキストをトークナイズ
    inputs = tokenizer.encode(prompt, return_tensors='pt')
    # トークナイズされたテキストを使用して新しいテキストを生成
    outputs = model.generate(inputs, max_length=300, temperature=1.0, top_k=50, top_p=0.95, do_sample=True)
    # 生成されたテキストをデコード
    predicted_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
    # デコードされたテキストを関数から返す
    return predicted_text

# Gradio UIを作成
iface = gr.Interface(
    # 上記で定義したテキスト生成関数を使用
    generate, 
    # 入力としてテキストボックスを使用
    inputs = gr.Textbox(label = "Input a question", default = "質問してください"), 
    # 出力はテキスト形式
    outputs="text", 
    # UIのタイトル設定
    title = "Mr Bot🤖")

# Gradio UIを起動
iface.launch()
requirements.txt
tensorflow
transformers
torch
sentencepiece

たったこれだけのコードでアプリはできています。本当に簡単です。

今回は「MrBot」という名前でテキスト生成AIのデモアプリを公開しました。
https://huggingface.co/spaces/yasunamiura/mr-bot
デモを動かすためのCPUサイズを無料枠の最小サイズにしているため料金はかかりません。

では、早速デモアプリを試してみましょう。

おや??意外と育児中の私に向けたアドバイスになってて偶然ですが嬉しいですね(笑)
自作モデルの作成から公開まで3日でできました!これはかなり面白いです!

まとめ

今回はrinnaモデルをファインチューニングして自作モデルを作り、デモアプリを公開するまでを書いてみました!

正直データ数が全然足りなくてファインチューニングというよりは、Inputに固定プロンプトを入れたことのほうが効果があったような気がします(笑)
もっと生成AIを極めていくために、つよつよなWindowsPCが欲しくなりました。

自作モデル作成からアプリ公開までできて嬉しかったので、これからも学習を進めていきます!

GitHubで編集を提案

Discussion