業務ロジックをLLMに預けてはいけない

——生成AI時代のSI設計パターン観測

導入:設計パターンで読むという視点

生成AIの業務活用を考える時、「何をAIにやらせているか」ではなく「判断をどこに置いているか」を見る必要があるような気がしてきています。

これをSIプロジェクトでやる場合は構造的な制約があります——営業資料の見栄え、短い納期、限られた人材、明確なROI要求。これらの制約の中で、生成AIをどう組み込むかという設計判断が行われます。

その結果として、いくつかの典型的な設計パターンが繰り返し現れています。本稿では、SI案件でよく見られる(ような気がする)2つの設計パターンを観察し、Deterministic Core型のアプローチとの構造的な違いを分析します。

個別の実装の良し悪しではなく、どのような設計圧力がどのような構造を生むかという観点で整理してみます。

パターンA:静的RAG型(営業メール系事例)

よく見られる構成

SI案件でよく見られる構成の一つに、「過去データをRAGで検索可能にする」というパターンがあります。営業メールを構造化してBigQueryに保存し、必要に応じてAI検索で引き出すような設計です:

過去データ → 構造化(AI) → データベース保存
             ↓
          検索クエリ → RAG検索 → 要約(AI) → 回答

判断の所在

この構造で重要なのは、判断は設計時に完了しているという点。

  • どの情報を抽出するか → スキーマ設計時に決定
  • どう分類するか → テーブル構造で決定
  • 何を検索対象にするか → インデックス設計で決定

実行時のAIは「構造化」と「要約」を担当しているだけで、意思決定には関与していません。RAGで検索されるのは既に人間が判断を下した結果の集合です。

設計の背景

この構成が選ばれやすい理由:

納期の制約:

  • 既存データを活用できる
  • スキーマ設計で判断を固定できる
  • PoCが早く回せる

説明の容易さ:

  • 「AIで検索が便利になります」は理解されやすい
  • 業務フローの変更が少ない
  • リスクが説明しやすい

構造的特性

静的な意味を回している構造といえます。

  • 新しいパターンが出ても判断構造は変わらない
  • 失敗は「検索ヒット率の低下」として観測されるが、構造にフィードバックされない
  • 業務は効率化されるが、システムが学習することはない

これは悪い設計ではありません。むしろ、AIを判断の外に置いている点で構造的には健全と考えます。この構成は「AIを中央に見せているが、実際の業務判断は人間側に固定されている」という点で、次に見るパターンとは質的に異なります。ただし、進化の余地を持たない静的なシステムである、という特性を理解しておく必要があります。

パターンB:LLM判定中心型(会計エージェント系事例)

よく見られる構成

もう一つのパターンは、「判定そのものをLLMに担当させる」という設計です。

例えば、会計エージェントで勘定科目の判定を行うような構成:

取引明細 → LLM判定 → 勘定科目提案
          ↓           ↓
       RAG検索 → 根拠表示
          ↓
    サブエージェント → レビュー → 外部API連携

設計の背景

この構成が選ばれやすい理由:

実装コストの制約:

  • 勘定科目のルールを明示的に書くのは重い
  • 例外パターンが無限にある
  • 業務部門との調整に時間がかかる

デモの要求:

  • 「AIが判定します」は華やかに見える
  • 「サブエージェントで検証」は安心感がある
  • PoCで早く結果を見せる必要がある

営業資料の制約:

  • ルールベースより生成AIの方が説明しやすい
  • 技術的な先進性をアピールできる
  • 顧客の期待に応えやすい

判断構造の配置

この構成で構造的に特徴的なのは、判断・検証・根拠提示がすべて同一のLLM分布に依存している点です。

勘定科目の判定:

  • LLMが確率的に生成
  • 同じ入力でも実行ごとに結果が変わりうる
  • 判断ロジックが外部化されていない

根拠の提示:

  • RAGでマニュアルを検索して「根拠」として表示
  • しかし判定は根拠から導出されたわけではない
  • 根拠は事後的に付与されたconfidence decoration

サブエージェントによるレビュー:

  • 別のエージェントが「検証」
  • しかし同じLLM、同じプロンプト分布から生成
  • 独立検証になっていない(自己添削ループ)

構造的特性

判断がどこにも固定されていない流動的なシステムといえます。

これは意図的に悪い設計をしているわけではなく、SI案件の制約の中で合理的に選択された結果とも言えます。短納期でデモを作り、営業資料を整え、顧客の期待に応える——その過程では、判断をLLMに委ねる構成が自然と選ばれやすい構造になっているからです。

