コンテンツにスキップ

LLMとプログラミング:委譲の損益分岐点と「もっともらしい誤り」の見抜き方

前提:AI時代のITエンジニアの生存戦略:自動化の上限を定量的に見積もる

生 Markdown
  • LLM に任せるべきかはモデルの賢さだけでは決まらず、成功率 pp、指示を書くコスト、検証するコストの三つで決まります。委譲が得になる条件は p>g+vp > g + vgg は指示比、vv は検証比)という一つの不等式に還元できます(命題 3.1)。
  • この不等式から、検証コストが自作コストと同程度に高いタスクは、モデルがどれだけ賢くなっても委譲では得をしないという結論が出ます(系 3.2)。新規アーキテクチャの設計が LLM に向かないのは、モデルが弱いからではなく vv11 に近いからです。
  • 失敗したら再生成する、という戦略を採っても損益分岐点は動きません(命題 3.3)。再生成が効くのは検証が信頼できるときだけです。
  • 採用した成果物が誤っている確率は、検証器の偽陽性率 α\alpha にほぼ比例します(定理 7.2)。「AI の嘘を見抜く力」とは、この α\alpha を下げる技術です。
  • 大きなタスクを一括で投げると期待コストは工程数に対して指数的に膨らみ、工程ごとに検証すれば線形に抑えられます(定理 5.2)。これが「小さく切って渡す」の定量的な根拠です。

1. 動機:なぜ「使える/使えない」で意見が割れるのか

Section titled “1. 動機:なぜ「使える/使えない」で意見が割れるのか”

LLM をプログラミングに使った人の感想は、驚くほど両極端に分かれます。「実装速度が倍になった」と言う人と、「結局全部書き直したので遅くなった」と言う人が、同じ会社の同じチームにいます。

この分裂は測定でも再現されています。GitHub Copilot を使って JavaScript の HTTP サーバーを実装させた対照実験では、支援を受けた群がタスクを 55.8% 速く完了しました(Peng et al., 2023)。一方、実務経験の長い開発者が自分の熟知した大規模 OSS リポジトリで作業した実験では、AI 支援を受けた群のほうが 19% 遅くなり、しかも本人たちは「速くなった」と感じていました(METR, 2025)。前者の課題は仕様が明確で正しさの確認が容易であり、後者は被験者が対象コードを熟知していて品質基準も高い、という違いがあります。この違いが結果を分けている、というのがこの記事の見立てです。

同じ技術で正反対の結果が出るのですから、「LLM は開発に役立つか」という問いの立て方が間違っています。正しい問いは**「どういう性質のタスクで役立ち、どういう性質のタスクで害になるのか」**です。そして、その性質を言い当てる変数を見つけなければ、議論は経験談の応酬で終わってしまいます。

この記事では、その変数を三つに絞り込みます。仕事を外部に委ねるかどうかの判断は、経済学でいう取引コストの問題です。外注先がどれだけ優秀でも、仕様を説明する手間と、上がってきた成果物を検品する手間が自分でやるより高ければ、外注は損になります。LLM も例外ではありません。違うのは、LLM の検品コストが人間の外注先より高くつきやすいという点です。人間の下請けは分からないところを質問しますが、LLM は分からないところをそれらしく埋めて返してくるからです。

以下ではこの構造を最小限のモデルにし、そこから「得意・不得意」「タスク分割」「デバッグ技術」の三つを順に導きます。前提となるエンジニア像の議論は AI時代のITエンジニアの生存戦略 を参照してください。とくに、工程ごとの自動化率が全体の短縮率をどこまでしか押し上げられないかは 自動化の上限(系 3.2)[AI時代のITエンジニアの生存戦略] にあります。

2. 準備:委譲をコストでモデル化する

Section titled “2. 準備:委譲をコストでモデル化する”

議論の対象は「ひとまとまりの作業単位」です。関数を一つ書く、テストを一式書く、API 仕様書を作る、といった粒度を想定してください。

定義 2.1委譲コストモデル

ひとつの作業単位 TT について、次の量を定めます。単位は時間でも金額でも構いませんが、記事全体で統一します。

  • ch>0c_h > 0TT を人間が最初から自分で仕上げるコスト(設計・記述・自己点検を含む)。
  • cg0c_g \ge 0:LLM に TT を依頼するための指示(プロンプト・文脈の提示)を書くコスト。
  • cv0c_v \ge 0:LLM の出力を検証するコスト。読む、実行する、テストする、仕様と突き合わせる、の総和。
  • p[0,1]p \in [0, 1]:LLM の出力が検証を通る確率(成功率)。

さらに、比として

g=cgch,v=cvchg = \frac{c_g}{c_h}, \qquad v = \frac{c_v}{c_h}

を定め、それぞれ指示比検証比と呼びます。

chc_h で割って無次元化するのが要点です。同じ「検証に 20 分かかる」でも、自作に 2 時間かかるタスクなら v=1/6v = 1/6 で軽い作業ですが、自作に 25 分のタスクなら v=0.8v = 0.8 で致命的に重い作業になります。効くのは絶対時間ではなく比です。

検証は「通る/通らない」の二値判定として扱います。この判定を行う主体を検証器と呼びます。

定義 2.2検証器と偽陽性率

出力を受け取って「合格」「不合格」を返す手続きを検証器と呼びます。テストスイート、型検査器、静的解析、人間のレビュー、およびそれらの組み合わせが該当します。

検証器について、

  • 偽陰性率:正しい出力を不合格にする確率。以下では簡単のため 00 と仮定します。
  • 偽陽性率 α[0,1]\alpha \in [0, 1]:誤った出力を合格にする確率。

α\alpha は検証器の穴の大きさです。テストが 3 ケースしかなければ α\alpha は大きく、境界値・退化ケース・並行実行まで網羅していれば小さくなります。

命題 3.1委譲が得になる条件

委譲コストモデル(定義 2.1) のもとで、次の戦略を考えます。

LLM に一度依頼し、出力を検証する。合格すれば採用して終了する。不合格なら出力を捨て、人間が最初から自分で仕上げる。

この戦略の期待コスト C1C_1

C1=cg+cv+(1p)chC_1 = c_g + c_v + (1 - p)\,c_h

であり、C1<chC_1 < c_h が成り立つのは

p>g+vp > g + v

のとき、かつそのときに限ります。

