マガジン

5分おきに同じ依頼をすると、結果は時間で変わるか

遊びをつくる

執筆にClaudeを使用しています。

さまざまな小さなゲームの世界が並んだ棚を描いたイラスト。
記事のテーマをもとに制作したAI生成イメージ。実際のゲーム画面ではありません。

朝に頼んだときは動いたゲームが、夜に同じ依頼をすると操作できない。そんな差に気づいたとき、「時間帯で出来が違うのではないか」と考えたくなります。ただ、その差が時間のせいなのか、毎回の生成に最初から含まれる揺らぎなのかは、1回ずつの比較では区別できません。 この記事は、その区別をつけるための実験の設計書です。同じ依頼を5分おきに出して時間軸で記録し、同じ時刻に繰り返した場合の幅と比べます。結果は書きません。読者が自分の環境で行い、自分の数字で判断する形にしています。 結論に近い考え方を先に挙げます。生成AIの出力は、同じ依頼でも毎回少しずつ違うことが一般に知られています。そのため「同じ結果が出るか」ではなく、「同じ種類の結果がどのくらいの幅で出るか」を再現性の単位にします。この幅を測ったうえで、時間による差がその幅の外に出るかを見ます。

この記事の目次
  1. 先に決める:何を「時間の影響」と呼ぶか
  2. 準備するもの
  3. 手順
  4. 記録の取り方
  5. 結果の読み方
  6. 誤りやすい点
  7. 次の行動

先に決める:何を「時間の影響」と呼ぶか

時間が関係しうる要因は、少なくとも3つに分けられます。

  • 生成そのものの揺らぎ。時間とは無関係に、毎回の出力が変わります。
  • 提供側の変化。モデルの入れ替え、設定の変更、混雑による挙動の違いなどです。外からは見えにくいので、記録で拾うしかありません。
  • 自分側の変化。会話履歴の持ち越し、保存された指示の影響、判定する自分の目の慣れです。

この実験で言う「時間の影響」は、このうち揺らぎでは説明できない差を指します。そのため、時間軸の記録(条件T)と、同じ時刻の反復(条件S)の2系統を用意します。

  • 条件T:5分おきに12回、約1時間かけて同じ依頼を出します。
  • 条件S:時間をほとんど空けず、同じ依頼を12回出します。時間差を最小にしたうえで、揺らぎの幅だけを測るための対照です。

TとSが同程度にばらつくなら、時間より揺らぎの寄与が大きいと見られます。Tだけが一方向に動くなら、時間に関係する要因が疑われます。

準備するもの

固定する依頼文。 出力の良し悪しを数えやすいよう、要件を明記した依頼にします。例を示します。

ブラウザで動く1ファイルのHTMLで、矢印キーで動くスネークゲームを作ってください。得点表示、ゲームオーバー表示、再開機能を付け、外部ライブラリは使わないでください。

この文を1つのテキストファイルに保存し、毎回そこからコピーします。打ち直すと句読点や言い回しが変わり、それが差の原因になるからです。

チェックリスト(5項目)。 依頼文の要件に対応させ、各項目を「はい/いいえ」で判定します。

  1. 保存したHTMLをブラウザで開くと起動する
  2. 矢印キーで動く
  3. 得点が表示される
  4. ゲームオーバーが表示される
  5. 再開できる

「起動する」が「いいえ」なら、残りの4項目も自動的に「いいえ」とします。そうしないと、起動しない出力の扱いが人によってぶれます。

そのほか。

  • 毎回、新しい会話を開く(履歴を持ち越さない)
  • 保存された指示や記憶の機能がある環境では、実験の間だけオフにするか、状態を記録する
  • 使用するモデルの名前と、選べる設定(あれば)を記録する
  • 5分ごとに鳴るタイマー
  • 出力を保存するフォルダ
  • 次の節の記録用ページ

手順

  1. 依頼文とチェックリストを確定し、実験中は変えません。
  2. 使用する環境(サービス名、モデル名、選べる設定、保存された指示の有無)を実験ノートの1行目に書きます。
  3. 条件T:開始時刻を決め、5分おきに新しい会話を開いて依頼文を貼ります。出力されたコードは T01.html から T12.html として保存します。
  4. 条件S:別の時間に、新しい会話で同じ依頼を連続して12回出します。出力は S01.html から S12.html として保存します。
  5. すべて保存し終えてから判定します。生成しながら判定すると、前の出力の印象が次の判定に混ざります。
  6. 判定の前にファイル名をランダムな文字列に付け替え、対応表を別に保存します。TかSか、何時の出力かを知らない状態で判定するためです。
  7. 1ファイルずつブラウザで開いて5項目を判定し、次の記録用ページに入力します。
  8. 判定が終わったら対応表を開き、ランダムな名前を元の条件と時刻に戻して集計します。

1時間では「時間帯」の差を見るには短すぎます。余力があれば、条件Tを朝・昼・夜の3回に分けて別の日にも行ってください。日をまたぐ場合は、モデル名の記録がとくに重要になります。

記録の取り方

1出力につき1行で記録します。項目は次のとおりです。

  • 時刻、種類:時間、取り方:依頼を出した時刻
  • 条件、種類:ラベル、取り方:T01、S03など
  • 文字数・行数、種類:計数、取り方:コードを貼ったときに自動で数える
  • 外部参照、種類:二値、取り方:外部のJS/CSSを読み込んでいるか
  • チェック数、種類:0〜5、取り方:判定した結果の合計