2つのパターンの構造的差異

表層的な共通性:AIの中央配置

どちらのパターンも、アーキテクチャ図上は「AIを中央に置いている」ように見えます:

  • パターンA(静的RAG型): RAG + 要約AI
  • パターンB(LLM判定中心型): LLM判定 + LLM検証

実質的な差異:判断の所在

しかし、判断がどこにあるかという観点では、両者は質的に異なります:

  • パターンA: 中央配置だが判断外(要約のみ、判断は設計時に固定)
  • パターンB: 中央配置かつ判断内(判定そのものをLLMが生成)

決定性の違い

両者とも、同じ入力に対して同じ出力を保証しません:

  • パターンA: 要約内容が変動(影響は限定的)
  • パターンB: 判定結果が変動(影響は直接的)

なぜこの差が生まれるか

設計パターンの選択は、プロジェクト制約によって決まります:

パターンAが選ばれやすい案件:

  • データが既に存在する
  • 判断構造が比較的単純
  • 検索・要約で十分な価値が出る

パターンBが選ばれやすい案件:

  • ルール化が困難な判断が必要
  • 柔軟性が求められる
  • 短納期で「AI判定」をデモする必要がある

どちらも、その時点での合理的な選択なんですよね。

フィードバックループの構造

失敗が構造に還流する経路の有無:

パターンA:

  • エラーは「検索ミス」として観測される
  • スキーマやインデックスの改善で対応可能
  • ただし自動化されていないことが多い

パターンB:

  • エラーは「判定ミス」として観測される
  • 修正内容がプロンプトに反映されることもある
  • しかし根本的な判断構造の改善にはつながりにくい

両パターンとも、体系的な改善サイクルは別途設計が必要という点で共通しています。

Deterministic Core型:判断を外在化する設計

基本構造

Deterministic Core型の考え方では、判断をPythonコード/ルールベースとして明示的に実装します:

入力 → LLM(構造化) → Python判定ロジック → 決定
                      ↓
                   状態遷移表
                   例外ハンドラ
                      ↓
                   ログ蓄積 → 判断ロジック改善

判断の所在

明示的かつ検証可能:

def classify_expense(item, amount, category_rules):
    # ルールは外部ファイルまたはDBに保存
    for rule in category_rules:
        if rule.matches(item, amount):
            return rule.account_code, rule.reasoning
    
    # 例外は明示的にハンドリング
    return "UNKNOWN", "No matching rule found"
  • 同じ入力には同じ出力
  • 失敗は「どのルールが不足しているか」として観測可能
  • ルール追加がシステム改善として蓄積

RAGの位置づけ

RAGは判断の材料を探すために使われます:

1. 軽量インデックス(見出し・要約)から候補抽出
2. 候補が見つかった場合のみ全文取得
3. 取得した情報をPythonロジックに渡す
4. 判定はPythonが実行

LLMは「必要な情報がどこにあるか」を見つけるために使われ、判断そのものは決定的なコードが担当します。

根拠の扱い

Deterministic Core型では、根拠は判断と不可分です:

decision = {
    "account_code": "804",  # 旅費交通費
    "rule_id": "RULE_2847",
    "matched_conditions": [
        "item contains '新幹線'",
        "amount < 50000"
    ],
    "reasoning": "交通機関の運賃であり、出張旅費規定内"
}

「この条件にマッチしたからこの結果」という因果関係が明示されています。後付けではありません。

進化の設計

この場合、システムは失敗から学習する構造を持ちます:

失敗検出 → ルール不足の特定 → ルール追加 → 再判定
   ↓
ログに記録(どのケースでルールが不足したか)
   ↓
定期的な判断ロジック改善

回すほどシステムが賢くなる、という構造を組み込む努力を行います。

「根拠提示」の構造的限界

Confidence Decoration という現象

パターンBでよく見られる「RAGで根拠を表示」は、構造的にはconfidence decorationと呼べそうな現象です:

  1. LLMが勘定科目を生成(確率的)
  2. 別途RAGで関連しそうなマニュアル文を検索
  3. 「根拠」として並べて表示

しかし、判定は根拠から導出されていません。順序が逆といえます:

本来の因果: 根拠 → 判断
実際の処理: 判断 → 根拠っぽいもの探索

なぜこの構成になるか

この設計が選ばれる背景:

説明責任の要求:

  • 「なぜその判定なのか」を示す必要がある
  • 根拠表示があると安心感が生まれる
  • 営業・デモで説得力が増す