証明(命題 3.1)

指示と検証は結果によらず必ず行うので、コスト cg+cvc_g + c_v は確率 11 で発生します。追加で人間が書き直す事象の確率は 1p1 - p定義 2.1pp の定義より、検証を通らない確率)であり、そのときのコストは chc_h です。期待値の線形性から

C1=(cg+cv)1+ch(1p)=cg+cv+(1p)ch.C_1 = (c_g + c_v) \cdot 1 + c_h \cdot (1 - p) = c_g + c_v + (1-p)c_h .

次に不等式を変形します。

C1<ch    cg+cv+(1p)ch<ch    cg+cv<ch(1p)ch=pch.\begin{aligned} C_1 < c_h &\iff c_g + c_v + (1-p)c_h < c_h \\ &\iff c_g + c_v < c_h - (1-p)c_h = p\,c_h . \end{aligned}

ch>0c_h > 0 なので両辺を chc_h で割れます。不等号の向きは変わりません。

cgch+cvch<p,\frac{c_g}{c_h} + \frac{c_v}{c_h} < p ,

すなわち 定義 2.1 の記号で g+v<pg + v < p です。すべて同値変形なので逆も成り立ちます。

この不等式は、読み下すと当たり前のことを言っています。「指示を書く手間と検品の手間の合計が、成功率で割り引いた自作コストより小さいなら任せる」。当たり前ですが、当たり前でない帰結を持ちます。

系 3.2検証が高いタスクは委譲不能

g+v1g + v \ge 1 であるようなタスクは、成功率 pp がどれほど高くても C1chC_1 \ge c_h となり、委譲によって得をすることはありません。

証明(系 3.2)

確率の定義から p1p \le 1 です。仮定より g+v1pg + v \ge 1 \ge p なので、p>g+vp > g+v は成り立ちません。命題 3.1 は同値条件なので、C1<chC_1 < c_h も成り立ちません。

系 3.2 は短い主張ですが、この記事でいちばん重要な結論です。ここには pp が現れません。つまりモデルの性能向上ではこの壁を越えられないということです。越えられるのは、vv を下げる工夫(検証を安くする。ただし下げ幅には 検証コストの床(系 4.3)[AI時代のITエンジニアの生存戦略] があります)か、chc_h を上げる状況(自作が本当に大変なタスクを選ぶ)だけです。

「一度で駄目なら捨てる」というのは現実的ではありません。ふつうは条件を足して再生成します(生成検証サイクル(定義 4.1)[AI時代のITエンジニアの生存戦略])。ところが、それでも境界は動きません。

命題 3.3再生成しても損益分岐点は変わらない

委譲コストモデル(定義 2.1) のもとで、各回の生成が互いに独立で、いずれも成功率 p(0,1]p \in (0,1] を持つとします。次の戦略を考えます。

生成と検証を最大 kk 回まで繰り返す。途中で合格すればそこで終了する。kk 回すべて不合格なら、人間が最初から自分で仕上げる。

このとき期待コストは

Ck=(cg+cv)1(1p)kp+(1p)kchC_k = (c_g + c_v)\,\frac{1 - (1-p)^k}{p} + (1-p)^k c_h

であり、数列 (Ck)k1(C_k)_{k \ge 1}

  • p>g+vp > g + v のとき狭義単調減少で、kk \to \infty の極限は (cg+cv)/p<ch(c_g + c_v)/p < c_h
  • p<g+vp < g + v のとき狭義単調増加で、すべての kk について Ck>chC_k > c_h
  • p=g+vp = g + v のとき定数で、すべての kk について Ck=chC_k = c_h

となります。とくに、ある kkCk<chC_k < c_h となることと p>g+vp > g+v とは同値です。

証明(命題 3.3)

ii 回目の生成が実行されるのは、11 回目から i1i-1 回目までがすべて不合格だった場合に限ります。独立性の仮定からその確率は (1p)i1(1-p)^{i-1} です。第 ii 回目を実行するときは必ず cg+cvc_g + c_v を払うので、期待値の線形性より生成・検証の期待コストは

i=1k(1p)i1(cg+cv)=(cg+cv)1(1p)k1(1p)=(cg+cv)1(1p)kp\sum_{i=1}^{k} (1-p)^{i-1}(c_g + c_v) = (c_g+c_v)\,\frac{1-(1-p)^k}{1-(1-p)} = (c_g+c_v)\,\frac{1-(1-p)^k}{p}

です(等比数列の和、公比 1p1-pp0p \ne 0 より分母は 00 でない)。人間が書き直すのは kk 回すべて不合格の場合だけで、その確率は (1p)k(1-p)^k、コストは chc_h です。両者を足して主張の式を得ます。

単調性は差を取れば分かります。

Ck+1Ck=(cg+cv)(1p)k(1p)k+1p+[(1p)k+1(1p)k]ch=(cg+cv)(1p)kpp(1p)kpch=(1p)k[(cg+cv)pch].\begin{aligned} C_{k+1} - C_k &= (c_g+c_v)\,\frac{(1-p)^k - (1-p)^{k+1}}{p} + \left[(1-p)^{k+1} - (1-p)^k\right] c_h \\ &= (c_g+c_v)\,\frac{(1-p)^k \, p}{p} - (1-p)^k p \, c_h \\ &= (1-p)^k \left[(c_g + c_v) - p\,c_h\right]. \end{aligned}

ここで (1p)k>0(1-p)^k > 0p<1p < 1 のとき。p=1p = 1 なら CkC_kk1k \ge 1 で定数 cg+cvc_g+c_v となり、主張は 命題 3.1 に帰着します)。したがって差の符号は (cg+cv)pch(c_g+c_v) - p\,c_h の符号に一致し、これは 命題 3.1 の証明中の変形から g+vg + vpp の大小に一致します。

kk \to \infty では 1p<1|1-p| < 1 より (1p)k0(1-p)^k \to 0 なので Ck(cg+cv)/pC_k \to (c_g+c_v)/p です。p>g+vp > g+v すなわち cg+cv<pchc_g + c_v < p\,c_h のとき、これは chc_h より小さくなります。C1=chC_1 = c_h となるのが p=g+vp = g+v のちょうどの場合であることは 命題 3.1 から従い、そこから単調性で全体が決まります。

