コムセント 技術情報

  1. TOP
  2. コムセント 技術情報
  3. 大規模言語モデルを利用してローカルで動作するAIChatBotを作成する

大規模言語モデルを利用してローカルで動作するAIChatBotを作成する

言語モデルとは

そもそも言語モデルとは、ChatGPTに代表される、テキストを入力すると、それに対する妥当な返答を返すAI技術の中核となるもので、各単語などの繋がりや意味的に近いかどうかなどを数学的に表したものを集合させたものです。このモデルは基本的に習得させている単語の数や繋がり情報の数が増えれば、精度が高くなると言うのは何となく想像が付くと思います。知らない単語が多すぎては答えようも無いですから。

この言語モデルのうち、単語数や繋がり情報の数(パラメータ数)を物凄く膨大にしたものが大規模言語モデルとされていて、概ね70億以上のパラメータから構成されているものを大規模言語モデル(LLM)とすることが多いように思います。
非常によく使われているChatGPTは、3.5の段階で1350億という桁違いに多いパラメータ数でしたので、70億でも相当多いように感じますが、大規模言語モデルの中では小さいモデル、ということになります。

現在の大規模言語モデル

現在の大規模言語モデルにおいては、パラメータ数が多いほど精度が高いとされているため、より多くのパラメータを入れ込むことで精度を上げていくアプローチの一方で、少ないパラメータでありながら、高精度を実現するための技術もさまざまな研究成果から実現し始めています。
パラメータ数が多いということはモデルのサイズ自体が大きくなります。そのためそれを用いて計算をする場合にも膨大なパワーが必要となりますが、モデルサイズが小さくなれば、パワーは少しでも済むことになります。
つまり、理想的にはモデルサイズを可能な限り小さくしつつ、精度を高めるという相反するモデルが実現できれば良いのですが、現状ではまだなかなか難しいところです。研究は進んでいて、実際にパラメータ数はChatGPTよりも大幅に少ないにも関わらず、精度は同等というモデルも登場してきています。

モデルサイズが小さくなれば、自分のPC上やスマートフォンでChatGPTと同じようなことができる可能性もあり、そうなるとセキュリティや情報漏洩などの危険を考えずに利用することができるほか、他のシステムに組み込んでより利便性の高い仕組みを作っていくことも可能です。

AIChatBotの作成

既にある程度のスペックのPCがあれば、自分で大規模言語モデルを取得してAIChatBotを作成することが可能です。
自分で大規模言語モデルを作成するのは、正直無理なので、条件付きながらも配布されている大規模言語モデルを利用するのがベストでしょう。

今回は、Meta社が提供しているLlama2をベースに株式会社ELYZAが公開した「ELYZA-japananese-Llama-2-7b」を利用します。元々のLlama2は英語が主で、基本的に英語を返答としては返してきます(日本語の理解はされます)。ELYZA-japananese-Llama-2-7bは日本語の追加事前学習モデルになっているため、日本語の利用に特化しています。
PCに物理メモリが16GB以上(できれば32GB以上)必要になります。GPUを使わずにCPUだけで演算をするので、かなり遅いです。(GPUを使うように設定することも可能です。設定すると、それなりに高速になります)

末尾の7bというのはパラメータ数を示し、Llama2では7B,13B,70Bの3種類あります。もっとも、13B辺りから普通のPCでは動作できなくなり、70Bでは相当な構成にする必要があり、一般的なPCで動かすのは現実的ではありません。精度は落ちますが、現状では7Bを使っておくのが無難です。更に量子化という処理をすることで、精度は若干落ちますが、より高性能なスペックが無いPCでも動作することができるようになっています。

作成には、Pythonを利用するのが楽です。もちろん他の言語からも利用が可能ですが、一番手間が掛からないのはPythonなので、今回はPythonから利用します。

言語と下準備

Pythonを言語としては利用しますが、今回はC言語用のコンパイラが必要です。一番簡単なのは、Windows環境の場合、VisualStudioをインストールし、C言語のコンパイラをインストールしておくのが簡単です(インストール時の設定で、「オプション」項目を開き、「最新の v143 ビルドツール用 C++ATL(x86 および x64)」と「最新の v143 ビルドツール用 C++MFC(x86 および x64)にもチェックを入れてインストールしておきます)。ライセンス規約に抵触しないのであれば、Community版で問題ありません。mac環境では、Xcodeをインストールしておきます。
Python3系列の最新版をダウンロードしてインストールしておきます。pipも忘れずにインストールしておきます。

