<p><!-- style_prompt: programming_cot_optimization -->
本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">CoT(思考連鎖)を用いた複雑なソースコードのバグ修正・リファクタリング支援</h1>
<h3 class="wp-block-heading">【ユースケース定義と課題】</h3>
<ul class="wp-block-list">
<li><p><strong>ユースケース</strong>:レガシーコードや複雑なアルゴリズムにおける、エッジケースを考慮したバグ特定と修正コードの生成。</p></li>
<li><p><strong>課題</strong>:LLMが即座にコードを出力すると、境界条件(NULL値、極値など)の考慮漏れや、既存ロジックの破壊が発生しやすい。</p></li>
<li><p><strong>入出力の型</strong>:</p>
<ul>
<li><p>入力:Markdown(コードブロック + バグの症状・要件)</p></li>
<li><p>出力:JSON形式(思考プロセス、修正方針、修正コード、テストケースの4要素を内包)</p></li>
</ul></li>
</ul>
<h3 class="wp-block-heading">【プロンプト設計のループ】</h3>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
graph TD
A["設計: 思考プロセスの分離"] --> B["実行: CoTプロンプトの適用"]
B --> C["評価: 精度・構文の自動検証"]
C -->|改善: 逸脱防止ルールの追加| A
</pre></div>
<ol class="wp-block-list">
<li><p><strong>設計</strong>:コード生成の前に「現状分析」「原因特定」「修正方針」「影響範囲」を強制的に思考(CoT)させるステップを定義します。</p></li>
<li><p><strong>実行</strong>:Few-shotを用いて、思考ステップを踏んでから最終出力を得るプロセスをLLMに学習させます。</p></li>
<li><p><strong>評価</strong>:生成されたコードが構文的に正しく、かつ指定したJSONフォーマットを遵守しているかを検証し、エラーがあればプロンプトにフィードバックします。</p></li>
</ol>
<h3 class="wp-block-heading">【プロンプトの実装案】</h3>
<div class="codehilite">
<pre data-enlighter-language="generic"># 指示
あなたは優秀なシニアソフトウェアエンジニアです。
提供されたソースコードのバグを修正し、指定されたJSONフォーマットで出力してください。
回答を出力する前に、必ず「思考プロセス(Chain-of-Thought)」を実行し、バグの原因、修正方針、影響範囲をステップ・バイ・ステップで分析してください。
# 出力フォーマット
必ず以下のJSONフォーマットのみで出力してください(マークダウンのコードブロックで囲んでください)。
{
"thought_process": {
"analysis": "コードの現状の挙動と問題点に対する詳細な分析",
"root_cause": "バグの根本原因の特定",
"edge_cases": ["考慮すべきエッジケース1", "考慮すべきエッジケース2"]
},
"fix_strategy": "修正方針の説明",
"fixed_code": "修正後のソースコード全体",
"test_cases": [
{
"input": "テスト入力",
"expected_output": "期待される出力"
}
]
}
# 例示(Few-Shot)
## 入力コード(Python)
def divide_list(values, divisor):
return [v / divisor for v in values]
## 入力バグ報告
divisorが0の場合にZeroDivisionErrorが発生する。空のリストが渡された場合は空のリストを返したい。
## 出力
{
"thought_process": {
"analysis": "与えられた関数はリストの各要素をdivisorで割る。divisorが0のとき、ゼロ除算エラーが発生する。",
"root_cause": "divisorが0である場合の例外処理およびバリデーションが不足している。",
"edge_cases": ["divisorが0の場合", "valuesが空リストの場合", "valuesに数値以外の型が含まれる場合"]
},
"fix_strategy": "divisorが0の場合はValueErrorを発生させるか、事前にバリデーションを行う。今回は安全のためにdivisorが0の場合はカスタム例外またはValueErrorを投げ、空リストの場合はそのまま空リストを返す仕様とする。",
"fixed_code": "def divide_list(values, divisor):\n if not values:\n return []\n if divisor == 0:\n raise ValueError('Divisor cannot be zero')\n return [v / divisor for v in values]",
"test_cases": [
{"input": "values=[], divisor=2", "expected_output": "[]"},
{"input": "values=[10, 20], divisor=0", "expected_output": "ValueError"}
]
}
# 修正対象のコード
{{INSERT_CODE_HERE}}
# バグ報告・要件
{{INSERT_BUG_REPORT_HERE}}
</pre>
</div>
<h3 class="wp-block-heading">【評価指標と誤り分析】</h3>
<p>最新のLLM(Gemini 1.5 ProやGPT-4oなど)であっても、以下のような失敗パターンが生じることがあります。</p>
<ul class="wp-block-list">
<li><p><strong>失敗パターン1(様式崩れ)</strong>:JSONのパースエラー(エスケープ文字の不備、不要なテキストの混入)。</p></li>
<li><p><strong>失敗パターン2(思考の浅さ)</strong>:<code>thought_process</code> の中身が形骸化し、十分な分析を行わずにコード生成へ進んでしまう。</p></li>
</ul>
<p>これらを防ぐための、LLM-as-a-Judge用の評価基準を以下に定義します。</p>
<figure class="wp-block-table"><table>
<thead>
<tr>
<th style="text-align:left;">評価項目</th>
<th style="text-align:left;">評価基準 (5点満点)</th>
<th style="text-align:left;">失敗時の対策</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><strong>フォーマット遵守率</strong></td>
<td style="text-align:left;">完全なJSONとしてパース可能であり、スキーマが一致しているか (5: 完全一致, 1: パース不可)</td>
<td style="text-align:left;">スキーマ定義をTypeScriptの型定義等で厳密に指定する。</td>
</tr>
<tr>
<td style="text-align:left;"><strong>CoTの深さ</strong></td>
<td style="text-align:left;">原因分析、エッジケースの洗い出しが具体的に行われているか (5: 網羅的, 1: 空欄または形骸化)</td>
<td style="text-align:left;">システムプロンプトで「各ステップに最低2行以上の記述を求める」制約を課す。</td>
</tr>
<tr>
<td style="text-align:left;"><strong>コードの正確性</strong></td>
<td style="text-align:left;">提示された修正コードがコンパイル/実行可能で、バグが解消されているか (5: 解消済, 1: 未解消)</td>
<td style="text-align:left;">コード生成用とコード検証用(テスト実行環境)でエージェントを分離する。</td>
</tr>
</tbody>
</table></figure>
<h3 class="wp-block-heading">【改良後の最適プロンプト】</h3>
<p>上記の分析結果と、Gemini 1.5 Pro等の「指示追従能力」を最大化するために構造化した、システム指示付きの最適プロンプトです。</p>
<div class="codehilite">
<pre data-enlighter-language="generic"># システムロール
あなたは堅牢なソフトウェア開発を専門とする、厳格なコード監査AIエージェントです。
# タスク
入力されたコードのバグを修正してください。ただし、直感的な修正に飛びついてはいけません。必ず以下のステップに従って「深く思考」した結果を、指定のJSON構造で出力してください。
# 思考プロセス(CoT)の実行ルール
1. **静的解析**: コードを1行ずつ読み、不適切な処理や脆弱性がないか調査する。
2. **データフローの追跡**: 異常値、境界値、NULL/None、型不一致が入力された際の挙動を追跡する。
3. **影響範囲特定**: 修正を行うことで、既存の他の処理に悪影響を及ぼさないか検証する。
# 出力フォーマット(厳守)
JSON以外のテキスト(挨拶、前置き、Markdown以外の説明など)は一切出力しないでください。以下のスキーマに従ったJSONブロックのみを出力してください。
```json
{
"thought_chain": {
"static_analysis": "コードの静的解析結果",
"vulnerabilities": ["検出されたバグ・脆弱性のリスト"],
"boundary_conditions": ["検証した境界条件(空、極大値、NULL等)"]
},
"resolution": {
"strategy": "影響範囲を最小限に抑えるための具体的な修正方針",
"code": "修正後の完全なコード(インデントや改行を正しくエスケープした文字列)"
}
}
</pre>
</div>
<h1 class="wp-block-heading">修正対象</h1>
<ul class="wp-block-list">
<li><p>対象言語: {{LANGUAGE}}</p></li>
<li><p>ソースコード:
{{SOURCE_CODE}}</p></li>
<li><p>発生している問題:
{{ISSUE_DESCRIPTION}}
“`</p></li>
</ul>
<h3 class="wp-block-heading">【まとめ】</h3>
<p>実務でこのプロンプトを運用するための3つの鉄則:</p>
<ol class="wp-block-list">
<li><p><strong>思考と出力を分離する</strong>:バグ修正のような複雑なタスクでは、ワンショットでコードを出力させるのではなく、必ず「思考(分析)」のステップをプロンプト内で明示的に踏ませる。</p></li>
<li><p><strong>JSONパースエラーはスキーマ制約で防ぐ</strong>:最新のLLM(GeminiのStructured Outputs等)を利用可能な場合は、APIレベルでスキーマを強制し、テキストとしての崩れを未然に防ぐ。</p></li>
<li><p><strong>エッジケースの定義をサボらせない</strong>:プロンプト内に「空値、極値、型例外」などの具体的な検証ワードを含めることで、LLMの思考の解像度を強制的に引き上げる。</p></li>
</ol>
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
CoT(思考連鎖)を用いた複雑なソースコードのバグ修正・リファクタリング支援
【ユースケース定義と課題】
【プロンプト設計のループ】
graph TD
A["設計: 思考プロセスの分離"] --> B["実行: CoTプロンプトの適用"]
B --> C["評価: 精度・構文の自動検証"]
C -->|改善: 逸脱防止ルールの追加| A
設計:コード生成の前に「現状分析」「原因特定」「修正方針」「影響範囲」を強制的に思考(CoT)させるステップを定義します。
実行:Few-shotを用いて、思考ステップを踏んでから最終出力を得るプロセスをLLMに学習させます。
評価:生成されたコードが構文的に正しく、かつ指定したJSONフォーマットを遵守しているかを検証し、エラーがあればプロンプトにフィードバックします。
【プロンプトの実装案】
# 指示
あなたは優秀なシニアソフトウェアエンジニアです。
提供されたソースコードのバグを修正し、指定されたJSONフォーマットで出力してください。
回答を出力する前に、必ず「思考プロセス(Chain-of-Thought)」を実行し、バグの原因、修正方針、影響範囲をステップ・バイ・ステップで分析してください。
# 出力フォーマット
必ず以下のJSONフォーマットのみで出力してください(マークダウンのコードブロックで囲んでください)。
{
"thought_process": {
"analysis": "コードの現状の挙動と問題点に対する詳細な分析",
"root_cause": "バグの根本原因の特定",
"edge_cases": ["考慮すべきエッジケース1", "考慮すべきエッジケース2"]
},
"fix_strategy": "修正方針の説明",
"fixed_code": "修正後のソースコード全体",
"test_cases": [
{
"input": "テスト入力",
"expected_output": "期待される出力"
}
]
}
# 例示(Few-Shot)
## 入力コード(Python)
def divide_list(values, divisor):
return [v / divisor for v in values]
## 入力バグ報告
divisorが0の場合にZeroDivisionErrorが発生する。空のリストが渡された場合は空のリストを返したい。
## 出力
{
"thought_process": {
"analysis": "与えられた関数はリストの各要素をdivisorで割る。divisorが0のとき、ゼロ除算エラーが発生する。",
"root_cause": "divisorが0である場合の例外処理およびバリデーションが不足している。",
"edge_cases": ["divisorが0の場合", "valuesが空リストの場合", "valuesに数値以外の型が含まれる場合"]
},
"fix_strategy": "divisorが0の場合はValueErrorを発生させるか、事前にバリデーションを行う。今回は安全のためにdivisorが0の場合はカスタム例外またはValueErrorを投げ、空リストの場合はそのまま空リストを返す仕様とする。",
"fixed_code": "def divide_list(values, divisor):\n if not values:\n return []\n if divisor == 0:\n raise ValueError('Divisor cannot be zero')\n return [v / divisor for v in values]",
"test_cases": [
{"input": "values=[], divisor=2", "expected_output": "[]"},
{"input": "values=[10, 20], divisor=0", "expected_output": "ValueError"}
]
}
# 修正対象のコード
{{INSERT_CODE_HERE}}
# バグ報告・要件
{{INSERT_BUG_REPORT_HERE}}
【評価指標と誤り分析】
最新のLLM(Gemini 1.5 ProやGPT-4oなど)であっても、以下のような失敗パターンが生じることがあります。
これらを防ぐための、LLM-as-a-Judge用の評価基準を以下に定義します。
| 評価項目 |
評価基準 (5点満点) |
失敗時の対策 |
| フォーマット遵守率 |
完全なJSONとしてパース可能であり、スキーマが一致しているか (5: 完全一致, 1: パース不可) |
スキーマ定義をTypeScriptの型定義等で厳密に指定する。 |
| CoTの深さ |
原因分析、エッジケースの洗い出しが具体的に行われているか (5: 網羅的, 1: 空欄または形骸化) |
システムプロンプトで「各ステップに最低2行以上の記述を求める」制約を課す。 |
| コードの正確性 |
提示された修正コードがコンパイル/実行可能で、バグが解消されているか (5: 解消済, 1: 未解消) |
コード生成用とコード検証用(テスト実行環境)でエージェントを分離する。 |
【改良後の最適プロンプト】
上記の分析結果と、Gemini 1.5 Pro等の「指示追従能力」を最大化するために構造化した、システム指示付きの最適プロンプトです。
# システムロール
あなたは堅牢なソフトウェア開発を専門とする、厳格なコード監査AIエージェントです。
# タスク
入力されたコードのバグを修正してください。ただし、直感的な修正に飛びついてはいけません。必ず以下のステップに従って「深く思考」した結果を、指定のJSON構造で出力してください。
# 思考プロセス(CoT)の実行ルール
1. **静的解析**: コードを1行ずつ読み、不適切な処理や脆弱性がないか調査する。
2. **データフローの追跡**: 異常値、境界値、NULL/None、型不一致が入力された際の挙動を追跡する。
3. **影響範囲特定**: 修正を行うことで、既存の他の処理に悪影響を及ぼさないか検証する。
# 出力フォーマット(厳守)
JSON以外のテキスト(挨拶、前置き、Markdown以外の説明など)は一切出力しないでください。以下のスキーマに従ったJSONブロックのみを出力してください。
```json
{
"thought_chain": {
"static_analysis": "コードの静的解析結果",
"vulnerabilities": ["検出されたバグ・脆弱性のリスト"],
"boundary_conditions": ["検証した境界条件(空、極大値、NULL等)"]
},
"resolution": {
"strategy": "影響範囲を最小限に抑えるための具体的な修正方針",
"code": "修正後の完全なコード(インデントや改行を正しくエスケープした文字列)"
}
}
修正対象
【まとめ】
実務でこのプロンプトを運用するための3つの鉄則:
思考と出力を分離する:バグ修正のような複雑なタスクでは、ワンショットでコードを出力させるのではなく、必ず「思考(分析)」のステップをプロンプト内で明示的に踏ませる。
JSONパースエラーはスキーマ制約で防ぐ:最新のLLM(GeminiのStructured Outputs等)を利用可能な場合は、APIレベルでスキーマを強制し、テキストとしての崩れを未然に防ぐ。
エッジケースの定義をサボらせない:プロンプト内に「空値、極値、型例外」などの具体的な検証ワードを含めることで、LLMの思考の解像度を強制的に引き上げる。
ライセンス:本記事のテキスト/コードは特記なき限り
CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。
コメント