実務的な含意は明快です。一度目で駄目だったものを粘って直させるかどうかは、判断の本質ではありません。粘るべきタスクは一度目から任せてよく、粘るべきでないタスクは一度目から任せるべきでないのです。「もう少しで動きそうだ」という感覚に従って三度四度と再生成を繰り返し、気づけば自分で書いたほうが速かった、という体験の正体がこれです。p<g+vp < g+v の領域では、再試行は状況を悪化させる一方です。

pp を横軸、vv を縦軸に取ると、命題 3.1 の条件は「直線 v=pgv = p - g より下」という半平面になります。指示比 gg0.050.05 と置いた図を示します。

定型コード生成ドキュメント生成テスト生成局所的なコードレビュー複雑な並行処理の実装新規アーキテクチャの決定自分で書くほうが安い委譲するほうが安い境界 v = p − g00.51成功率 p検証比 v
委譲の損益分岐(横軸:成功率 p、縦軸:検証比 v、指示比 g = 0.05)。点の位置は説明のための概算です。

注意 3.4

図中の点の座標は概算であって測定値ではありません。主張したいのは個々の数値ではなく、タスクが平面上のどこに位置するかで判断が決まるという構造です。自分のチームでの実際の位置を知りたければ、しばらく「指示を書いた時間」「レビューに使った時間」「差し戻した回数」を記録してください。この三つから ggvvpp の推定値が得られます。

命題 3.1系 3.2 を使って、よくある作業を分類します。判定に必要なのは「モデルがどれくらい賢いか」ではなく、そのタスクの正しさをどれくらい安く確かめられるかです。

作業成功率 pp検証比 vv判定検証が安い/高い理由
定型的なコード生成(DTO 変換、CRUD、設定ファイル)委譲する実行すれば分かる。仕様が閉じており、想定外の入力が少ない
ドキュメント・コメント・コミットメッセージ委譲する正しさの基準がコード本体にあり、突き合わせが速い
既知のアルゴリズムの実装中〜高委譲する参照実装・既知の性質(不変量)と照合できる
テストコードの生成低〜中条件付きで委譲する実行できるが、「何を検査していないか」の確認が要る
局所的なコードレビュー(規約違反、未処理の例外、既知の脆弱性パターン)委譲する指摘を一つ見れば真偽が判定できる。誤指摘のコストが小さい
既存コードの機械的リファクタリング場合によるテストの網羅度に完全に依存する
複雑な並行処理・分散処理の実装委譲しないテストを通っても正しさが保証されない。再現しない誤りが残る
性能要件を伴う設計判断委譲しない判定に負荷試験か解析が必要で、それ自体が本作業
新規性の高いアーキテクチャの決定1\approx 1委譲しない判定するには自分で設計するのと同じ思考が要る

最下段の 3 行に注目してください。共通しているのは「pp が低い」ことではなく、「vv が高い」ことです。この違いは重要です。pp が低いだけなら、モデルの進歩が解決してくれます。vv が高い場合は 系 3.2 により解決しません。

例 4.1定型コードの数値評価

社内 API のレスポンス型からフロントエンド用の型定義と変換関数を書く作業を考えます。手で書けば 90 分(ch=90c_h = 90)、API 仕様を貼り付けて指示を書くのに 8 分(cg=8c_g = 8)、生成物を読んで型検査を通し既存のテストを走らせるのに 12 分(cv=12c_v = 12)とします。

g+v=8+1290=20900.222.g + v = \frac{8 + 12}{90} = \frac{20}{90} \approx 0.222 .

したがって、命題 3.1 より、成功率が 22.2%22.2\% を超えれば委譲が得です。実際には p0.8p \approx 0.8 程度は期待できますから、余裕をもって条件を満たします。無限に再試行できる場合の期待コストは 命題 3.3 より

cg+cvp=200.8=25 分\frac{c_g + c_v}{p} = \frac{20}{0.8} = 25 \ \text{分}

で、自作の 9090 分に対しておよそ 3.63.6 倍の効率です。この種のタスクで「劇的に速くなった」という体験が生まれます。

例 4.2新規アーキテクチャ設計の数値評価

これまで単一データベースで動いていたサービスを、地域ごとに分割して結果整合で運用する構成に移行するか判断する、という作業を考えます。自分で結論を出すには、障害モードの列挙、整合性要件の棚卸し、移行計画の粗い見積もりが必要で、ch=40c_h = 40 時間とします。

LLM に「この要件で最適な構成を提案して」と依頼するのは 0.5 時間で済みます(g=0.0125g = 0.0125)。問題は検証です。返ってきた構成が要件を満たすかを判断するには、結局、障害モードの列挙も整合性要件の棚卸しも自分でやらなければなりません。楽になるのは「選択肢を思いつく」段階だけですから、cv=35c_v = 35 時間、v=0.875v = 0.875 と見積もられます。

g+v=0.0125+0.875=0.8875.g + v = 0.0125 + 0.875 = 0.8875 .

p>0.8875p > 0.8875、つまり一発で採用できる設計が返ってくる確率が 9 割でなければ、委譲は損になります。現実の成功率はこれよりはるかに低いので、この作業は委譲に向きません。しかも仮に cvc_v の見積もりが甘く cv=40c_v = 40 だったなら g+v>1g + v > 1 となり、系 3.2 よりどんなモデルでも救えません。

注意 4.3

例 4.2 の結論は「設計に LLM を使うな」ではありません。委譲という使い方をするな、です。同じ場面でも、「この構成で起きうる障害モードを 20 個挙げてください」という使い方なら話が変わります。この場合、成果物は候補リストであり、各項目の妥当性は一つずつ独立に、しかも短時間で判定できます。つまり vv が劇的に下がり、なおかつ chc_h(自分だけで 20 個挙げる手間)は小さくありません。

要点は、高い vv のタスクを、低い vv の部分タスクへ翻訳することです。「答えを出させる」のではなく「見落としを潰させる」「選択肢を広げさせる」形に問いを変換する。これが設計工程における LLM の正しい使い方だと考えています。

「大きな仕事を一度に投げず、小さく切って渡せ」という助言は経験則としてよく語られます。これは定理として証明できます。

定義 5.1工程分解と工程正答率