モデルをダウンロードしておきます。
https://huggingface.co/mmnga/ELYZA-japanese-Llama-2-7b-fast-instruct-gguf/tree/main
へアクセスし、ELYZA-japanese-Llama-2-7b-fast-instruct-q8_0.ggufをダウンロードしておきます。これは7B(70億)のパラメータで、8Bit量子化を行なっているモデルです。

pipで必要なツールを入れていきます。ターミナルなどを起動して、

$pip install llama-cpp-python
でllama.cppというモデルを読み込んで使えるようにしてくれるC++言語のライブラリーを導入します。同時にllama.cppを使うためのPython用ライブラリも導入されます。

導入が終わったらPythonを書いていきます。旧来のllama-cpp-pythonはGGML形式に対応していましたが、現在のllama-cpp-pythonはGGUF形式のみに対応しています。もし、GGML形式のモデルを使いたい場合は、変換が可能なのでGGUF形式に変換すれば使用することが可能です。

!/usr/bin/env python3
import sys
import os
from llama_cpp import Llama
sys.stdout.reconfigure(encoding='utf-8')

#プロンプトを記入
prompt = """You are a helpful, respectful and honest assistant. Always answer as helpfully as possible, while being safe.
Your answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content.
Please ensure that your responses are socially unbiased and positive in nature.
If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct.
If you don't know the answer to a question, please don't share false information.
"""+ここにプロンプトを記入+"""
Assistant:"""
# スクリプトのディレクトリを取得
script_dir = os.path.dirname(os.path.realpath(__file__))
model_path = os.path.join(script_dir, "models", "ELYZA-japanese-Llama-2-7b-fast-instruct-q8_0.gguf")

llm = Llama(model_path=model_path)

# 生成実行
output = llm(prompt,max_tokens=500)
output_res = output['choices'][0]['text']
print(output_res)

「ここにプロンプトを記入」のところで、聞きたいことを入力して実行すれば結果が表示されます。
ただ、これだと、単発の会話で終わってしまい、ChatGPT的な言葉の流れを考慮した結果は得られません。流れを考慮した結果を得るためには、会話の内容を保存しておいて、毎回質問を投げるときに合わせて保存している会話の内容を与える必要があります。

文脈を考慮したパターン

!/usr/bin/env python3
import sys
import os
from llama_cpp import Llama
sys.stdout.reconfigure(encoding='utf-8')

messages = list()#会話履歴を保存する配列

#プロンプトを記入

prompt = """You are a helpful, respectful and honest assistant. Always answer as helpfully as possible, while being safe.
Your answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content.
Please ensure that your responses are socially unbiased and positive in nature.
If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct.
If you don't know the answer to a question, please don't share false information.
"""+ここにプロンプトを記入+"""
Assistant:"""

#スクリプトのディレクトリを取得
script_dir = os.path.dirname(os.path.realpath(file))
model_path = os.path.join(script_dir, "models", "ELYZA-japanese-Llama-2-7b-fast-instruct-q8_0.gguf")

llm = Llama(model_path=model_path)

chat_completion_message: ChatCompletionMessage = dict(role="user", content=prompt)
messages.append(chat_completion_message)
output = llm.create_chat_completion(messages=messages)
output_res = output['choices'][0]['message']
print(output_res["content"])

if output_res["role"] == "assistant":
    chat_completion_message = dict(role="assistant", content=output_res["content"])
    messages.append(chat_completion_message)

のようにして、配列に双方の入力内容を格納し、都度モデルに与えることで文脈を考慮した結果を受け取ることができます。

このサンプルでは、CPUだけの処理になっているため、結果が得られるまでそれなりに時間が掛かります。もし、高速化したい場合は、GPUを使うようにするなど設定を変えてみてください。
7Bモデルを使っているため、精度はイマイチですが、必要に応じて追加学習を行なうことで、ある程度特化した汎用的なモデルにしていくことも可能でしょう。

まとめ

なかなか個人レベルですと、実用的な速度で動かすのは難しいところもありますが、モデルさえ手に入れば比較的簡単に作成できることがわかるのでは無いでしょうか?
他にもモデルはいろいろと登場しています。自分にとって適切と思えるようなモデルを選択して、使ってみるのも手でしょう。

おすすめ記事