local LLMをChatGPT API互換サーバとして使う方法まとめ(2023/10版)

# はじめに

openai chat completions api(以下ChatGPT API)を使っているが、コストダウンやドメインに特化したfinetuneモデルを使いたいといったニーズでlocal LLMを使いたいというニーズがあると思います。
その場合に、ChatGPT APIを利用する側のアプリケーションコードはそのままで、local LLMをサーバとしてたてて、使用するLLMだけ変えるという実現方法が考えられます。
幾つか良い実現方法があったため、現状、どのようなツールを使用して実現できるか簡単にまとめました。

ところで、偉い人に「うちもChatGPT作って」と言われた時、あなたならどうしますか？
（その答えの一つを「おわりに」に書きました）

# 解説

ChatGPT API互換サーバを作る場合、自分でlocal LLMをラップしてAPIサーバを実装してしまうことも考えられますが、そんなことをしなくても簡単に以下の方法でlocal LLMをChatGPT API互換サーバとしてたてることが可能です。
- text-generation-webuiを使ってlocal LLMをChatGPT API互換サーバとしてたてる
- FastChatを使ってlocal LLMをChatGPT API互換サーバとしてたてる
- LiteLLMを使ってChatGPT API互換サーバをたてる

他にも探せばありそうですが、一旦上記3つをご紹介します。

## 動作確認環境
python 3.10.8
ubuntu 20.04

## text-generation-webui

https://github.com/oobabooga/text-generation-webui

### 特徴
- webuiのお試し利用の延長でChatGPT API互換APIサーバとして利用可能
- llama.cppでCPUでもそれなりに動くモデルをlocal LLMとしてホストできる
- 高速なexllamaも動く
- RTX3060のようなスタンダードなGPUメモリのグラボを使用している人で通常ならGPUメモリにのりきらないモデルでも、GPUオフロード(--n-gpu-layersを指定)でGPUメモリにのせるモデルをレイヤ単位で細かく調整して動かすことができる
- condaベース(conda必須というわけではない)

### install
```
git clone https://github.com/oobabooga/text-generation-webui.git
git checkout ef1489cd4d0ecd192c9d68bc5cc740f7c018076e
```

### mistral-7b-instructをChatGPT API互換サーバとして起動
ここではmistral-7b-instructを例にします。お好きなモデルで大丈夫です。

#### mistral-7b-instructモデルをdownload

https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.1-GGUF

Files and Versionsタブから以下をダウンロードします。
- config.json
- Mistral-7B-instruct-v0.1.Q4_K_S.gguf

ダウンロードしたファイルを以下に配置します。
text-generation-webui/models/mistral-7b-instruct

#### APIサーバ起動
```
export OPENEDAI_PORT=8000
./start_linux.sh --extensions openai --listen --loader llama.cpp --model mistral-7b-instruct
```

GPUを使う場合
```
export OPENEDAI_PORT=8000
./start_linux.sh --extensions openai --listen --loader llama.cpp --n-gpu-layers 40 --model mistral-7b-instruct
```

初回起動はcondaのsetupで時間がかかりますが、2回目以降は手元の環境でGPUを使う場合で数秒で以下の通りopenai互換サーバが起動しました
```
2023-10-27 02:48:49 INFO:Loading mistral-7b-instruct...
2023-10-27 02:48:49 INFO:llama.cpp weights detected: models/mistral-7b-instruct/mistral-7b-instruct-v0.1.Q4_K_S.gguf
2023-10-27 02:48:49 INFO:Cache capacity is 0 bytes
...
llama_new_context_with_model: total VRAM used: 10109.56 MB (model: 3877.55 MB, context: 6232.00 MB)
AVX = 1 | AVX2 = 1 | AVX512 = 0 | AVX512_VBMI = 0 | AVX512_VNNI = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | F16C = 1 | FP16_VA = 0 | WASM_SIMD = 0 | BLAS = 1 | SSE3 = 1 | SSSE3 = 1 | VSX = 0 | 
2023-10-27 02:48:52 INFO:Loaded the model in 2.79 seconds.
2023-10-27 02:48:52 INFO:Loading the extension "openai"...
2023-10-27 02:48:52 INFO:Loading the extension "gallery"...
OpenAI compatible API ready at: OPENAI_API_BASE=http://0.0.0.0:8000/v1
Running on local URL:  http://0.0.0.0:7860

To create a public link, set `share=True` in `launch()`.
```

ちなみに、GPUを使って手元の環境で秒間40tokenぐらい出てました。

## FastChat

https://github.com/lm-sys/FastChat

### 特徴
- APIサーバとcontrollerとworkerでサーバが分かれてていてるので、初見は少し複雑に見える
- キューをはさんでいるので、安定なAPIサーバを構築可能
- キュー制御にラウンドロビンと、キュー長を見る方法を選べる
- transformersベースで、自動的にモデルをダウンロードしてきてくれるので、ささっと使える
- LangChainやPEFTもサポート

### セットアップ手順
```
pip3 install fschat==0.2.31
```

### vicuna-7b-v1.5をChatGPT API互換サーバとして起動
ここではvicuna-7b-v1.5を例にします。お好きなモデルで大丈夫です。
以下でChatGPT API互換サーバが起動します。
```
python3 -m fastchat.serve.controller

python3 -m fastchat.serve.model_worker --model-names "gpt-3.5-turbo,text-davinci-003,text-embedding-ada-002" --model-path lmsys/vicuna-7b-v1.5 --load-8bit

python3 -m fastchat.serve.openai_api_server --host localhost --port 8000
```

