LangServe×Ollamaを使ってローカルPCでLLMサーバーを立ち上げてみる

## はじめに
LangServeはLangChainをREST APIとしてデプロイするのに役立つツールです。LangServeはFastAPIで構築されており、pydanticによる検証が可能です。(公式日本語訳)

https://python.langchain.com/docs/langserve/

今回は技術調査も兼ねてLangServeでLLMサーバーを立ち上げ、特徴について記事にまとめます。

使用技術は以下です。

- LangChain
- LangServe
- Ollama
- FastAPI
- (LangSmith)

::: note 
API使用料などかからず、全て無料でできます。
:::

:::note warn 
N番煎じの内容ですが、ご容赦ください🙇‍♂️
:::

## 環境構築
まずはじめに仮想環境へライブラリをインストールします。
```bash 
(仮想環境)$ pip install langchain "langserve[all]" fastapi pydantic==1.10.13
```

次にローカルPCでLLMサーバーを立ち上げるということで、Ollamaをダウンロードします。

https://ollama.com/

![スクリーンショット 2024-05-01 9.57.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/468ee310-5acd-7bf1-6d57-904232a89053.png)


ダウンロードしたら、Ollamaの指示通りにインストールまで行ってください。

今回はOllamaを用いてLlama3の8Bを使ってみます。

CLIで以下のように`llama3`を事前にpullしておきます。

```bash 
% ollama pull llama3
```

他モデルの情報は以下です。([公式のGitHubのREADME](https://github.com/ollama/ollama)から転用)

| Model                | Parameters | Size   | Download                        |
|----------------------|------------|--------|----------------------------------|
| Llama 3              | 8B         | 4.7GB  | ollama run llama3               |
| Llama 3              | 70B        | 40GB   | ollama run llama3:70b           |
| Phi-3                | 3.8B       | 2.3GB  | ollama run phi3                 |
| Mistral              | 7B         | 4.1GB  | ollama run mistral              |
| Neural Chat          | 7B         | 4.1GB  | ollama run neural-chat          |
| Starling             | 7B         | 4.1GB  | ollama run starling-lm          |
| Code Llama           | 7B         | 3.8GB  | ollama run codellama            |
| Llama 2 Uncensored   | 7B         | 3.8GB  | ollama run llama2-uncensored    |
| LLaVA                | 7B         | 4.5GB  | ollama run llava                |
| Gemma                | 2B         | 1.4GB  | ollama run gemma:2b             |
| Gemma                | 7B         | 4.8GB  | ollama run gemma:7b             |
| Solar                | 10.7B      | 6.1GB  | ollama run solar                |

公式からの目安として、7Bのモデルは8GBのRAM、13Bのモデルは16GBのRAM、33Bのモデルは32GBのRAMが必要です。

Ollamaのモデルライブラリにもう少し詳しい情報がまとまっています。

https://ollama.com/library



## LangServe×Ollamaを使ってローカルPCでLLMサーバーを立ち上げるプログラム
LangServe×Ollamaを使ってローカルPCでLLMサーバーを立ち上げるプログラムは以下です。

```main.py
from fastapi import FastAPI
from langchain_community.llms import Ollama
from langserve import add_routes

app = FastAPI(
    title="LangChain Server",
    version="1.0",
    description="A simple api server using Langchain's Runnable interfaces",
)

add_routes(
    app,
    Ollama(model="llama3"),
    path="/chat",
)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="localhost", port=8000)
```

## 使い方について
### サーバーの立ち上げ
```bash 
$ python main.py
```
上記で`http://localhost:8000/`にサーバーが立ち上がります。

### ドキュメント
`http://localhost:8000/docs`にアクセスすればAPI一覧が確認可能です。
　 
![スクリーンショット 2024-04-30 17.12.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/ade6dd61-ab11-b3bd-1a3a-53586ad41abe.png)

ちなみにSwaggerの「Try it out」を押せば簡単にテストできます。（POSTメソッドの時はパラメータを適宜入力してください。）

![スクリーンショット 2024-05-01 10.14.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/33a662c4-0964-27a2-fd3d-bacbe0644915.png)

FastAPIでアプリを立ち上げているので、`http://localhost:8000/redoc`でも確認可能です。

![スクリーンショット 2024-04-30 17.25.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/d0123408-9f0b-7cad-0af1-06b0d5be994f.png)

### curlコマンド
ローカルLLMをAPIとして使う場合、例えば`curl`コマンドを用いて以下のように使います。

```bash 
curl -X 'POST' \
  'http://localhost:8000/chat/invoke' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "input": "好きなメッセージを入れてください",
  "config": {},
  "kwargs": {}
}'
```

### playground
`http://localhost:8000/{設定したパス}/playground/`にアクセスすれば、Chat形式のUI上で簡易的なテストが可能です。

![スクリーンショット 2024-04-30 17.17.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/858bbe95-505c-d2fe-6611-1084eb45c147.png)

ちなみに回答は以下のように得られます。

![スクリーンショット 2024-04-30 17.17.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/1541446a-dc69-2f8b-26b7-e06bee474074.png)


## LangServeの特徴
先述したFastAPIとpydanticとの関連については除いて特徴を記述します。

### ローコードで構築が可能
LangServeを使えば少ないコード記述量でサーバーを構築できます。

またドキュメントで確認しましたが、デフォルトでAPIが複数設定されていることがわかります。（注: APIは本数が多ければ多いというわけではありませんが。）

LangServeを使用しない場合は、FastAPIの`APIRouter`を用いてルーティングを定義する必要があるなど、コード記述量が増えてしまいます。（一方で詳細かつ厳密なコーデングが要求される場合は、どちらを用いるべきかを精査する必要があります。）

### LangSmithとの接続が容易
LangSmithとはLangChain運用時の便利ツールであり、LLMのトークン数や出力、レイテンシなどを確認することができます。

LangSmithの使用には、API Keyが必要です。

以下リンクからアカウントを作成してAPI Keyを取得します。

https://smith.langchain.com/


![スクリーンショット 2024-05-01 10.35.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/a1a35b7b-c56b-75b3-0496-a14467445c05.png)

API Keyを取得したら以下のように環境変数に入れてください。

```bash 
export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="..."　//API Key
```

次にプロジェクト名（プロジェクトとは、ここではLLMとの履歴を保存するためのもの）は環境変数の`LANGCHAIN_PROJECT`で設定します。

```bash 
export LANGCHAIN_PROJECT="..." //プロジェクト名
```

uuidやulidを用いてプロジェクト名を設定したい場合は以下のようにプログラムで設定すると良いです。

```python 
import os

# uuidもしくulidの例
## uuid 
from uuid import uuid4
unique_id = uuid4().hex[:12]

## ulid: 事前にpip install python-ulid
from ulid import ULID 
unique_id = ULID().hex[:12]

os.environ["LANGCHAIN_PROJECT"] = f"Tracing Walkthrough - {unique_id}"
```

正しく設定が完了したのちに、ローカルPCで立ち上げたLLMサーバーにAPIを送ってみてください。（UIからでもなんでも大丈夫です。）

以下のようにLangSmithに応答履歴が保存されているはずです。

![スクリーンショット 2024-05-01 10.38.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/c58f0d83-9539-696c-4fb6-4659c7ed9e11.png)


## おわりに
LangServe×Ollamaを使ってローカルPCでLLMサーバーを立ち上げてみるという内容でした。

全て無料なので、ぜひ試してみてください。