AIにチャレンジ！OpenAI APIのパラメータ設定を完全攻略その3(logprobsとtop_logprobs)

こんにちは、みなさん！
今回は生成AIの思考を覗くパラメータについて解説します。

# 生成AIの思考を覗くパラメータは2つです。
表は前回の記事からの抜粋です。

| No | パラメーター             | 型        | 必須/オプション | 説明                                                                        |
|----|----------------------|-----------|-----------------|-----------------------------------------------------------------------------|
| 11 | logprobs             | bool      | オプション       | 出力トークンの確率を返すかどうかを指定します。                               |
| 12 | top_logprobs         | integer   | オプション       | 採用されなかったトークンの確率も知りたいときに指定します。                    |

## logprobs
Trueを指定すると採用したトークンの確率を返します。

## top_logprobs
上位何位までの確率を返すかを0から20で指定します。

この説明だけでは何のことだか分かりませんよね。
早速動かしてみましょう。

## 動かしてみる
今回のサンプルコードはこちらです。
動きを比較するために`top_logprobs=3,`をコメントアウトしています。
後でコメントを外して動かします。

```Python
from openai import OpenAI
client = OpenAI()

completion = client.chat.completions.create(
  model="gpt-4o",
  messages=[
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "1995年にCLの覇者は？"
        }
      ]
    },
    {
      "role": "assistant",
      "content": [
        {
          "type": "text",
          "text": "アヤックス・アムステルダムです。"
        }
      ]
    },
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "決勝はどこで行われましたか？10文字以内で答えてください。"
        }
      ]
    }
  ],
  temperature=0.1,
  logprobs=True,
  # top_logprobs=3,
)

print(completion)
```

実行結果は以下の通りです。
```JSON
{
  "id": "chatcmpl-9a0d9YLZxKl4u332d0vE5qatBbO0M",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "logprobs": {
        "content": [
          {
            "token": "ウ",
            "bytes": [227, 130, 166],
            "logprob": -0.14363798,
            "top_logprobs": []
          },
          {
            "token": "ィ",
            "bytes": [227, 130, 163],
            "logprob": -0.00023143037,
            "top_logprobs": []
          },
          {
            "token": "ーン",
            "bytes": [227, 131, 188, 227, 131, 179],
            "logprob": -0.00027122974,
            "top_logprobs": []
          }
        ]
      },
      "message": {
        "content": "ウィーン",
        "role": "assistant",
        "function_call": null,
        "tool_calls": null
      }
    }
  ],
  "created": 1718369259,
  "model": "gpt-4o-2024-05-13",
  "object": "chat.completion",
  "system_fingerprint": "fp_319be4768e",
  "usage": {
    "completion_tokens": 3,
    "prompt_tokens": 57,
    "total_tokens": 60
  }
}
```

### 結果の解説
messageのcontentを確認すると`"content": "ウィーン"`と回答していることが分かります。

logprobsの中を見ると最初のトークンが"ウ"で確率が-0.14363798、次のトークンが"ィ"で確率が-0.00023143037、最後のトークンが"ーン"で確率が-0.00027122974だったことが分かります。

このようにlogprobsを指定することで採用したトークンの確率が表示されます。

## top_logprobsを指定してみる。
top_logprobsを指定して動かした結果は以下の通りです。
```JSON
{
  "id": "chatcmpl-9a0Y0AZ1Pf22FPtk9UFSDH9w24etH",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "logprobs": {
        "content": [
          {
            "token": "ウ",
            "bytes": [227, 130, 166],
            "logprob": -0.10124033,
            "top_logprobs": [
              {
                "token": "ウ",
                "bytes": [227, 130, 166],
                "logprob": -0.10124033
              },
              {
                "token": "エ",
                "bytes": [227, 130, 168],
                "logprob": -2.3512404
              },
              {
                "token": "ビ",
                "bytes": [227, 131, 147],
                "logprob": -7.97624
              }
            ]
          },
          {
            "token": "ィ",
            "bytes": [227, 130, 163],
            "logprob": -0.00029685118,
            "top_logprobs": [
              {
                "token": "ィ",
                "bytes": [227, 130, 163],
                "logprob": -0.00029685118
              },
              {
                "token": "イ",
                "bytes": [227, 130, 164],
                "logprob": -8.125297
              },
              {
                "token": " エ",
                "bytes": [227, 130, 168],
                "logprob": -14.875297
              }
            ]
          },
          {
            "token": "ーン",
            "bytes": [227, 131, 188, 227, 131, 179],
            "logprob": -0.0004721411,
            "top_logprobs": [
              {
                "token": "ーン",
                "bytes": [227, 131, 188, 227, 131, 179],
                "logprob": -0.0004721411
              },
              {
                "token": "ーナ",
                "bytes": [227, 131, 188, 227, 131, 138],
                "logprob": -7.750472
              },
              {
                "token": "―",
                "bytes": [226, 128, 149],
                "logprob": -10.250472
              }
            ]
          }
        ]
      },
      "message": {
        "content": "ウィーン",
        "role": "assistant",
        "function_call": null,
        "tool_calls": null
      }
    }
  ],
  "created": 1718368940,
  "model": "gpt-4o-2024-05-13",
  "object": "chat.completion",
  "system_fingerprint": "fp_319be4768e",
  "usage": {
    "completion_tokens": 3,
    "prompt_tokens": 57,
    "total_tokens": 60
  }
}
```

top_logprobsが追加されていることが分かります。
top_logprobsの中身を見ると生成AIが最初のトークン"ウ"を採用する過程で"ウ"の他に"エ"と"ビ"を検討したことが分かります。
"ウ"の確率が-0.10124033、"エ"の確率が-2.3512404、"ビ"の確率が-7.97624だったことも分かります。
確率の一番大きい"ウ"が採用されました。

# まとめ
生成AIの思考回路を覗くパラメータlogprobsとtop_logprobsについて理解できたでしょうか？
正直使いどころは分かっていませんが、どうしてそんな回答になったかを確認するためには使えそうです。