DatabricksのモデルサービングでLLMを用いたチャットボットを動かす

こちらの続きです。

https://qiita.com/taka_yayoi/items/431fa69430c5c6a5e741

https://qiita.com/taka_yayoi/items/ad370a7f57c4eae58800

MLflowでLLMを記録できるということは、MLflowの[モデルサービング](https://qiita.com/taka_yayoi/items/b5a5f83beb4c532cf921)を使ってLLMをサービングできるのでは、そして、streamlitと組み合わせたらチャットボットを動かせるのではと思い立ちました。結論、いけました。

ここで使う用語をまとめておきます。

- **モデルサービング**: REST API経由でアクセスできるように機械学習モデルをホスティングする機能。
- **モデルレジストリ**: 機械学習モデルを集中管理するためのハブのようなものです。バージョン管理も可能です。
- **エンドポイント**: 機械学習モデルのREST APIエンドポイントです。

# LLMのロギング

以下のようなコードを実行します。

```py:Python
import transformers
import mlflow

chat_pipeline = transformers.pipeline(model="microsoft/DialoGPT-medium")

with mlflow.start_run():
  model_info = mlflow.transformers.log_model(
    transformers_model=chat_pipeline,
    artifact_path="chatbot",
    input_example="Hi there!"
  )
```

これでHugging Faceで公開されているLLMがロギングされます。
![Screenshot 2023-04-19 at 21.01.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/e61d750f-e537-9122-185c-517b350571ae.png)

MLflowランの画面にアクセスして、[モデルレジストリ](https://qiita.com/taka_yayoi/items/e7a4bec6420eb7069995)にモデルを登録します。モデルをサービングするにはモデルレジストリに登録する必要があります。
![Screenshot 2023-04-19 at 21.03.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/7493ad6c-a458-8165-c377-0f23ad680ce3.png)
![Screenshot 2023-04-19 at 21.05.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/62beb51a-3244-4ffd-31dd-3b0208572cbd.png)

# REST APIエンドポイントの作成

:::note
**注意**
以降では、[サーバレスリアルタイム推論を用いたDatabricksのモデルサービング](https://qiita.com/taka_yayoi/items/32266655075795f5ab65)で説明されているサーバレスエンドポイントを使用しています。この記事の執筆時点では日本リージョンではまだ利用できません。
:::

サイドメニューの**サービング**にアクセスし、エンドポイントを作成します。少し待つとモデルがサービングされるようになります。そうすると、REST API経由でモデル、すなわちLLMにアクセスできるようになります。アクセスする際には[パーソナルアクセストークン](https://qiita.com/taka_yayoi/items/fa7f10bc80475c513383)が必要になります。
![Screenshot 2023-04-19 at 21.06.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/60924a23-dcb2-8f18-e8e4-eb5049ff8522.png)

なお、この時点でも動作確認が可能です。右上の**Query endpoint**をクリックして、エンドポイントにリクエストを投げることができます。
![Screenshot 2023-04-19 at 21.10.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d65ed9c2-49bc-c1d6-7b43-a4d217e9405c.png)

# GUIの作成

[こちら](https://qiita.com/taka_yayoi/items/ce79c29df59a99bf872b)で行ったのと同じアプローチで、streamlitでチャットボットのGUIを作成します。

```py:chatbot.py
import streamlit as st 
import numpy as np 
from PIL import Image
import base64
import io

import os
import requests
import numpy as np
import pandas as pd

import json

#st.title('Chatbot')
st.header('Chatbot on Databrikcs')
#st.write('![](https://sajpstorage.blob.core.windows.net/yayoi/hotel_image.png)')
st.write('''
- [MLflow 2\.3のご紹介：ネイティブLLMのサポートと新機能による強化 \- Qiita](https://qiita.com/taka_yayoi/items/431fa69430c5c6a5e741)
- [MLflow 2\.3のHugging Faceトランスフォーマーのサポートを試す \- Qiita](https://qiita.com/taka_yayoi/items/ad370a7f57c4eae58800)
''')

def score_model(prompt):
  # 1. パーソナルアクセストークンを設定してください
  # 今回はデモのため平文で記載していますが、実際に使用する際には環境変数経由で取得する様にしてください。
  token = "<personal access token>"
  #token = os.environ.get("DATABRICKS_TOKEN")

  # 2. モデルエンドポイントのURLを設定してください
  url = '<endpoint url>'
  headers = {'Authorization': f'Bearer {token}'}
  #st.write(token)
  
  data_json_str = f"""
  {{
  "inputs": [
    [
      "{prompt}"
    ]
  ]
}}
  """
  #st.write(data_json_str)

  data_json = json.loads(data_json_str)
   
  response = requests.request(method='POST', headers=headers, url=url, json=data_json)
  if response.status_code != 200:
    raise Exception(f'Request failed with status {response.status_code}, {response.text}')
  return response.json()

prompt = st.text_input("プロンプト")

if prompt != "":
  response = score_model(prompt)
  st.write(response['predictions'])
```

今回はローカルマシンで起動します。

```
streamlit run chatbot.py
```

動きました！
![Screenshot 2023-04-19 at 21.15.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5a79aa86-aa81-c5b5-7de8-74218137191e.png)
![Screenshot 2023-04-19 at 21.18.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/e2fcefa1-9683-66dc-fdd8-6a9f20447f0d.png)

今回使用しているサーバレスエンドポイントは、リクエストがない場合には計算資源がゼロにまでスケールダウンするので経済的です。そして、エンドポイントではリクエストの状況などをモニタリングすることもできます。
![Screenshot 2023-04-19 at 21.20.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/2ddb6acf-dcfd-e771-d87e-aa4e0729c570.png)
![Screenshot 2023-04-19 at 21.16.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/0e97a3e3-34c6-10e5-45e8-673b73cf7450.png)

モデルの改善も進めていきますが、足回りも整っていく感じがして良いですね。

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)