MLflow 2.4のmlflow.evaluateとアーティファクトビューでLLMの評価が捗る件

以前こちらの記事を翻訳したのですが、その際に触れていたLLM比較のインタフェースであるアーティファクトビューを試してみました。思った以上に便利。

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

MLflowのマニュアルはこちら。

https://mlflow.org/docs/latest/models.html#evaluating-with-llms

> MLflow 2.4.0の[mlflow\.evaluate\(\)](https://mlflow.org/docs/latest/python_api/mlflow.html#mlflow.evaluate)では、テキスト要約、テキスト分類、質疑応答、テキスト生成を含むLLMの様々なタスクに対するビルトインのサポートがあります。

試してみます。なお、Databricks機械学習ランタイム13.2であれば最初からMLflow 2.4.0が入っています。

# 環境設定、ライブラリのインポート

OpenAI APIを使うので、シークレットに保存してあるAPIキーを環境変数に設定します。

```py
import os
os.environ["OPENAI_API_KEY"] = dbutils.secrets.get("demo-token-takaaki.yayoi", "openai_api_key")
```

```py
import pandas as pd

import mlflow
import openai
```

# プロンプトとモデルの記録

プロンプトの試行錯誤を想定しているので、モデルの呼び出しと評価のロジックを関数にします。

```py
# OpenAIを用いたプロンプトエンジニアリングによる質疑応答モデルの作成
# MLflowトラッキングにプロンプトとモデルを記録
def evaluate_gpt(system_prompt):

  mlflow.log_param("system_prompt", system_prompt)
  logged_model = mlflow.openai.log_model(
    model="gpt-3.5-turbo",
    task=openai.ChatCompletion,
    artifact_path="model",
    messages=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": "{question}"},
    ],
  )

  # 同じサンプル質問でモデルを評価
  questions = pd.DataFrame(
    {
        "question": [
            "MLflowでランをどのように作成しますか？",
            "MLflowでどのようにモデルを記録しますか？",
            "フランスの首都はどこですか？",
        ]
    }
  )
  mlflow.evaluate(
    model=logged_model.model_uri,
    model_type="question-answering",
    data=questions,
  )
```

プロンプトを微妙に変えながら、モデルの評価を行います。

```py
with mlflow.start_run():
  system_prompt = (
    "あなたの仕事はMLflowに関する質問に回答することです。MLflowについて質問された際には、"
    " それに反応してください。コードサンプルを含めるようにしてください。質問がMLflowに関係がない場合には、"
    " 質問が無関係ですと言って、質問を拒否してください。"
  )
  evaluate_gpt(system_prompt)

with mlflow.start_run():
  system_prompt = (
    "あなたの仕事はMLflowに関する質問に回答することです。MLflowについて質問された際には、"
    " それに反応してください。コードサンプルを含めないでください。質問がMLflowに関係がない場合には、"
    " 質問が無関係ですと言って、質問を拒否してください。"
  )
  evaluate_gpt(system_prompt)

with mlflow.start_run():
  system_prompt = (
    "あなたの仕事はMLflowに関する質問に回答することです。MLflowについて質問された際には、"
    " それに反応してください。コードサンプルを含めないでください。質問がMLflowに関係がない場合でも、"
    " 嫌がりながらも質問に回答してください。"
  )
  evaluate_gpt(system_prompt)
```

これでモデルとパラメーター、評価結果が記録されます。
![Screenshot 2023-06-29 at 17.21.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/47fd83f6-e959-cf68-fabe-32f013fe63ad.png)

# モデルの評価

評価結果のデータにアクセスすることができます。

```py
# 評価結果をロードして調査
results: pd.DataFrame = mlflow.load_table(
    "eval_results_table.json", extra_columns=["run_id", "params.system_prompt"]
)
results_grouped_by_question = results.sort_values(by="question")
display(results_grouped_by_question[
        ["run_id", "params.system_prompt", "question", "outputs"]
    ])
```
![Screenshot 2023-06-29 at 17.31.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d3275e6a-7073-d06f-64cf-deb6300843d6.png)


より詳細に比較するために、MLflowランの右にある![Screenshot 2023-06-29 at 17.21.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5a089cc7-8bc3-f324-576a-15a8da326116.png)をクリックします。

このように一覧が表示されますが、これで終わりではありません。**Evaluation**をクリックします。
![Screenshot 2023-06-29 at 17.32.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/a7feb470-acb1-efd4-d09a-85338891fca4.png)

このようにテーブル形式でモデルごとの質問に対する回答を確認することができます。
![Screenshot 2023-06-29 at 17.32.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/68bfc872-fad0-dc7d-1232-cf070bf91b50.png)

定量的な評価が難しいLLMですが、少なくともこの機能を活用することで人間の目でのチェックが楽になるかと思います。

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

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


### Databricks無料トライアル

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