結論
LLM に業務文書の下書きを作らせると、内容は悪くないのに毎回アウトプットの形が変わるという問題に当たります。実務のフォーマットに毎回貼り直す手間が発生し、案件どうしを見比べることもできません。
これに対して有効だった対策は次の4点です。
- 出力の構造を固定する(セクション名・順序・粒度を決め打ちする)
- 形だけ固定しても中身は汎用化するので、入力から「対象の構造」を推定させ、その構造に紐づく内容を必ず含めさせる
- 出力の型をコードで縛り、検証してから使う。崩れていたら決め打ちの内容にフォールバックする
- キーワードによる分類は誤判定するので、利用者が明示的に指定した値を推論結果で上書きしない
題材は「曖昧な開発依頼を、提案前に使える要件整理の下書きに変換する」というタスクです。要件定義に限らず、LLM の出力を業務フォーマットに載せる場面で使える形だと思います。
何が困るのか
たとえば、こういう依頼を受けたとします。
紙とExcelでやっている勤怠管理をWeb化したい。打刻、月次の締め、残業申請を一元化して、締め作業の手間を減らしたい。
このままでは見積もりも提案もできないので整理が必要です。LLM に投げれば、それなりの整理は返ってきます。内容自体は悪くありません。
困るのは形が毎回変わることです。
- ある時は箇条書き、ある時は表、ある時は長い散文
- 見出しの粒度も名前も毎回違う(「課題」「前提」「検討事項」…)
- 実務のフォーマットに合わせるために、毎回整え直す
- 案件間で見比べられない
そして、形を指定せずに頼むと内容にも傾向が出ます。
- 予算はどの程度を想定していますか?
- 希望の納期はいつですか?
- 現在の課題は何ですか?
間違ってはいませんが、どの案件でも同じことしか言っていない。本当に欲しいのは「この業務だからこそ最初に確認すべきこと」です。
1. 出力の構造を固定する
まず、出力するセクションを固定します。今回は次の7つにしました。
| セクション | 役割 |
|---|---|
| Summary | 依頼の要約 |
| Purpose | 何のためにやるのか |
| Key Points | 最初に考えるべき問い |
| Missing Information | 現時点で不足している情報 |
| Risks | 想定されるリスク |
| Solution Options | 進め方の3段階(軽量 / 標準 / 発展) |
| Next Actions | 次のアクション |
設計上のポイントは、「決まっていること」と「決まっていないこと」を別のセクションに分けたことです。
LLM の出力は、与えられた情報から「分かっていること」を滑らかにまとめる方向に寄ります。その結果、何が欠けているのかが見えなくなる。不足情報を独立したセクションとして必ず出させると、そのまま次回の確認事項リストになります。
Solution Options も、「機能が多い案 / 少ない案」ではなく検討の深さで3段階に分けました。
| 段階 | 意味 |
|---|---|
| 軽量 | 今決めるべき最小限の論点だけ整理して、早く前に進む |
| 標準 | 主要機能・利用者・データの切り口まで考える |
| 発展 | 運用・連携・非機能・段階展開まで視野に入れる |
2. 形だけ固定しても、中身は汎用的になる
ここが本題です。セクション名を固定しただけでは、Key Points は結局「予算は?納期は?」で埋まります。形が揃った汎用回答が出てくるだけです。
そこで、入力文から対象業務の構造を推定させ、その構造に応じた問いを必ず含めるよう制約しました。
| 構造 | 典型例 | 最初に聞くべきこと |
|---|---|---|
| 記録系 | 出退勤・日報・点検記録 | 何を・いつ・誰が記録するか |
| トランザクション系 | 販売・受注・請求 | 状態遷移と確定タイミングは何か |
| ワークフロー系 | 承認・申請・審査 | 承認ルートと差し戻し条件は何か |
| 分析系 | BI・ダッシュボード | 何を見て・どう判断するか |
| 管理系 | 顧客管理・在庫管理 | 何を・どの粒度で・誰が管理するか |
| 予約系 | 会議室・設備予約 | 何を誰がいつ押さえるか |
| 共有系 | 問い合わせ・情報共有 | 何を投稿し誰がどう対応するか |
| 連携系 | データ同期・外部連携 | 何をどの方式で同期するか |
| 自動化系 | バッチ・通知・定型処理 | 何が起点で何が自動実行されるか |
複数が混ざる場合は「主構造 + 副構造」として扱い、「汎用」には逃がさないようにしています。逃げ道を用意すると、必ずそこに落ちるからです。
アクション項目にも制約を入れました。「ヒアリングする」で終わらせず、行動 + 成果物を1文にする、というルールです。
- ❌ 業務フローをヒアリングする
- ✅ 【顧客確認】出退勤の記録タイミング・修正ルール・例外処理をヒアリングし、現行フローを一覧化する
「誰が」「何を作るか」まで書かれていないアクションは、実際には動かないので。
この設計で出てくるもの
冒頭の勤怠管理の依頼に対して、Key Points はこうなります。
- 打刻時のリアルタイム入力と後入力はどのように区分すべきか?
- 残業申請の承認フローは誰が担うべきか?
- 月次の締め作業を行う際の条件はどのように設定するか?
アクションはこうです。
- 【業務リーダー】承認フロー図を作成し、申請者・承認者・差戻し条件を記載し、具体的な承認手続きを決める。
- 【データ管理者】記録項目一覧を作成し、打刻方法・月次締め・残業申請のデータ項目を記載し、必要なデータ構造を決める。
「打刻」「締め」「残業申請」という、入力文に出てきた業務の言葉が問いの中に入っている点が重要です。ここに固有の言葉が出てこない場合、それはテンプレートを貼っているだけのサインなので、品質チェックの指標としても使えます。
3. 出力の型をコードで縛り、検証する
LLM の出力をそのまま画面に流すと、形が崩れた瞬間にクラッシュします。実際に踏んだのは、配列で返ってくる前提のフィールドが文字列で返ってくるケースです。.map() を呼んだところで落ちます。
そこで、契約をコードで縛りました。
type DocumentOutput = {
summary: string;
purpose: string;
keyPoints: string[];
missingInformation: string[];
risksAndConcerns: string[];
solutionOptions: SolutionOption[];
nextActions: string[];
};
// 受け取った値が契約どおりかを検証してから使う
function isDocumentOutput(value: unknown): value is DocumentOutput {
const v = value as Partial<DocumentOutput>;
return (
typeof v?.summary === 'string' &&
Array.isArray(v?.keyPoints) &&
Array.isArray(v?.missingInformation) &&
Array.isArray(v?.nextActions)
);
}
検証に落ちたら LLM の出力は捨てて、決め打ちの整理結果にフォールバックします。「LLM が失敗したときに画面が壊れる」ことを許さないのが、日常的に使ってもらうための最低条件でした。
プロンプト側では、「良い例」を並べるより禁止事項を明示したほうが安定しました。
- 固定パターン(出退勤テンプレ、販売テンプレ)をそのまま貼らない
- Key Points をプロジェクト管理系の汎用質問だけで埋めない
- 不足情報は「業務の実態 > プロジェクト管理情報」の順で書く(KPI・予算・組織図の詳細は初回では後回し)
4. キーワードによる分類は誤判定する
いちばん厄介だったのがこれです。
入力文に「集計」「可視化」「指標」といった単語が含まれていると、**分析系(BI・ダッシュボード)**だと推定してしまい、記録系の依頼なのに「何を見て、どう判断するか」を中心に整理される、という事故が起きました。
「勤怠を記録して月次で集計したい」は記録系です。分析系ではありません。しかし単語だけを見ると、分析系の特徴語が入っています。
対策は2つです。
- 利用者が画面で明示的に選んだ種別を、テキスト推論の結果で上書きしない。推論はあくまで参考値として扱う
- サンプルや例文を書くときに、記録系の題材で「集計」のような分析系の特徴語をむやみに使わない(「締め」「振り返り」などに言い換える)
1 のほうが本質的です。利用者の明示的な入力は、モデルの推測より常に優先されるべきで、これは LLM を組み込むプロダクト全般に言えると思います。
まとめ
- 繰り返す作業では、出力の形が毎回変わること自体がコストになる。まず構造を固定する
- ただし形だけ固定しても、中身は汎用的な内容で埋まる。入力から対象の構造を推定させ、それに紐づく内容を必ず含めさせる
- 出力の型をコードで縛り、検証し、崩れたらフォールバックする。LLM の失敗で画面を壊さない
- キーワードによる分類は誤判定する。利用者の明示的な選択を推論で上書きしない
「出力の形を先に決めて、型で縛り、崩れたらフォールバックする」の3点は、要件定義に限らず、LLM の出力を業務フォーマットに載せる場面で共通して使える型だと考えています。