作業 TTnn 個の工程 T1,,TnT_1, \dots, T_n に分解され、各工程について生成と検証にかかるコストの合計が 11(単位コスト)であるとします。各工程の出力が正しい確率を r(0,1)r \in (0, 1) とし、異なる工程の正誤および同一工程の再試行は互いに独立であるとします。この rr工程正答率と呼びます。

定理 5.2逐次検証の優位性

工程分解(定義 5.1) のもとで、検証は完全(偽陽性率 α=0\alpha = 0、偽陰性率 00)とし、次の二つの方式を比較します。

  • 一括方式nn 工程をまとめて一度に生成し、全体をまとめて検証する。不合格なら全体を破棄して最初から生成し直す。合格するまで繰り返す。
  • 逐次方式:工程 T1,,TnT_1, \dots, T_n をこの順に生成し、各工程の生成直後にその工程だけを検証する。不合格ならその工程だけを生成し直す。合格したら次の工程へ進む。

このとき、完成までの期待総コストはそれぞれ

E一括=nrn,E逐次=nrE_{\text{一括}} = \frac{n}{r^{\,n}}, \qquad E_{\text{逐次}} = \frac{n}{r}

であり、その比は

E一括E逐次=(1r)n1\frac{E_{\text{一括}}}{E_{\text{逐次}}} = \left(\frac{1}{r}\right)^{n-1}

となります。すなわち一括方式のコストは工程数 nn について指数的に増大します。

証明(定理 5.2)

まず補助的な事実を確認します。成功確率 s(0,1]s \in (0,1] の独立試行を成功するまで繰り返すとき、試行回数 NN は幾何分布に従い、E[N]=1/s\mathbb{E}[N] = 1/s です。実際、Pr[N=i]=(1s)i1s\Pr[N = i] = (1-s)^{i-1}s より

E[N]=i=1i(1s)i1s=s1(1(1s))2=1s\mathbb{E}[N] = \sum_{i=1}^{\infty} i (1-s)^{i-1} s = s \cdot \frac{1}{(1-(1-s))^2} = \frac{1}{s}

i1ixi1=(1x)2\sum_{i \ge 1} i x^{i-1} = (1-x)^{-2}x<1|x| < 1x=1sx = 1-s に適用)。

一括方式nn 工程すべてが正しい確率は、独立性の仮定(定義 5.1)より rnr^n です。検証は完全なので、合格することと全体が正しいことは同値であり、1 回の試行の成功確率は s=rns = r^n です。1 回の試行では nn 工程すべてを生成・検証するのでコストは nn。したがって期待総コストは nE[N]=n/rnn \cdot \mathbb{E}[N] = n / r^n です。

逐次方式。工程 TiT_i に着目します。1 回の試行の成功確率は s=rs = r、1 回の試行のコストは 11 なので、TiT_i を完成させるまでの期待コストは 1/r1/r です。工程は互いに独立で、しかも各工程は前の工程が確定してから始まるため、総コストは各工程のコストの和です。期待値の線形性から

E逐次=i=1n1r=nr.E_{\text{逐次}} = \sum_{i=1}^{n} \frac{1}{r} = \frac{n}{r} .

比を取ると n/rnn/r=r1n=(1/r)n1\dfrac{n/r^n}{n/r} = r^{1-n} = (1/r)^{n-1} を得ます。

例 5.3工程数と一括方式の損失

工程正答率 r=0.98r = 0.98(一つの工程を 98% の確率で正しく仕上げる、かなり優秀なモデル)としたときの比 (1/0.98)n1(1/0.98)^{n-1} を計算します。ln(1/0.98)=0.020203\ln(1/0.98) = 0.020203 を使います。

工程数 nn指数 (n1)ln(1/r)(n-1)\ln(1/r)一括方式のコスト倍率
10100.18180.18181.201.20
50500.98990.98992.692.69
2002004.02044.020455.755.7

工程 10 個なら一括で投げても 2 割増しに過ぎず、体感では差が出ません。ところが 200 個になると 56 倍です。「小さな試作では快適だったのに、実際の機能開発に使うと破綻する」という現象は、この指数関数で説明できます。モデルの rr0.980.98 から 0.990.99 に上げても、n=200n = 200 での倍率は (1/0.99)199=e2.07.4(1/0.99)^{199} = e^{2.0} \approx 7.4 倍で、依然として大きい。分割は、モデルの改善よりも効きます。

注意 5.4

定理 5.2 の逐次方式が成立するには、「工程 TiT_i の誤りが TiT_i 単独で検出できる」ことが必要です。個々の関数は正しいのに組み合わせるとインタフェースの解釈がずれていて壊れる、という誤りはこの仮定の外にあります。

したがって実務では、工程分割と同時に結合部の検証(統合テスト、契約テスト、型による境界の固定)を用意しなければなりません。分割の利得は、境界を明示的に定義するコストと引き換えに得られます。境界を固定することで一度に検査すべき対象がどれだけ減るかは モジュール分割による検査対象の削減(命題 7.1)[AI時代のITエンジニアの生存戦略] にあります。裏を返せば、境界が明確でないコードベースでは分割の効果が薄く、LLM の導入効果も出にくくなります。

以上を踏まえて、工程ごとの具体的な使い方を整理します。方針は一貫しています。vv を下げる形に問いを変換し、nn を小さく切り、検証を先に用意する。

flowchart TD
A["仕様と受け入れ条件を人が書く"] --> B["LLM が候補を生成"]
B --> C&#123;"検証器にかける"&#125;
C -->|"不合格"| B
C -->|"合格"| D["採用"]
D --> E["本当に正しい"]
D --> F["偽陽性: もっともらしい誤りが残る"]
生成と検証のループ。偽陽性の経路(右下)だけが本番に誤りを運びます。

設計。 答えを出させず、材料を出させます。「この要件を満たす構成案を 3 つ、それぞれの失敗モードとともに挙げてください」「この設計で最初に壊れるのはどこですか」「この仕様に書かれていない前提を列挙してください」。いずれも出力が箇条書きで、一項目ずつ独立に真偽を判定できます。注意 4.3 の翻訳を実行しているわけです。決定そのものは人間が行います。決定を委ねた瞬間に vv が跳ね上がるからです。

