Frqux’s AI laboratory

AIの技術が進化する今日

Windows11のWSL2でDocker環境を構築する(Docker Desktop)

目次


対象の読者

  • WSLやLinuxの知識がない方
  • Dockerの環境をWindowsPCに作りたい方


 最近は、生成AIを使うためにDockerを導入する方が増えてきてるので、誰にでも分かるようにできるだけ丁寧に説明します。

 筆者の環境としては、PC買いたての何も入っていない状態ですので、今回初めてWSLやDockerに触れる方と似た環境だと思います。




WSLの有効化


 まず、WSLの有効化を行います。

 これをしないと、Windows上でLinuxを扱えません。


1.検索窓に、「Windowsの機能の有効化または無効化」と入力

検索窓での検索結果例


 ここで、おそらく最上部に表示される「Windowsの機能の有効化または無効化」を押します。


2.WSLを有効化

 1を実行すると、以下のようなウィンドウが表示されると思います。

Windowsの機能の有効化または無効化

 ここで、「LinuxWindows サブシステム」にチェックを入れてください。

LinuxWindows サブシステム にチェックを入れる


3.Hyper-V仮想マシンプラットフォーム)を有効化する

 2と同様のウィンドウで、「仮想マシンプラットフォーム」も有効化するためにチェックを入れておきましょう。

仮想マシン プラットフォーム を有効化

 この機能は、Dockerを使うために必要です。
 WSLを使うだけであれば必要ありません。

 これで、右下の『OK』を押してください。

 すると、必要なファイルの検索を自動で行ってくれます。


 しばらくすると、以下のような画面になるので、再起動を行ってください。

Windowsの機能の有効化完了


Ubuntuの導入

 Ubuntuは、OSの一種で、Linuxの派生OSです。

 WSLを有効化したことによって、Windows上でLinuxを動かせるようになったので、使えるようになります。

 Ubuntuの詳しい説明は省きますが、新しいOSをPCに入れると思ってください。

 「新しいOSなんか入れて大丈夫なの?」と思う方がいるかもしれませんが、今入っているWindowsOSに影響はないので、安心して入れてくださいね。


 Ubuntuは、今回はMicrosoft Storeを使って入れます。

 Microsoft Storeで『Ubuntu』と検索すると、Ubuntuが検索結果に出てくるので、Ubuntuをインストールしてください。

1.『Ubuntu』検索結果

 ここで、『Ubuntu 22.04.3 LTS』や、『Ubuntu 20.04.6 LTS』などUbuntuがたくさん出てきますが、今回はただの『Ubuntu』をインストールします。

 これらは、バージョンの違いで、数値が小さいほど古いバージョンになっています。

 必ずしも新しいバージョンでいいわけではないので、使用用途に沿ってバージョンを決めるようにしましょう。バージョンによって、
 今回は『Ubuntu』で大丈夫なので、これをインストールしましょう。

 今後、別バージョンを使うとなっても、簡単に切り替えれるので安心してください。

2.『Ubuntu』インストール


 インストールが完了すると、『入手』が『開く』に変わるので、『開く』を押して、Ubuntuを起動しましょう。

 すると、以下のような画面になります。

Ubuntu 初回起動画面(Linuxカーネルなし)


 これは、Linux カーネルが入っていない場合に表示される画面です。
 初めてWSLを使うなら、ほぼ必ずこの画面になると思いますが、もしLinuxカーネルがすでに入っていた場合は、この画面にならずにインストール作業に入るので、次の章は飛ばしてください。


Linuxカーネルの導入

 先ほどの表示画面に記載されているURLにアクセスすれば、Linuxカーネルのダウンロードページに移動しますので、そこからダウンロードします。

 わからない方は、以下のURLからページに飛んでください。

Manual installation steps for older versions of WSL | Microsoft Learn

 Microsoftのページに飛びましたら、赤丸で囲んでいるところをクリックして、ダウンロードしてください。

Linuxカーネルページ

 その後、『wsl_update_x64.msi』というファイルがダウンロードされるので、実行しましょう。

 すると、以下のようなかわいいペンギンが書いてある画面が出るので、『NEXT』をクリックします。
 ちなみに、このペンギンの名前は"タックス"というらしいです。
 これからお世話になるので、覚えてあげておきましょう。

カーネル更新1

 すると、Windows側で実行の許可について聞かれるので、許可してください。

 すると、数秒で更新が終了し、以下の画面になるので、『Finish』を押して終了してください。

カーネル更新2

 これで、Ubuntuが正常に起動するようになりますので、設定に移っていきましょう。


Ubuntuの初期設定

  Linuxカーネルを更新した後Ubuntuを起動すると、以下の画面になります。

Ubuntu

 インストールが完了すると、以下のようにユーザーネームの設定を促されますので、お好きな名前を入力して、Enterを押して決定してください。

Ubuntu

 次にパスワードの設定を促されますので、お好きなパスワードを設定してください。

 確認のための入力と、合わせて2回パスワードの入力を求められるため、2回とも同じパスワードを入力してください。
 この時、パスワードは入力中でも画面に表示されることはありません。ご注意ください。

Ubuntu

 その後、以下のような画面になれば設定完了になります。

Ubuntu

 これでUbuntuのインストール・設定作業は終わりです。


Docker Desktopのインストール

 次は、Docker Desktopのインストールです。

 Docker Desktopは、現在Dockerを使う際に推奨されているソフトウェアで、様々な機能や状態の管理がGUI上で行える便利なソフトウェアです。

 ではまず、Docker Desktopのインストーラーをダウンロードしてきましょう。

 以下のURLから、Docker DesktopのWebサイトに飛んで、インストーラーをダウンロードしてください。

www.docker.com

Docker Desktop Webページ

 『Download for Windows』ボタンにカーソルを合わせると、以下のように『Download for Linux』や『Download for Mac』など色々出ますが、『Download for Windows』からインストーラーをダウンロードしてください。

Docker Dektop Webページ

 すると、『Docker Desktop Installer.exe』というファイルがダウンロードされるので実行しましょう。この時、ユーザーアカウント制御の許可を求められるので許可しましょう。

 すると、デスクトップショートカットを作成するか聞かれるので、必要であればチェックのまま右下の『OK』を押してください。PC操作に慣れていない方であれば、ショートカットは作成したほうがいいでしょう。

Docker Desktop Installer

 『OK』を押すと、下の画像のようにインストールが始まりますので、しばらく待ちましょう。

Docker Desktop Installer

 数分後完了すると思うので、以下の画面になったら『Close and log out』を押しましょう。
 ※ このボタンを押すと、いったんWindowsでサインインしているユーザーからログアウトされるので、何か作業中であればそれが終わってから押すようにしましょう。

Docker Desktop Installer


Docker Desktopの初回設定

 ログアウト後ログインするか、もしくは再起動後に以下の画面が出るので、『Accept』を押してください。

Docker Desktop 初回起動画面

 すると、ウィンドウが閉じて、次のようなウィンドウが立ち上がります。

Docker Desktop 初回起動 設定

 ここでは、上の『Use recommended Settings (require administrator password)』にチェックを入れたまま、『Finish』を押してください。

 これは、Docker Desktopでおすすめ設定を使うか、手動で設定を行うかの違いで、知識がある方や特定のタスクにて設定を特化させる場合は下の『Use advanced settings』のほうにチェックを入れて、ご自身で設定を行ってください。

 とりあえずDocker Desktopを使いたい方や、今は特に何にDockerを使うか考えていない方は、上の『Use recommended Settings (require administrator password)』にチェックを入れることで、おすすめ設定でを自動で設定してくれます。

 この『Finish』を押すと、ユーザーアカウント制御の許可を求められるので、『許可』するようにお願いします。

 その後、ログイン画面が出るかと思いますが、アカウントを作成・ログインしなくてもDockerは使えるので、ログインしなくてもよいです。
 今回は、『continue without signing in』を押してログインせずに進めます。

  • アカウントを作る場合 ... 緑色の丸で囲った部分をクリック
  • すでにアカウントを持っていて、ログインする場合 ... 黄色の丸で囲った部分をクリック
  • ログインせずに始める場合 ... 赤色の丸で囲った部分をクリック
Docker Desktop ログイン画面

 アカウントを作ってログインしておくと、Docker Hubを使うことができるようになります。

 Docker Hubは、様々な仮想環境設定が配布されているプラットフォームです。

 Docker Hubを使うことで、自分で環境設定を考えなくても、既にほかの人がその環境用に仮想環境を作って配布してくれていれば、それをDocker Hubからダウンロードして使うことができます。

 例えば、AIの学習の環境を構築したい場合、「OSは何にするか」「AI開発を行うフレームワークはどうするか」「PythonJavaのバージョンは何にするか」「ライブラリには何を使うか・バージョンは何のものを使うか」などなど設定しなければいけません。

 しかし、Docker Hubを使えば有識者がすでに設定を行い、その環境設定を配布しています。

 AI開発環境でいえば、Pytorchフレームワーク開発元の『Pytorch』が、Pytorchのおすすめ環境設定を配布していますし、Tensorflowフレームワークも同様に公式が環境設定を配布しています。ほかにもNVIDIA社の開発環境であったりなどが数多く配布しているので、実際に企業が開発で使っている環境と同じ環境で開発を行うことができたりします。

 以上が簡単なDocker Hubの説明でした。


 ログインしなくても、後からログインしたりアカウントを作ることができますので、最初はログインなしでもいいかもしれません。

 次に、あなたの役職を選択する画面に移るので、ご自身の役職を選んでください。
 アンケートのようなもので、答えなくても大丈夫なので、答えたくない方は下部の『Skip survey』から次の画面に移りましょう。

