猫も杓子もLLMの時代、一家に一台はLLMサーバーを持っておかないといけません。
というわけで、LLMを使えるAPIサーバーを立ててみました。
日本語LLMはELYZAさんのLlama-3-ELYZA-JPを利用しました。
Hugging Faceに記載されている通りに実行すれば、LLMをローカルで動かすことができます。
LM Studioというツールがあり、そのツールを使うと、モデルのダウンロードから、チャット利用、APIサーバーの起動までできますので、簡単に動かすことができます。
準備
LM Studioをインストールする。
左メニューからDeveloperを選択し、APIサーバーモードにする。
モデルをダウンロードする。
上部のSelect a model to loadを選択し、モデル名を入力して検索すると、Hugging Faceに登録されたモデルが出てくるので、選択します。 今回は
elyza/Llama-3-ELYZA-JP-8B-GGU
を入力します。左上のStatusのトグルボタンをクリックしてRunningにします。
これで準備完了です。 とっても簡単ですね。
APIの使い方
OpenAI API互換なのでとても簡単です。
import openai client = openai.OpenAI( base_url="http://localhost:1234/v1", api_key = "dummy_api_key" ) completion = client.chat.completions.create( model="dummy_model_name", messages=[ {"role": "system", "content": "あなたは誠実で優秀な日本人のアシスタントです。特に指示が無い場合は、常に日本語で回答してください。"}, {"role": "user", "content": "古代ギリシャを学ぶ上で知っておくべきポイントは?"} ] ) print(completion)
これを実行すると、結果が表示されます。
ストリーミングで使う
私の環境はノートPCで、Core i7-13620H 2.40GHz、32GB RAM、NVIDIA GeForce RTX4060 Laptop GPUという構成です。 上記のコードではレスポンスが返ってくるまでに20秒弱かかってしまうので、あまり実用的ではないですね。
ストリーミング機能を使って、レスポンスを改善できるか試してみます。 LM Studioのドキュメントのストリーミングのサンプルを少し変更して簡単にしたのがこちらです。
from openai import OpenAI system_prompt = "あなたは誠実で優秀な日本人のアシスタントです。特に指示が無い場合は、常に日本語で回答してください。" client = OpenAI(base_url="http://127.0.0.1:1234/v1", api_key="lm-studio") MODEL = "dummy_model_name" def process_stream(stream, add_assistant_label=True): """Handle streaming responses from the API""" collected_text = "" first_chunk = True for chunk in stream: delta = chunk.choices[0].delta # Handle regular text output if delta.content: if first_chunk: print() if add_assistant_label: print("Assistant:", end=" ", flush=True) first_chunk = False print(delta.content, end="", flush=True) collected_text += delta.content return collected_text def chat_loop(): messages = [ { "role": "system", "content": system_prompt } ] while True: user_input = input("\nYou: ").strip() if user_input.lower() == "quit": break messages.append({"role": "user", "content": user_input}) # Get initial response response_text = process_stream( client.chat.completions.create( model=MODEL, messages=messages, stream=True, temperature=0.2 ) ) text_in_first_response = len(response_text) > 0 if text_in_first_response: messages.append({"role": "assistant", "content": response_text}) if __name__ == "__main__": chat_loop()
入力から最初のレスポンスが返ってくるまでは一瞬で、それから全部の文章が表示し終わるまでに10秒強ほどとなりました。
これなら十分実用的に使えます。
システムプロンプトを変えれば、どんな種類の応答も実現できます。 プロンプトの書き方はいろんな記事があるので、参考にするとよいでしょう。