Closed1

OpenAI ChatCompletion APIのReproducible outputsを試してみる

kun432kun432

Stable DiffusionでいうところのSeedと同じようなものだと思う。

!pip install --upgrade openai
from google.colab import userdata
import os

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

temperature=0で。

from openai import OpenAI
from pprint import pprint
import json

model = "gpt-4-1106-preview"

messages = [
    {"role": "system", "content": "あなたは詩的なアシスタントで、複雑なプログラミングのコンセプトをクリエイティブなセンスで説明することに長けている。"},
    {"role": "user", "content": "プログラミングにおける再帰の概念を説明する詩を作ってください。日本語で。"}
]

client = OpenAI()

res = client.chat.completions.create(
    model=model,
    messages=messages,
    temperature=0,
)

print(res.json(indent=2, ensure_ascii=False))

結果

{
  "id": "chatcmpl-8IG0Z9prqPzalgrKOCBoceSjXmIfi",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "深い森の中、道は続く、\n自らの足跡を辿る旅人、\n一歩進むごとに問いかける、\n「終わりはどこか、見えるのか?」\n\n再帰は、魔法のような手法、\n関数が自分自身を呼び出す、\n問題を分割し、小さくして、\n答えを見つける、繊細な探求。\n\n基底条件が、道標となり、\n無限のループから救い出す、\nそれが見つかるその瞬間、\n旅は終わり、解が明らかに。\n\nフィボナッチの数、塔のハノイ、\n再帰の力、美しく解く、\nシンプルながら、深い洞察を、\nプログラマーに、与えるのだ。\n\n繰り返すこと、自己参照の美、\nコードの中に、秩序を生む、\n再帰の詩、終わりなき旅、\n理解の鍵、心に響く。",
        "role": "assistant",
        "function_call": null,
        "tool_calls": null
      }
    }
  ],
  "created": 1699362131,
  "model": "gpt-4-1106-preview",
  "object": "chat.completion",
  "system_fingerprint": "fp_a24b4d720c",
  "usage": {
    "completion_tokens": 319,
    "prompt_tokens": 107,
    "total_tokens": 426
  }
}

再度実行した結果。temperature=0でも生成される文章が違っているのがわかる。

{
  "id": "chatcmpl-8IG110aWSrjzZkbLv2PGziJSZEaWI",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "深い森の中、小径を歩くかのよう、\n足跡を辿りながら、また元の場所へと戻る。\nそこには再帰の魔法が息づいている、\n自らの名を呼び、自らの終わりを知る。\n\n関数は詩人、自己の詩を紡ぎながら、\n「私は私を呼ぶ」と囁き続ける。\n終わりの条件、それが「基底ケース」となり、\n無限の迷宮から抜け出す鍵となる。\n\n小さな問題へと分けてゆく、\n大きな問題は、小さな自己に姿を変える。\nそれぞれが答えを持ち帰り、\n一つの解へと結びつく。\n\n再帰は、時間を巻き戻す旅人、\n過去を訪れ、未来を紡ぐ。\nコードの中で、時は螺旋を描き、\n始点と終点が、やがて一つになる。\n\nだが注意せよ、無限の呼び声には、\n制限を設けぬと、永遠に戻れず。\nスタックオーバーフロー、深淵に落ちる前に、\n基底ケースで、安全な帰還を約束するのだ。\n\n再帰は、プログラマの詩、\n自己参照の美しき輪廻。\n解を求め、自らを呼び続ける、\nそれが再帰、永遠の旅路。",
        "role": "assistant",
        "function_call": null,
        "tool_calls": null
      }
    }
  ],
  "created": 1699362159,
  "model": "gpt-4-1106-preview",
  "object": "chat.completion",
  "system_fingerprint": "fp_a24b4d720c",
  "usage": {
    "completion_tokens": 458,
    "prompt_tokens": 107,
    "total_tokens": 565
  }
}

こんな感じでseed値を指定する。

res = client.chat.completions.create(
    model=model,
    messages=messages,
    temperature=0,
    seed=1234567890
)

1回目。