役職選択画面

 次は、Dokcerの使用理由について聞かれているので、あてはまるものを選択、もしくは『Skip survey』を押してスキップしましょう。

Docker 使用理由選択画面

 『Continue』を押すと、初回設定完了となり、Docker Desktopのコンテナ表示画面に移ります。

Docker Desktop コンテナ表示画面


WSLのUbuntuからDockerを使えるようにする

 次は、UbuntuからDockerを扱うための設定を行います。


1.まず、右上の歯車(⚙)マークから、設定画面に飛びます。

歯車マークをクリック

2.『Resources』タブをクリックします。

『Resources』タブをクリック

3.『WSL integration』をクリックして、『Ubuntu』を有効にする。

 有効化する場合は、赤丸の部分のスイッチボタンをクリックすれば有効になります。

WSL integration OFF状態

 有効になった(スイッチが青色になった)あと、右下の『Apply & restart』をクリックして終了します。

WSL integration ON状態


 これで、UbuntuからDockerを使えるようにする設定は完了です。


使えるようになっているか確認

 では、Ubuntuを開いて、Dockerが使えるようになっているか確認してみましょう。

 Ubuntuコマンドラインにて『docker』と入力して実行してみましょう。

 すると、以下のような、Dockerのコマンドヘルプが表示されると思います。
 これが表示されれば、Dockerが使えるということになります。

Docker command help


おわりに

 これで、設定は終わりです。

 お疲れさまでした。


 Dockerは簡単に環境構築ができるので、使う方は頻繁に使うものになると思います。

 ほかにも、仮想環境を作るソフトウェアとしては、『VMware』や『VirtualBox』などがあります。

 それぞれに特徴があるのですが、私の場合、WindowsXPなどの古いOSでの開発やWindowsGUI上で開発を行いたい場合は『VMware』で、コマンドラインで完結できる開発(AI開発など)は『Docker』で行うようにしています。『VirtualBox』は使ったことがないです。


 皆さんも、いろんな環境を作ってみて、楽しく開発していきましょう。

 最後まで読んでいただきありがとうございました。

 Dockerを使って、生成AIを使う環境構築を説明している記事もアップしているので、別の記事も是非読んでいってください。


 お疲れさまでした。

AIの可能性を探る ~ AI研究を進めて感じたAIの可能性 ~

目次



はじめに

 こんにちは。ふらうと申します。

 今年2月まで、大学院でAIの研究をしておりまして、現在システムエンジニアとして企業に就職いたしました。

 これまでAIの研究をしていた中で感じたことを、皆様と共有したいと思い、本記事を書いております。


AI研究・開発上の問題点

 まずAIについて、皆様が思うことは、著作権侵害や悪用についてでしょう。GoogleやYahooのニュース、X(旧Twitter)などのSNSでは、生成AIの学習材料にてアーティストの著作物(写真・絵・音声など...)の無断使用が問題視されています。


 また、ディープフェイク技術を用いた悪用なども近年報告が増えています。


 これらの問題は、これからも議論が必要な問題でありますし、早急な問題解決が必要です。

 その中でAI研究に携わっている方々も、この問題を深刻に受け止めていることも理解していただきたいと思います。



 実際、AIを開発する上で学習材料となるデータの詳細な提示・AIの利用目的などについて倫理審査を行う必要があります。

 例えば、病院の医療データを学習させるのであれば

  • 学習データに何を使うのか
  • 許可は取れているのか
  • 加工後のデータはどうなっているのか
  • 個人情報は守られているのか
  • etc...

 など、データを提供している医療機関の倫理審査に通る必要があります。


 また、医療の場合は個人情報の塊ですから、個人が特定できる可能性が少しでもあるデータが混ざっていた場合は修正が必要であり、情報部門の方と確認しながら学習材料を選定していきます。


 他にも、様々な協議を重ねてようやく開発に着手することができるようになります。このように、AI開発・研究に携わる人もこういった問題に敏感であることが分かると思います。中にはデータの収集・選定だけで、未だに研究に着手できていないところもあります。



 日本の法律が、AIの登場を想定して作られていないためにこのような問題があるのだと感じるので、今後も改善が必要であることは確かです。

 だからと言って、AI開発を中止することはあってはならないと考えています。この問題は少し複雑ですので、時間はかかるかと思いますが、技術の発展のためにも頑張りたいですね。



 ここで正直な自分の意見を言いたいです。




 反対意見もあると思いますが、一人間として考えを綴ります。


 画像生成のAIは、絵を生成してくれます。

 もちろん、絵を生成するには学習材料が必要です。

 学習材料にもいろいろありますが、写真・イラスト・数値データ(イラストデータの近似データ等)などがあります。


 人間も絵を書くときは、学習材料が必要です。

 人間も、自分の目に映った風景や人間、デザイン集やネットに公開されている他人のイラストを自分の目で見て、模写したりして上達していくはずです。

 分かりましたか?

 人間もAIと同じく学習材料として、多くの著作物を頭にインプットしているんです。


 しかし今の世の中では、AIにはそれが許されていません。

 しかしAIには学習材料が必要です。なぜなら、ニューラルネットワークなど今のAIの仕組みそのものが人間の脳を模して考えられ、作られているからです。

 人間は他人の著作物を模写して、勉強して上達した画力で、新しいシチュエーションの絵を書いて販売することが許されています。

 AIも、著作物の特徴をつかませて、違うシチュエーションの絵を書かせることができます。

 しかし人間が、そうさせません。
 生成AIを利用する人間が悪意のある使い方をするためです。学習材料にしたアーティストに成りすまして絵を売るのも、特定の人間を学習させて悪意のある生成物を作るのも人間なんです。


 力のあるAIが人間に悪意のあるやり方で操られて、AIが批判を受ける。


 ちょっと納得できないです。
 

 AIが学習材料に、歩きながら撮影した写真を使うのも問題になるでしょう。写真に写る人間・建物・風景、それらすべてにおいて、写真に偶然映ったものに対して「AIが〇〇(建物名)を学習材料にしている!」「AIが〇〇(町名)を学習材料にしている!」と叫ぶ人が出てきます。


 この問題はAI開発側だけの問題ではないように思いませんか。

 

 はい。個人的な意見でした。


AIが仕事を奪う

 これは確かにあると思います。
 というか、AI自体がそういうコンセプトで作っているのだと感じています。


 人間がやるには、ヒューマンエラーが多すぎて一生問題が解決しないような仕事があります。

 こういった仕事はAIに置き換わるべきなのです。


 人間が作る機械というのは、昔からそうなんです。


「自分でやるのが面倒だから機械にやらせる」

「人間ができないから機械にやらせる」


 人間がやっている仕事を置き換えるために、技術は発展しているんです。


 AIが人間の仕事を奪うのではないです。

 人間がAIに仕事を奪ってもらってるんです。



 技術の発展はそういうものだと私は考えております。


AIの可能性

 AIには可能性があります。

 この人間社会を、良くも悪くも大きく変える力を持っています。


 AIの発展には夢があるんです。

 私と同じオタク気質の方は、一度は夢見たことないですか?


「ゲーム・アニメの中に入ってみたい。」

「ゲーム・アニメのキャラクターと話してみたい。」


 できるんです。AIなら。


 あの頃考えた夢物語が現実にできるんです。


 これに限らず、人間が見つけられなかった医療の問題を見つけて、不治の病も直せるようになるかもしれないんです。

 過労死する人間を救えるかもしれないんです。

 
 AIは、今の人間に絶対必要な技術だと私は考えてます。

 
 だから、AIの可能性を信じて、これからもAIについて学ぶ姿勢は続けていくつもりです。


おわりに

 昨今のAI開発は、確かに問題だらけです。

 しかし、無くなってはいけない技術だと考えています。

 悪事を働く人間には、何を言っても無駄です。

 人間を変えることが不可能なら、AIのほうを変えなければいけないというのが世の中の意見だと、私は勝手に解釈してます。


 善良な人間を操って悪事を働く人間がいる以上、AIをどれだけ改良しても、悪用がなくなることはない気がします。

 だからと言って、無視していい問題でもないですし、少しでも変えていかなければいけないのは確かです。


 様々な意見があると思いますが、今回は自分の考えを記事にさせていただきました。


 間違った意見なんて存在しないので、皆さんも自分の考えを大切にしてください。


 それでは、最後まで閲覧いただきありがとうございました。

 今後とも、AIに関することをマイペースで記事にして記録していきたいと思っておりますので、よろしくお願いします。

Azure OpenAI APIを使ったLangChain使用方法

目次

LangChainって何?

 LangChainはプロンプトエンジニアリングのサポートをするライブラリです。


 おそらくこの記事を見ている方は既に知っていると思うので、詳しい説明は割愛します。

 「いや知らないよ!」という方は、後に別記事で説明記事を投稿するのでそちらへ飛ぶか、ググるだけでもわかりやすく説明してくれている方が多くいるので、そちらの記事に目を通してきてくださると、理解しながらこの記事を見れると思います。


 LangChainを使う目的としては以下のようなことが挙げられると思います。

  • 自社のデータを参照してGPTに回答させたい。(Retrieval)
  • GPTの回答を自動で解析してもらいたい。(Chains)(Agents)
  • GPTに計算知識を与えたい。(Agents)
  • 質問によって使うモデルを切り替えたい。(Models)

  などなど...

 このような問題を解決するべく生まれたのがLangChainです。


