OpenAIの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)
サンプルがあまり適切ではないのかも。
注意書きがある。
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
(関数呼び出しはサポートされていません)
一見嬉しそうなオプションなんだけど、本当に嬉しいユースケースがピンとこなかった。
ユースケース的に「変更点が少ない」というケースであれば、サンプルのようにコードを少し修正したいとか、あとChatGPTのCanvasみたいなケースがハマるんだろうなとは思うのだけども、試した限りはいかんせんレイテンシーが改善するほど違いが見えなかったので、わかりやすくハマるサンプルを知りたい。
むー、なるほど