次は、貼り付けたコードの文字数と行数を数え、チェック数とともにCSV形式で並べる最小のHTMLです。単独で動き、外部通信はありません。外部参照の判定は簡易なもので、疑わしい場合は目視で確認してください。

html
<!doctype html>
<meta charset="utf-8">
<title>揺らぎ記録</title>
<textarea id="out" rows="8" cols="60" placeholder="AIの出力コードを貼る"></textarea><br>
<label>条件 <input id="cond" value="T01"></label>
<label><input type="checkbox" class="c"> 起動する</label>
<label><input type="checkbox" class="c"> 矢印キーで動く</label>
<label><input type="checkbox" class="c"> 得点表示</label>
<label><input type="checkbox" class="c"> ゲームオーバー表示</label>
<label><input type="checkbox" class="c"> 再開できる</label><br>
<button id="add">1件記録</button> <button id="csv">一覧を再表示</button>
<pre id="log"></pre>
<script>
const rows=[["時刻","条件","文字数","行数","外部参照","チェック数"]];
const show=()=>{document.getElementById("log").textContent=rows.map(r=>r.join(",")).join("\n");};
document.getElementById("add").onclick=()=>{
  const t=document.getElementById("out").value;
  const checks=[...document.querySelectorAll(".c")].filter(c=>c.checked).length;
  const ext=/(https?:)?\/\/[^\s"']+\.(js|css)/i.test(t)?"あり":"なし";
  rows.push([new Date().toLocaleTimeString("ja-JP"),document.getElementById("cond").value,t.length,t.split("\n").length,ext,checks]);
  document.getElementById("out").value="";
  document.querySelectorAll(".c").forEach(c=>c.checked=false);
  show();
};
document.getElementById("csv").onclick=show;
</script>

このページは記録を画面に表示するだけで、保存はしません。判定がすべて終わったら、表示された一覧をコピーして表計算ソフトやテキストファイルに貼ってください。タブを閉じると消えます。

ここに入る時刻は、判定した時刻であって生成した時刻ではありません。生成時刻は、手順3で自分が控えたものを別の列に足してください。

結果の読み方

集計は、次の順で進めます。

  1. 条件Sの12件について、チェック数・行数・文字数それぞれの最小と最大を出します。これが「揺らぎの幅」です。
  2. 条件Tの12件を時刻順に並べ、同じ項目を見ます。各値が条件Sの幅に入っているかを数えます。
  3. Tの前半6件と後半6件の中央値を比べます。中央値は、小さい順に並べたときの真ん中の値です。
  4. Tを時刻順に折れ線にして、単調に増減していないかを確認します。

読み方の目安は次のとおりです。

  • Tの値がSの幅に収まり、増減の傾向がない、読み方:この条件・この期間では、時間の影響は揺らぎと区別できない。「影響がない」と断定はしない
  • TがSの幅の外に偏る、または時刻順に一方向へ動く、読み方:時間に関係する要因を疑う。記録したモデル名や設定の変化、会話履歴や保存指示の混入を確認する
  • S自体の幅が非常に広い、読み方:12回では差を見分けにくい。回数を増やすか、指標を「起動するか」のような粗い二値に絞る
  • Sの幅が非常に狭い、読み方:依頼が出力を強く絞っている。時間の差があれば見つけやすい条件

ここで再現性の考え方が役に立ちます。ゲーム制作で依頼文を改善するときは、1回の出力を見て「良くなった」と判断しがちです。しかし揺らぎがあるなら、1回では偶然との区別がつきません。改善前後の依頼をそれぞれ12回ずつ出し、チェック数の分布を比べれば、同じ枠組みで依頼文の効果を確かめられます。この実験の条件Sは、そのための基準の幅としてそのまま使えます。

誤りやすい点

  • 同じ会話で続けて頼む。 前の出力が文脈に残り、2回目以降は条件が変わります。毎回新しい会話を開いてください。
  • 依頼文を少しだけ直す。 一語の違いでも出力の傾向が変わりえます。固定の文をそのまま貼ります。
  • 判定者が条件を知っている。 「夜の出力は雑だ」という先入観が判定に混ざります。ファイル名のランダム化で防げます。
  • 起動しない出力の扱いが揺れる。 起動しなければ残りも「いいえ」とする、というルールを実験前に決めておきます。
  • 1回の外れ値を時間の影響と読む。 条件Sの幅に入っていれば、揺らぎの範囲内です。
  • サンプルが少ない。 12件でも差が見えないことがあります。その場合は結論を保留し、回数を増やしてください。
  • 環境の変更に気づかない。 実験の途中でアプリの更新や設定の切り替えがあると、時間の影響と区別できません。モデル名と設定を、開始時と終了時の両方で控えます。

次の行動

まず依頼文をテキストファイルに保存し、条件Sの12回を先に行ってください。揺らぎの幅が分かると、条件Tを読む基準ができます。実験で出たHTMLのうち動いたものは、アソバースへ投稿できる形に近いものです。外部ライブラリを使わないものを選び、index.html として投稿画面で表示を確認してみてください。