Azure OpenAIって何?

 この記事を見ている方なら知っているうえでたどり着いたのだと思うので、ここでも詳しい説明は割愛いたします。

 簡単に言うと、GPT-3.5やGPT-4はOpenAIのほかにMicrosoftにも提供を行っています。
 現在この2社のみがGPTのAPIを公開するサービスを持っています。

 そのMicrosoftがGPTを提供するために始まったサービスが、Azure OpenAIです。


 じゃあOpenAIのAPIとAzureのGPTは何が違うの?と思うかもしれません。

 サービスや料金自体に違いはないのですが、応答速度が違います。

 Azure OpenAIのAPIサービスを使ったほうが生成が早いと言われています。
 ※しかし、最近利用者が増えたせいか、GPT-4での生成がかなり遅くなりました。しかし、GPT-3.5-turboでは高速な生成がまだ可能なので、Azureを選ぶという選択肢はアリです。


 Azure OpenAIは誰でも登録できるわけではなく、APIの利用を申請して認証された方がリソースを作成でき、APIの利用が可能になります。

 なので、お金を払えばだれでもOKのOpenAI APIと違い、利用者が制限されることで安定した高速な利用が可能になっています。


LangChainの使い方

 今回、LangChainはPythonで使います。C#JavaScriptでも利用できるらしいので、そちらを知りたい方はこの記事は参考にならないかもしれません。


実験環境

  • Python 3.10.12
  • jupyterlab 4.0.6
  • openai 0.28.0
  • langchain 0.0.310

ライブラリバージョンでほかに知りたいものがあれば気軽にコメントでお知らせください。


基本ライブラリのインポート

import os
import openai

from langchain.llms import AzureOpenAI
from langchain.chat_models import AzureChatOpenAI
from langchain.embeddings import OpenAIEmbeddings

各ライブラリの役割について説明します。

  • os ... 環境変数を編集するために使用します。場合によっては".env"ファイルを作ってそこからAPIキーなどを抽出する使い方もできるので必須です。
  • openai ... openaiのライブラリです。こちらはlangchainに渡すAPIキーや環境変数を指定するために使用します。
  • AzureOpenAI ... Azure OpenAIの大規模言語モデル(llm)を利用するために使用します。主に"text-davinci-003"(GPT-3)を使用するために使われると思います。
  • AzureChatOpenAI ... Azure OpenAIのチャットモデルを利用するために使用します。主に"GPT-3.5-turbo"や"GPT-4"を使うために使用されます。
  • OpenAIEmbeddings ... Azure OpenAIのエンベディングモデルを利用する際に使用されます。主に"text-embedding-ada-002"を使う際に使用されます。


環境変数の設定

 Azure OpenAIのAPIをLangChainで使う際には、環境変数を設定しなければなりません。そこで以下のようなコードを実行してください。

os.environ["OPENAI_API_TYPE"] = "azure"
os.environ["OPENAI_API_KEY"] = "@@@@@"
os.environ["OPENAI_API_BASE"] = "xxxxx"
os.environ["OPENAI_API_VERSION"] = "....."


OPENAI_API_TYPEはAzure OpenAIの場合は、ほとんどの方が"Azure"になると思います。

@@@@@の部分にはAzure OpenAIのAPIキーを入力してください。

xxxxxの部分にはAzure OpenAIでデプロイしたリソースのエンドポイントを入力してください。
(例)os.environ["OPENAI_API_BASE"] = "https://ここにリソース名.openai.azure.com/"

.....の部分にはAzure OpenAIでデプロイしたリソースのバージョンを入力してください。
(例)os.environ["OPENAI_API_VERSION"] = "2023-05-15"


次にopenaiのライブラリにも設定してあげます。

openai.api_type = "azure"
openai.api_key = "@@@@@"
openai.api_base = "xxxxx"
openai.api_version = "....."

ここにも同じく、API_TYPE、API_KEY、API_BASE(エンドポイント)、API_VERSIONの4つを入力します。


各モデルのインスタンスを作成

  • llmモデルの場合
llm = AzureOpenAI(
    deployment_name = "デプロイ名",
    model_name = "モデル名"
)

deployment_nameにはAzure OpenAIでデプロイしたllmリソースの名前を入力してください。
※(例)deployment_name = "test-gpt3",

model_nameにはAzure OpenAIでデプロイしたllmリソースのモデル名を入力してください。
※(例)model_name = "text-davinci-003"

chat = AzureChatOpenAI(
        client=None,
        deployment_name="デプロイ名",
        openai_api_base=openai.api_base,
        openai_api_version=openai.api_version or "",
        openai_api_key=openai.api_key or "",
        temperature=0.7,
        request_timeout=180,
    )

deployment_nameにはAzure OpenAIでデプロイしたチャットモデルリソースの名前を入力してください。
※(例)deployment_name="test-chatmodel"

  • エンベディングモデルの場合
embedding = OpenAIEmbeddings(
        model="エンベディングモデル名",
        deployment="デプロイ名",
        openai_api_key= openai.api_key,
        openai_api_base=openai.api_base,
        openai_api_type=openai.api_type,
        openai_api_version=openai.api_version,
    )

modelにはAzure OpenAIでデプロイしたエンベディングモデルリソースのモデル名を入力してください。
※(例)model="text-embedding-ada-002"

deploymentにはAzure OpenAIでデプロイしたエンベディングモデルリソースのデプロイ名を入力してください。
※(例)deployment="test-embedmodel"


あとはこれらをLangChainの記法に合わせて使用していけば問題なく使えるはずです。


ConversationalRetrievalChainの実行例

 先で設定したAzure OpenAIの設定をもとにLangChainを動かしてみたいと思います。

 今回実行するのは、ConversationalRetrievalChainです。

 ConversationalRetrievalChainは、独自データを参照させながらチャットモデルとの会話ができるようになるChainsです。

 詳しい説明は別記事でしますので、今は簡単にそういうものだと思ってください。


ライブラリのインポート

from langchain.chains import ConversationalRetrievalChain
from langchain.document_loaders.csv_loader import CSVLoader
from langchain.memory import ConversationBufferWindowMemory
from langchain.vectorstores import Chroma
import chromadb
from chromadb.config import Settings

from langchain.schema import (
    SystemMessage,
    HumanMessage,
    AIMessage,
)

from langchain.prompts import (
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
    AIMessagePromptTemplate,
    ChatPromptTemplate,
    PromptTemplate,
)

各ライブラリの役割について説明します。

  • ConversationalRetrievalChain ... 前述のConversationalRetrievalChainを行うためのライブラリです。
  • CSVLoader ... CSVのデータを読み取るためのライブラリです。今回参照させるデータはcsv形式なのでCSVLoaderを選択しました。
  • ConversationBufferWindowMemory ... AIとの会話履歴を保存するためのライブラリです。会話を実現させるために必要になってきます。
  • Chroma ... ベクトル化したデータを格納できるデータベースを扱うライブラリです。これによって読み込んだデータを格納して自由に扱うことができるようになります。
  • chromadb ... 前述のデータベースです。
  • Settings ... chromaDBに関する様々な設定を行うことができるライブラリです。
  • SystemMessage ... システムメッセージを格納するライブラリです。LangChainではロール(役割)を分けることができるので、その形式に当てはめるためのものになります。
  • HumanMessage ... ユーザーのメッセージを格納するライブラリです。
  • AIMessage ... AIのメッセージを格納するライブラリです。
  • SystemMessagePromptTemplate ... システムメッセージのプロンプトテンプレートを格納できるライブラリです。
  • HumanMessagePromptTemplate ... ユーザーのメッセージのプロンプトテンプレートを格納できるライブラリです。
  • AIMessagePromptTemplate ... AIのメッセージのプロンプトテンプレートを格納できるライブラリです。
  • ChatPromptTemplate ... チャット全体のプロンプトテンプレートを格納できるライブラリです。
  • PromptTemplate ... プロンプトテンプレートを作成し格納できるライブラリです。


 以上がConversationalRetrievalChainで使うライブラリになります。


memoryの初期化

 会話履歴(記憶)を保持するためのmemoryを初期化します。

 これから行うAIとの会話履歴がここに格納されていきます。

# 直近k個の会話履歴を保持するメモリ
memory = ConversationBufferWindowMemory(k=7, memory_key='chat_history', input_key="question", return_messages=True)

 今回使用するConversationBufferWindowMemoryですが、指定する"k"の数値の回数分の会話履歴を保存することができるものになります。

 今回kに7を入れてますので、7ターンの会話ののち初めの方から記憶が順に消去されていくことになります。


 ほかにも、全履歴をそのまま残す"ConversationBufferMemory"や、会話履歴をllmで要約して格納していく"ConversationSummaryBufferMemory"などがあります。


CSVLoaderでデータを取得・構造化を行う

 まずCSVLoaderでデータを取得しましょう。

loader = CSVLoader(file_path='data/tokyo.csv')
data = loader.load()

 今回、dataフォルダを作ってその中にtokyo.csvというcsvを入れています。
 tokyo.csvは、東京の世帯数および人口の推移について書かれたデータです。

 これを少し整形して、utf-8の形式で保存しなおしたものを読み取ります。

catalog.data.metro.tokyo.lg.jp


 どんな風に取得できたか確認してみましょう。

print("\n取得したデータ数 : ", len(data))
print("\n9番目のデータを見てみる : \n\n", str(data[9].page_content))

--------表示された情報--------
取得したデータ数 :  42

9番目のデータを見てみる : 

 年次: 1991
世帯数: 20453
人口総数(人): 58103
人口男性(人): 29947
人口女性(人): 28156
増加人口(人): 1601
対前年比増減率(%): 2.8
1世帯当たり人員(人): 2.84
1平方km当たり人口密度(人/平方km): 3242

 うまくデータを取得できました。

 これをベクトル化してchromaDBに格納します。

persist_directory = 'tokyoDB'
client = chromadb.PersistentClient(path=persist_directory)