実装。 工程を切り、検証を先に用意します。テストを先に書くと、cvc_v が「テストを実行する時間」まで下がります。例 4.1vv が小さかったのは、まさに既存のテストと型検査があったからです。逆に、テストのないコードベースに LLM で機能を追加すると、cvc_v は「生成された全行を人間が読む時間」になります。これは往々にして自分で書く時間を超えます。テスト駆動開発が LLM 時代に再評価されているのは、思想の問題ではなく 命題 3.1 の問題です。

テスト。 LLM にテストを書かせるのは有効ですが、一つ落とし穴があります。同じモデルに実装とテストの両方を、同じ文脈で書かせてはいけません。 モデルが実装で誤解した仕様は、テストでも同じように誤解されます。すると誤った実装が誤ったテストを通り、偽陽性率 α\alpha が跳ね上がります。検証器は、検証される対象と独立でなければ意味がありません。実務的には、テストは仕様書から(実装コードを見せずに)生成する、期待値は人間が手で埋める、境界値だけは自分で列挙する、といった分離が有効です。

レビュー。 LLM によるコードレビューは、実は最も費用対効果の高い使い方です。理由は vv の小ささにあります。「この行で null が来る可能性があります」という指摘は、その行を見れば数秒で真偽が分かります。誤指摘が混ざっても、失うのは数十秒であって本番の障害ではありません。指摘は間違っていてもよいが、コードは間違っていては困るという非対称性が、レビュー用途を有利にしています。ただし「この抽象化はこの先 2 年の変更に耐えるか」といった設計レベルの問いは 例 4.2 と同じ構造で、検証が高くつきます。

ここまでは検証器を所与としてきました。最後に、検証器そのものの質を扱います。プログラムの意味的な性質を機械的に完全に判定することは ライスの定理(定理 5.1)[AI時代のITエンジニアの生存戦略] によって不可能ですから、現実の検証器の偽陽性率 α\alpha00 にすることはできません。ここが LLM 時代のデバッグ技術の中心です。

定義 7.1もっともらしい誤り

LLM の出力のうち、形式的な整合性(構文が通る、型が合う、命名規則に従っている、説明が自然な日本語や英語になっている)を満たしながら、意味的に偽であるものを、この記事ではもっともらしい誤りと呼びます。存在しない API の呼び出し、境界条件を落とした実装、実際とは異なる出典の引用などが該当します。

もっともらしい誤りが厄介なのは、人間の第一印象という検証器を素通りする点にあります。構文の乱れは注意を引きますが、もっともらしい誤りは引きません。むしろ、整った命名と丁寧なコメントがついているぶん、自分で書いたコードより信頼されがちです。実験でもこの効果が観測されています。AI 支援を受けた被験者は、支援なしの被験者より安全性の低いコードを書いたにもかかわらず、自分は安全なコードを書けたと信じる傾向が強かったという報告があります(Perry et al., 2023)。これは α\alpha の上昇そのものです。

では α\alpha はどれだけ効くのでしょうか。定量的に答えられます。計算の構造は、検査が陽性と言ったときの的中率を求める問題(検知率 99%、誤検知率 1% のモデルが出す警告の信頼度(例 5.4)[数学を学び直す意義])と同じものです。

定理 7.2採用物の誤り率

検証器(定義 2.2) の偽陽性率を α[0,1]\alpha \in [0,1]、偽陰性率を 00 とします。各回の生成は独立で、出力が正しい確率は p(0,1)p \in (0,1) とします。合格が出るまで生成を繰り返し、最初に合格した出力を採用するとき、少なくとも 1 回は合格が出るという条件のもとで、採用された出力が誤りである確率は

Perr=(1p)αp+(1p)αP_{\text{err}} = \frac{(1-p)\,\alpha}{p + (1-p)\,\alpha}

です。とくに α\alpha が小さいとき

Perr1ppαP_{\text{err}} \approx \frac{1-p}{p}\,\alpha

と近似され、誤り率は偽陽性率にほぼ比例します。この値は試行回数の上限に依存しません。

証明(定理 7.2)

1 回の生成について、次の三つは互いに排反で、これで全事象を尽くします。

  • 正しく、かつ合格する:確率 pp(偽陰性率 00 の仮定より、正しい出力は必ず合格します)。
  • 誤りで、かつ合格する:確率 (1p)α(1-p)\alpha定義 2.2α\alpha の定義)。
  • 誤りで、かつ不合格:確率 (1p)(1α)(1-p)(1-\alpha)

したがって 1 回の生成が合格する確率は q=p+(1p)αq = p + (1-p)\alpha です。p>0p > 0 より q>0q > 0 です。

「最初の合格が第 ii 回目に起きる」という事象の確率は、独立性より (1q)i1q(1-q)^{i-1}q です。その合格が誤りである確率は、第 ii 回目の生成が「誤りかつ合格」である確率と「合格」である確率の比、すなわち (1p)α/q(1-p)\alpha / q で、ii に依存しません。よって全確率の公式から

Perr=i1(1q)i1(1p)αi1(1q)i1q=(1p)α1qq1q=(1p)αq=(1p)αp+(1p)α.P_{\text{err}} = \frac{\sum_{i \ge 1} (1-q)^{i-1}(1-p)\alpha}{\sum_{i \ge 1} (1-q)^{i-1} q} = \frac{(1-p)\alpha \cdot \frac{1}{q}}{q \cdot \frac{1}{q}} = \frac{(1-p)\alpha}{q} = \frac{(1-p)\alpha}{p + (1-p)\alpha}.

ここで両方の級数は 0<q10 < q \le 1 より収束します。

近似は、α0\alpha \to 0 のとき分母が p+O(α)pp + O(\alpha) \to p となることから従います。

例 7.3偽陽性率と成功率、どちらを改善すべきか

定理 7.2 の式に数値を入れます。Perr=(1p)α/(p+(1p)α)P_{\text{err}} = (1-p)\alpha / (p + (1-p)\alpha) をそのまま計算します。

ppα\alpha計算PerrP_{\text{err}}
0.40.40.400.400.24/(0.40+0.24)0.24 / (0.40 + 0.24)37.5%37.5\%
0.70.70.400.400.12/(0.70+0.12)0.12 / (0.70 + 0.12)14.6%14.6\%
0.40.40.050.050.03/(0.40+0.03)0.03 / (0.40 + 0.03)7.0%7.0\%
0.70.70.050.050.015/(0.70+0.015)0.015 / (0.70 + 0.015)2.1%2.1\%

