生成AI にデータ分析のコードを書かせるとき、結果のばらつきを抑えるカギは プロンプトの構造化 にあります。本記事では「何を / どんな入力で / どんな出力に / どんな制約で」を分けて書く設計フォーマットと、具体例を整理します。

目次

  1. なぜ「構造化」するのか
  2. 4 ブロックの基本テンプレート
  3. ブロックごとの書き方
  4. 良い例 vs 悪い例
  5. 反復のための差分プロンプト
  6. サンプルデータを添える
  7. 出力フォーマットを縛る
  8. 失敗を防ぐ小さな工夫
  9. 生成AI へのプロンプト例(メタ)

なぜ「構造化」するのか

同じ分析依頼でも、書き方の違いで返ってくるコードの質が大きく変わります。短く曖昧なプロンプトは、生成AI に「行間の補完」を強いる形になります。補完は推測なので、必ずしも意図と一致しません。

構造化プロンプトの目的は、推測の余地を減らす ことです。具体的には次の 4 点を明示します。

  • 目的(何を達成したいか)
  • 入力(どんなデータが既にあるか)
  • 出力(どんな形で結果を返してほしいか)
  • 制約(言語・ライブラリ・バージョン・コーディング規約など)

この 4 点が揃えば、生成AI は「ゴールに向かう一直線」のコードを返しやすくなります。

4 ブロックの基本テンプレート

最小構成のテンプレートはこの形です。

Python のコードを書いてください。
【目的】
(1〜2 行で、何をしたいかを書く)
【入力】
(変数名・列名・型・サンプル値・件数規模など)
【出力】
(返り値の型・列構成・並び順・ファイル形式など)
【制約】
- 言語/バージョン: Python 3.12 / pandas 2.2 系
- ライブラリ: 標準 + pandas のみ
- コードスタイル: 関数化し、docstring を日本語で
- 実行環境: 単一スクリプト

ブロックの順序は固定で構いません。生成AI 側のテンプレートに沿わせるより、利用者が 毎回同じ枠で考える ことに意味があります。

ブロックごとの書き方

目的(WHAT と WHY)

「何をしたいか」だけでなく、可能なら「なぜそれが欲しいか」を 1 行添えます。WHY があると、生成AI が代替案や関連処理を提案しやすくなります。

【目的】
日次株価データから 5 日・25 日移動平均を計算し、ゴールデンクロス(5 日線が 25 日線を下から上に抜けた日)を抽出する。
理由: バックテストの入口として、シグナル発生日のリストを再利用したい。

入力(あるものを正確に)

「ある列名・型・粒度・件数」を書きます。実データの先頭数行を貼り付けてもよいですが、機密性のあるデータはサンプル化または架空値にします。

【入力】
DataFrame `df` には次の列があります:
- date (datetime64[ns]): 営業日のみ、昇順
- ticker (str): 銘柄コード(複数銘柄)
- close (float): 調整後終値
期間: 2020-01-01 〜 2025-12-31
銘柄数: 約 100
1 銘柄あたり行数: 約 1,500 行

出力(返す形を確定する)

返り値の型・並び順・ファイル形式まで指定します。曖昧だと、生成AI は読みやすさ優先の形で返し、後段で扱いづらいことがあります。

【出力】
DataFrame を返してください。列構成は次の通りです:
- date, ticker, close, sma5, sma25, golden_cross (bool)
並び順: ticker 昇順, date 昇順
golden_cross は当日の sma5 > sma25 かつ 前日の sma5 <= sma25 で True。

制約(後段の都合を反映する)

実行環境・ライブラリ・コードスタイルなど、後段の都合をここに集約します。テストやデプロイ先がある場合も、ここで宣言します。

【制約】
- pandas 2.2 系 / numpy 2.x
- ライブラリは pandas, numpy のみ(追加の pip install は不可)
- main 関数を持つ単一スクリプト形式
- 関数は型ヒント付き、docstring は日本語
- 入力・出力は CSV(UTF-8、ヘッダーあり)

良い例 vs 悪い例

同じやりたいことを、悪いプロンプトと良いプロンプトで並べます。

観点悪いプロンプト良いプロンプト
目的「移動平均出して」「5 日 / 25 日 SMA を出してゴールデンクロス日を抽出」
入力暗黙「DataFrame、date / ticker / close、約 100 銘柄」
出力「結果を見せて」「golden_cross 列付き DataFrame を ticker / date 昇順で」
制約無し「pandas 2.2、main 関数、型ヒント、docstring 日本語」

良い側のプロンプトでは、生成AI は やり直しの少ないコード を返しやすくなります。

反復のための差分プロンプト

最初の出力にすべてを盛り込もうとすると、長すぎて品質が下がります。最初の依頼で土台を作り、2 回目以降は「差分」を依頼するほうが効率的です。

さきほどのコードに次の機能を追加してください。
差分:
- 出力 DataFrame に dead_cross (bool) 列を追加
- 当日 sma5 < sma25 かつ 前日 sma5 >= sma25 で True
- main の最後で golden_cross の件数と dead_cross の件数を print
その他の挙動は維持してください。

「差分」「その他の挙動は維持」と明記することで、不要な書き換えを抑制できます。

サンプルデータを添える

生成AI はデータの形を「読み取って推測」しています。可能なら、サンプル値を 3〜5 行添えると精度が上がります。

【入力サンプル】
date,ticker,close
2025-01-06,7203,2901.0
2025-01-07,7203,2920.5
2025-01-06,9984,9700.0
2025-01-07,9984,9750.0

機密データはサンプル化、もしくは架空値で代用します。元データそのままを貼らないことがプライバシー上の作法です(詳細は#7-4「AI が書いたコードを安全にレビューする観点」)。

出力フォーマットを縛る

レポート形式の出力を求める場合、Markdown / JSON / CSV など 形式を名指し します。形式が決まると、後段のスクリプトに流し込みやすくなります。

【出力フォーマット】
JSON 配列で返してください。各要素は次のキーを持ちます:
- ticker (str)
- date (str, "YYYY-MM-DD")
- signal ("golden" | "dead")
それ以外のキー・コメントは含めないでください。

「それ以外を含めない」という否定的指定が効きます。

失敗を防ぐ小さな工夫

  • 長文は箇条書きで構造化する(平文で書くと前提が埋もれます)
  • 数字は単位ごと書く(「100」ではなく「100 銘柄」「100 円」「100 行」)
  • 時間範囲は半開区間で書く(「2024-01-01 〜 2024-12-31」など揺れがちな範囲表記を統一)
  • 何を「しないでほしいか」も書く(「ファイル書き込みは行わないでください」)

生成AI へのプロンプト例(メタ)

このプロンプト設計を、生成AI 自身に補助させることもできます。

次のプロンプトを「目的・入力・出力・制約」の 4 ブロックに整理してください。
不足している情報があれば、質問の形で列挙してください。
元のプロンプト:
"日次の株価から PER の時系列を出したい。"

この使い方をすると、自分で書きかけたプロンプトを構造化された形に整える壁打ち相手として活用できます。

まとめ

  • プロンプトは「目的 / 入力 / 出力 / 制約」の 4 ブロックで構造化する
  • 入力は列名・型・粒度・件数まで書く
  • 出力は形式・並び順・ファイル形式まで指定する
  • 反復は差分プロンプトで「その他は維持」と明記する
  • 機密データを直接貼らず、サンプル値で代用する