db = Chroma(
            collection_name="langchain_store",
            embedding_function=embedding,
            client=client,
            )
db.add_documents(documents=data, embedding=embedding)

 ここでは、persist_directory変数にデータベースの名前を指定しています。すると、この名前でフォルダがつくられて、そこにaqlite3のデータベースが構築されます。


 一度データベースを構築しておくと、次から同じデータを参照したいときに、以下のようにコードを書けばデータベースを使えます。

 なので毎回csvを読み込んでエンベディングモデルでベクトル化して...のような手順が必要なくなるため、エンベディングモデルの利用料金の節約にもなります。

persist_directory = 'tokyoDB'
client = chromadb.PersistentClient(path=persist_directory)

vector_store = Chroma(
    collection_name="langchain_store",
    embedding_function=embedding,
    client=client,
)


 試しにデータ抽出を体験してみましょう。

 以下のコードでは、queryの文章と意味が近いデータを探して持ってきてくれます。

query = "1999年の東京の人口は何人ですか?"
retriever = vector_store.as_retriever(search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.7, "k":3})
docs_test = retriever.get_relevant_documents(query)
print("\t抽出データ数: ", len(docs_test))
print(docs_test)

 今回は類似度スコアが0.7以上("score_threshold": 0.7)のデータを最大3件("k":3)持ってくるように指示をしています。
 すると、以下のようなデータが取れました。

抽出データ数:  3
[Document(page_content='\ufeff年次: 1999\n世帯数: 25496\n人口総数(人): 64960\n人口男性(人): 33379\n人口女性(人): 31581\n増加人口(人): 953\n対前年比増減率(%): 1.4\n1世帯当たり人員(人): 2.55\n1平方km当たり人口密度(人/平方km): 3615', metadata={'row': 17, 'source': 'data/tokyo.csv'}), Document(page_content='\ufeff年次: 1989\n世帯数: 18279\n人口総数(人): 53642\n人口男性(人): 27513\n人口女性(人): 26129\n増加人口(人): 1658\n対前年比増減率(%): 3.2\n1世帯当たり人員(人): 2.93\n1平方km当たり人口密度(人/平方km): 3046', metadata={'row': 7, 'source': 'data/tokyo.csv'}), Document(page_content='\ufeff年次: 1998\n世帯数: 24829\n人口総数(人): 64007\n人口男性(人): 32914\n人口女性(人): 31093\n増加人口(人): 648\n対前年比増減率(%): 1\n1世帯当たり人員(人): 2.58\n1平方km当たり人口密度(人/平方km): 3562', metadata={'row': 16, 'source': 'data/tokyo.csv'})]

 年次が1999のデータを先頭に持ってきていることから、正しくデータが取れていることが分かります。


システムプロンプトを定義し、テンプレートを作成

 Q&Aを作るならシステムメッセージは欠かせませんし、設定したいと思いますので、やり方を紹介します。

 簡単に言うと、事前に会話履歴を定義して、その中にシステムメッセージを入れるというやり方です。

 まず、以下のようにシステムメッセージテンプレートを作成します。

system_prompt = """
あなたは、東京の情報を提供する優秀なチャットボットです。
以下にお客様とAIの親し気な会話履歴を提示しますので、それに基づいて発言しなさい。
発言内容はコンテキスト情報を参照して回答してください。コンテキスト情報にない場合は事前学習されたデータも使って回答してください。
'''
#会話履歴:

{history}
'''

'''
#コンテキスト情報:
      
{context}
'''
"""

 本来、記憶保持はmemoryがあるため会話が成り立つようになっているのですが、ユーザーの質問を要約してGPTに投げるチェインなので、会話が成り立たない場合が多い印象を受けました。なので、システムメッセージに会話履歴を入れて、それを参照するように指示をしています。
 しかし、この方法だとシステムプロンプトが冗長になってしまい、料金が会話履歴のぶん多くかかるのでご注意ください。

 その部分を改良したい場合は、condense_question_templateを変更してください。
 このテンプレートは、ユーザーの質問をGPTへ投げる際に要約されるよう指示するプロンプト(質問凝縮プロンプト)です。
 これを適切に変えることで、ユーザーの質問が適切な形でGPTに送られるようになるかと思います。

 ちなみに、デフォルトでは以下のようなプロンプトになっています。

Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language.

Chat History:\n{chat_history}
Follow Up Input: {question}
Standalone question:

 質問凝縮プロンプトを設定したら、以下のようにテンプレートとしてまとめておいてください。

condense_question_prompt = PromptTemplate(
    template=condense_question_template,
    input_variables=["chat_history", "question"]
)

 簡単に翻訳すると、「元の言語でユーザーの質問を会話履歴をもとに独立した質問に直しなさい。」という指示になっています。

 次にユーザーからの質問を入れるテンプレートを作成します。

human_prompt = "{question}"

 あとはこれをチャットテンプレートとしてまとめます。

messages = [
            SystemMessagePromptTemplate.from_template(system_prompt),
            HumanMessagePromptTemplate.from_template(human_prompt),
]
qa_prompt = ChatPromptTemplate.from_messages( messages )


Chainの作成

 ここまで来れば、あとは今まで設定した設定をつけたQ&Aを作るだけです。

 以下のように、対応した引数に入れることで完成します。

qa = ConversationalRetrievalChain.from_llm(
    llm=chat,
    retriever = vector_store.as_retriever(search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.7, "k":60}),
    memory=memory,
    combine_docs_chain_kwargs={"prompt": qa_prompt},
    condense_question_prompt=condense_question_prompt,
    condense_question_llm=chat
)

 この、condense_question_promptとcondense_question_llmは、質問凝縮プロンプトと、質問凝縮に使うモデルの指定をしています。

 もちろん使わない場合は指定せずに、以下のようにしても大丈夫ですので、質問凝縮はデフォルトのもので行いたい場合は書かなくて大丈夫です。

qa = ConversationalRetrievalChain.from_llm(
    llm=chat,
    retriever = vector_store.as_retriever(search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.7, "k":60}),
    memory=memory,
    combine_docs_chain_kwargs={"prompt": qa_prompt},
)

 次に、システムプロンプトに埋め込む会話履歴を作成する関数を作っておきます。
 これはmemoryに入っているデータを文字列に変換するだけなので、もっといいやり方は全然あると思いますので、ご自分で変更してください。

def list_to_string(input_list):
    # リスト内の要素を文字列に変換し、結合して文字列を作成
    result_string = ''.join(map(str, input_list))
    return result_string


チャットの実践

 では実際にチャットをしてみましょう。

# 入力テキスト
query = "1999年の東京の人口を教えてください。"

# 記憶(memory)の内容を読み込む ※dict型
buffer = memory.load_memory_variables({})

# 記憶(memory)の内容を読み込む ※list型
memory_context = buffer["chat_history"]

# 記憶をstr型に変換
memory_str = list_to_string(memory_context)

# Tempateの{history_mem}に値を埋め込んで実行
answer = qa.run({"question": query, "history": memory_str})
print("\n A# \n", answer)

 結果は以下のようになりました。

 A# 
 1999年の東京の人口総数は64,960人で、男性は33,379人、女性は31,581人でした。

 「CSVLoaderでデータを取得・構造化を行う」の説明の時に、試験的に取り出したデータと同じ数値になっていることから、うまくデータが取り出せていることが分かります。


おわりに

 今回、遅れながらAzure OpenAI利用者向けlangchainの解説をしました。

 あまりドキュメントがなく、調べるのに苦労しましたが何とか実装できてよかったと思います。

 また、いろんなサイトやブログを参考にしてコーディングをしたので、「別のブログに同じコードがあったな...」とかはあると思います。
 でも、極力オリジナリティが出るよう工夫はしているつもりですので大目に見てください...。

 ちなみに、私のコードは全然コピペしまくってもらって結構ですので、皆さんの役に立てば幸いです。

 
 余談ですが、最近Azure OpenAIでも、Azure AI Search(旧cognitive search)でコーディングなしでRAGを用いたアプリができたり、OpenAIのGPTsでも同じようなことができたりと、わざわざlangchainを使う必要がなくなってきているんですよね。

 閲覧ありがとうございました。

無料で使える!!rinna株式会社の対話GPT言語モデルを試してみる


環境構築

  • まず、フォルダを作りましょう。
mkdir rinna-gpt

 これで、"rinna-gpt"という名前のディレクトリが作成されます。

 これから作成するファイルはすべてこのディレクトリの中に置いてください。
 また、実行する場合もこのディレクトリの中で行ってください。

  • 続いて、環境構築はDockerを使います。

 Dockerを使うためには、Docker Engine か Docker Desktop が必要です。
 入れていない方は、調べてみて自分の環境に導入してください。
 今後、私のほうでもDocker Engine等のインストール記事を書くかもしれないので、投稿次第リンクを貼ります。

 また、Dockerというものについては、過去記事で簡単に解説しているので、Dockerが分からない方は目を通しておくと理解が早まるかもしれません。

frqux.hatenablog.com


 以下、Dockerfileのコードです。

FROM pytorch/pytorch:latest

WORKDIR /app

COPY requirements.txt .

RUN apt-get update && \
    apt-get install -y python3-pip

RUN pip3 install --no-cache-dir -r requirements.txt

COPY . .

 上記Dockerfileでは、pytorchベースのコンテナを作成しています。

  • 次に、requirements.txtを作成しましょう。

 以下のような内容のrequirements.txtを作成してください。

transformers
sentencepiece

 本来であればバージョン指定すべきなのでしょうが、推奨が分からないので、とりあえず指定しないで最新版にしておきます。

 環境はこれで大丈夫でしょう。


