現役のITエンジニアが、 システム開発の現場で求められる知識を発信
記事検索
公開

生成AIのテキスト生成のしくみとパラメータ

生成AI関連

はじめに

生成AIを使っていると、temperaturetop_ptop_k といったパラメータを目にする機会は多いものの、「雰囲気で設定している」「正直よく分かっていない」というケースも少なくありません。
近年の生成AI(特に推論型)では、

  • temperatureを下げるのは非推奨 / そもそも設定できなくなってきている
  • top_p、top_kも設定できなくなってきている

といった設計になってきており、人間が細かくチューニングする場面は確実に減りつつあります。
一方で、これらの仕組みを理解しているかどうかで、

  • 出力がなぜ揺らぐのか
  • なぜ決定的にしすぎると不安定になるのか

といった挙動の理解度は大きく変わります。
本記事では、生成AIの仕組みに触れながら、数式は使わずPython(numpy)による再現コードを使って生成AIがどのようにテキストを生成しているのかを見ていきましょう。

※ 実装は、pytorchを使ったほうが圧倒的に楽に実装できますが、わかりやすさを重視しnumpyを使用します。
※ また、各社によって実装の仕方に差異があるため、参考程度とお考えください。

生成AIは「次のトークンを確率で選んでいる」

生成AIは文章を一気に生成しているわけではなく、1トークンずつ「次に何を出すか」を選択しています。
※ トークンとは、生成AIが文章を理解・生成する際に使う情報の最小単位のことです。

ではどのように選んでいるのでしょうか?まずはシンプルな例を考えてみます。

1. 各トークンのスコアを算出する

たとえば、お正月らしく次の文を考えてみます。


「おせちの具材といえば」

この続きとして、生成AIのモデル内部では次のような候補(tokens)とスコア(logitsといいます)が並んでいると考えられます。
(説明用に極端に簡略化しています。また、具材のチョイスはAIによるものです。)

simple_softmax_sample.py

import numpy as np

# トークンの候補(簡略版。実際には数万~数十万トークンの候補が並ぶ)
tokens = ["黒豆", "数の子", "伊達巻", "昆布巻き", "ハンバーグ"]
logits = np.array([2.0, 1.3, 1.0, 0.4, -1.5])
  • 黒豆:定番
  • 数の子:かなりあり
  • 伊達巻:十分あり
  • 昆布巻き:微妙ライン
  • ハンバーグ:ほぼ来ない

実際のモデルでは、このtokens(トークン候補)が数万~数十万個ほど存在しています。
また、トークンは実際にはもっと細かい単位ですが、わかりやすさを重視し1単語としています。

2. softmaxで確率に変換する

logitsはそのままでは使われず、softmaxという操作によって確率に変換されます。
softmaxとは、下記のような関数で表されます。

simple_softmax_sample.py(続き)

def softmax(x):
    exp_x = np.exp(x - np.max(x))
    return exp_x / exp_x.sum()

probs = softmax(logits) # 確率分布を生成

出力は次のようになり、tokensの各要素の生成確率が並びます。つまりsoftmaxは、合計を1にすることで、数字→確率に変換してくれます。


probs=array([0.47697211, 0.23685734, 0.17546823, 0.09629901, 0.01440331])

ここで少しsoftmaxについて補足します。なにがsoftかといいますと、

  • 一番大きい値だけを選ぶのが hardmax(argmax)
  • hardmaxと比較し、大きい値を「なだらかに強調」するのが softmax

という意味があります。
hardに対してsoftという名前になっているのは、この挙動の違いからです。
softmax によって、「一番大きい値以外の候補も、確率はゼロではない」という状態が作られます。

※ softmax の実装では、数値安定性のために x – max(x) を引いてから exp を取る手法が一般的です。本記事では、この数値安定化を考慮した実装を用いています。

3. 確率に基づいてトークンを選択する

確率が得られた後、生成では確率分布に基づいてランダムに1つ選択されます。
例えばこのような操作です。

simple_softmax_sample.py(続き)

choice = np.random.choice(tokens, p=probs)
print(f"{choice=}")

これにより、

  • 黒豆は出やすい
  • しかし必ず黒豆になるわけではない

という、自然な揺らぎが生まれます。

テキスト生成のされ方を左右するパラメータたち

ここで、テキストの生成に関わる3つの代表的なパラメータを見ていきましょう。
これらを変更することで、生成AIの出力のクセが変化していきます。

temperature

temperature は、

確率分布の鋭さを調節する

