見出し画像

Llama.cpp の HTTPサーバー機能を試す

「Llama.cpp」のHTTPサーバー機能を試したのでまとめました。

・Mac M1


1. モデルの準備

今回は、「vicuna-7b-v1.5.ggmlv3.q4_K_M.bin」を使います。

TheBloke/vicuna-7B-v1.5-GGML
TheBloke/vicuna-7B-v1.5-16K-GGML
TheBloke/vicuna-13B-v1.5-GGML
TheBloke/vicuna-13B-v1.5-16K-GGML

2. ローカルPCでの実行

ローカルPCでの実行手順は、次のとおりです。

(1) Llama.cppのインストールとビルド。

$ git clone https://github.com/ggerganov/llama.cpp
$ cd llama.cpp
$ make

(2) modelsフォルダにモデルを配置。
今回は、「vicuna-7b-v1.5.ggmlv3.q4_K_M.bin」を使います。

(3) 推論の実行。

./main -m ./models/vicuna-7b-v1.5.ggmlv3.q4_K_M.bin --temp 0.1 -p "User:日本語で回答してください。富士山の高さは? Assistant:"
富士山の高さは3,776メートルです。 [end of text]

M1 Macでは、7Bは13.48トークン/秒、13Bは6.90トークン/秒でした。

3. HTTPサーバーの実行

Llama.cppのHTTPサーバーの実行手順は、次のとおりです。

(1) HTTPサーバーの起動。

$ ./server -m models/vicuna-7b-v1.5.ggmlv3.q4_K_M.bin -c 2048

(2) curlでの動作確認。

$ curl --request POST \
    --url http://localhost:8080/completion \
    --header "Content-Type: application/json" \
    --data '{"prompt": "User:日本語で回答してください。富士山の高さは? Assistant: ","n_predict": 128}'

{
    "content":"富士山の高さは、3,776メートルです。",
    "generation_settings":{
        "frequency_penalty":0.0,
        "grammar":"",
        "ignore_eos":false,
        "logit_bias":[],"mirostat":0,
        "mirostat_eta":0.10000000149011612,
        "mirostat_tau":5.0,
        "model":"models/vicuna-7b-v1.5.ggmlv3.q4_K_M.bin",
        "n_ctx":2048,
        "n_keep":0,
        "n_predict":128,
        "n_probs":0,
        "penalize_nl":true,
        "presence_penalty":0.0,
        "repeat_last_n":64,
        "repeat_penalty":1.100000023841858,
        "seed":4294967295,
        "stop":[],
        "stream":false,"temp":0.800000011920929,
        "tfs_z":1.0,
        "top_k":40,
        "top_p":0.949999988079071,
        "typical_p":1.0
    },
    "model":"models/vicuna-7b-v1.5.ggmlv3.q4_K_M.bin",
    "prompt":" User:日本語で回答してください。富士山の高さは? Assistant: ",
    "stop":true,
    "stopped_eos":true,
    "stopped_limit":false,
    "stopped_word":false,
    "stopping_word":"",
    "timings":{
        "predicted_ms":1469.095,
        "predicted_n":20,
        "predicted_per_second":13.613823476357894,
        "predicted_per_token_ms":73.45475,
        "prompt_ms":1720.364,"prompt_n":20,
        "prompt_per_second":17.43817006168462,
        "prompt_per_token_ms":57.34546666666667
    },
    "tokens_cached":50,
    "tokens_evaluated":30,
    "tokens_predicted":21,
    "truncated":false
}

serverのパラメータは、次のとおりです。

・--threads N, -t N : スレッド数
・-m FNAME, --model FNAME : モデルのパス (models/7B/ggml-model.bin)
・-m ALIAS, --alias ALIAS : モデルのエイリアスを設定。エイリアスはAPIのレスポンスで返される
・-c N, --ctx-size N : プロンプトのコンテキストサイズの設定
・-ngl N、--n-gpu-layers N : cuBLASの計算のために一部のレイヤーをGPUにオフロード。
・-mg i, --main-gpu i : メインGPU。cuBLASが必要 (default:GPU 0)
・-ts SPLIT, --tensor-split SPLIT : 複数のGPUにどのように分割するかを制御。「3,2」では、データの60% がGPU 0に割り当てられ、40%がGPU 1に割り当てられる (default:VRAMに比例して分割)
・-lv, --low-vram : 一時的な結果を保持するためにVRAMスクラッチバッファを割り当てない。パフォーマンス、特に迅速な処理速度を犠牲にしてVRAMの使用量を削減。cuBLASが必要
・-b N, --batch-size N : バッチサイズ (default:512)
・--memory-f32 : メモリのキーと値に16bit浮動小数点の代わりに32bit浮動小数点を使用 (非推奨)
・--mlock : モデルをメモリ内にロックし、メモリマップ時にモデルがスワップアウトされないようにする
・--no-mmap : モデルをメモリマップしない (default:メモリマップする)
・--lora FNAME : LoRAアダプタ
・--lora-base FNAME : LoRAアダプタのベースモデル
・-to N, --timeout N : サーバーの読み取り/書き込みタイムアウト (default:600(秒))
・--host : リッスンするホスト名/IPアドレス (default:127.0.0.1)
・--port : リッスンするポート (default:8080)
・--path : 静的ファイルの提供元のパス (default:example/server/public)
・--embedding : 埋め込み抽出を有効 (default:無効)

4. OpenAI APIからLlama.cppへの切り替え

OpenAI APIを利用していたコードを、環境変数の変更のみで、Llama.cppに切り替えることができるコード「api_like_oai.py」が提供されています。(completionsのみ)

(1) HTTPサーバーの起動。

$ ./server -m models/vicuna-7b-v1.5.ggmlv3.q4_K_M.bin -c 2048

(2) 「examples/server/api_like_oai.py」の編集。
「api_like_oai.py」のエンドポイントのパス (@app.route()) を、OpenAI APIを利用していたコードの設定 (デフォルトは「/engines/text-davinci-003/」) に応じて追加します。

・completions

@app.route('/chat/completions', methods=['POST'])
@app.route('/v1/chat/completions', methods=['POST'])

@app.route('/engines/text-davinci-003/completions', methods=['POST'])
@app.route('/completions', methods=['POST'])
@app.route('/v1/completions', methods=['POST'])

・chat/completions


@app.route('/chat/completions', methods=['POST'])
@app.route('/v1/chat/completions', methods=['POST'])

@app.route('/engines/text-davinci-003/chat/completions', methods=['POST'])
@app.route('/chat/completions', methods=['POST'])
@app.route('/v1/chat/completions', methods=['POST'])

(3) 「examples/server/api_like_oai.py」の起動。

$ python examples/server/api_like_OAI.py

(4) OpenAI APIの呼び出し元に「openai.api_base = "http://localhost:8081"」を追加。
OpenAI APIキーは使用しないので、空文字を指定しています。

・test.py

import openai

# APIキーの設定
openai.api_base = "http://localhost:8081"
openai.api_key = ""

# 推論
response = openai.Completion.create(
    engine="text-davinci-003", 
    prompt="User:日本語で回答してください。富士山の高さは? Assistant:")
print(response['choices'][0]['text'])

(5) OpenAI APIの呼び出し元の実行。

$ python test.py
富士山の高さは、3,776メートルです



この記事が気に入ったらサポートをしてみませんか?