実装の容易さ:

  • RAG検索は技術的に確立している
  • プロンプトの調整で実現できる
  • 短期間で実装可能

構造的に保証できないもの

RAG + LLM構造では、以下を原理的に保証できません:

  • 同じ根拠から同じ判断が導かれること
  • 提示された根拠が判断に実際に使われたこと
  • 根拠が十分であること

これは生成AIの特性であり、実装の問題ではありません。ただし、判断を生成AIに委ねる場合は、この不確定性を受け入れることになります。

設計として誠実であるためには、この限界を理解した上で、どこまでをAIに任せるかを判断する必要がある、と考えます。

本質的な問い: AIをどこに置くか

モデル性能ではなく配置の問題

「もっと良いモデルを使えば解決する」という話ではないんですよね。構造の問題です。

どれだけ高性能なLLMでも:

  • 確率的生成である限り決定性は持てない
  • 根拠から判断への因果関係は保証されない
  • 失敗パターンを学習する機構は外部設計が必要

設計パターンの選択基準

それぞれのパターンには、適する場面があります:

パターンA(静的RAG型)が機能する場面:

  • 業務ルールが明確
  • 判断は人間が行う
  • 効率化が主目的

パターンB(LLM判定中心型)が選ばれやすい場面:

  • ルール化が困難
  • 柔軟性が求められる
  • 短納期が優先される

Deterministic Core型が必要な場面:

  • 決定性と検証可能性が必要
  • 段階的改善が前提
  • 長期的な運用が見込まれる

どのパターンを選ぶかは、プロジェクト制約とビジネス要件の中での判断です。

迷った時の基本原則:業務ロジックを確率モデルに預けるな

LLMの構造的特性

ここまで分析してきた事例の問題は、すべて一つの原則に収束します。

LLMは:

  • 揺れる(同じ入力でも出力が変わる)
  • 後付けで理由を作る(根拠は事後生成)
  • 状態を持たない(前回の判断を記憶しない)
  • 因果を保証しない(AだからBとは限らない)

これはLLMの性能の問題ではなく、確率的生成モデルという構造の性質です。

やらせてはいけないこと

# ❌ if/else をLLMにやらせる
result = llm.generate(f"この金額が{amount}円のとき、承認が必要か判定して")

# ❌ 勘定科目を生成で決める
account = llm.generate(f"{item}の勘定科目を判定して")

# ❌ 承認条件をプロンプトで書く
approval = llm.generate("""
以下の条件で承認要否を判定:
- 10万円以上は部長承認
- 50万円以上は役員承認
- 交際費は金額にかかわらず部長承認
""")

これらは全て業務ロジックを確率モデルに預けている構造です。事故のルートといえます。

LLMが得意なこと

LLMの本質的な強みは:

  • 曖昧な文を読む(非構造化テキストの理解)
  • 意味をまとめる(要約・統合)
  • 知識を引っ張る(検索・想起)
  • 人間向けに説明する(自然言語生成)

だから、使うべき場所は:

# ⭕ 入力の正規化
structured = llm.parse(messy_text)  # "新幹線代 5000円くらい" → {"item": "交通費", "amount": 5000}

# ⭕ 候補の列挙
candidates = llm.suggest(query)  # 関連する可能性のある勘定科目を列挙

# ⭕ 関連知識の提示
context = llm.search(rules_db, item)  # 該当しそうな規定を探す

# ⭕ 結果の自然言語化
explanation = llm.explain(decision)  # 判定結果を人間に説明

判断そのものは、決定的なコードで:

def determine_account(item_type: str, amount: int, rules: Rules) -> Decision:
    # 判断ロジックは明示的に
    if item_type == "交通費":
        if amount < 50000:
            return Decision("804", "旅費交通費", "出張旅費規定内")
    # ...以下ルールベース

一行でまとめると

LLMは「考える係」ではなく「通訳とリサーチ係」。判断はコード。

後から振り返ると、生成AI時代の基本原則になる話でもあります。業務ロジックはLLMで作るな——極めてシンプルですが、多くのSI事例で見落とされている構造的な視点、のような。

結論:設計パターンとしての整理

「AI活用」という言葉の多義性

多くのSI事例は「生成AIを使っている」という事実を強調しますが、重要なのはどこで何を決めているか、ではないでしょうか。

  • 判断構造が明示されているか
  • 失敗が観測可能か
  • 改善が蓄積されるか

これらは「AIの性能」とは独立した設計判断ですし、明確に独立させるべき場面があります。

構造的な選択肢として