パラメータです。
softmax の前に logits を割ることで確率分布の形を変える係数として作用します。

softmax_with_temperature.py(抜粋)

def softmax_with_temperature(logits, temperature):
    adjusted = logits / temperature
    return softmax(adjusted)

probs = softmax_with_temperature(logits, 2.0)
print(f"{probs=}")

probs=array([0.34079427, 0.24015366, 0.20670217, 0.15312874, 0.05922116])

温度による確率分布の違いはこのようになります。

温度による確率分布の違い

  • temperature が低い(青いグラフ) → 確率が尖る(ほぼ決定的)
  • temperature が高い(緑のグラフ) → 確率がなだらか(多様性が増す)
temperature = 0.0 が危険な理由

temperature = 0.0 は理論的には割り算できないため、実装上は argmax 相当の挙動になることが多いです。
筆者が社内アプリで temperature = 0.0 を指定し、Structured Output(構造化出力)生成を行っていた際、

  1. 同じ文章が生成され続け、ループ状態になる
  2. トークンの生成上限に達する
  3. JSON が閉じきらず、パースエラーで失敗する

という問題が発生しました。
これはtemperature = 0.0(つまり決定的)であるため、何度リトライしても同じ失敗パターンを繰り返すことになります。

決定的すぎる生成は、安全とは限らない
これが temperature = 0.0 が非推奨とされる理由の一つです。
Gemini 3でも非推奨とされています。

注: Gemini 3 モデルを使用する場合は、temperature をデフォルト値の 1.0 に維持することを強くおすすめします。温度を変更する(1.0 未満に設定する)と、特に複雑な数学的タスクや推論タスクで、ループやパフォーマンスの低下などの予期しない動作が発生する可能性があります。

top_p(nucleus sampling)

top_p は、

確率の高い順に足し上げ、合計が p (0.0 ~ 1.0) を超えるまで候補を残す

という方法です。

  • 文脈によって候補数が変わる
  • 不自然な低確率トークンを除外しやすい

という特徴があります。

長くなるため実装は割愛しますが、例えばp = 0.9で実施した例を見てみましょう。
例えば、temperature = 1.0で実行した結果が下記のようになったとします。


probs=array([0.47697211, 0.23685734, 0.17546823, 0.09629901, 0.01440331])

これを、top_pの考え方に当てはめると、確率の高い順に足し上げた結果、4個目の確率を足したところで0.9を超えることになります。
したがって、p = 0.9の結果は下記のようになります(全体の和が1となるように調整済み)。


probs=array([0.48394248,0.24031872,0.17803249,0.0977063,0.        ])

top_k

top_k は、

確率(または logits)が高い上位 k (正の整数) 個のトークンのみを選択する

という手法です。
下記はtop_k = 3の際の実行例です。

top_k.py(抜粋)

def kth_largest(values: np.ndarray, k: int) -> float:
    """配列の中で大きい順に k 番目の値を返す"""
    if k <= 0 or k > values.size:
        raise ValueError("k は 1〜配列長の範囲で指定してください")

    # 全体をソートせずに k 番目の値だけ取得する
    return np.partition(values, -k)[-k]


threshold = kth_largest(logits, 3)

# しきい値未満の logits を -inf にマスクする
masked_logits = np.where(
    logits >= threshold,
    logits,
    -np.inf,
)

probs = softmax_with_temperature(masked_logits, 1.0)
print(f"{probs=}")

probs=array([0.53634696, 0.26634202, 0.19731102, 0.        , 0.        ])

このように、logitsの大きかった3つのみが値を持ち、残りは0となりました。
この中から確率的にトークンを選択するのが、top_kの仕組みです。

※ 数学の話になるため詳しくは触れませんが、不要なトークンのlogitsマイナス無限にしてからsoftmaxを行うと、そのトークンの確率は0となります。

デモ:temperature の違いによる出力の変化

ここでは Gemini を使って、temperature = 0.0デフォルト設定で複数回生成したときの挙動を比較します。
ソースコードは下記を用いました。

parameter_check_temperature_0.py

from dotenv import load_dotenv
from google import genai

load_dotenv()

vertex_client = genai.Client()

res = vertex_client.models.generate_content(
    model="gemini-2.5-flash",
    contents="こんにちは!おせちに入ってる具、1つ選ぶとしたら何を選びますか?",
    config={
        "temperature": 0.0,  # デフォルトの場合はこちらをコメントアウト
        "thinking_config": {"thinking_budget": 0},
    },
)

print(res.text)

