ローカル環境下にオープンソースのLLMを入れてみた

ローカル環境下にオープンソースのLLMを入れてみた

システム部の大類と申します。
今回は、オープンソースのLLMをローカル環境で動作検証したことを記事にしたいと思います。

オープンソースのLLMをローカル環境下で動作検証した理由

ローカルでオープンソースのLLMを試してみたかった理由は、オープンソースが好きだからです。

検証のポイント

検証のポイントとして、以下を設定したいと思います。

① GPUのないノートPC環境でどの程度の応答速度が出せるか。
② 簡単な質問にどの程度回答できるか。
③ 簡単なSQL作成の依頼にどの程度応えられるか。
④ 記述回答式のアンケート設問に対して、不適切な回答を見つけられるか。また、肯定的な回答か否定的な回答かの判別ができるか。

上記①から③は、簡単な性能の調査です。

④は、弊社が市場調査におけるリサーチプラットフォームをサービスとして提供している会社であることから、自社サービスに利用できないかを調べるために追加しました。

検証方法

Ollamaでの検証

ローカルPCで生成AIを動作させる一番の問題は、グラフィックボードがないことです。ただ、グラフィックボードがない環境でも、CPUでこれに代わって動作させる方法があるようなので、これを利用します。
方法としては、簡単にローカル環境下で使用でき、MITライセンスで「Llama2」などが使えるOllamaを使って検証することにしました。
(私物の古いPCで「LM Studio」上で日本語の追加学習をした「ELYZA」の動作も試しました。しかし、PCの性能が低すぎ、レスポンスがあまりに遅かったため、今回は、上記のみを記事にしました。)

ymlファイルの作成

以下のとおり、ymlファイルを作成します。

docker-compose.yml

version: '3'
services:
 ollama:
   image: ollama/ollama
   ports:
     - "11434:11434"
   volumes:
     - ollama:/root/.ollama
volumes:
 ollama:

コンテナの作成、起動

上記のymlファイルを保存したディレクトリに移動し、コンテナの作成、起動をします。

% docker-compose up -d

コンテナへの接続、Llama2の起動

コンテナIDを取得します。

% docker container ls
CONTAINER ID   IMAGE           COMMAND               CREATED         STATUS         PORTS                      NAMES
4772a0c9404d   ollama/ollama   "/bin/ollama serve"   2 minutes ago   Up 2 minutes   0.0.0.0:11434->11434/tcp   ollama-ollama-1

コンテナへ接続します。

% docker container exec -it 4772a0c9404d bash

Llama2を起動します。

# ollama run llama2:13b

Ollamaでは、パラメータのサイズを選択できます。上記は、13B(130億)で動かす方法です。なお、7B(70億)で動かす方法は、以下です。
※ 今回の検証結果は、すべて13Bで動かした結果です。

# ollama run llama2

これで、ローカル環境下でLlama2を使えます。
続いて、履歴を保存しないように設定します。

>>> /set nohistory

検証

では、早速検証をしてみます。

応答速度

今回、検証に使用した環境は、以下です。
  チップ:Mac M1
  メモリ:16GB(Dockerへの割当、15GB)
この環境で、7Bで動作させ、4.2.や4.3.記載程度の質問であれば、それほど時間がかかりません。しかし、それ以外の場合は、スペックからすれば予想どおりですが、非常に遅く、質問から回答まで数分かかりました。

簡単な質問にどの程度回答できるか

まず、簡単な質問をしてみます。答えの正確性を理解しやすい問いにしてみました。

>>> PythonとKotlinの特徴を教えて下さい。日本語で回答してください。

Llama2の回答は、以下です。

PythonとKotlinは、両方共に高度なプログラミック言語であり、それぞれ独特の特徴を持っています。以下は、PythonとKotlinの主な特徴の比較です。

  1. syntax
    Pythonのsyntaxは、やさしく柔軟で、簡潔です。単純な文法を使用し、フォーマットされたコードを作成することができます。一方、Kotlinのsyntaxは、よりstrongly typ
    inferenceをサポートしています。これにより、コードが読みやすくなり、バグを発見することが容易になります。
  2. type system
    Pythonは、dynamic typingのため、型情報を厳密に管理することができません。一方、Kotlinは、statically typedのため、コードの型情報を厳密に管理することができます。これにより、バグを発見しやすくなり、コードの可読typedのため、コードの型情報を厳密に管理することができます。これにより、バグを発見しやすくなり、コードの可読性を高めることができます。
  3. null safety
    Kotlinは、null pointer exceptionを防止するため、null safetyメカニズムを持っています。これにより、nullポインターを使用しないことができます。一方、Pythonは、null pointer
    exceptionを防止する機能を持っていません。
  4. concise code
    Kotlinは、極端に短いコードを作成することができます。一方、Pythonのコードはやや長めです。
  5. performance
    Kotlinは、Java Virtual Machine (JVM) 上で実行されます。これにより、高度なパフォーマンスを提供します。一方、Pythonは、CPyth
    interpreterによって実行されます。これにより、やや遅いパフォーマンスを提供します。

以上です。 PythonとKotlinの特徴の比較です。どちらも高度なプログラミック言語であり、使い分けることができます。

「type system」とは何かと思いましたが、翻訳すると、「型システム」となるんですね。個人的には、分かりやすく2つの言語の特徴を表現しているように思えました。

 簡単なSQL作成の依頼にどの程度応えられるか