実行ファイル作成

 次に実行するPythonファイルを作成しましょう。

 以下、huggingfaceの公式ページ(
rinna/japanese-gpt-neox-3.6b-instruction-sft · Hugging Face
)よりサンプルコードを使いましょう。

 本ブログでは、以下のスクリプトを、"talk.py"と命名します。(なんでもいいです)

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained("rinna/japanese-gpt-neox-3.6b-instruction-sft", use_fast=False)
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt-neox-3.6b-instruction-sft")

prompt = [
    {
        "speaker": "ユーザー",
        "text": "日本のおすすめの観光地を教えてください。"
    },
    {
        "speaker": "システム",
        "text": "どの地域の観光地が知りたいですか?"
    },
    {
        "speaker": "ユーザー",
        "text": "渋谷の観光地を教えてください。"
    }
]
prompt = [
    f"{uttr['speaker']}: {uttr['text']}"
    for uttr in prompt
]
prompt = "<NL>".join(prompt)
prompt = (
    prompt
    + "<NL>"
    + "システム: "
)
print(prompt)
# "ユーザー: 日本のおすすめの観光地を教えてください。<NL>システム: どの地域の観光地が知りたいですか?<NL>ユーザー: 渋谷の観光地を教えてください。<NL>システム: "


if torch.cuda.is_available():
    model = model.to("cuda")

token_ids = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt")

with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        do_sample=True,
        max_new_tokens=128,
        temperature=0.7,
        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][token_ids.size(1):])
output = output.replace("<NL>", "\n")
print(output)
"""分かりました。いくつかのおすすめを紹介します。
1. ハチ公像です。ハチ公像は、日本の観光スポットの1つとして人気があります。
2. スクランブル交差点です。多くの人々が行き交う大きな交差点で、観光客に人気のスポットです。
3. 109です。109は、ショッピングやエンターテイメント施設です。
4. 道玄坂です。道玄坂は、日本の商業地区である坂道です。</s>"""


サンプルコードを実行してみる

 まず、ビルドしましょう。

 以下のコマンドでDockerイメージを作成しましょう。

docker build -t rinna-gpt .

 終わったらrunしてみましょう。

docker run --rm -it  --gpus all rinna-gpt:latest

 いろいろオプションがついてますが、GPUが使えない環境の方は、"-gpus all"を消してください。

 うまく動いて、コンテナに入れば環境はOKです。

 次に以下のコマンドをコンテナ内で実行してください。

python talk.py

 すると、以下のようにtokenizer等のダウンロードが始まります。

Downloading (…)okenizer_config.json: 100%|█████████████████████████████████████████████| 284/284 [00:00<00:00, 2.23MB/s]
Downloading spiece.model: 100%|██████████████████████████████████████████████████████| 786k/786k [00:00<00:00, 12.9MB/s]

 次に、configとモデルのダウンロードが始まると思います。

Downloading (…)lve/main/config.json: 100%|█████████████████████████████████████████████| 534/534 [00:00<00:00, 5.52MB/s]
Downloading model.safetensors: 100%|███████████████████████████████████████████████| 7.37G/7.37G [02:58<00:00, 41.3MB/s]

 これが終われば、ようやくGPTに質問を自動で投げかけます。

ユーザー: 日本のおすすめの観光地を教えてください。<NL>システム: どの地域の観光地が知りたいですか?<NL>ユーザー: 渋谷の観光地を教えてください。<NL>システム:

 これは、以下のように、
ユーザー:日本のおすすめの観光地を教えてください。
AI:どの地域の観光地が知りたいですか?
ユーザー:渋谷の観光地を教えてください。

と、一連の会話の流れを与えたうえで、次に返されるAIの返答を待っています。

 しばらく待つと返答が返ってきてプログラムが終了します。

 私の場合は、「どのような種類の観光地に興味がありますか?」と返ってきました。


完全な対話形式に改造する。

 今のサンプルコードでは、自分で質問を連続して送れないので、サンプルコードを改造して好きに対話できるようにします。

 以下に改造後のコードを載せます。

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained("rinna/japanese-gpt-neox-3.6b-instruction-sft", use_fast=False)
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt-neox-3.6b-instruction-sft")

if torch.cuda.is_available():
    model = model.to("cuda")

output = ""
request = ""

prompt = [
    {
        "speaker": "ユーザー",
        "text": "こんにちは。"
    },
    {
        "speaker": "システム",
        "text": "こんにちは!何かお聞きしたいことはありますか?"
    }
]
prompt = [
    f"{uttr['speaker']}: {uttr['text']}"
    for uttr in prompt
]
prompt = "<NL>".join(prompt)

while True:
    text = input("\n話しかけてください。終わる場合は「end」と入力して下さい:")
    if (text == "end"):
        break
    request = prompt + "<NL>ユーザー: " + text + "<NL>システム: "
    request = request.replace("\n", "<NL>")

    token_ids = tokenizer.encode(request, add_special_tokens=False, return_tensors="pt")

    with torch.no_grad():
        output_ids = model.generate(
            token_ids.to(model.device),
            do_sample=True,
            max_new_tokens=128,
            temperature=0.7,
            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][token_ids.size(1):])
    output = output.replace("<NL>", "\n")
    prompt = request + output
    print(output)

    print("\n\nデバッグ情報#")
    print("会話履歴:" + prompt)
    print("入力テキスト:" + text)
    print("リクエストテキスト:" + request)
    print("レスポンス:" + output)

 これで、cmd上でGPTと会話を続けることができます。

 急ぎで作ったので、コードが汚い・無駄が多い・例外処理が無いのは目を瞑ってください...。

 では、もう一度ビルドと実行をしましょう。

docker build -t rinna-gpt .
docker run --rm -it  --gpus all rinna-gpt:latest python talk.py

 モデルのダウンロードが終わったら

話しかけてください。終わる場合は「end」と入力して下さい:

と表示されるので、好きに入力して実行しましょう。

 しばらく待つと返答が返ってきて、また自分のターンが来ますので、そのまま好きなだけ会話を続けてください。

 今回の改造後のコードには、デバッグ用に

  • 会話履歴
  • 入力テキスト
  • リクエストテキスト
  • レスポンス

が表示されるようにしてあります。

 必要ない場合は、最後辺りのprint文のコードを消すか、以下のようにコメントアウトしてください。

#print("\n\nデバッグ情報#")
#print("会話履歴:" + prompt)
#print("入力テキスト:" + text)
#print("リクエストテキスト:" + request)
#print("レスポンス:" + output)


まとめ

 今回、rinna株式会社様が公開されたGPTモデルを使う方法を解説しました。

 レスポンスは、やはり遅めでOpenAIのAPIと比べると劣るのですが、無料で使えるので状況に応じて使用するのがいいですね。

 回答内容としては、簡潔な内容が返ってくるなぁといった印象です。

 OpenAIのGPTだと、何十行も返ってくる文章が、20文字、30文字ほどで、さっぱりと生成されています。
 ちょっと機械的というか、冷たい感じがしますね...。

 皆様の研究や勉強に役立てることができたのなら幸いです。


各種リンク

  • rinna、日本語に特化した36億パラメータのGPT言語モデルを公開

rinna、日本語に特化した36億パラメータのGPT言語モデルを公開|rinna株式会社のプレスリリース

  • Hugging Face

rinna/japanese-gpt-neox-3.6b-instruction-sft · Hugging Face

オンラインゲームの様々な問題の解決案をAIに聞いてみる #1(チームゲームでのトロールは本当に悪か。)

オンラインゲームで生じている様々な問題

 昨今、ネットや高性能なゲーム機の普及によって、オンラインゲームが多くの人に遊ばれるようになってきました。また、プレイ人口増加に伴って年齢層の幅も大きく広がってきました。

 たくさんの人でプレイするゲームは楽しいものです。

 ...しかし実際は、そう簡単に多くの人が平等に楽しめるということは少ないのです。

 ゲームのプレイスタイルはプレイしているプレイヤーの数ほどありますし、全く同じ考えでプレイすることも少ないです。
 そういったこともあって、楽しいと思ってやっていることでも、ほかの人にとっては面白くないという結果になってしまったりと、コミュニケーションに関する問題が発生してきます。

 また、コミュニケーション以外にも、運営の方針とプレイヤーの意見が食い違って問題になるケースもあります。運営は硬派なゲームにしていきたいが、プレイヤーにとっては硬派すぎて難しいから簡単にしてほしい意見が出るなどです。

 こういった問題は、かなり前から議論されている問題で、いまだに解決案が出ていません。

 これについてAIと議論をしてみようと思いました。

 私自身ゲームが好きで、青春の95%をゲームにささげたといっても過言ではないほどのゲーマーです。今でももちろん好きです。
 だからこそ、皆が楽しめるゲーム作りについて今後も考えていく必要があると考えています。

 具体的な問題を簡単に挙げると、

  • チームゲームでのトロールは本当に悪か。
  • コミュニケーションをとりたくない人はチームゲームをしてはいけないのか。
  • 運営の方針とプレイヤーの要望はどちらが優先されるべきなのか。
  • フルパ論争(野良に文句があるならフルパを組めという論争)

などがあります。

 今回は、その中でも"チームゲームでのトロールは本当に悪か。"についてAIと議論します。

 皆さんはトロールは悪だと思いますか?おそらく大半の人は悪だと思っていると思います。
 ですが、本当に悪だと言い切れるでしょうか?

 この問題は、個人的なものでもあるのかもしれませんが、自分の中で反対意見が出ないために、トロールを容認してしまっている人もいるのではないでしょうか?

 「トロールしてて楽しいから放っておいてくれ」とか「ゲームは楽しむためのものだからトロールもok」という意見を聞いて、「確かに...」となってませんか?

 私が今そうなっている状態です...w

 ゲームを楽しんでいるんだから、ゲーム本来の目的に沿っているという考えにも納得してしまいそうになり、悪ではないんじゃないかという風に考えてしまいます。

 そこで、トロールは本当に悪なのかについて深堀します。