{
  "id": "chatcmpl-8IG1vzORCFNguupCdv1SH2tRDDw15",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "深い森の中、小径を歩くかのよう、\n足跡を辿りながら、また元の場所へと戻る。\nそこには再帰の魔法が息づいている、\n自らの名を呼び、自らの終わりを知る。\n\n関数は呼び出し、自身を見つめ直す、\n問いを細分化し、答えを紡ぎ出す。\n繰り返しはない、ただ一つの道を、\n自分自身で切り開き、謎を解く。\n\n小さな問題に分け、解を求める旅、\n基底条件が、その旅の終わりを告げる。\n無限の階段を、一歩ずつ降りてゆく、\n答えを手に入れる、その瞬間まで。\n\n再帰は、自己参照の美しい詩、\nコードの中で、無限を可能にする。\nしかし注意せよ、無限のループには、\n終わりを告げる、安全の綱が必要だ。\n\nプログラムの世界で、再帰は詩人、\n複雑な問題を、シンプルに変える。\n一つの関数が、自らを呼び出し、\n解の花を咲かせる、無限の庭で。",
        "role": "assistant",
        "function_call": null,
        "tool_calls": null
      }
    }
  ],
  "created": 1699362215,
  "model": "gpt-4-1106-preview",
  "object": "chat.completion",
  "system_fingerprint": "fp_a24b4d720c",
  "usage": {
    "completion_tokens": 389,
    "prompt_tokens": 107,
    "total_tokens": 496
  }
}

2回目。同じ内容が生成されているのがわかる。

{
  "id": "chatcmpl-8IG2fAW8pE8yVnmws1k3NYLXReL9z",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "深い森の中、小径を歩くかのよう、\n足跡を辿りながら、また元の場所へと戻る。\nそこには再帰の魔法が息づいている、\n自らの名を呼び、自らの終わりを知る。\n\n関数は呼び出し、自身を見つめ直す、\n問いを細分化し、答えを紡ぎ出す。\n繰り返しはない、ただ一つの道を、\n自分自身で切り開き、謎を解く。\n\n小さな問題に分け、解を求める旅、\n基底条件が、その旅の終わりを告げる。\n無限の階段を、一歩ずつ降りてゆく、\n答えを手に入れる、その瞬間まで。\n\n再帰は、自己参照の美しい詩、\nコードの中で、無限を可能にする。\nしかし注意せよ、無限のループには、\n終わりを告げる、安全の綱が必要だ。\n\nプログラムの世界で、再帰は詩人、\n複雑な問題を、シンプルに変える。\n一つの関数が、自らを呼び出し、\n解の花を咲かせる、無限の庭で。",
        "role": "assistant",
        "function_call": null,
        "tool_calls": null
      }
    }
  ],
  "created": 1699362261,
  "model": "gpt-4-1106-preview",
  "object": "chat.completion",
  "system_fingerprint": "fp_a24b4d720c",
  "usage": {
    "completion_tokens": 389,
    "prompt_tokens": 107,
    "total_tokens": 496
  }
}

レスポンス中のsystem_fingerprintは常に同じ値になっている

  "system_fingerprint": "fp_a24b4d720c",

APIコール全体で(ほぼ)決定論的な出力を受け取るには、以下の方法がある:

  • seedパラメータを好きな整数に設定し、決定論的出力が必要なリクエストで 同じ値を使う。
  • 他のすべてのパラメータ(プロンプトや 温度など)が、リクエスト間でまったく同じであることを確認する。

時には、OpenAI が私たちの側でモデルの設定に必要な変更を加えるために、決定論が影響を受けるかもしれません。このような変更を追跡できるように、system_fingerprintフィールドを公開しています。この値が異なる場合、我々のシステムで行った変更により、異なる出力が表示されるかもしれません。

なるほど、基本的にseed値含めたリクエスト内容が全部同じであれば、同じレスポンスが変えるはずだけど、もし違ったレスポンスが返ってきたら、system_fingerprintでOpenAI側で変更があったかどうかがわかるということみたい。

このスクラップは2023/11/07にクローズされました