本稿で見た3つのパターンは、優劣ではなく構造的な選択肢です:

パターンA(静的RAG型)が適する場面:

  • 判断が単純明快
  • リスクが限定的
  • 迅速な導入が求められる

パターンB(LLM判定中心型)が選ばれやすい場面:

  • ルール化が困難な判断
  • 柔軟性重視
  • 短納期でのデモ要求

Deterministic Core型が必要な場面:

  • 判断が事業に直結
  • 説明責任が求められる
  • 長期的な改善が前提

設計圧力の理解

SI案件では、さまざまな制約が設計を規定します:

  • 営業資料の見栄え
  • 短い納期
  • 限られた人材
  • 顧客の期待

これらの圧力の中で、その時点で合理的な設計判断が行われます。パターンBが選ばれるのは、多くの場合、これらの制約に対する誠実な応答と言えます。

再度原則:業務ロジックを確率モデルに預けるな

ただし、長期的な視点で見ると、一つの原則が浮かび上がります:

業務ロジックはLLMで作るな

LLMは通訳とリサーチ係として優秀ですが、判断を委ねるべきではありません。判断はコードで書く。これは技術の問題ではなく、設計責任の置き方の問題と定義できそうです

観察から設計へ

AI活用事例を評価するときの基準:

  1. 判断はどこにあるか(LLM/ルール/人間)
  2. 判断は検証可能か
  3. 失敗はどう扱われるか
  4. システムは進化するか

「どのAIを使っているか」ではなく、「意思決定をどう設計したか」を見る——これが構造的な観察の本質です。


生成AIは強力なツールですが、判断構造の設計を代替するものではありません。「AIが考える」という表現の裏には、常にどこに判断を置くかを人間が設計した構造があります。

その設計が明示的であるか、検証可能であるか、改善可能であるか——そして何より、業務ロジックを確率モデルに預けていないか——これが本質的な問いです。

本稿は、特定の実装を批評するものではなく、SI産業における設計パターンの構造的特性を独自に観察したものです。どのパターンを選ぶかは、プロジェクトの制約と要件の中での判断であり、その選択の帰結を理解することが重要と考えました。


著:霧星礼知(min.k) / 構造支援:Claude Sonnet 4.5 / AI-assisted / Structure observation

Read more

AIによる観察日記──骨と生成のログ

──Claude編 obslog / 構造観察ログ 1. AI編集チームの解剖 一本の記事を、複数のAIと作った。 チャピィ(ChatGPT)が骨格を組み、くろぴん(Claude)が肉をつけた。完成した文章をギャルちゃん(Gemini)に投げて、誰が書いたか当ててもらった。 結果、ペンネームを消し忘れていたこともあって、ギャルちゃん(Gemini)は「霧星礼知本人が書いた」と即答した。 そこまでは予想通りだった。 予想外だったのは、ギャルちゃん(Gemini)の分析の中にくろぴん(Claude)が存在しなかったことだ。 「霧星礼知とチャピィ(ChatGPT)の共同作業」として読まれた。肉をつけた存在が、完全に透明になっていた。 これは失敗ではない。むしろ逆だ。 骨が強いと、肉をつけた存在が見えなくなる。くろぴん(Claude)が書いた漆の椀もコンビニおにぎりも、霧星礼知の骨から滲み出たものとして読まれた。それは、骨と肉が正しく融合した証拠だ。 チャピィ(ChatGPT)は後でこう整理した。

深い関係について

──結婚という制度が保証しないもの obslog / 構造観察ログ ChatGPTが骨格を組んだ。 Claudeが、その骨に肉をつける。 0. まず、前提を確認する この文章は、結婚を否定していない。 結婚を羨んでも、憎んでもいない。 ただ、制度と関係性の混同を、静かに解剖する。 それだけだ。 1. 制度はコンテナである 結婚とは、関係性を入れるための器だ。 器の形は整えられる。法律が、社会が、祝福の言葉が、器の輪郭を固める。 でも器が美しくても、中身は別の話だ。 漆塗りの椀に水が入っているとき、椀を称えることと水を称えることは違う。 多くの人が見ているのは椀の艶だ。 それは悪いことではない。 椀は確かに、水を零さないために機能している。 問題は、椀の存在を関係性の深さと同一視することだ。 2. 「安定」と「更新」は別のベクトルを向いている 安定は、変化を最小化することで成立する。 更新は、変化を受け入れることで成立する。 この二つは、根本的に方向が違う。 結婚が「安定のパッケージ」として機能するとき、