「チームゲームでのトロールは本当に悪か。」についてのAIとの対話ログ


私:チームゲームでのトロールは本当に悪なのでしょうか?


AI:チームゲームでのトロール行為は、一般的には悪い行為とみなされることが多いです。トロール行為は、ゲーム内で仲間のプレイヤーやチームメイトを意図的に妨害し、勝利やゲーム体験を台無しにする行為を指します。

以下は、トロール行為がなぜ悪いとされるのかについての理由です:

1. フェアプレイの侵害: チームゲームは協力して目標を達成することが重要です。トロール行為は、他のプレイヤーやチームメイトとの協力を妨げるため、フェアプレイの原則に反します。

2. チームの士気低下: トロール行為によって、他のプレイヤーやチームメイトは不快な体験をする可能性が高くなります。その結果、チーム全体の士気が低下し、勝利することが難しくなります。

3. コミュニティの健全性: トロール行為はゲームコミュニティの健全性に悪影響を及ぼすことがあります。プレイヤーがトロール行為を受けると、不快な体験をしたり、不適切な行動を取ることもあるため、コミュニティ全体の雰囲気が悪化する可能性があります。

4. ゲーム体験の台無し: ゲームは楽しむためにプレイされるものであり、トロール行為によって他のプレイヤーのゲーム体験が台無しになることは非常に不快です。

ただし、トロール行為には場合によっては議論の余地がある場合もあります。例えば、一部のプレイヤーはジョークや冗談としてトロール行為を行うこともありますが、それが他のプレイヤーにとって不快になることもあるため、状況やコンテキストを考慮する必要があります。

総じて言えることは、トロール行為は他のプレイヤーやチームメイトとの良好な協力を妨げ、ゲーム体験を損なう可能性があるため、慎重に行動することが重要であると言えます。


私:トロール行為が、そのプレイヤーにとって楽しい行動だとすれば、「本来のゲームは楽しむもの」というゲームの根本の目的に則っているようですがどうですか?


AI:ゲームの根本の目的は、確かに楽しむことです。一般的に、ゲームは娯楽や楽しみを提供することを目的としています。したがって、トロール行為がそのプレイヤーにとって楽しい行動である場合、その観点からは「本来のゲームは楽しむもの」という目的に則っていると言えるでしょう。

ただし、楽しみを得るために他のプレイヤーやチームメイトに不快な体験を与えることは、それらのプレイヤーやコミュニティ全体にとって好ましい結果ではありません。トロール行為が楽しいと感じるプレイヤーにとっては楽しいかもしれませんが、他のプレイヤーにとってはゲーム体験が台無しになり、士気が低下する可能性があります。

ここで重要なのは、他のプレイヤーやコミュニティの意見や体験を尊重することです。ゲームは多くのプレイヤーが参加して楽しむ場であり、トロール行為が他の人々の楽しみを妨害しないように心がけることが大切です。

また、ゲーム内でトロール行為が許容されるかどうかは、ゲームのルールやコミュニティの慣習によっても異なります。一部のゲームではトロール行為が許容されているか、あるいはジョークや冗談の一部として受け入れられているかもしれませんが、他のゲームでは禁止されている場合もあります。

総じて言えることは、ゲームを楽しむことが大切であると同時に、他のプレイヤーやコミュニティの体験を尊重し、トロール行為が不快な結果をもたらさないようにすることが重要であるという点です。


私:では、トロールをしているプレイヤーが半数を超えているコミュニティではどうなのでしょうか?半数以上が楽しいと感じているということはトロールは悪ではなくなるのでしょうか?


AI:半数以上のプレイヤーがトロール行為を楽しんでいるコミュニティの場合、その状況は少し複雑です。トロール行為が多数派に受け入れられているという事実は、そのコミュニティの文化やルールが異なることを示唆しています。

こうした場合には、一般的なゲームコミュニティとは異なる倫理観やルールが成立している可能性があります。つまり、そのコミュニティがトロール行為を許容しているということです。ただし、それが他のゲームコミュニティにも適用されるべきかどうかは別の問題です。

トロール行為が多数派に受け入れられている場合でも、他のプレイヤーやコミュニティの意見や感情を無視することは良い行為とは言えません。他の人々に不快感や不幸を与えることは依然として倫理的な問題です。

このような状況では、以下の点に留意することが重要です:

1. コミュニティルールの遵守: トロール行為が許容されているコミュニティでも、ルールやガイドラインを守ることが重要です。そのコミュニティのルールに則って行動することで、他のプレイヤーやメンバーの意見を尊重する姿勢を示せます。

2. 新参者への配慮: トロール行為が受け入れられているコミュニティに新たに参加したプレイヤーや初心者は、文化やルールに適応するのに時間がかかる場合があります。彼らの意見や感情を尊重し、ゲームを楽しんでもらうことが大切です。

3. 柔軟性とコミュニケーション: トロール行為が許容されているコミュニティでも、それが他のプレイヤーやメンバーにとって適切な行為かどうかについて議論する余地があるかもしれません。コミュニケーションを通じて異なる意見を理解し合うことが重要です。

最終的に、コミュニティのルールと倫理観に則って行動することが重要です。個々のコミュニティが異なるため、トロール行為が悪とされるかどうかはそのコミュニティの文化に依存します。ただし、他のプレイヤーやメンバーの意見と感情を尊重する姿勢は、どのような状況でも重要な価値観であるべきです。


私:ではトロールは、所属するコミュニティによって悪にもなりえるし、許容される場合もあるということですか?


AI:正確です。トロール行為は、所属するコミュニティによって悪にもなりえるし、許容される場合もあります。それは、個々のゲームコミュニティの文化やルール、コミュニティメンバーの慣習や価値観によって異なるためです。

一部のコミュニティではトロール行為が悪とされ、そのような行為を行うプレイヤーは排除される可能性があります。これは、他のプレイヤーやメンバーの楽しみや体験を妨害することが、そのコミュニティの基本的なルールに違反すると見なされるためです。

一方で、他のコミュニティではトロール行為が許容される場合もあります。これは、そのコミュニティがトロール行為をジョークや冗談として受け入れている場合や、ゲーム内でのトロール行為がそのゲームの戦術や戦略の一部としてみなされる場合が考えられます。

しかし、トロール行為が許容されるコミュニティでも、全てのプレイヤーがその行為を楽しんでいるわけではありません。一部のプレイヤーや新参者にとっては不快な経験となる可能性があります。したがって、トロール行為が許容される場合でも、他のプレイヤーやメンバーの意見と感情を尊重する姿勢が重要です。

総じて言えることは、トロール行為の是非はコミュニティによって異なるということです。ただし、他のプレイヤーやメンバーの体験や楽しみを大切にし、倫理的な行動を心掛けることはどのコミュニティにおいても重要な価値観であるべきです。


私:では、トロールが大半のコミュニティにおいても、少数のプレイヤーのために"健全なプレイ"をすべきなのでしょうか?トロールが大半のコミュニティにおいて、そのコミュニティの総意は「トロールが楽しい」だと思うので、少数の「健全なプレイがしたい」というプレイヤーがやめるべきだと思いませんか?


AI:このような状況において、トロールが大半のコミュニティにおいて受け入れられている場合、少数のプレイヤーが健全なプレイを望むことは難しいことがあります。なぜなら、トロールがそのコミュニティの総意であるならば、健全なプレイを求めるプレイヤーは周囲の環境と合わない可能性が高いからです。

一部のプレイヤーが少数派であっても、そのプレイヤーが楽しいと感じられる健全なプレイを望むことは重要です。ゲームの目的は楽しむことであり、プレイヤーの幸福感と楽しみが大切な要素です。トロール行為が大多数のプレイヤーにとって楽しいとされる場合でも、他のプレイヤーが不快な体験をすることは避けるべきです。

そのような状況で考えられるアプローチは以下の通りです:

1. 別のコミュニティを探す: 健全なプレイを望むプレイヤーは、自分に合ったコミュニティを探すことを検討することが大切です。ゲームにはさまざまなコミュニティが存在し、自分のプレイスタイルに合った環境を見つけることが可能です。

2. コミュニティに対して意見を表明する: 健全なプレイを望むプレイヤーは、トロール行為を減らすような提案や意見をコミュニティに対して表明することができます。一部のプレイヤーの声が大きくなれば、コミュニティの風潮に影響を与える可能性もあります。

3. 健全な行動を見せる: 少数派の健全なプレイヤーが、自らの行動を通じて他のプレイヤーやメンバーに良い影響を与えることができます。良い行動の例を示すことで、他のプレイヤーにもプラスの影響を与える可能性があります。

トロール行為が大半のコミュニティにおいて受け入れられている場合でも、個々のプレイヤーの意見や感情を尊重することが重要です。健全なプレイを望むプレイヤーが自分自身を大切にし、楽しみながらプレイできる環境を見つけることが理想的です。


私:個々のプレイヤーの意見や感情を尊重することが重要ということは、トロールプレイヤーの意見も尊重すべきということですよね。


AI:個々のプレイヤーの意見や感情を尊重することは非常に重要ですが、トロールプレイヤーの意見に対しては状況によって異なります。

トロールプレイヤーが自分の行動を楽しんでいるという観点から、彼らの意見や感情を尊重すべきという考え方もあります。彼らは自分のスタイルでゲームを楽しんでおり、その自由を尊重する必要があります。