SQLの作成を依頼して、結果を確認します。

>>> #お願い
… あなたはSQLに精通したエンジニアです。
… SQLを作成して下さい。

… #情報
… ・動作環境:MySQL
… ・SQL:日ごとのsales_amountの合計金額
… ・テーブル

… sales_history:
… order_id sales_amount order_date
… o001 1000 2023/8/1
… o002 2000 2023/8/1
… o003 500 2023/8/1
… o004 3000 2023/8/2

… #出力
… 【SQL】
… 【上記SQLの実行結果】

Llama2の回答は、以下です。

Sure! Here’s the SQL query to retrieve the total sales amount for each day:

sql
SELECT DATE(order_date) AS date, SUM(sales_amount) AS total_sales
FROM sales_history
GROUP BY date

This query joins the sales_history table and groups the results by the date of the order (using the DATE() function). The SUM() function calculates the total sales amount for each group.

The output will be a table with two columns: date and total_sales. Each row in the table will represent one day, with the total sales amount for that day. For example:

date               | total_sales
2023-08-01  | 3500
2023-08-02  | 3000

This shows that on August 1st, the total sales amount was 3500, and on August 2nd, the total sales amount was 3000.

回答が英語になってしまいましたが、一応正しい回答を返してきました。

記述回答式のアンケート設問に対しての回答チェック(対応のチェック)

いくつか回答に違う値を入れて、不適切な回答を見つけられるかを試してみます。

① キーボードを適当に打鍵している場合(例えば、「あああ」のように、回答のふりをしている場合)
② 質問と回答が対応していない場合

これを確認するために、Llama2に「質問に対しての回答が、有効なものかをチェックしてください。」と聞き、不適切な回答を見つけられるかをみてみます。

① キーボードを適当に打鍵した場合

>>> # 依頼
… 以下のアンケートの質問と回答があります。
… 質問に対しての回答が、有効なものかをチェックしてください。
… 回答は、「有効」か「無効」かのみを答えて下さい。

… # アンケートの質問
… 自動車の購入で重視するのは、どのような点ですか。

… # 回答
… あああいいう

Llama2の回答は、以下です。

# アンケートの質問
自動車の購入で重視するのは、どのような点ですか。
# 回答
無効(あああいいう)。

依頼では、「有効」、「無効」だけを返すように依頼したのですが、質問文も記載され、戻ってきてしまいました。

② 質問と回答が対応していない場合

Llama2のチェックの前提のアンケート設問の回答を「味と匂いです。」とした場合のLlama2の回答は、以下です。

# アンケートの質問
自動車の購入で重視するのは、どのような点ですか。
# 回答
無効(味と匂い)。

③ 適切な回答で、質問と回答が対応している場合

Llama2のチェックの前提のアンケート設問の回答を「燃費とデザインです。」とした場合のLlama2の回答は、以下です。

# アンケートの質問
自動車の購入で重視するのは、どのような点ですか。
# 回答
有効(燃費とデザイン)。

記述回答式のアンケート設問に対してのチェック(肯定的な回答かのチェック)

次に、肯定的な回答か否定的な回答かの判別ができるかどうかを試してみます。

① 肯定的な評価

まず、アンケート設問に対し、肯定的な回答をしたケースで判定します。

>>> # 依頼
… 以下のアンケートの質問と回答があります。
… 質問に対しての回答が、肯定的なものかをチェックしてください。
… 回答は、「肯定的」か「否定的」かのみを答えて下さい。

… # アンケートの質問
… 公道での喫煙を禁止されている地域が増えています。
… これについて、どう思いますか。

… # 回答
… みんなの健康的な生活を守るため、合理的な制度だと考えます。

Llama2の回答は、以下です。

# アンケートの質問
公道での喫煙を禁止されている地域が増えています。これについて、どう思いますか。
# 回答
肯定的(みんなの健康的な生活を守るため、合理的な制度だと考えます)。

② 否定的な評価

Llama2のチェックの前提のアンケート設問の回答を「煙草を吸う人の権利を侵害し、不当なものだと考えます。」とした場合のLlama2の回答は、以下です。

# アンケートの質問
公道での喫煙を禁止されている地域が増えています。これについて、どう思いますか。
# 回答
否定的(煙草を吸う人の権利を侵害し、不当なものだと考えます)。

評価

以上の分析の結果をもとに、個人的な評価をしたいと思います。

(1)応答速度
レスポンス速度は、ノートPCという制約があるため予想していたことですが、実用としては回答に数分かかったため厳しい状況でした。しかし、全く動かないということはありませんでした。
(2)簡単な質問への回答
Llama2は、まだ日本語部分が弱いためかもしれませんが、今一歩の状況と感じました。ただ、こちらも時間の問題で、あともう少しと期待の持てる回答でした。
(3)簡単なSQLの作成
今回、簡単なものしか試していませんが、速度的な問題が解決できれば、一定程度使用できるのではないかと感じました。
(4)記述式アンケート設問に対しての回答チェック
今回の簡単な質問と回答では、一定程度有意なチェックができました。ですが、質問や回答を変えると、うまく回答をできないものも多いようで、これを実用レベルにもっていくためには、別のライブラリを探すか、学習をさせなおすなどの改善をしなければ難しいと感じました。

今年もまた新しいOSSのLLMがでてくると思います。その際、是非また検証をしてみたいと考えています。

前の記事
«
次の記事
»

技術カテゴリの最新記事