Skip to content

EP-022 paid_article_ai_generate_all_considerations(有料記事 AI 考察一括生成) ​

← EP-一覧 · CPT-002 有料記事 · EP-021 欄ごと生成

概要 ​

有料記事の編集画面から、画面上の全考察欄の下書きを 1 回の LLM 呼び出しで生成する。ハンドラは target_field => 本文 のマップを JSON で返す。post meta への自動保存はしない。欄ごとの生成は EP-021 を残す。

POST パラメータ ​

フィールド必須型・制約説明
action○文字列paid_article_ai_generate_all_considerations
_wpnonce○文字列paid_article_ai_generate_consideration で発行した nonce。nonce でも受け付ける
post_id○正整数対象の paid_article 投稿 ID
target_fields○許可リスト文字列の配列生成対象。編集画面上の考察欄(target_fields[])

target_field 許可リストは EP-021 と同じ。空配列・許可リスト外・31 件超は失敗。重複は除去する。

成功時 data ​

論理名物理名型説明
本文群contentsobjectキーが target_field、値が生成した考察 HTML

LLM が返さなかった欄はマップに含めない。フロントは返った欄だけエディタへ入れる。返った欄がリクエストより少ないときは部分成功の案内を出す。生成中は欄ごとボタンと一括ボタンの両方を無効化する。

出力トークンは欄数に応じて増やす(6 欄未満は 8192、6 欄以上は 16384 起算で最大 32768)。Gemini へ渡す maxOutputTokens はモデル上限でクランプする。モデル名に gemini-2.5 を含む場合は 65536、それ以外は 8192 が上限である。欄ごと生成(EP-021)の既定 4096 はこの上限より低い。Claude の stop_reason === max_tokens と Gemini の finishReason === MAX_TOKENS は失敗とし、途中切れの JSON を成功扱いにしない。

Gemini の generationConfig.thinkingConfig(thinkingBudget: 0)はモデル名に gemini-2.5 を含むときだけ送る。未対応モデルへ送ると HTTP 400 になる。ツール定義の parameters.properties は JSON オブジェクトにする(空でも {}。PHP の空配列は [] になり HTTP 400 になる)。HTTP 非 200 時の error.message は画面に出さず、error_log の要約(summary=)で追う(Issue #3866)。

システムプロンプトの「HTML のみ」指示は一括時に JSON 契約へ置き換える。トップレベルが配列なら items とみなす。

ツール呼び出しループの経過秒数上限は 150 秒(欄ごと生成は 90 秒)。1 回の LLM HTTP 待ち秒数の上限は 90 秒(欄ごと生成は 30 秒)。次の HTTP は残り予算(最大 90 秒)で始めるので、ツール往復が 60 秒を超えても最終回答に進める。PHP 実行上限は 270 秒。

失敗・ブロック(success: false の data に含み得るキー) ​

条件message の内容
AJAX コンテキスト外・nonce 不正Messages::AUTH_FAILED
post_id が不正、または投稿タイプが paid_article でないPaidArticleAiGenerationAjaxCopy::INVALID_POST
edit_post 権限なしMessages::PERMISSION_DENIED
target_fields が空PaidArticleAiGenerationServiceCopy::TARGET_FIELDS_EMPTY
いずれかの target_field が許可リスト外PaidArticleAiGenerationServiceCopy::TARGET_FIELD_INVALID
件数が上限超過PaidArticleAiGenerationServiceCopy::TARGET_FIELDS_TOO_MANY
結果 JSON が不正・有効な本文が 0 件PaidArticleAiGenerationServiceCopy::BULK_RESPONSE_INVALID
出力が max_tokens で途中切れPaidArticleAiGenerationServiceCopy::OUTPUT_TRUNCATED_BULK
API キー未設定・対象月未設定・指針未設定・応答切れ・形式不正・ループ上限対応する PaidArticleAiGenerationServiceCopy の固定文言
HTTP 429 / quota(Service 例外)Messages::AI_LLM_CLAUDE_RATE_LIMITED / AI_LLM_GEMINI_RATE_LIMITED(応答から取れた待ち秒が 1〜120 なら「(約 N 秒後)」を付与。生レスポンスは出さない)
HTTP 401 / 403(Service 例外)Messages::AI_LLM_CLAUDE_AUTH_FAILED / AI_LLM_GEMINI_AUTH_FAILED
HTTP タイムアウト・経過上限(Service 例外)Messages::AI_LLM_CLAUDE_TIMEOUT / AI_LLM_GEMINI_TIMEOUT
接続失敗(WP_Error、タイムアウト以外)(Service 例外)Messages::AI_LLM_CLAUDE_CONNECTION_FAILED / AI_LLM_GEMINI_CONNECTION_FAILED
その他の HTTP 非 200(Service 例外)Messages::AI_LLM_CLAUDE_HTTP_ERROR / AI_LLM_GEMINI_HTTP_ERROR(ステータスコードのみ。例: …(HTTP 500)。)
上記以外の Service 例外PaidArticleAiGenerationAjaxCopy::NOTICE_GENERIC_ERROR(詳細は error_log)

上流 API のレスポンス本文や WP_Error の生メッセージは画面・JSON に載せない(Issue #3866)。ArticleAiLlmClient は ArticleAiLlmHttpErrorMode::ClientSafe で固定文言だけを例外に入れ、PaidArticleAiGenerationAjaxHandler は ArticleAiLlmClientErrorFilter で許可した文言以外を汎用文言に置き換える。上流の詳細は ExternalApiErrorLogFormatter の要約(HTTP ステータス・短い要約・ハッシュ)で error_log に残す。

権限 ​

  • ログイン必須(wp_ajax_ のみ。nopriv は付けない)
  • capability: edit_post(対象 post_id)

生成契約 ​

  • 編集画面では「基本情報」の直下(ブロックエディタ本文の下、メタボックス先頭)に置く。ブロックエディタの右サイドバーには出ない
  • 1 リクエストにつき LLM 1 系列(ツール呼び出しループは欄ごと生成と同じ上限)
  • プロンプトで「記事全体で調子を一貫させる」「同じ事実を欄ごとに繰り返さない」「欄の趣旨に合わせる」を指示する
  • 既存本文は保存済み post meta のみ。未保存のエディタ内容は見えない
  • set_post_context() の current_field は空(一括のため生成中欄を区別しない)