実行結果(デフォルト設定)

デフォルト温度でのGemini実行結果

毎回内容が変わっていますね。
このように、毎回少し違った意見を得ることが出来ます。
これは、独創的なアイデアが生まれやすいため、創造性が重要となるタスク(アイデアの考案など)に向いています。

実行結果(temperature = 0.0)

温度0でのGemini実行結果

このように、同じ文言での回答が得られます。これは、再現性が欲しいタスクに向いています。

ただし、下記の注意は必要です。
まずは先述の通り、1度エラーがでてしまうと、プロンプトを変更しない限り解消が難しいこと。
そしてもう一つが、必ず同じ回答が得られるわけではないことです。
AI側の実装の仕方だったり、logits(各トークンのスコア)の段階で値が同じだと、スコアが同じトークンがランダムで選ばれることになるため、回答に若干の差異が生まれることがあります。

まとめると、以下のようになります。

  • デフォルト設定→ 表現や選択肢が毎回変化する
  • temperature = 0.0→ (ほとんど)毎回同じ結果になる

温度の違いが、挙動として明確に確認できましたね。

Google と OpenAI の最近の設計方針

最後に、GoogleとOpenAIを例に、各種パラメータがどのように扱われているか確認してみましょう。

Google(Gemini)

Geminiは、Gemini 2.0以降は下記のようになっており、top_kのみ自身で設定ができなくなっています。

  • Temperature: 0.0~2.0(デフォルトは 1.0)
  • topP: 0.0~1.0(デフォルトは 0.95)
  • topK: 64(固定)

OpenAI(GPT-5 系)

OpenAIは、gpt-5, gpt-5-mini, gpt-5-nanoでは何も設定できず、gpt-5.2で推論を行わない場合にのみ設定ができるようになっています。
また、top_kについては言及されていませんでした。

GPT-5.2 parameter compatibility
The following parameters are only supported when using GPT-5.2 with reasoning effort set to none:

  • temperature
  • top_p
  • logprobs

Requests to GPT-5.2 or GPT-5.1 with any other reasoning effort setting, or to older GPT-5 models (e.g., gpt-5, gpt-5-mini, gpt-5-nano) that include these fields will raise an error.

まとめ

今回は生成AIのテキスト生成の仕組みと、それに関わる3つのパラメータを紹介しました。
生成AIの API では、パラメータを直接触れなくなりつつあります。
しかし、設定できなくなっていってるだけであって、なくなっているわけではありません。

  • なぜ出力が揺らぐのか
  • なぜ決定的にすると不安定になるのか

これらはテキスト生成のしくみとパラメータを理解しておくことで、原因を考えやすくなります。
今後は生成AIを「魔法」としてではなく、確率モデルとして捉える視点を持つことを意識していきましょう。

生成AI活用支援サービスのご紹介

Tech Funでは、お客様のフェーズに合わせ、生成AI活用に向けた支援を3つのパックでご提供しています。

  1. 無料診断パック:業務・プロセスの現状を無料で診断し、生成AI活用の可能性をレポートします。
  2. 検証(PoC)パック:診断で有効性が確認された業務を対象に、プロトタイプ構築を支援します。
  3. コンサルティングサービス:生成AI導入戦略の策定から運用体制構築までを包括的に支援します。

生成AIに限らず、Web・業務システム開発やインフラ設計など、技術領域を問わずご相談を承っています。「何から始めれば良いか分からない」という段階でも構いませんので、ぜひお気軽にお問い合わせください。

執筆・編集

Tech Fun Magazine R&Dチーム
Tech Funの生成AI研究に携わるエンジニアが、最新のAIモデル動向やプロンプト設計、実業務への応用手法など、生成AIに特化した知見を執筆・編集しています。
モデル評価や業務シナリオに応じたAI活用設計など、日々のR&D活動で得られる実践的なノウハウをわかりやすく紹介します。

ARTICLE
生成AI関連記事一覧

生成AI関連

生成AIのテキスト生成のしくみとパラメータ

生成AI関連

生成AIの導入と定着に向けて

生成AI関連

AI議事録のしくみ

生成AI関連

「良いプロンプト」はAIに作らせよう

生成AI関連

生成AIの“知識の限界”をどう突破する?

生成AI関連

GPT-5.2 徹底解説

生成AI関連

MCPサーバーを活用する【後編:実行編】

生成AI関連

生成AIに機密情報を渡していいの?

生成AI関連

MCPサーバーを活用する【前編:自作編】

記事一覧を見る