1 行目を基準にすると、モデルを賢くして pp0.40.4 から 0.70.7 に上げた場合の改善は 37.5%14.6%37.5\% \to 14.6\%、検証を厳しくして α\alpha0.400.40 から 0.050.05 に下げた場合の改善は 37.5%7.0%37.5\% \to 7.0\% です。後者のほうが大きい。しかも pp を上げるにはモデルを取り替えるしかないのに対し、α\alpha を下げるのは自分の手でできます。テストを 1 ケース足すほうが、モデルを乗り換えるより効く場面が多い、というのがこの表の読み方です。

注意 7.4

定理 7.2 は各回の生成が独立であることを仮定しています。失敗したテストの出力を LLM に渡して修正させる運用では、この仮定が破れます。しかも破れ方が悪い方向です。モデルはそのテストを通すことを目標に出力を調整するので、テストが検査していない部分の正しさは保証されなくなります。極端な場合、期待値をハードコードして通してしまいます。実効的な α\alpha が上がるわけです。

この現象は測定されています。コード生成の標準的なベンチマークである HumanEval に対しテストケースを大幅に増やした EvalPlus では、多くのモデルの合格率が十数ポイント下落しました(Liu et al., 2023)。元のテストが α>0\alpha > 0 の検証器だったという直接の証拠です。ベンチマークの合格率をそのままモデルの pp と読んではいけません。

7.1. 見抜くための具体的な手続き

Section titled “7.1. 見抜くための具体的な手続き”

α\alpha を下げるには、次の五つが実際に効きます。

  1. 主張を実行可能な形に落とす。 「この関数は空リストでも動きます」という説明を読んで納得しない。空リストを渡すコードを 1 行書く。LLM の自然言語による説明は、それ自体は検証されていない出力です。
  2. 存在するかを一次資料で確かめる。 ライブラリの関数名、引数、戻り値の型は、公式ドキュメントか型定義ファイルで確認します。もっともらしい誤りの中で最も多いのは、実在する命名規則に沿って作られた実在しない API です。エディタの補完が効かないなら、それは存在しない可能性が高い。
  3. 退化ケースを自分で列挙する。 空、1 要素、重複、最大値、負、ゼロ除算、null、極端に大きい入力、同時アクセス。この列挙を LLM に任せてはいけません。注意 7.4 のとおり、検証器は検証対象と独立でなければならないからです。
  4. 差分を 1 行ずつ読む。 自分が書いていない行こそ丁寧に読む必要がありますが、実際には逆になりがちです。読む量を減らすには、定理 5.2 のとおり工程を小さく切ることです。
  5. 説明とコードの不一致を疑う。 コメントには正しい仕様が書いてあるのに実装がそれと違う、というパターンは頻出します。コメントは「モデルが何をしようとしたか」の証拠であって、「何をしたか」の証拠ではありません。

次の例は、これらの手続きがなぜ必要かを一つのコードで示します。

例 7.5テストを通るのに答えが 3 倍ずれるコード

「数値のリストの分散(母分散)を返す関数を書いてください」と依頼すると、次のようなコードがよく返ってきます。

def variance(xs):
n = len(xs)
s1 = sum(xs)
s2 = sum(x * x for x in xs)
return s2 / n - (s1 / n) ** 2

Var(X)=E[X2](E[X])2\operatorname{Var}(X) = \mathbb{E}[X^2] - (\mathbb{E}[X])^2 という公式そのままで、数学的には正しい式です。素朴なテストも通ります。variance([1, 2, 3, 4])E[X2]=30/4=7.5\mathbb{E}[X^2] = 30/4 = 7.5(E[X])2=2.52=6.25(\mathbb{E}[X])^2 = 2.5^2 = 6.25 より 1.251.25 を返し、これは正解です。

ところが xs = [1e8, 1e8 + 1, 1e8 + 2] を渡すと、真の母分散は

(1)2+02+123=230.6667\frac{(-1)^2 + 0^2 + 1^2}{3} = \frac{2}{3} \approx 0.6667

であるのに対し、IEEE 754 倍精度でこのコードを評価した結果は 2.02.0 になります。真値の 3 倍です。詳しい追跡は Appendix に置きますが、原因は 101610^{16} 付近の浮動小数点数の間隔が 22 もあるため、s2/ns_2/n(s1/n)2(s_1/n)^2 というほとんど等しい二つの巨大な数の差を取る段階で、有効数字が丸ごと消えることにあります(桁落ち)。

このコードは、構文も型も通り、公式も合っており、説明も自然で、代表的なテストも通ります。まさに 定義 7.1 の意味でもっともらしい誤りです。検出するには、手続き 3 の「退化ケースを自分で列挙する」を実行して、平均が大きく分散が小さいデータを自分でテストに加えるしかありません。そしてこの列挙は、統計計算の数値的安定性という事前の知識がなければ思いつけません。

正しい実装は二パス法(先に平均を求め、偏差の二乗和を取る)か Welford のオンライン法です。二パス法なら

def variance(xs):
n = len(xs)
m = sum(xs) / n
return sum((x - m) ** 2 for x in xs) / n

となり、同じ入力に対して 2/32/3 を正しく返します。

例 7.5 が示しているのは、LLM の誤りを見抜く能力がその分野の知識そのものだということです。桁落ちを知らない人にとって、あの 4 行はどこまで読んでも正しいコードです。「AI が書くから知識は要らなくなる」という予想が外れるのはここです。生成が安くなるほど、検証の能力が相対的に価値を持ちます。この帰結を数学の学習という側面から掘り下げたものが 数学を学び直す意義 です。

演習 8.1

ある機能の実装について、自分で書くと 120 分(ch=120c_h = 120)、LLM への指示を書くのに 10 分(cg=10c_g = 10)、生成物の検証に 20 分(cv=20c_v = 20)かかると見積もりました。

  1. 一度だけ試して駄目なら自分で書く、という戦略が得になるための成功率 pp の条件を求めてください。
  2. p=0.5p = 0.5 のとき、この戦略の期待コストを求めてください。
  3. p=0.5p = 0.5 のとき、合格するまで再生成を続ける戦略の期待コスト(試行回数に上限を設けない場合)を求めてください。
解答

1. 定義 2.1 より

g+v=cg+cvch=10+20120=30120=0.25.g + v = \frac{c_g + c_v}{c_h} = \frac{10 + 20}{120} = \frac{30}{120} = 0.25 .

