Closed4

OpenAIのPredicted Outputsを試す

kun432kun432

ここで知った。

https://twitter.com/OpenAIDevs/status/1853564730872607229

ドキュメント

https://platform.openai.com/docs/guides/latency-optimization#use-predicted-outputs

場合によっては、LLMの出力のほとんどが前もってわかっていることもある。例えば、わずかな変更でテキストやコードの書き換えをモデルに依頼する場合、予測出力を使用し、既存のコンテンツを予測として渡すことで、待ち時間を大幅に短縮することができる。

例としてあげられているのは、コードのちょっとした修正。たしかに少しだけ修正するならば、イチから生成する必要はない。なので、その場合は、コードを明示的にリファレンスとしてリクエストに追加することで、レイテンシーが少なくなる、ということらしい。

Colaboratoryで試してみる。

!pip install -U openai
!pip freeze | grep -i openai

なお、バージョンは1.54.0以上である必要がある。普通にインストールしたら1.52.2がインストールされて「predictionなんて引数はねえよ」と怒られたので、-Uをつけている。

出力
openai==1.54.0

OpenAI APIキーをセット

import os
from google.colab import userdata

os.environ['OPENAI_API_KEY'] = userdata.get('OPENAI_API_KEY')

まず普通に試してみる。Usageを出力させているのはキャッシュが有効になっていないことを確認するため(このレベルだと小さすぎてキャッシュされないはずだけど一応)

%%timeit

from openai import OpenAI
import json

code = """
/// <summary>
/// 姓、名、ユーザー名を持つユーザーを表す
/// </summary>
public class User
{
    /// <summary>
    /// ユーザーの姓名のうち性を取得・設定
    /// </summary>
    public string LastName { get; set; }

    /// <summary>
    /// ユーザーの姓名のうち名を取得・設定
    /// </summary>
    public string FirstName { get; set; }

    /// <summary>
    /// ユーザーのユーザー名を取得・設定
    /// </summary>
    public string Username { get; set; }
}
"""

client = OpenAI()

completion = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {
            "role": "user",
            "content": "UsernameプロパティをEmailプロパティに置き換えて。Markdownのフォーマットは絶対に使わずに、コードのみを出力して。"
        },
        {
            "role": "user",
            "content": code
        }
    ]
)

print("----- Response -----")
print(completion.choices[0].message.content)
print()
print("----- Usage -----")
print(json.dumps(completion.dict()["usage"], indent=2, ensure_ascii=False))
出力
(snip)
----- Response -----
```csharp
/// <summary>
/// 姓、名、メールアドレスを持つユーザーを表す
/// </summary>
public class User
{
    /// <summary>
    /// ユーザーの姓名のうち性を取得・設定
    /// </summary>
    public string LastName { get; set; }

    /// <summary>
    /// ユーザーの姓名のうち名を取得・設定
    /// </summary>
    public string FirstName { get; set; }

    /// <summary>
    /// ユーザーのメールアドレスを取得・設定
    /// </summary>
    public string Email { get; set; }
}
```

----- Usage -----
{
  "completion_tokens": 149,
  "prompt_tokens": 190,
  "total_tokens": 339,
  "completion_tokens_details": {
    "audio_tokens": null,
    "reasoning_tokens": 0,
    "accepted_prediction_tokens": 0,
    "rejected_prediction_tokens": 0
  },
  "prompt_tokens_details": {
    "audio_tokens": null,
    "cached_tokens": 0
  }
}
2.65 s ± 287 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

ではPredicted Outputsを試す。リクエストにpredictionパラメータを追加してここにコンテンツを記載する。

%%timeit

(snip)

completion = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {
            "role": "user",
            "content": "UsernameプロパティをEmailプロパティに置き換えて。Markdownのフォーマットは絶対に使わずに、コードのみを出力して。"
        },
        {
            "role": "user",
            "content": code
        }
    ],
    # predictionパラメータでコードを渡す
    prediction={
        "type": "content",
        "content": code
    }
)

(snip)
出力
(snip)
----- Response -----
```csharp
/// <summary>
/// 姓、名、メールアドレスを持つユーザーを表す
/// </summary>
public class User
{
    /// <summary>
    /// ユーザーの姓名のうち性を取得・設定
    /// </summary>
    public string LastName { get; set; }

    /// <summary>
    /// ユーザーの姓名のうち名を取得・設定
    /// </summary>
    public string FirstName { get; set; }

    /// <summary>
    /// ユーザーのメールアドレスを取得・設定
    /// </summary>
    public string Email { get; set; }
}
```

----- Usage -----
{
  "completion_tokens": 223,
  "prompt_tokens": 206,
  "total_tokens": 429,
  "completion_tokens_details": {
    "accepted_prediction_tokens": 72,
    "audio_tokens": null,
    "reasoning_tokens": 0,
    "rejected_prediction_tokens": 73
  },
  "prompt_tokens_details": {
    "audio_tokens": null,
    "cached_tokens": 0
  }
}
2.67 s ± 1.07 s per loop (mean ± std. dev. of 7 runs, 1 loop each)

うーん、much lower latencyというほどの違いが全然わからない。例が良くないのかな?

ちなみにgpt-4o-miniがレスポンス速すぎてダメなのかな?と思ってgpt-4oに変えてみたけども、むしろprediction有効にしないほうが速かったり。

gpt-4oでのprediction無効

出力
2.08 s ± 272 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

gpt-4oでのprediction有効

出力
2.87 s ± 968 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

サンプルがあまり適切ではないのかも。

kun432kun432

注意書きがある。

Predicted Outputsの使用に関する注意事項

  • Predicted Outputsは、GPT-4oおよびGPT-4o-miniシリーズのモデルでのみサポートされています。
  • 予測を提供する際、最終的な完了出力の一部でないトークンについても、完了トークンの料金が適用されます。
  • Predicted Outputsを使用する場合、以下のAPIパラメータはサポートされていません:
    • n の値が1を超えるもの
    • logprobs
    • presence_penalty が0より大きい値
    • frequency_penalty が0より大きい値
    • audio オプション
    • テキスト以外のmodalities
    • max_completion_tokens
    • tools(関数呼び出しはサポートされていません)
kun432kun432

一見嬉しそうなオプションなんだけど、本当に嬉しいユースケースがピンとこなかった。

ユースケース的に「変更点が少ない」というケースであれば、サンプルのようにコードを少し修正したいとか、あとChatGPTのCanvasみたいなケースがハマるんだろうなとは思うのだけども、試した限りはいかんせんレイテンシーが改善するほど違いが見えなかったので、わかりやすくハマるサンプルを知りたい。

このスクラップは2ヶ月前にクローズされました