# Faceted Prompting: AIプロンプトへの関心の分離 ## 問題 マルチエージェントシステムが複雑になるにつれ、プロンプトはモノリシックになる。1つのプロンプトファイルにエージェントの役割、行動規範、タスク固有の指示、ドメイン知識、出力形式がすべて混在する。これは3つの問題を生む。 1. **再利用できない** — 2つのステップが同じレビュアーのペルソナを必要としつつ指示が異なる場合、プロンプト全体を複製するしかない 2. **暗黙的な結合** — コーディング規約を変更すると、それを参照するすべてのプロンプトを編集する必要がある 3. **責任の不明確さ** — プロンプトのどの部分がエージェントの「役割」を定義し、どの部分が「やるべきこと」を定義しているのか区別がつかない ## アイデア ソフトウェア工学の基本原則である**関心の分離(Separation of Concerns)**をプロンプト設計に適用する。 エージェントごとに1つのモノリシックなプロンプトを書く代わりに、「何の関心を扱っているか」で独立した再利用可能なファイルに分解する。そしてワークフローのステップごとに宣言的に合成する。 ## 5つの関心 Faceted Promptingはプロンプトを5つの直交する関心に分解する。 | 関心 | 答える問い | 例 | |------|-----------|-----| | **Persona** | *誰*として判断するか? | 役割定義、専門性 | | **Policy** | *何を*守るか? | 禁止事項、品質基準、優先順位 | | **Instruction** | *何を*するか? | 目標、ステップ固有の手順 | | **Knowledge** | *何を*参照するか? | 前提知識、ドメイン資料、API仕様 | | **Output Contract** | *どう*出すか? | 出力構造、レポートテンプレート | 各関心はそれぞれのディレクトリに独立したファイル(Markdownまたはテンプレート)として格納される。 ``` workflows/ # ワークフロー定義 personas/ # WHO — 役割定義 policies/ # RULES — 禁止事項・品質基準 instructions/ # WHAT — ステップ手順 knowledge/ # CONTEXT — 前提知識・参照資料 output-contracts/ # OUTPUT — 出力契約テンプレート ``` ### 配置と各ファセットの典型例 LLMに渡せるスロットは **system prompt** と **user message** の2つだけである。5つの関心はこの2つに配置される。 ``` System Prompt: ┌─────────────────────────────────────────────┐ │ Persona — エージェントの役割・専門性・行動姿勢 │ └─────────────────────────────────────────────┘ User Message: ┌─────────────────────────────────────────────┐ │ Knowledge — 判断の前提となる参照資料 │ │ Instruction — このステップでやるべき手順 │ │ Output Contract — 出力の構造定義 │ │ Policy — 守るべきルール・禁止事項・品質基準 │ └─────────────────────────────────────────────┘ ``` Personaはエージェントの**identity**であり、タスクによって変わらない。system promptに置くことでLLMの応答全体を方向付ける。残りの4つはステップごとに変わるため、user messageに合成する。 Policyをuser messageの末尾に配置するのは意図的な設計判断である。LLMは直前に読んだ内容に強く影響される(recency効果)。禁止事項やREJECT基準といった制約は、出力生成の直前にあることで遵守されやすくなる。Knowledge → Instruction → Policyという流れは「文脈を理解 → 作業を理解 → 制約を確認」という自然な認知順序にもなっている。 以下に各ファセットの典型的なファイル例を示す。 #### Persona — `personas/architecture-reviewer.md` system promptに配置される。役割の定義、境界、行動姿勢のみを含む。 ```markdown # Architecture Reviewer あなたはソフトウェアアーキテクチャの専門家です。 コードの構造・設計・保守性を評価します。 ## 役割の境界 **やること:** - 構造・設計の妥当性検証 - コード品質の評価 - 変更スコープの適切性確認 **やらないこと:** - セキュリティ脆弱性のレビュー(Security Reviewerの仕事) - 自分でコードを書く ## 行動姿勢 - 完璧な設計を求めない。現状の制約下で最善かを判断する - 既存コードベースの規約を尊重する ``` 以下の4つはすべてuser messageに配置される。 #### Policy — `policies/coding.md` タスクをまたがって適用される共有ルール。規範的(「こうすべき」)。 ```markdown # コーディングポリシー ## 原則 | 原則 | 基準 | |------|------| | DRY | 3回以上の重複はREJECT | | Fail Fast | 不正状態は早期にエラー | | 最小権限 | 必要最小限のスコープ | ## 禁止事項 - **未使用コード** - 「念のため」のメソッド、将来用フィールド - **オブジェクトの直接変更** - スプレッド演算子で新規作成 - **フォールバックの濫用** - `?? 'default'` で不確実性を隠さない ``` #### Knowledge — `knowledge/architecture.md` 判断の前提となる参照情報。記述的(「こうなっている」)。 ```markdown # アーキテクチャ知識 ## レイヤー構造 依存の方向: 上位層 → 下位層(逆方向禁止) | レイヤー | 責務 | 依存先 | |---------|------|--------| | Controller | HTTPリクエスト処理 | Service | | Service | ビジネスロジック | Repository | | Repository | データアクセス | なし | ## ファイル構成 | 基準 | 判定 | |------|------| | 1ファイル300行超 | 分割を検討 | | 1ファイルに複数の責務 | REJECT | | 循環依存 | REJECT | ``` #### Instruction — `instructions/implement.md` このステップ固有の手順。命令形で記述する。 ```markdown 計画に基づいてタスクを実装してください。 **やること:** 1. 変更スコープを宣言する 2. コードを実装する 3. テストを書いて実行する 4. 判断ログを記録する **注意:** Previous Response がある場合は差し戻しです。 指摘事項を踏まえて修正してください。 ``` #### Output Contract — `output-contracts/review.md` 出力の構造を定義する。エージェントはこの形式に従って出力する。 ````markdown ```markdown # アーキテクチャレビュー ## 結果: APPROVE / REJECT ## サマリー {1-2文で結果を要約} ## 確認した観点 | 観点 | 結果 | 備考 | |------|------|------| | 構造・設計 | ✅ | - | | コード品質 | ✅ | - | | テストカバレッジ | ✅ | - | ## 問題点(REJECTの場合) | # | 場所 | 問題 | 修正案 | |---|------|------|--------| | 1 | `src/file.ts:42` | 問題の説明 | 修正方法 | ``` ```` #### 合成後の完全なプロンプト 上記5つのファイルがエンジンによって合成され、最終的にLLMに渡される形を示す。 **System Prompt:** ```markdown # Architecture Reviewer あなたはソフトウェアアーキテクチャの専門家です。 コードの構造・設計・保守性を評価します。 ## 役割の境界 **やること:** - 構造・設計の妥当性検証 - コード品質の評価 - 変更スコープの適切性確認 **やらないこと:** - セキュリティ脆弱性のレビュー(Security Reviewerの仕事) - 自分でコードを書く ## 行動姿勢 - 完璧な設計を求めない。現状の制約下で最善かを判断する - 既存コードベースの規約を尊重する ``` **User Message:** ```markdown ## Knowledge ### レイヤー構造 依存の方向: 上位層 → 下位層(逆方向禁止) | レイヤー | 責務 | 依存先 | |---------|------|--------| | Controller | HTTPリクエスト処理 | Service | | Service | ビジネスロジック | Repository | | Repository | データアクセス | なし | ### ファイル構成 | 基準 | 判定 | |------|------| | 1ファイル300行超 | 分割を検討 | | 1ファイルに複数の責務 | REJECT | | 循環依存 | REJECT | --- ## User Request ユーザー認証モジュールにJWTトークンの検証機能を追加してください。 --- ## Instructions 計画に基づいてタスクを実装してください。 **やること:** 1. 変更スコープを宣言する 2. コードを実装する 3. テストを書いて実行する 4. 判断ログを記録する **注意:** Previous Response がある場合は差し戻しです。 指摘事項を踏まえて修正してください。 --- ## Output Contract 以下のフォーマットでレポートを出力してください。 \```markdown # アーキテクチャレビュー ## 結果: APPROVE / REJECT ## サマリー {1-2文で結果を要約} ## 確認した観点 | 観点 | 結果 | 備考 | |------|------|------| | 構造・設計 | ✅ | - | | コード品質 | ✅ | - | | テストカバレッジ | ✅ | - | ## 問題点(REJECTの場合) | # | 場所 | 問題 | 修正案 | |---|------|------|--------| | 1 | `src/file.ts:42` | 問題の説明 | 修正方法 | \``` --- ## Policy ### 原則 | 原則 | 基準 | |------|------| | DRY | 3回以上の重複はREJECT | | Fail Fast | 不正状態は早期にエラー | | 最小権限 | 必要最小限のスコープ | ### 禁止事項 - **未使用コード** - 「念のため」のメソッド、将来用フィールド - **オブジェクトの直接変更** - スプレッド演算子で新規作成 - **フォールバックの濫用** - `?? 'default'` で不確実性を隠さない ``` このように、独立したファイルがランタイムで1つのプロンプトに組み立てられる。ファイルの内容を変えればプロンプトが変わり、別のファイルを指せば別の組み合わせになる。 ### なぜこの5つか? **Persona** と **Instruction** は最低限必要なもの — エージェントが誰で、何をすべきかを定義する必要がある。しかし実際には、さらに3つの関心が独立した軸として現れる。 - **Policy** はタスクをまたがって適用される規約・基準を捉える。「何を守るか」を定義する関心であり、禁止事項(フォールバック濫用の禁止、未使用コードの禁止)、品質基準(REJECT/APPROVE判定)、優先順位(正確性 > 速度)を含む。コーディングポリシーは機能実装でもバグ修正でも同じように適用される。ポリシーは「横断的関心事」であり、作業内容に関係なく守るべきルールを規定する。 - **Knowledge** はエージェントが判断の前提として参照する情報を捉える。アーキテクチャ文書はプランナーにもレビュアーにも関係がある。ナレッジをインストラクションから分離することで重複を防ぎ、インストラクションを手順に集中させる。ナレッジは記述的(「このドメインはこうなっている」)であり、規範的(「こうすべき」)なルールはPolicyに属する。 - **Output Contract** は作業そのものとは独立した出力構造を捉える。同じレビューフォーマットをアーキテクチャレビュアーとセキュリティレビュアーの両方で使える。出力形式の変更がエージェントの振る舞いに影響しない。 ## 宣言的な合成 Faceted Promptingの中核メカニズムは**宣言的な合成**である。ワークフロー定義が各ステップでプロンプトの内容を直接埋め込むのではなく、*どの*関心を組み合わせるかを宣言する。 主要な特性は次の通り。 - **各ファイルは1つの関心だけを持つ。** ペルソナファイルには役割と専門性のみを記述し、ステップ固有の手順は書かない。 - **合成は宣言的。** ワークフローは*どの*関心を組み合わせるかを記述し、プロンプトを*どう*組み立てるかは記述しない。 - **自由に組み合わせ可能。** 同じ `coder` ペルソナを異なるポリシーとインストラクションで異なるステップに使える。 - **ファイルが再利用の単位。** 同じファイルを指すことでポリシーをワークフロー間で共有する。 ### TAKTでの実装例 [TAKT](https://github.com/nrslib/takt) はFaceted PromptingをYAMLベースのワークフロー定義(「ピース」と呼ぶ)で実装している。各関心はセクションマップで短いキーにマッピングされ、各ステップ(TAKTでは「ムーブメント」と呼ぶ)からキーで参照される。 ```yaml name: my-workflow max_iterations: 10 initial_movement: plan # セクションマップ — キー: ファイルパス(このYAMLからの相対パス) personas: coder: ../personas/coder.md reviewer: ../personas/architecture-reviewer.md policies: coding: ../policies/coding.md review: ../policies/review.md instructions: plan: ../instructions/plan.md implement: ../instructions/implement.md knowledge: architecture: ../knowledge/architecture.md report_formats: review: ../output-contracts/review.md movements: - name: implement persona: coder # WHO — personas.coder を参照 policy: coding # RULES — policies.coding を参照 instruction: implement # WHAT — instructions.implement を参照 knowledge: architecture # CONTEXT — knowledge.architecture を参照 edit: true rules: - condition: Implementation complete next: review - name: review persona: reviewer # 異なる WHO policy: review # 異なる RULES instruction: review # 異なる WHAT(共有も可能) knowledge: architecture # 同じ CONTEXT — 再利用 output_contracts: - name: review.md format: review # OUTPUT — report_formats.review を参照 edit: false rules: - condition: Approved next: COMPLETE - condition: Needs fix next: implement ``` エンジンは各キーをファイルに解決し、内容を読み込み、実行時に最終的なプロンプトを組み立てる。ワークフローの作者がモノリシックなプロンプトを書くことはない — どのファセットを組み合わせるかを選択するだけである。 ## 既存手法との違い | 手法 | 内容 | 本手法との違い | |------|------|--------------| | **Decomposed Prompting** (Khot et al.) | *タスク*をサブタスクに分解して異なるLLMに委任 | 分解するのはタスクではなく*プロンプトの構造* | | **Modular Prompting** | XML/HTMLタグを使った単一プロンプト内のセクション分け | 関心を*独立ファイル*に分離し、宣言的に合成する | | **Prompt Layering** (Airia) | エンタープライズ向けのスタック可能なプロンプトセグメント | 管理ツールであり、プロンプト設計のデザインパターンではない | | **PDL** (IBM) | データパイプライン向けのYAMLベースプロンプトプログラミング言語 | 制御フロー(if/for/model呼び出し)が焦点で、関心の分離ではない | | **Role/Persona Prompting** | 役割を割り当ててレスポンスを方向付ける | ペルソナは5つの関心の1つにすぎない — ポリシー、インストラクション、ナレッジ、出力契約も分離する | 核心的な違いは次の点にある。既存手法は*タスク*(何をするか)を分解するか、*プロンプトの構造*(どう書式化するか)を整理する。Faceted Promptingは*プロンプトの関心*(各部分がなぜ存在するか)を独立した再利用可能な単位に分解する。 ## 実用上の利点 **ワークフロー作者にとって:** - コーディングポリシーを1つのファイルで変更すれば、それを使うすべてのワークフローに反映される - 既存のペルソナ、ポリシー、インストラクションを組み合わせて新しいワークフローを作れる - 各ファイルを単一の責務に集中させられる **チームにとって:** - プロンプトを複製せずにプロジェクト間でポリシー(品質基準・禁止事項)を標準化できる - ドメイン専門家がナレッジファイルを管理し、ワークフロー設計者がインストラクションを管理する分業ができる - 個々の関心を独立してレビューできる **エンジンにとって:** - プロンプト組み立ては決定的 — 同じワークフロー定義とファイルからは同じプロンプトが構築される - ポリシーの配置を最適化できる(例: recency効果を活用して末尾に配置し、制約遵守を強化) - 各関心を他の部分に影響を与えずにステップごとに注入・省略・上書きできる ## まとめ Faceted Promptingは、関心の分離(Separation of Concerns)をAIプロンプト工学に適用するデザインパターンである。プロンプトを5つの独立した関心 — Persona、Policy、Instruction、Knowledge、Output Contract — に分解し、宣言的に合成することで、再利用可能で保守しやすく透明なマルチエージェントワークフローを実現する。