命題 3.1 より、条件は p>0.25p > 0.25 です。成功率が 4 回に 1 回を上回れば委譲が得になります。

2. 命題 3.1 の式に代入します。

C1=cg+cv+(1p)ch=10+20+0.5×120=30+60=90 分.C_1 = c_g + c_v + (1-p)c_h = 10 + 20 + 0.5 \times 120 = 30 + 60 = 90 \ \text{分}.

自作の 120 分より 30 分安い。

3. 命題 3.3kk \to \infty の極限より

cg+cvp=300.5=60 分.\frac{c_g + c_v}{p} = \frac{30}{0.5} = 60 \ \text{分}.

期待試行回数が 1/p=21/p = 2 回なので、30×2=6030 \times 2 = 60 分と考えても同じです。p=0.25p = 0.25 という閾値を上回っているので、命題 3.3 のとおり試行を増やすほど期待コストが下がっています。

演習 8.2標準

成功率 p=0.6p = 0.6 の生成に対し、偽陽性率 α=0.25\alpha = 0.25 の検証器(穴のあるテストスイート)を使い、合格するまで再生成して最初に合格したものを採用します。

  1. 採用した成果物が誤っている確率を求めてください。
  2. この確率を 5%5\% 以下に抑えるには、α\alpha をいくつ以下にすればよいですか。
解答

1. 定理 7.2 の式に p=0.6p = 0.6α=0.25\alpha = 0.25 を代入します。分子は (1p)α=0.4×0.25=0.1(1-p)\alpha = 0.4 \times 0.25 = 0.1、分母は p+(1p)α=0.6+0.1=0.7p + (1-p)\alpha = 0.6 + 0.1 = 0.7 なので

Perr=0.10.7=170.143.P_{\text{err}} = \frac{0.1}{0.7} = \frac{1}{7} \approx 0.143 .

14.3%14.3\% です。7 回に 1 回、誤ったものを本番に通すことになります。

2. Perr0.05P_{\text{err}} \le 0.05α\alpha について解きます。分母は正なので、不等号の向きを保ったまま払えます。

0.4α0.6+0.4α0.05    0.4α0.05(0.6+0.4α)    0.4α0.03+0.02α    0.38α0.03    α0.030.380.0789.\begin{aligned} \frac{0.4\alpha}{0.6 + 0.4\alpha} \le 0.05 &\iff 0.4\alpha \le 0.05(0.6 + 0.4\alpha) \\ &\iff 0.4\alpha \le 0.03 + 0.02\alpha \\ &\iff 0.38\alpha \le 0.03 \\ &\iff \alpha \le \frac{0.03}{0.38} \approx 0.0789 . \end{aligned}

偽陽性率を約 7.9%7.9\% 以下、つまり「誤った実装を 13 回に 12 回は落とせる」水準までテストを強化する必要があります。定理 7.2 の近似式 Perr1ppα=23αP_{\text{err}} \approx \frac{1-p}{p}\alpha = \frac{2}{3}\alpha を使うと α0.075\alpha \le 0.075 が得られ、厳密解に近い値になります。

演習 8.3

定理 5.2 の逐次方式で、各工程の検証器が完全ではなく、偽陽性率 β[0,1)\beta \in [0,1)(偽陰性率 00)を持つ場合を考えます。工程正答率を rr、工程数を nn、各工程の生成と検証は独立とします。各工程では合格が出るまで生成を繰り返し、最初に合格した出力を採用して次へ進みます。

  1. 最終成果物(nn 工程すべて)が正しい確率を rrβ\betann で表してください。
  2. r=0.98r = 0.98β=0.2\beta = 0.2n=50n = 50 のときの値を求めてください。
  3. 得られた結果から、工程分割についてどのような実務的な結論が導かれますか。
解答

1. 一つの工程に 定理 7.2 を適用します。同定理で prp \to rαβ\alpha \to \beta と置き換えると、その工程で採用された出力が誤りである確率は

(1r)βr+(1r)β\frac{(1-r)\beta}{r + (1-r)\beta}

です。よって正しい確率は

ρ=1(1r)βr+(1r)β=rr+(1r)β\rho = 1 - \frac{(1-r)\beta}{r + (1-r)\beta} = \frac{r}{r + (1-r)\beta}

となります。工程どうしは独立なので、nn 工程すべてが正しい確率は

ρn=(rr+(1r)β)n.\rho^{\,n} = \left(\frac{r}{r + (1-r)\beta}\right)^{n} .

2. 数値を入れます。(1r)β=0.02×0.2=0.004(1-r)\beta = 0.02 \times 0.2 = 0.004、分母は 0.98+0.004=0.9840.98 + 0.004 = 0.984 なので

ρ=0.980.984=0.995935.\rho = \frac{0.98}{0.984} = 0.995935 .

lnρ=0.0040733\ln \rho = -0.0040733 より

ρ50=e50×(0.0040733)=e0.203660.816.\rho^{50} = e^{50 \times (-0.0040733)} = e^{-0.20366} \approx 0.816 .

81.6%81.6\% です。裏返すと、約 18.4%18.4\% の確率でどこかの工程に誤りが残ったまま完成します。

3. 定理 5.2 の分割は期待コストを指数的に改善しますが、正しさは工程数に対して指数的に劣化します(ρ<1\rho < 1 なので ρn\rho^nnn について減少)。分割は検証の穴を消すのではなく、穴を通り抜ける機会を nn 回に増やすからです。

