7
11

More than 1 year has passed since last update.

LLAMA2を使った自作Chatbotを自宅PCで作成してみた

Posted at

Llama2とは

Meta社が開発した商用利用可能なLLM(大規模言語モデル)

3つの事前学習モデル

 70億(7B)のパラメーターで学習されたモデル
 130億(13B)のパラメーターで学習されたモデル
 700億(70B)のパラメーターで学習されたモデル

一般的には、パラメータ数が多いほど回答の精度が高くなるが、膨大になると計算コストがかかる。
 ※計算コストとは、より高性能なグラフィックボード(GRAM)が必要になったり、回答出力までの時間がかかる 等

 chatGPTのモデルの大きさについてはこちらの記事を
 https://meditech-ai.com/gpt-ai-evolution/

LLAMA2 量子化モデル

とはいえ、いわゆるチャットAIモデルを動作させるために、十~数百GBのVRAMなど非常に高いマシンスペックを要求するのが一般的。※Meta社に直接申請してダウンロードしたモデルは、うちのPCだとスペック不足でダメでした(そもそもGPU複数枚刺し前提)
そこで量子化という手法を用いることで、モデルを軽量化することによって、本来の要求スペックより引くいスペックのマシンでも動作可能とした。

そもそも量子化とは

下記が一番簡潔でわかりやすかった

・TensorFlowやPyTorchのフレームワークで扱われるモデルは、32ビット浮動小数点精度(float型)の配列で表現される。この32ビットがサイズを大きくする要因
・このビット数を8ビットや4ビットでの表現に置き換えることによってサイズを圧縮する。

実装

進め方やコードはほとんど下記の方の引用です。

モデルのダウンロード

下記から量子化されたモデルをダウンロードします。
※今回はllama-2-7bの中でも、「llama-2-7b-chat.ggmlv3.q4_K_M.bin」をチョイス

※選定基準

こちらの記事を基に決定

ライブラリ

pip install  gradio
pip install llama-cpp-python

pip install llama-cpp-python の前に
CMAKEのインストールや、環境変数の設定がいるかも

$env:CMAKE_ARGS = "-DLLAMA_OPENBLAS=on"
$env:FORCE_CMAKE = 1

全コード

import gradio as gr
from llama_cpp import Llama

##日本語も英語に変換してから扱うために入れた翻訳ライブラリ
from deep_translator import GoogleTranslator

model_path = "model/llama-2-7b-chat.ggmlv3.q4_K_M.bin"
llama = Llama(model_path)

def predict(message, history):
    messages = []
    for human_content, system_content in history:
        message_human = {
            "role":"user",
            "content": human_content+"\n",
        }
        message_system = {
            "role":"system",
            "content": system_content+"\n",
        }
        messages.append(message_human)
        messages.append(message_system)
    message_human = {
        "role":"user",
        "content":message+"\n",
    }
    messages.append(message_human)
    # Llama2回答
    streamer = llama.create_chat_completion(messages, stream=True)
    

    partial_message = ""
    for msg in streamer:
        message = msg['choices'][0]['delta']
        if 'content' in message:
            partial_message += message['content']
            yield partial_message

    #translated = GoogleTranslator(source='auto',target='ja').translate(partial_message)
    #return translated

gr.ChatInterface(predict).queue().launch()

ちょっと解説

yield partial_message

yieldとは、関数を一時的に実行停止させることが出来る機能を持つ文
つまりは、その時点での値をreturnして、また続きの処理を再開する。

for msg in streamer:
        message = msg['choices'][0]['delta']
        if 'content' in message:
            partial_message += message['content']
            yield partial_message

これによって回答が少しずつ描画されていくような演出になる。
※ほんとはメモリ節約のためとかに使用されるらしい
yield_image.JPG
まとめて表示したい場合はfor分を抜けた後に
return partial_message

とする。

最後に

こんな簡単に実装できるとは・・

7
11
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
11