GEPA で契約書レビュー Agent を育てる — DSPy 5 部品の実装骨格¶
作成日: 2026-07-01 出典 / きっかけ: 申請レビュー Agent の DSPy 構造を「取引先ドラフト契約書を自社基準でレビューし、問題条項を指摘する法務レビュー Agent」に置き換えて、コードの骨格を端から端まで通した設計メモ。 芯(1行): GEPA は重みを一切触らず、法務の過去判断(データ)と名指しの feedback を燃料に、指示文だけを「自社の法務基準が染み込んだもの」に育てる。ただし燃料(正解データ)とハーネス(足場)が先で、プロンプト最適化は後。 関連: dspy_現場プロンプト改善ループ_metricと所有権境界_整理(ループ・metric・所有権の理論) / 法務経理ai_改善ループとガードレール_事例込み資料(他社事例+ガードレール) / 法務経理ai_芯_現場はsignal源_1枚整理(芯の1枚) / agentic_reference_architecture_評価ループ 元論文: GEPA: Reflective Prompt Evolution Can Outperform Reinforcement Learning(Agrawal et al., ICLR 2026 Oral)— 要約は Zotero ノートに保存済み。
0. 要点(3行)¶
- 申請レビューの
application_text → judgment, remand_commentは、契約書チェックのcontract_text → risk_level, issuesにそのまま対応する。骨格は Signature / Module / Metric / Dataset / Optimizer の 5 部品。 - 契約書が申請レビューと決定的に違うのは、「判定が合ってるか」だけでは足りない点。「要修正」と当てても危険条項を見落とせば実務では0点。だから metric を2軸(判定一致+論点の取りこぼし)にし、feedback に「どの論点を見落としたか」を名指しで入れる。これが GEPA の reflection に効く。
- 教科書どおりにいかない現実は3つ: ①正解データ(過去の法務判断の構造化)が最大のボトルネック、②プロンプト最適化の前にハーネス(条項分割・出力拘束・実在性チェック)を締める、③ハルシネーション不許容なので最終ゲートは人間の法務。
1. Signature:入出力の定義(人間が書く枠組み)¶
import dspy
class ContractReview(dspy.Signature):
"""契約書をレビューし、リスク判定と指摘コメントを返す。"""
contract_text: str = dspy.InputField(description="契約書ドラフトの本文")
risk_level: str = dspy.OutputField(description="リスク判定:問題なし / 要修正 / 締結不可")
issues: str = dspy.OutputField(description="問題条項の指摘と修正提案")
申請レビューの application_text → judgment, remand_comment が、そのまま contract_text → risk_level, issues に対応している。
2. Module:推論モジュール¶
3. Metric:採点基準(設計の勘所)¶
契約書チェックが申請レビューと違うのは「判定が合ってるか」だけでは足りない点。採点を 2 軸に分ける。
def contract_metric_with_feedback(example, pred, trace=None):
# 軸1:リスク判定が一致しているか
level_ok = (example.risk_level == pred.risk_level)
# 軸2:指摘すべき条項をちゃんと拾えているか(見落としが致命的)
expected_issues = set(example.issue_tags) # 例:{"損害賠償無制限", "自動更新", "準拠法"}
caught = set(pred.issues_tags) if hasattr(pred, "issues_tags") else set()
missed = expected_issues - caught # 見落とした論点
if level_ok and not missed:
return dspy.Prediction(score=1.0, feedback="判定・指摘ともに基準どおり。")
# 部分点:判定は当たったが見落としあり → 0.5、判定も外した → 0.0
score = 0.5 if level_ok else 0.0
return dspy.Prediction(
score=score,
feedback=(
f"契約書:『{example.contract_text[:200]}…』\n"
f"期待リスク判定:{example.risk_level} / 予測:{pred.risk_level}\n"
f"見落とした論点:{missed if missed else 'なし'}\n"
f"想定される指摘:『{example.issues}』\n"
f"実際の指摘:『{pred.issues}』\n"
"特に『見落とした論点』を確実に検知できるよう、"
"チェック観点や条項のパターンを指示文に追加・修正してください。"
)
)
ポイントは、単に「合ってる/外れてる」ではなく 「どの論点を見落としたか」を feedback に名指しで入れること。これで reflection_lm が「損害賠償の無制限条項を見落とす失敗が多い → 指示文に『損害賠償上限の有無を必ず確認せよ』を追記しよう」と、具体的に育てられる。
4. データセット:正解つきの実例(燃料)¶
trainset = [
dspy.Example(
contract_text="…業務委託契約のドラフト本文…",
risk_level="要修正",
issue_tags=["損害賠償無制限", "自動更新"],
issues="第12条の損害賠償が上限なし。第3条の自動更新条項に解約予告期間の記載なし。",
).with_inputs("contract_text"),
# …過去に法務がレビューした契約書を数十件…
]
.with_inputs("contract_text") で「Agent に渡すのは本文だけ」と宣言。risk_level と issues(=過去に法務担当者が実際に下した判断)は答え合わせ用に取っておく。
5. Optimizer:GEPA で指示文を育てる¶
dspy.configure(lm=dspy.LM("openai/gpt-4.4-mini")) # 推論用:安く速く
reflection_lm = dspy.LM("openai/gpt-4.4") # 反省用:賢いモデル
optimizer = dspy.GEPA(
metric=contract_metric_with_feedback,
reflection_lm=reflection_lm,
max_full_evals=20,
)
optimized_reviewer = optimizer.compile(reviewer, trainset=trainset, valset=valset)
回すと、素朴だった指示文が法務の過去判断と feedback を燃料に育つ。
- 最初: 「契約書をレビューせよ」
- 世代を経て: 「契約書をレビューせよ。特に以下を必ず確認:①損害賠償条項に上限額の定めがあるか(無制限は要修正)、②自動更新条項に解約予告期間の明記があるか、③準拠法・管轄裁判所が自社に不利でないか…」
——自社の法務基準が染み込んだ指示文に育つ。モデルの重みは gpt-4.4-mini のまま変わらず、指示文だけが賢くなる。
※ 上記のモデル名は「推論用は安く速く / 反省用は賢く」を示す例示。実装時は現行の実在モデル ID に置き換える。
契約書チェック特有の、実務での注意¶
教科書どおりにいかない現実。財務・法務・コンプラの会社全体 AI 化にモロに刺さる部分。
① 正解データの用意が最大のボトルネック¶
GEPA は「正解つきの過去事例」がないと1ミリも動かない。契約書チェックの正解=法務担当者の判断だが、これがきれいに構造化されて残っている会社はまれ。過去のレビュー済み契約書と指摘履歴を dspy.Example に整える前処理が、実は本番作業の大半。数十件でも始められるが、質の高い「却下例・修正例」がどれだけ集まるかで効果が決まる。
② プロンプト最適化の前に「ハーネス」を整える¶
GEPA で指示文を磨く前に、足場を先に固める:
- 契約書 PDF → 構造化テキスト(条項ごとに分割)
- 出力を JSON Schema / Pydantic で拘束(
risk_levelが3値のどれか、issuesが条項番号つき、を機械的に強制) - 「第12条」と言われたら本当にその条項が存在するかの 実在性チェック
ハーネス整備とプロンプト最適化はトレードオフではなく両輪。足場が締まっているほど GEPA が探索すべき範囲が狭まり、少ないデータで本質を学べる。契約書のように出力の正確性が命の領域では、ここを飛ばすと「それっぽいけど条項番号がデタラメ」な Agent が育つ。
③ ハルシネーションが許されない領域¶
間違った「問題なし」が事故に直結する。GEPA で精度を上げても、最終的には人間の法務がゲートに立つ設計(Agent は一次スクリーニング、確定判断は人間)が現実的。普段の checker gate / human gate の発想がそのまま活きる。
つながり(このメモの位置づけ)¶
- 理論(metric・所有権の境界・成果物は文字列でなく program)は dspy_現場プロンプト改善ループ_metricと所有権境界_整理。
- 他社事例+ガードレールの枠組み(データ分類 × リスク階層 × 承認 × 監査証跡)は 法務経理ai_改善ループとガードレール_事例込み資料。
- 本メモはその2つに対する「契約書レビューという具体題材で 5 部品を端から端まで通した実装骨格」にあたる。
深掘り候補(未着手)¶
- 実際に動く最小サンプル(ダミー契約書データ込み)を1ファイルに。
- ②のハーネス側、特に「条項の実在性チェック」と「Pydantic での出力拘束」の組み方。
- 正解データが少ないときのブートストラップ戦略(合成データ生成含む)。
作成: 2026-07-01 / 最終更新: 2026-07-01