しかし、トロール行為が他のプレイヤーやコミュニティメンバーに不快感や不幸をもたらす可能性がある場合、その行為を絶対的に尊重するというわけではありません。個々の楽しみが他のプレイヤーの不幸を引き起こす場合、それは問題となります。

ゲームのコミュニティは多様であり、プレイヤーは異なる目標や価値観を持ちます。一部のコミュニティではトロール行為が受け入れられるかもしれませんが、他のコミュニティでは許容されない可能性があります。

重要なのは、トロール行為が他のプレイヤーやコミュニティメンバーに対して負の影響を及ぼすことを理解し、その行為を適切にコントロールすることです。自分の楽しみを追求する一方で、他のプレイヤーの楽しみや体験を尊重する姿勢が重要であり、健全なコミュニケーションやフェアプレイを心がけることが大切です。


私:なぜ、他のプレイヤーの楽しみや体験を尊重する姿勢が重要なのですか?各自が自分が楽しいプレイをすればそれでいいではないのですか?


AI:他のプレイヤーの楽しみや体験を尊重する姿勢が重要な理由にはいくつかあります:

1. ゲームコミュニティの健全性: ゲームはコミュニケーションと相互作用を重視する傾向があります。他のプレイヤーと協力したり、競い合ったりすることで楽しみを共有し、より豊かな体験を得ることができます。他のプレイヤーの楽しみや体験を尊重する姿勢は、コミュニティ全体の健全性を維持するために重要です。

2. ポジティブなゲーム体験の促進: 他のプレイヤーの楽しみを尊重することで、協力やチームプレイが促進され、ゲームの質が向上します。ポジティブなゲーム体験が共有されることで、プレイヤーたちはより満足感を得ることができます。

3. 不快感や対立の回避: 他のプレイヤーの楽しみを軽視したり、トロール行為を行うことで、不快感や対立が生じる可能性が高まります。これはゲームの楽しさを損なうだけでなく、コミュニティ内のトラブルや不和を生み出す原因となります。

4. コミュニティの発展: ポジティブなゲーム体験を共有するコミュニティは成長し、多くのプレイヤーを引き寄せる可能性が高まります。一方で、他のプレイヤーを不快にさせるコミュニティは、新規参加者を遠ざける可能性があります。

ただし、個々のプレイヤーが自分が楽しいプレイをすることは重要です。楽しみを追求することはゲームの目的の一つですが、他のプレイヤーやコミュニティメンバーとの協力や共有も大切な要素です。他のプレイヤーの楽しみや体験を尊重することで、より豊かなゲーム体験を共有し、良いコミュニケーションを築くことができるのです。


私:すべてのプレイヤーが楽しくプレイするためにトロールの行動は問題視されなければいけないということですね。


AI:正確です。全てのプレイヤーが楽しくプレイすることが重要なゲームコミュニティにおいて、トロールの行動は問題視されるべきです。

トロール行為は他のプレイヤーやチームメイトの楽しみを妨害し、不快な体験を与える可能性があるため、ゲームのコミュニティにとってマイナスの影響を及ぼすことがあります。一部のプレイヤーが楽しんでいるかもしれない行為でも、他のプレイヤーやコミュニティ全体にとって不快な結果をもたらす場合は問題と見なされるべきです。

ゲームは協力や競争を通じて楽しむものであり、他のプレイヤーと良好な関係を築くことが重要です。トロール行為はコミュニケーションやチームワークを妨げ、コミュニティの結束を弱める可能性があります。

より健全なゲームコミュニティを築くためには、トロール行為を抑制し、ポジティブなプレイを奨励する必要があります。プレイヤーたちは自分の楽しみを大切にしながらも、他のプレイヤーの楽しみや体験を尊重する姿勢を持つことが重要です。このような協力的な姿勢がコミュニティ全体の幸福感を高め、より良いゲーム体験を共有するための基盤を築くことにつながります。


以上です。

 結論として、トロールはコミュニティによって悪にもなりうるし、許容される場合があるということ。しかし、すべてのプレイヤーが楽しめるゲームにするために、トロールは問題視しなければならないということでした。

 ちなみに、質問の仕方的に自分がトロール側であるかのような立ち位置になっていますが、私自身もトロールは排除すべき存在だと考えています。



AIと対話してみての発見

 AIと話していて新たな発見がありました。それは、

ゲームを楽しむ ≠ 大半が楽しいと思えるゲームプレイをする

であるということです。自分自身、「ゲームを楽しむ = 大半が楽しいと思えるゲームプレイをする」派だったのですが、今回AIと話していて違うのではないかと考えるようになりました。

 正しくは以下の式が成り立つべきだと考えました。

ゲームを楽しむ = 全員が楽しいと思えるゲームプレイをする

 「大半が楽しいと思えるゲームプレイをする」と「全員が楽しいと思えるゲームプレイをする」は似ているようで全く違います。

 前者は、楽しいと思えない少数派のプレイヤーの意見を無視して、そのプレイヤーを迫害するコミュニティになります。その結果、少数派の意見を尊重することができないプレイヤー故に、その後もプレイヤー同士の意見の押し付け合いが蔓延り、マナーやモラルの低下、迫害が正当化されたコミュニティのため、さらに生まれた少数派を迫害していき、人口減少につながります。
 また、少数派でも多数派に合わせたプレイングを強要されることで「ゲームがつまらない」、「ゲームが怖い」と感じてしまうようになることも問題です。 こうなってしまったコミュニティの行きつく先は、コミュニティの崩壊・ゲーム運営の終了(サ終)です。

 しかし、後者は少数派の意見も重要にするという意味合いを持っております。自分が楽しいと思うプレイングを追求しながら、ほかのプレイヤーも楽しめるプレイングも考えるという点で前者と大きく違います。
 1億人いたうちの1人でも「楽しくない」と思えば、その意見を尊重し皆で解決すべきです。もちろん、その1人も他の9999万9999人のプレイヤーの意見を尊重すべきです。
 その結果、皆で楽しめるゲーム体験ができるようになり、ユーザー・運営ともに質の高い活動ができるようになります。


 なので、「トロールは面白くない」「トロールがいると楽しくない」と思う人が少しでもいる限り、許されないなのです。



解決案

 次に解決案を挙げてもらうよう言ってみました。


私:このトロール問題の解決案を出してください。


AI:トロール問題を解決するためには、以下のような対策が考えられます:

1. 教育と啓発: ゲームコミュニティ内でのトロール行為に対して、プレイヤーに対して啓発活動を行うことが重要です。トロール行為が他のプレイヤーやコミュニティに与える影響や問題点について認識させ、倫理的なプレイを促進するための教育プログラムを導入することが考えられます。

2. ルールとペナルティの強化: ゲーム運営者は、トロール行為を適切に防止するために、ルールとペナルティを明確に示す必要があります。トロール行為を行ったプレイヤーには適切な制裁を与え、その行為の再発防止を図ることが重要です。

3. コミュニティの監視と報告システム: プレイヤーがトロール行為を発見した場合、運営に報告できる仕組みを整備することで、早期に問題を対処できます。また、コミュニティ全体で監視を行い、問題のある行動を素早く見つけ出すことが重要です。

4. ポジティブな行動の促進: コミュニティ内でのポジティブな行動やフェアプレイを奨励する仕組みを導入し、優れたプレイヤーを称えることで、良い行動がコミュニティの価値観として浸透するようにします。

5. コミュニケーションと協力: コミュニケーションと協力を重視するゲームプレイを奨励することで、トロール行為を減らすことができます。チームプレイを促進し、互いに尊重し合う環境を作ることが大切です。

6. ゲームデザインの改善: ゲームデザインの改善により、トロール行為を防ぐための仕組みを導入することが考えられます。例えば、トロール行為を抑止する報酬システムや行動制約の導入などがあります。

これらの対策を組み合わせることで、トロール問題の解決に向けた努力ができるでしょう。ただし、全てのコミュニティにおいて同じ対策が有効かどうかは異なるため、具体的なゲームやコミュニティの特性に合わせてカスタマイズする必要があります。



なるほど。

 個人的には、2と6の案が納得いく解決案だと感じました。

 1については、意味がないと感じています。トロールしている人は悪いことをしている自覚があるからです。悪いことをしていることが"楽しい"・"かっこいい"と感じている方たちですので、そもそもこういった教育は意味をなさないと感じています。

 2については、ペナルティを与えることについて賛成です。これは、モラルなどの感情論ではなく、物理的に接続制限を与えることでトロールを抑制できるからです。しかし、これも慎重な判断が必要だと思っていて、トロール情状酌量の余地なく片っ端からBANしていたら「大半のプレイヤーが楽しいと思えるゲームプレイをする」ことになってしまいます。
 皆で寄り添いあうことで楽しいゲームプレイができるよう、協力すべきですね。

 3はすでに多くのゲームで実装されているので今更議論する必要はないかと思いますが、トロールの減少に貢献しているか微妙なところです。
 実際ほとんどのゲームに通報システムなどは導入されていますが、ゴキブリのようにワラワラ湧いてきます。今現在もこの論争が続いている時点で解決策としては薄いような気がしますね。

 4もすでに導入されているゲームを見かけるようになりましたよね。r6sの評価システムや、オーバーウォッチ2の評価システムなどです。
 この評価システムもうまく使えば抑止力になります。例えばr6sでは、アカウントを作り直せば評価は通常に戻ります。ですがオーバーウォッチ2の場合、アカウントを作るのに電話番号認証が必要なため、作り直すことが難しくなっています。そのため、使いようによっては抑止力になると考えています。

 5は重要なことではありますが、トロールの抑止力にはならないと思います。そもそもコミュニケーションをとることを目的としているトロールも存在するからです。「ほかのプレイヤーにいやな気持になってもらいたい」、「ほかのプレイヤーが嫌がる声が聴きたい」などです。こういったプレイヤーには逆効果なのでこれについては意味をなさないのではないかと考えます。

 6は2と同じように、精神的な問題ではなく物理的に抑止することでトロール問題を解決に導くことができるのではと考えています。トロールしても楽しくないゲームシステムの構築や、そもそもトロールができないゲームシステムにすることなどは大きな抑止力になりえますね。



