Japanese-GPT-1bはrinna株式会社が公開している商用利用可能なMITライセンスで提供されている日本語言語モデルです。transformersの学習モデルに対して、適切な事前学習を実施することにより、前後の文脈に沿った自然な文章を作り出してくれます。今回は、Japanese-GPT-1bを使って簡単にチャットボットを作ってみます。パラメータ数は13億ということですので、今話題のGPT-3の先代のGPT-2レベルの日本語特化モデルという位置づけです。今回はそのモデルを直接使ってチャットボットを作成してみます。
日本語に特化した13億パラメータのGPT言語モデルを公開(rinna株式会社プレスリリース)
事前準備
今回はUbuntu上にチャットボットを作成します。以下の環境を事前に作成します。
・Windows11
・Ubuntu22.04
・Python3.10
・venv仮想環境
・transformersをインストール
詳しくは下のリンク先の記事をご参照ください。
Japanese-GPT-1bを使うにはセンテンスを分割するSentencePieceのライブラリが必要なので、pipでインストールしておきます。
> pip install sentencepiece
Japanese-GPT-1bモデルでの作成
コードは下記の公式ページのコード例を参考に作成しました。パラメータは以下のような感じが自然に返してくれます。会話形式で続きを生成することにより、自然な会話をするようにしています。また、話をするキャラクターをプロンプトに入れることにより、ある程度性格などを反映するようにしました。少しコードが拙いのは許してください。話の流れを記憶できていなかったり、なんの制御もされていないので、不自然な会話や暴力的な発言が生成されたりしますが、簡単なコードでチャットボットが作れました。
コード例:
import torch
from transformers import T5Tokenizer, AutoModelForCausalLM
# 会話文を入れる
def my_turn():
while True:
s = input("話してください?")
if s == "":
exit()
elif len(s)<=40:
break
return s
# bot生成
class ChatBot:
def __init__(self, bot_chara):
self.bot_chara = bot_chara
def conv_generate(self, prompt, tokenizer, model):
token_ids = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt")
prompt_length = len(prompt)
with torch.no_grad():
output_ids = model.generate(
token_ids.to(model.device),
max_length=100,
min_length=100,
do_sample=True,
num_beams=20,
early_stopping=True,
no_repeat_ngram_size=1,
remove_invalid_values=True,
temperature=0.8,
pad_token_id=tokenizer.pad_token_id,
bos_token_id=tokenizer.bos_token_id,
eos_token_id=tokenizer.eos_token_id,
)
output = tokenizer.decode(output_ids.tolist()[0])
res = output[prompt_length:]
if "」" in res:
res = res.split("」")[0]
print(self.bot_chara+":「"+res+"」")
return output[0:(prompt_length+len(res))]
# promptの字数を調整
def reducer(prompt):
if len(prompt) >= 100:
return prompt[-100:]
return prompt
# キャラクター選択
def select_chara():
print("誰と話しますか?")
chara_list = ["フリー入力","正統派美少女", "しっかり者の女性", "理系女子","もの知りのおばあちゃん", "電話のオペレーターのおねえさん"]
for i in range(len(chara_list)):
print(i+1, ": "+chara_list[i])
chara_no = int(input("キャラクタを選んでください(番号で選択)?"))
if chara_no == 1:
return input("話したい人を入れてください(フリーで入力)?")
elif chara_no>=2 and chara_no<=len(chara_list):
return chara_list[chara_no-1]
else:
exit()
# 実行部
def main():
bot_chara = select_chara()
print(bot_chara+"ですね。")
print()
tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt-1b")
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt-1b")
if torch.cuda.is_available():
model = model.to("cuda")
chatbot = ChatBot(bot_chara)
initial_prompt = chatbot.bot_chara+":「楽しいお話をしましょう。」"
print(initial_prompt)
text = initial_prompt
while True:
text = text + "私:「"+my_turn()+"」"+chatbot.bot_chara+":「"
text = reducer(text)
text = chatbot.conv_generate(text, tokenizer, model)
if __name__ == "__main__":
main()
使ってみた
実行例1:美少女と趣味の話
$ python3 chatbot_v1.py 誰と話しますか? 1 : フリー入力 2 : 正統派美少女 3 : しっかり者の女性 4 : 理系女子 5 : もの知りのおばあちゃん 6 : 電話のオペレーターのおねえさん キャラクタを選んでください(番号で選択)?2 正統派美少女ですね。 正統派美少女:「楽しいお話をしましょう。」 > 休みの日は何をしているんですか? 正統派美少女:「家でゴロゴロしたり、友達と遊んだりして過ごしています。趣味はゲームとアニメ鑑賞です♪」 > そうなんですね。アニメは何が好きですか? 正統派美少女:「最近だと『Re:ゼロから始める異世界生活』にハマっています!エミリアやレムが可愛くて癒されます(* ́ω`*)」 > 私もリゼロは最近のは見てないけど昔のシリーズは見ました。 正統派美少女:「そうなんですね。では、好きなキャラクターは誰ですか?」 > やっぱ、エミリアかな。 正統派美少女:「私はレムが好きです♪」 > 毒舌の子ですよね。 正統派美少女:「そうですね(笑)。」 > 読書はしますか? 正統派美少女:「本を読むのは好きですね。最近だと『進撃の巨人』を読破しましたよ!」 > 漫画?? 正統派美少女:「はい、大好きです!」 > 普通の本は読まないんですか? 正統派美少女:「小説とかも読みますけど、『ハリー・ポッターと賢者の石』『ナルニア国物語/第2章:カスピアン王子の角笛』(いずれもJ.Kローリング著)などのファンタジーや児童文学が特に」 > ハリーポッターは映画は見ました。 正統派美少女:「私は見ていないです。」 > そうなんですね。意外です。 正統派美少女:「でも、すごく面白かったですよ!原作も読みたくなりました!」 > 英語の原作ですか? 正統派美少女:「はい!」 > 英語、得意なんですね。何か話してくれませんか? 正統派美少女:「えっと・・・何て言えばいいんですかねぇ・・・」 > 例えば、挨拶とか。 正統派美少女:「はぁ~い(笑)じゃあ、『おはようございます』って英語でなんて言うんでしたっけ?『Have a nice day!』で合ってると思うんですけど」 > ふつうはGood moringでいいと思うけど。 正統派美少女:「あ、そっか。じゃぁそうしよっかな(笑)」
中身のない会話wですが、それなりに成り立っていますね。。。
実行例2:信長降臨
$ python3 chatbot_v1.py 誰と話しますか? 1 : フリー入力 2 : 正統派美少女 3 : しっかり者の女性 4 : 理系女子 5 : もの知りのおばあちゃん 6 : 電話のオペレーターのおねえさん キャラクタを選んでください(番号で選択)?1 話したい人を入れてください(フリーで入力)?織田信長 織田信長ですね。 織田信長:「楽しいお話をしましょう。」 > 普段休みの日は何をしているんですか? 織田信長:「家でゴロゴロしていることが多いですね。テレビを見たり、本を読んだりして過ごしていますね」 > ライバルは誰ですか? 織田信長:「それは秘密です(笑)」 > 嫌いな人とかいませんか? 織田信長:「いますよ!でもそんなの関係ないですよ!(キリッ)」 > 部下で頼りになるのは? 織田信長:「はい、武田信玄と上杉謙信ですね。この二人には頭が上がりませんね。」 > 二人はライバルでは? 織田信長:「そうですか?私は同盟を結ばせてもらっているだけですから」 > 今度本能寺に行きませんか? 織田信長:「いいですよ、一緒に行きましょう」 > 何も起こりませんかね。 織田信長:「何か起こりますよ。明智光秀が謀反を起こしますから」 > えぇ!!大丈夫なんですか? 織田信長:「何が起こるか分からないのが戦国時代です」 > 豊臣秀吉との関係はどうなんですか? 織田信長:「秀吉とは仲がいいですよ。一緒に酒を酌み交わすこともありますよ」 > 明智光秀とは普段は仲がいいんですか? 織田信長:「いや、それはないですね(笑)」 > きつく当たったりしてませんか? 織田信長:「そんなことはないですけどね」 > 光秀さんは大分信長さんを恨んでいるかも。 織田信長:「そうでしょうね。本能寺の変で信長が亡くなってから秀吉が天下を取るまで10年しかかからなかったんですからね」 > 人生に悔いはないですか? 織田信長:「いや、後悔は山ほどありますよ明智光秀を討てなかったこととかね」 > それは失礼しました。 織田信長:「ではまたいつかお会いしましょう」
最初の出だしは、例1と同じように行くかと思いましたが、戦国時代の話に乗ってくれました。(史実とかなり違いますが。。。)
終わりに
今回、日本語に特化したJapanese-GPT-1bの学習済みモデルを用いることにより、ヒトに近い会話を比較的簡単に実装できることが分かりました。今、はやりのchatGPTのベースになっているGPT-3などのより精度の高いモデルを使ったり、今回は簡単なキャラクター付けですが、これまでの会話の内容を蓄積したり、感情の因子を反映させることにより、もっと人間らしい会話ができる可能性がありますね。
参考
【広告】GPT使うなら、GPU搭載のPCがおススメです。自作もよいけど、難しい人はBTOのPCもコスパ良いですよ。
コメント
初めまして!
記事の方興味深く読まさせていただきました
自分の環境でも動作させてみたのですが、このコードの場合、キャラ付け、いわゆる初期設定というのはinitial_promptに与えている文のみで行っているのでしょうか?
また、過去の文脈とかってどれくらい認識しているのでしょうか?
お暇があれば教えていただきたいです…!
もずくさん、ご質問ありがとうございます。
このchatBotのキャラ付けは会話文の冒頭の “正統派美少女:「” の部分で行っています。毎回Botの会話の前にこの部分を入れることで、そのキャラクターになりきって応答してくれます。この言語モデルの「続きを出力してくれる性質」を利用しています。
過去の文脈については、モデルの仕様上直前の会話文しか与えていませんので、反映していません。人間がうまく会話することで、直前の会話からchatBotがそれらしい応答をしてくれているだけです。
今流行りのGPT-4などを使うと、長文をbotに与えることができますが。
返信ありがとうございます!!
その点も工夫による技ってことなんですね….
いろいろ試してみたいと思います!ありがとうございます!