Domain 4: Prompt Engineering & Structured Output
配点 20% — Task 4.1〜4.6
4.1 明示的な基準で精度を上げる
| ❌ 曖昧な指示(効果なし) | ✅ 明示的なカテゴリ基準 |
|---|---|
| 「保守的に報告してください」 「高信頼度の発見のみ報告する」 「be conservative」 → LLM には意味をなさず精度向上しない | 「コメントが実際のコード動作と矛盾する場合のみフラグ」 「スタイル問題はスキップ、バグとセキュリティのみ報告」 各 severity レベルにコード例を提示 |
false positive 率が高いカテゴリへの対処
false positive 率が高いカテゴリは一時的に無効にしてそのカテゴリのプロンプトを改善する間、開発者の信頼を維持する。高い false positive カテゴリは正確なカテゴリへの信頼も損なう。
4.2 Few-shot prompting
Few-shot は 「指示文より具体例の方が LLM の行動を変えやすい」 という性質を活用するパターンです。試験では「明示的な基準が効かないシナリオで Few-shot をどう設計するか」が問われます。以下の 5 パターンは試験頻出の用途別に分類したものです。
| 使いどころ | 例 | 例示するもの |
|---|---|---|
| 一貫したフォーマット出力が必要 | コードレビューの出力フォーマット統一 | location・issue・severity・suggested fix の形式 |
| 曖昧なシナリオの判断基準 | ツール選択の境界ケース | なぜ A 選択肢ではなく B を選んだか(理由付き) |
| 抽出タスクのハルシネーション削減 | 多様な文書構造からの抽出 | inline citation と bibliography で異なる処理例 |
パターン 1: 曖昧シナリオでの判断基準を例示する
「保守的に判定して」のような形容詞は LLM に効きません(4.1 参照)。代わりに 境界ケースの正解と不正解 を 2〜3 例ずつ提示します。
以下のコードレビューコメントについて、type を "bug" / "style" / "question" のいずれかに分類してください。
例:
入力: "この関数は null チェックが抜けています。クラッシュします。"
出力: { "type": "bug", "reason": "明示的なクラッシュ条件" }
入力: "この変数名は説明的でないと思います"
出力: { "type": "style", "reason": "命名は実行に影響しない" }
入力: "ここで使われている `O(n^2)` は意図的ですか?"
出力: { "type": "question", "reason": "確認を求めている。バグ確定ではない" }
判断に迷う場合は { "type": "question" } を選んでください。パターン 2: 出力フォーマットを例示する
JSON Schema は構造を強制しますが、フィールドの記述スタイル(簡潔さ・トーン・粒度)までは強制できません。スタイルを揃えたいときは Few-shot で揃えます。
以下のコード変更について、PR description の "Why" セクションを書いてください。
例:
diff: 「キャッシュ TTL を 60s → 300s に変更」
出力:
{
"why": "本番のキャッシュヒット率が 40% で、上流 API が rate limit に達する頻度が高い。
TTL を 5 倍にすることで rate limit エラーを抑える狙い。
stale データの許容度は事前に PdM と確認済み(本機能は近似値で十分)。"
}
→ 出力例の「現状の数値 / 変更の狙い / 副作用への配慮」の 3 段構成に揃えてください。パターン 3: 許容コードと問題コードの区別を例示する
セキュリティレビュー・コード品質判定では、「許容するコード」「拒否するコード」を両方 提示することが必須です。片方だけでは LLM が境界線を引けず false positive / false negative が増えます。
以下の SQL クエリ生成コードについて、SQL injection の可能性を判定してください。
✅ 許容例:
const stmt = db.prepare("SELECT * FROM users WHERE id = ?");
stmt.get(userId);
→ { "vulnerable": false, "reason": "prepared statement + bound parameter" }
❌ 問題例:
const query = `SELECT * FROM users WHERE id = ${userId}`;
db.query(query);
→ { "vulnerable": true, "reason": "テンプレートリテラルでユーザー入力を直接埋込" }
❌ 問題例(紛らわしいパターン):
const query = sql`SELECT * FROM users WHERE id = ${userId}`;
db.execute(query);
→ { "vulnerable": false, "reason": "sql タグ付きテンプレートは parameterized query を生成(要:使用ライブラリの確認)" }パターン 4: ドキュメント構造別の抽出例を提示する
抽出タスクで対象ドキュメントの構造が複数パターンに分かれる場合(学術論文の inline citation / bibliography / footnote など)、それぞれの構造に対する抽出例を 1 つずつ 提示します。1 例しか出さないと、構造が異なる文書でハルシネーションが起きます。
以下の論文から引用文献を抽出してください。
例 A (inline citation):
"...as shown by Smith et al. (2023), the effect is significant..."
→ { "type": "inline", "authors": "Smith et al.", "year": 2023 }
例 B (numbered bibliography):
"...the effect is significant [12]..."
(末尾の References:)"[12] Smith, J. (2023). Title. Journal, 4(2), 100-120."
→ { "type": "numbered", "ref_number": 12, "authors": "Smith, J.", "year": 2023, "title": "Title" }
例 C (footnote):
"...the effect is significant¹..."
(脚注:)"¹ Smith 2023, "Title", Journal 4(2)."
→ { "type": "footnote", "marker": "¹", "authors": "Smith", "year": 2023 }
文書全体を読んでから、上記 3 種類のいずれに該当するかを判定して抽出してください。パターン 5: 非公式測定値・近似表現の解釈を例示する
「約 5MB」「だいたい 1 時間程度」「ほぼ満タン」のような 非公式な測定値・近似表現 をどの粒度で構造化するかは、Few-shot で例示しないと一貫しません。
以下の障害報告から、影響範囲とダウンタイムを構造化してください。
例:
入力: "ストレージがほぼ満タンの状態で、約 1 時間ほど書き込みが失敗していた。
影響を受けたユーザーはおおよそ 5,000 人前後"
出力:
{
"storage_state": { "raw": "ほぼ満タン", "normalized": "near_capacity", "approximate": true },
"downtime": { "raw": "約 1 時間", "minutes_estimate": 60, "approximate": true },
"affected_users": { "raw": "おおよそ 5,000 人前後", "count_estimate": 5000, "approximate": true }
}
→ raw(原文ママ)+ normalized(カテゴリ)/ estimate(数値概算)+ approximate フラグの形式に揃えてください。
正確な数値が原文にない場合は approximate: true を必ず付け、estimate は中央値で記録します。Few-shot 設計の共通原則
- 境界例を含める — 「明らかに正解」だけでなく、「迷いやすいが正解はこれ」を必ず 1 例入れる
- 理由(reason)を併記する — 出力フォーマットに
reasonフィールドを設けると、LLM がパターンマッチではなく 判断軸 を学ぶ - ネガティブ例も役立つ —
❌ 問題例のラベルで反例を提示すると false positive が減る(ただし、ネガティブ例は出力例ではなく 判定対象の例 であることを明示すること) - 3〜5 例で十分 — それ以上は coverage より一貫性のリスクが上がる
4.3 tool_use + JSON Schema で構造化出力
JSON Schema 設計の重要原則
tool_useは JSON 構文エラーをなくす が、意味エラー(line items の合計 ≠ 総額等)は残る- nullable フィールド:情報が存在しないかもしれないフィールドは optional 化 → required にするとハルシネーション(hallucination)が発生
enum + "other"パターン:"other"値 + detail フィールドで拡張可能なカテゴリを設計"unclear"値:曖昧なケース用の enum 値を追加してモデルに選択肢を与える
4.4 バリデーション・リトライ・フィードバックループ
// retry-with-error-feedback パターン
const result = await extractWithSchema(document);
const errors = validateSchema(result);
if (errors.length > 0) {
// ✅ 元のドキュメント + 失敗した抽出結果 + 具体的なエラーを追加して再送
const retry = await extractWithFeedback({
document,
failedExtraction: result,
validationErrors: errors // 具体的なエラーが重要
});
}
// ❌ リトライが効果ない場合:情報がそもそもドキュメントに存在しない
// → 情報不在はフォーマットエラーと違い、リトライで解決しない4.5 Message Batches API の使い分け
| ✅ Batch API が適する(非同期・レイテンシ耐性あり) | ❌ 同期 API が必要(ブロッキング) |
|---|---|
| 翌朝レビューの技術的負債レポート 週次セキュリティ監査 夜間テスト生成 → 50% コスト削減・最大 24 時間・SLA 保証なし・エージェンティックループ非対応 | pre-merge ブロッキングチェック ユーザー向けリアルタイム抽出 → 開発者・ユーザーが結果を待っている SLA 保証なしの Batch API は使えない |
Batch API の「multi-turn 制約」を正確に理解する
「マルチターン tool calling 非対応」という記述は誤解を招きやすいため、より正確には 「エージェンティックループ非対応」。
正確な仕様:
- バッチ内の各リクエストは 1 回のメッセージ生成 で完結する(1 往復のみ)
- リクエスト内に user / assistant が交互に並んだ multi-turn の会話履歴を含めることは可能
- しかし、tool_use → ツール実行 → 結果を返して継続、という エージェンティックループはバッチでは展開できない(ツール実行をバッチが代行する仕組みがないため)
つまり「ツール呼び出しを含むワークフローは Batch ではなく同期 API で」が正しい判断基準。試験では「pre-merge チェックに Batch」「リアルタイム抽出に Batch」の両方が誤答として出ます。
Batch API の SLA ウィンドウ計算
Batch API は 最大 24 時間 で結果を返す保証ですが、実際には早く完了することも多いです。試験では「結果が必要な時刻 − 24 時間 = いつまでに送信すべきか」のような ウィンドウ計算問題 が出ます。
SLA ウィンドウの基本式
送信ウィンドウ = 結果が必要な時刻 − Batch API 上限 (24h) − 後処理時間「Batch を投げたいが、X 時間以内に結果が必要」というシナリオでは、24 − X が 負 になっていないかをまず確認します。
| シナリオ | 結果が必要な時刻 | 送信ウィンドウ計算(必要時刻 − 24h) | 結論 |
|---|---|---|---|
| 翌朝のレビュー(30 時間後でよい) | T + 30h | 30 − 24 = T + 6h まで送信可 | ✅ Batch を使う |
| 8 時間後のスタンドアップで結果が欲しい | T + 8h | 8 − 24 = −16h(ウィンドウなし) | ❌ Batch 不可 → 同期 API |
| 週次セキュリティ監査(1 週間後でよい) | T + 168h | 168 − 24 = T + 144h まで送信可 | ✅ Batch を使う |
| pre-merge チェック(PR 作成から 5 分以内) | T + 5min | 5min − 24h ≪ 0(ウィンドウなし) | ❌ Batch 不可 → 同期 API |
| 夜間テスト生成(朝 9 時までに必要・現在 21 時) | T + 12h | 12 − 24 = −12h(ウィンドウなし) | ❌ Batch 不可 → 同期 API |
「Batch なら 50% コスト削減できる」を理由に SLA を犠牲にしない
Batch API のコスト削減は魅力的ですが、SLA を満たせないシナリオに無理に Batch を当てると、結果が間に合わず再処理が必要になり 総コストは同期 API より高くなります。試験では「コスト削減のため Batch を採用」が罠の選択肢として頻出します。判断順序は ① SLA を満たせるか → ② 満たせるなら Batch → ③ 満たせないなら同期 API です。
4.6 マルチインスタンス・マルチパスレビュー
| パターン | 説明 | 理由 |
|---|---|---|
| 独立インスタンスレビュー | 生成したコードを別の Claude インスタンスでレビュー | 生成セッションは推論コンテキストを保持し自己批判が困難 |
| マルチパスレビュー | ① ファイル別ローカル分析パス + ② クロスファイル統合パス | 一度に全ファイルを処理すると注意分散(attention dilution)で矛盾発生 |
| 信頼スコア付き検証 | 各 finding に信頼スコアを自己報告させてルーティング | レビューリソースを効率的に配分 |