したがって、工程を細かく切るなら同時に一工程あたりの β\beta を下げなければなりません。n=50n = 50 で最終正答率を 95%95\% 以上にするには ρ0.951/50=e0.001026=0.998975\rho \ge 0.95^{1/50} = e^{-0.001026} = 0.998975、すなわち 0.98/(0.98+0.02β)0.9989750.98 / (0.98 + 0.02\beta) \ge 0.998975 から β0.05\beta \le 0.05 程度が要求されます。「小さく切って渡す」という助言は、「切った各断面に検証を置く」という条件とセットでのみ成立します。

  • Frederick P. Brooks, Jr., “No Silver Bullet: Essence and Accidents of Software Engineering”, IEEE Computer 20(4) (1987), 10–19. 本質的複雑性と偶有的複雑性の区別。この記事の vv が高いタスクは、おおむね本質的複雑性が支配する領域に対応します。
  • Brian W. Kernighan and P. J. Plauger, The Elements of Programming Style, 2nd ed., McGraw-Hill, 1978. 「デバッグはコードを書くことの 2 倍難しい」という有名な指摘の出典。検証比 vv の大きさに関する古典的な観察です。
  • Mark Chen et al., “Evaluating Large Language Models Trained on Code”, 2021. arXiv:2107.03374 — HumanEval と pass@k の原論文。
  • Jiawei Liu, Chunqiu Steven Xia, Yuyao Wang, Lingming Zhang, “Is Your Code Generated by ChatGPT Really Correct? Rigorous Evaluation of Large Language Models for Code Synthesis”, NeurIPS 2023. arXiv:2305.01210 — EvalPlus。テストを強化すると合格率が下がることを示した研究。
  • Neil Perry, Megha Srivastava, Deepak Kumar, Dan Boneh, “Do Users Write More Insecure Code with AI Assistants?”, ACM CCS 2023. arXiv:2211.03622
  • Sida Peng, Eirini Kalliamvakou, Peter Cihon, Mert Demirer, “The Impact of AI on Developer Productivity: Evidence from GitHub Copilot”, 2023. arXiv:2302.06590 — 対象は「JavaScript で HTTP サーバーを実装する」という単一の、仕様が明確なタスクです。
  • METR, “Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity”, 2025 — 被験者は自分が保守している大規模リポジトリで作業しており、chc_h が小さく(熟知しているので速い)cvc_v が大きい(品質基準が高い)状況に当たります。
  • Nicholas J. Higham, Accuracy and Stability of Numerical Algorithms, 2nd ed., SIAM, 2002 — 分散計算の数値的安定性は第 1 章で扱われています。例 7.5 の背景。

例 7.5 の返り値が 2.02.0 になる理由を、IEEE 754 倍精度で追跡します。 倍精度は仮数部が 53 ビットなので、253=90071992547409929.007×10152^{53} = 9007199254740992 \approx 9.007 \times 10^{15} を超えると整数を 1 刻みでは表せません。区間 [253,254)[2^{53}, 2^{54}) での刻み幅(ulp)は 22、区間 [254,255)[2^{54}, 2^{55}) では 44 です。

入力は x1=108x_1 = 10^8x2=108+1x_2 = 10^8+1x3=108+2x_3 = 10^8+2n=3n = 3 です。これらは小さいので厳密に表せます。

  • s1=300000003s_1 = 300000003s1/n=100000001s_1/n = 100000001。ともに厳密。
  • (s1/n)2(s_1/n)^2 の真値は 1000000020000000110000000200000001。これは [253,254)[2^{53}, 2^{54}) に入り刻み幅は 22、値は奇数なので 10000000200000000100000002000000001000000020000000210000000200000002 のちょうど中間です。偶数丸め(最近接偶数への丸め)の規則により、仮数部の最下位ビットが 00 になる 1000000020000000010000000200000000 が選ばれます。
  • s2s_2 の各項は 1000000000000000010000000000000000100000002000000011000000020000000010000000200000001 \to 10000000200000000(同じ理由)、1000000040000000410000000400000004(偶数なので厳密)。左から順に足すと 2000000020000000020000000200000000、続いて 3000000060000000430000000600000004 となり、いずれも刻み幅の倍数なので丸め誤差は入りません。
  • s2/n=30000000600000004/3=10000000200000001.333s_2 / n = 30000000600000004 / 3 = 10000000200000001.333\ldots。刻み幅 22 の候補 1000000020000000010000000200000000(距離 1.3331.333)と 1000000020000000210000000200000002(距離 0.6670.667)のうち近いほうが選ばれ、1000000020000000210000000200000002 となります。

最後の引き算は 1000000020000000210000000200000000=2.010000000200000002 - 10000000200000000 = 2.0 で、この減算自体には誤差がありません。すなわち返り値は厳密に 2.02.0、真値 2/32/3 の 3 倍です。誤差が入ったのは引き算ではなく、その前の二つの丸めです。 引き算はその誤差を露わにしただけで、これが桁落ちという現象の本質です。

この誤差は入力の大きさとともに悪化します。 平均を μ\mu、標準偏差を σ\sigma とすると、E[X2]μ2\mathbb{E}[X^2] \approx \mu^2(E[X])2μ2(\mathbb{E}[X])^2 \approx \mu^2 の差 σ2\sigma^2 を取る計算なので、相対的に失われる桁数はおよそ log10(μ2/σ2)=2log10(μ/σ)\log_{10}(\mu^2/\sigma^2) = 2\log_{10}(\mu/\sigma) 桁です。μ/σ\mu/\sigma10810^8 程度なら 16 桁で、倍精度の有効桁数を丸ごと食い潰します。例 7.5 はまさにこの状況でした。

Appendix: pass@k とこの記事のモデルの関係

Section titled “Appendix: pass@k とこの記事のモデルの関係”

コード生成モデルの論文でよく見る pass@k は、この記事の枠組みで読み替えられます。 pass@k は「kk 個のサンプルのうち少なくとも 1 つがテストを通る確率」(pass@k(定義 4.4)[AI時代のITエンジニアの生存戦略])で、各サンプルが独立に確率 pp で通るなら 1(1p)k1 - (1-p)^k です。これは 命題 3.3 の「kk 回以内に合格する確率」と同じ量です。

注意点が二つあります。第一に、pass@k はコストを数えていませんkk を増やせば合格確率は上がりますが、そのぶん検証の回数も増えます(pass@k は上がるが、検証回数も上がる(例 4.5)[AI時代のITエンジニアの生存戦略])。実務で効くのは合格確率ではなく期待コストで、そちらは g+vg+v という閾値に支配されます(命題 3.3)。第二に、pass@k のテストスイートは 定義 2.2 の意味で α>0\alpha > 0 の検証器です(Liu et al., 2023)。ベンチマークの数値は pp の上限であって pp そのものではなく、自分のプロジェクトでの実効的な pp は自分の検証器で測るしかありません。

この記事の誤りを報告する ・運営: 夢現技研合同会社料金プラン利用条件特定商取引法に基づく表記

© 2026 夢現技研合同会社 ・本文の LLM への入力は自由です。コード例は MIT ライセンスです。