### 詳細情報
より詳しい情報の入手は、こちらの公式ドキュメントあたりから読むのが良いと思います。
[FastChat/docs/openai_api.md at main · lm-sys/FastChat](https://github.com/lm-sys/FastChat/blob/main/docs/openai_api.md)

## LiteLLM

https://github.com/BerriAI/litellm

### 特徴
- LiteLLM自体はChatGPT API互換proxyサーバで、単体ではlocal LLMのホスト機能はない。ollamaなどとの組み合わせで利用する。
- local LLMに限定されない
  - AWS Bedrockをサポートしていて(現状openaiよりAPI単価が安い)、アプリ側のIFを変えずにopenaiからAWS Bedrockに乗り換え利用が可能 
      - 例えば、しかたなくazure OpenAI使ってみたけどマルチクラウドはつらいのでAWSで閉じる形に戻したいケース
- open-interpreterのlocal LLM利用時に使われている
- loggingやmonitoringのサポートが良さそう

### セットアップ手順
```
curl https://ollama.ai/install.sh | sh
pip install litellm==0.12.5
```

### codellamaをChatGPT API互換サーバとして起動
ここではcodellamaを例にします。お好きなモデルで大丈夫です。
以下でopenai互換サーバが起動します。
```
ollama serve
ollama run codellama
litellm --model ollama/codellama
```

### 詳細情報
より詳しい情報の入手は、こちらの公式ドキュメントあたりから読むのが良いと思います。
[💥 LiteLLM Server - Deploy LiteLLM | liteLLM](https://docs.litellm.ai/docs/simple_proxy)

## ChatGPT API利用側アプリケーションの修正例

### ChatVRM

https://github.com/pixiv/ChatVRM

ChatVRMはPixiv様が開発されているオープンソースのアバターチャットツールです。
以下の、軽微な修正だけで簡単にlocal LLMを使うように修正できます。

```
git clone https://github.com/pixiv/ChatVRM.git
git checkout d1412db27cddcb09a03a00c0a52dc89c0f01e249
```

[元のコード](https://github.com/pixiv/ChatVRM/blob/d1412db27cddcb09a03a00c0a52dc89c0f01e249/src/features/chat/openAiChat.ts#L41-L45)
```
  const res = await fetch("https://api.openai.com/v1/chat/completions", {
    headers: headers,
    method: "POST",
    body: JSON.stringify({
      model: "gpt-3.5-turbo",
```

- text-generation-webui(mistral-7b-instruct)の場合の修正
```
  const res = await fetch("http://127.0.0.1:8000/v1/chat/completions", {
    headers: headers,
    method: "POST",
    body: JSON.stringify({
      model: "mistral-instruct-7b",
```

- FastChat/LiteLLMの場合の修正
```
  const res = await fetch("http://127.0.0.1:8000/v1/chat/completions", {
    headers: headers,
    method: "POST",
    body: JSON.stringify({
      model: "gpt-3.5-turbo",
```

ChatVRMの起動
```
npm install
npm run dev
```

APIキーを聞いてきますが、使われないので何かいれれば大丈夫です。
以下はfastchatを使ってfinetune済のLoRAをChatGPT API互換サーバとして起動してアバターとチャットしている例です。
![スクリーンショット 2023-10-27 034557.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116075/d483757a-0216-22c4-2ed1-2e71c539c286.png)

Elyza-7Bを絶対服従ずんだもんギアス(finetune)をかけてjailbreakして爆弾の作り方を教えてもらおうと遊んでたけどうまくfinetuneできなかったです（何やってんだワイ・・・？）

(興味のある人向けに論文リンク貼っておきます)
[[arxiv] FINE-TUNING ALIGNED LANGUAGE MODELS COMPROMISES SAFETY, EVEN WHEN USERS DO NOT INTEND TO!](https://arxiv.org/abs/2310.03693)

https://llm-tuning-safety.github.io/

ChatVRMはChatGPT APIを使う前提となっていますが、openaiに課金する必要があるため、自分の好きなアバターとお話してみたいし興味はあるけど、どれだけお金がかかるかわからないし、お金を払ってまで動かしてみるのは躊躇してしまっていた人も多いのではないでしょうか。
グラボを持っていなくてもCPUでもそれなりに動くLLMモデルがありますし、好きなだけ自分の好きなアバターとお話しても、かかるのは電気代だけです。ですので、気のすむまでお話してみてください。
自分好みにアバターをカスタムしたい場合は、少し前に書いて若干古くなってしまいましたが、こちらの記事を確認してみてください。

https://qiita.com/takaaki_inada/items/9a9c07e85e46ec0e872e

# おわりに
今後、local LLMをAPIサーバとしてホストしたいというニーズはエンタープライズ、AIベンチャー、SaaS、あらゆるところで出てきて、求められるスキルになると思います。
特に次に急速な進化が予測されるAIAgent、MultiAgentを扱っていくうえでも必要になってくる技術でもあると思いますので、アンテナを貼っておくと良いと思います。

解説で紹介した通り簡単にopenai互換サーバをたてられますので、いざとなって、例えば偉い人に「うちもChatGPT作って」と言われた時でも、慌てずに、ぱぱっとそれできますよ（キリッ）と言えそうです。認証画面をcongitoかazure adのありあわせのものぱくってきて上記のコード動かしとけばいいんです。というわけで、覚えておいて損はないと思います。
変化も激しく数か月後には状況は変わっていると思いますし、あくまで現状はこういう方法がありますという紹介の記事になりますが、お役に立てれば幸いです。