終わりに

 今回は、「チームゲームでのトロールは本当に悪か。」についてAIと議論してみました。自分の考えも少し変わり、大きな発見もありました。

 自分自身、この問題で何度も悩まされてきて、「もしかしたらゲームの楽しみ方の本来の姿がトロールなのでは?自分が異端なのでは?」と思うようになっていたので、大きな気付きを得れて本当に良かったですね。

 というか、多数派が絶対で少数派が排除されるべきという思考に至っていた自分に驚きましたね。全員が楽しむためのゲームという事を忘れてました。本当に恐ろしい事です...。

 ただ、オンラインゲームに限った話なので、オフラインゲームではチートしようがトロールしようが、プレイしているのは自分一人なので何してもokだと個人的には思ってます。

 では、マナーとモラルを守って、よいゲームライフを!

(忘備録)wslのubuntuインストール時の"Processing fstab with mount -a failed"というエラーの回避方法

旧PCのWSLをver2に移行するため、powershellにて

wsl --update

wsl --install

を実行し、Ubuntuをインストールしたところ、以下のようなエラーが出た。

Processing fstab with mount -a failed.

<3>WSL (7) ERROR: CreateProcessEntryCommon:370: getpwuid(1000) failed 2
<3>WSL (7) ERROR: CreateProcessEntryCommon:374: getpwuid(0) failed 2
<3>WSL (7) ERROR: CreateProcessEntryCommon:577: execvpe /bin/sh failed 2
<3>WSL (7) ERROR: CreateProcessEntryCommon:586: Create process not expected to return
...以下10行ほど

調べたところ、指定の場所にマウントができない問題のようだった。

いろいろいじくるのが面倒だったため、Microdoft StoreからUbuntuを再インストールところ、すんなり行けた。

ちなみに別の方の記事で、powershellにて

wsl --list

を実行後に、"docker-desktop-data"が既定になっているのでUbuntuを規定に直すとできたと書かれていたが、現在”docker-desktop-data”が規定になっていても動いているので、似ているエラーで別の問題なのではないかと思うので注意したい。

BERTの仕組みを解説!自然言語処理の次世代を担うアルゴリズム

 こんにちは。ふらうです。

 今回は、自然言語処理に革命を与えたBERTを解説していきたいと思います。

 私自身、今勉強中の身であるため、解釈違いなどがあると思いますが、ご理解ください。

 今回はBERTの概要とアルゴリズムの解説を行いますが、今後別記事で事前学習の実践とファインチューニングの実践を行う予定ですので、またよろしくお願いします。

BERTの概要

 BERTとはBidirectional Encoder Representations from Transformersの略で、訳すると「Transformerによる双方向エンコーダ表現」です。

 BERTは、2018年に発表された論文

"BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding"

で世に広まることとなりました。

 以下に論文のリンクを貼ります。
[1810.04805] BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

 BERTは、transformerモデルのエンコーダー部分を利用したモデルです。

 transformerモデルは、Encoder-Decoderモデルで、Encoder部分で時系列データをベクトルへ変換し、Decoder部分でベクトル情報から人間にわかる出力へと変換します。

 なので、BERTは人間が入力した情報を特徴量に変換し出力するので、数値情報の出力の観点から、文書分類や単語の類似度算出、感情分析などのタスクに利用されます。

 逆に、Decoder部分はGPTなどの人間がわかる文章を出力するモデルに利用されます。
 最近話題のOpenAIのChatGPTは、このGPTモデルのGPT-3.5をベースに作られています。これはアルゴリズムなどは公開されてないのですが、基本的にtransformerモデルを利用していると思われます。
 また、最近では米国時間2023年3月14日に、OpenAIはGPT-4も公開しています。

 このように、現代でも研究が加速しているモデルの基盤としてtransformerモデルがあるのです。

 transformerは、双方向理解ができる点から、より深く文脈を加味できるという点も注目ポイントです。
 このアルゴリズムは後程説明しますが、文章を前後両方から読んで意味を理解するとともに、今までなかった機構をモデル内に取り付けたことで、飛躍的に性能を向上させることができました。

 では、これらのアルゴリズムについてひも解いていきます。


BERTの基本構造と仕組み

 ここからは、詳しいBERTのアルゴリズムの解説に入ります。

 できる限り専門用語などは省くように説明しますので、よろしくお願いします。


モデル構造

 BERTは以下のような、たくさんの層が重なっている構造になっています。

BERTの基本構造

 各層の役割とアルゴリズムについて解説していきます。


入力

 まず、入力されるデータは文字の時系列データです。要するに文章です。

 この文章は、単語に分割されて分かち書きされている必要があります。
 そのあと、文章の初めに"[CLS]"というトークンを、終了地点もしくは別の文章に切り替わる部分で"[SEP]"トークンを取り付け、入力とします。
 これは、文章の初めて終わりを明確に指定することで、文章を上手くAIに理解させようとしているものになります。

 なので、「私は猫が好き。」という文章を入力したい場合、「[CLS], "私", "は", "猫", "が", "好き", "。", [SEP]」となります。

 結論、入力は単語の列によって表現されBERTの入力となります。


単語埋め込み層

 これは、一般にはembedding層と呼ばれるもので、単語それぞれに対応する単語ベクトルを割り振ります。
 この単語ベクトルは、学習過程で変化していき、この単語ごとのベクトルがうまく分かれることで文章をうまく理解することが可能になります。

 この単語ベクトルはランダムな初期値で振られ、学習が進むにつれて似た意味を持つ単語同士は似たベクトルになり、意味が離れた単語ほど逆向きのベクトルとなります。

 BERTの特徴が深く表れている面がここにもあり、同じ単語でも文章の流れ(文脈)によって違うベクトルに直される場合があります。今までの分類モデルでは、同じ単語はすべて同一の単語ベクトルへ定義されていたのですが、BERTでは文脈を加味したベクトルへ直される構造をとっているため、文脈によってベクトルが変化します。


セグメント埋め込み層

 ここでは、まず文章の連結を検知してそれぞれの文章に対応したIDを割り振ります。
 BERTでは、入力の際に複数の文章を入力すると、「[CLS]私は猫が好き。[SEP]俺は犬が好き。[SEP]」のように複数の文章が連結して入力されます。これはmax_lengthなどで指定することができ、512とした場合、合計が512文字になるよう文章が連結します。

 なので、どこからどこが一文なのかを理解するために、IDを割り振ります。「私は猫が好き。」には1を。「俺は犬が好き。」には2を割り振る場合は、「[CLS], 1, 1, 1, 1, 1, 1, 1(SEP), 2, 2, 2, 2, 2, 2, 2(SEP)」という風な位置セグメントIDが割り振られます。

 そのあと、そのIDぶんの重みをトークンのベクトルに加算します。そうすることで、文章間の分かれ目を見分けることが可能になります。

 この層があることで、文章の分かれ目を明示的に示すことで、より文脈を認識させることが可能になります。


transformer層

 transformer層は、transformerモデルのEncoder部分です。

 これは、過去記事で解説したものと同様の処理を行うため、以下に記事のリンクを貼っておきますので、そちらからご確認ください。

frqux.hatenablog.com

 今回は、このtransformerモデルにAttentionMASKというものが追加されています。
 これは何なのかというと、不必要な部分にマスクをかけて学習の際に該当箇所を読まないようにする処理です。

 例えば1文章ごとに、頭から100文字をそれぞれ学習データとして読んでほしい場合に、頭から100文字に"1"を、それ以降に"0"を当てはめて、0が割り当てられた部分を読まないように処理を変更することで可能になります。

 この利点としては、文章が混ざってしまっている場合やメモリの節約で読むデータを減らしたいときに有効になります。
 主に大規模言語モデルでは、512もしくは768に設定されることが多いです。


出力

 出力層では、学習されたベクトルが出力されます。

 入力された単語列がベクトルとなって出力層から出力されます。

 このベクトルを使って、文書分類や類似単語検索などを行う様々なタスクへと応用させます。


おわりに

 今回、BERTについて解説しました。文書分類や様々なタスクに応用が利くほか、追加の学習(微調整)で必要となるデータが少量でいいことが魅力となり革新的なAIモデルとなりました。

 しかし現在、GPT-4やBard、bingAIの登場によって、文書分類などのタスクをこなす文章生成モデルが登場してきたことで下火になってきた感じが多少ですがあります。また、langchainやLlamaIndexを使うことで単語や文章をベクトルに変換することも可能ですし、変換機としての役割も果たしてしまっています。Decoder部分でEncoderの役割まで網羅してしまうなんてすごいですわ(Encoderも使っているかも?よくわからないです)。

 ですがGPT-4などは微調整がまだできませんし、できるとしてもあそこまで大規模なもモデルであれば、対話データが大量に必要になってくる可能性があります。また、利用にお金がかかる点でBERTがまだ活躍できる場は全然あります。

 現在、研究でGPT-4を使っての文章分類を試験的に行っていますが、BERTをも超える場合があると感じているのも確かです。しかも分類した理由まで説明してくれるもんですから感激しました。

 これからもいろんなAIが登場してくると思うので、楽しみですね。

 では。

ps.最近、粉瘤らしきものができて気になってる。手術怖い。