はじめに
社内の申請フローや承認ルールは一見すると if/else で書けそうに見えます。
しかし実際に自動化しようとすると、
- 例外が多い
- 過去事例を参照しないと判断できない
- 判断理由の説明が求められる
といった「人間的な判断」が立ちはだかります。
本記事では、このような業務ルールをどのように構造化し、自動化の土台にできるかを考える中で、「論理プログラミングが意外と相性が良いのではないか」と感じた理由を整理します。
1. なぜ難しい? 社内申請フローの“人間領域”
社内の申請フローは一見すると、
「A なら B に回す」「C の場合は D の承認が必要」
といった分岐の集合に見えます。
しかし実際には、以下のような“人間の判断”が多く含まれます。
- 文書の書き方の癖で意味が微妙に変わる
- 例外・暫定運用が積み増しされ、ルールが複雑化している
- 暗黙知や過去事例の参照が前提になっている(ベテラン依存)
プログラムならすぐ実行して差分を検証できますが、人間の判断は“慎重さ”が要求されるためスピードが出ません。
では自動化の方向性はどこにあるのか?
まずは既存のアプローチを検討しました。
2. ワークフロー自動化ツールでの限界
Power Automate や ServiceNow などのワークフロー製品は、
繰り返し処理や明確な条件分岐を自動化する点では非常に優秀です。
一方で、
- 文面のわずかな違いで判断が変わる
- 例外や暫定ルールが積み重なっている
- 過去事例を踏まえた判断が必要
といった領域では、分岐構造が複雑化しやすく、
判断ロジックそのものの保守が難しくなります。
今回の関心は、
「処理の自動化」ではなく
「判断ロジックの管理」にありました。
3. 生成AI単体アプローチの限界
昨今の生成AIは、文章の要点抽出や構造化が得意です。
実際、社内申請・規程・契約書などを読み込ませれば、
「この申請はどのレビュー先に回すべきですか?」
と質問して、それっぽい回答を返してくれます。
しかし、判定ロジックの“代替”として使うには、
- 判断の根拠がブラックボックス化しやすい
- あいまいなケースで回答が揺れやすく再現性が低い
- 「どの規程に基づいて判断したか」の説明が難しい
といった課題が残ります。
社内ガバナンス上は、判断根拠と再現性が必要です。
生成AIだけに判定ロジックを担わせるのは難しく、別の仕組みで補完する必要があると感じました。
4. なぜ論理プログラミングに着目したのか
Prolog や Picat、Mercury などの論理プログラミング(および制約論理プログラミング)言語は、条件を宣言的に記述し、問い合わせによって結果を導くスタイルを取ります。
これらの言語は
- 条件を追加するとそのままロジックが拡張される
- 宣言的なので“変更の影響範囲が局所化”しやすい
- 過去事例を fact として蓄積できる
- “候補を列挙する”という挙動が人間の判断に近い
という特徴を持ちます。
特に今回のような “例外が後から増えるタイプの業務ロジック” に非常に向いています。
なぜ向いているのか(技術的に一歩踏み込んだ理由)
- if/else のような分岐ツリーは条件が増えるほど「どこを直すべきか」が分かりにくくなる
→ 宣言的ルールは 1行=1条件なので、増えても可読性・局所性が保たれる。 - Prolog の“単一化(Unification)”はパターンマッチが強力
→ 過去事例を fact として持っておけば自然に照合できる。 - バックトラッキングによる“複数候補の列挙”が標準機能
→ 「どのレビュー先の可能性があるか?」を機械的に出せる。 - 説明責任がコードで担保される
→ どのルールが発火したか trace で追跡できる(後述)。
こうした特性は、手続き型では得がたいメリットです。
5. なぜ過去のルールベースは定着しなかったのか
業務ルールや判断ロジックを Prolog のような論理言語で表現しようとする試み自体は決して新しいものではありません。
1990 年代から 2000 年代にかけて、エキスパートシステムやルールベースシステムとして業務知識を論理的に記述する取り組みが数多く行われてきましたが、
- ルール記述のコストが高い
- 暗黙知や例外を整理する支援技術が乏しい
- 論理言語が判断から実行までを担う前提だった
といった理由から、現場への定着は限定的でした。
現在では、生成AIや検索技術、ワークフロー製品などが発展し、
論理プログラミングに「判断ロジック」だけを担当させる分業が可能になっています。
6. 生成AI × ロジック × ワークフローの三層構造
現実的な解として、次の三層構造を考えました。
1. 生成AI(テキスト → 構造化データ)
- 長い申請書・規程・契約書から情報抽出
- 「クラウド利用有無」「IP条項の有無」などを項目化
- 曖昧な表現を整理して正規化する
ここはAIが最も得意とする領域です。
2. ロジック(構造化データ → 厳密判定)
- どのレビュー先に回すか
- 承認者の特定
- 追加手続きの要否
などを、透明性のあるルールとして実行します。
3. ワークフロー製品(判定結果 → 実務処理)
- チケット起票
- メール通知
- 承認フロー実行
といった“動作部分”を担当します。
このように領域を分けると
- AIが苦手な「説明責任」「再現性」をロジックで補完
- ロジックが苦手な「柔らかい文章の解釈」をAIが補完
- ワークフロー製品は“自動実行の土台”に専念
という分担が可能になります。
7. 業務ルールをロジックで表現してみる
ここからは簡単なモデルケースです。
実際の社内ルールとは関係していません。
入力データ(例)
service_type: internal / external
delivery_form: package / cloud
has_contract: yes / no
contains_clause: ip / sla / none
判定したい内容
- レビュー先(法務/セキュリティなど)
- 承認者
- 追加手続きの要否
Prologで書くと
Prolog は「事実(facts)」と「規則(rules)」を宣言的に書き、問い合わせ(query)で結果を得る言語です。if/else を積み上げる代わりに「どの条件が成り立つか」を列挙できるため、例外が増える判定ロジックと相性が良いです。
先ほどの抽象モデルを申請内容を引数として渡す形で Prolog のルールにしてみます。
% rules.pl
%
% review/5:
% review(ServiceType, DeliveryForm, HasContract, Clause, ReviewResult).
%
% additional_process/5:
% additional_process(ServiceType, DeliveryForm, HasContract, Clause, Process).
% ServiceType : internal / external
% DeliveryForm : package / cloud
% HasContract : yes / no
% Clause : ip / sla / none
% ReviewResult : legal / security / none
% Process : cloud_risk_check / contract_check / ...
% ------------------------------
% レビュー先の判定ロジック
% ------------------------------
% 外部サービス × クラウド × 契約書あり × IP条項あり → セキュリティレビュー
review(external, cloud, yes, ip, security) :- !.
% 契約書あり × IP条項あり → 法務レビュー
review(_Service, _Delivery, yes, ip, legal) :- !.
% 内部サービス → レビュー不要
review(internal, _Delivery, _HasContract, _Clause, none) :- !.
% それ以外 → レビュー不要
review(_Service, _Delivery, _HasContract, _Clause, none).
% ------------------------------
% 追加手続きの判定ロジック
% ------------------------------
% 外部クラウドサービスはクラウドリスクチェックが必要
additional_process(external, cloud, _HasContract, _Clause, cloud_risk_check).
% 契約書がある場合は契約チェック
additional_process(_Service, _Delivery, yes, _Clause, contract_check).
複雑な条件を“宣言的に”記述できるため、手続き型言語より管理しやすいです。
review/5 は、業務的に「最終的に1つのレビュー先に決める」ことを想定しているので、上から優先順位順に評価し、!(カット)を使って 最初にマッチしたルールを確定させています。
一方で additional_process/5 は、「この申請に必要な追加手続きを列挙する」用途を想定しており、マッチするものが複数あれば複数候補を返すようにしています。
動作確認
この記事の Prolog のサンプルコードは、次の環境で動作確認しています。
- SWI-Prolog: 9.2.9
- OS: macOS 12.6.6 (Monterey)
実行例
まず、rules.pl を用意して swipl を起動します。
$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 9.2.9)
?- [rules].
true.
外部クラウドサービスで、契約書あり+IP条項ありのケースを投げてみます。
?- review(external, cloud, yes, ip, R).
R = security.
セキュリティレビューが必要だという結果が返ってきました。
内部サービスの場合はレビュー不要(none)になります。
?- review(internal, package, no, none, R).
R = none.
additional_process/5 は追加手続きで、複数マッチし得ます。
?- additional_process(external, cloud, yes, ip, P).
P = cloud_risk_check ;
P = contract_check.
;で次の候補を見ていくと、クラウドリスクチェックと契約チェックの2つの手続きが返ってきました。
trace で"説明可能性"を可視化してみる
Prolog が「どのルールを採用したか」を実際に追跡してみます。
?- trace, review(external, cloud, yes, ip, R).
出力例:
[trace] ?- trace, review(external, cloud, yes, ip, R).
Call: (13) review(external, cloud, yes, ip, _27746) ? creep
Exit: (13) review(external, cloud, yes, ip, security) ? creep
R = security.
このように、
- どのルールが呼ばれ
- どこで確定し
- どういう途中経過を辿ったか
が機械的に追える点は、業務ロジックを扱う上で非常に重要です。
Mercury で書いた場合
同じ判定ロジックを型安全に書きたい場合は Mercury も有力です。
Mercury は Prolog 系の宣言的スタイルを保ちつつ、型安全性や大規模開発を意識した設計が特徴です。
※ Mercury のコードは「Prolog との構文比較」を目的とした抜粋であり、実行用の main 関数は省略しています。
:- import_module bool.
% 申請情報の属性
:- type clause ---> ip ; sla ; none.
:- type service ---> internal ; external.
:- type delivery ---> package ; cloud.
% レビュー結果
:- type review ---> legal ; security ; none.
% review(Service, Delivery, HasContract, Clause) = Review の関数版
:- func review(service, delivery, bool, clause) = review.
% 外部サービス × クラウド × 契約書あり × IP条項あり → セキュリティレビュー
review(external, cloud, yes, ip) = security.
% 契約書あり × IP条項あり → 法務レビュー
review(_Service, _Delivery, yes, ip) = legal.
% 内部サービス → レビュー不要
review(internal, _Delivery, _HasContract, _Clause) = none.
% それ以外 → レビュー不要
review(_Service, _Delivery, _HasContract, _Clause) = none.
review/4 は常に review 型の値を1つ返す純粋関数として書けるため、大規模化してもロジックの破綻に気づきやすいのが利点です。
この記事ではコード例として Prolog と Mercury を掲載しています。
Picat も考え方としては近く、より実務寄りの構文で書ける言語です。制約プログラミングとの親和性が高く、探索と最適化を組み合わせやすい点が特徴になります。
8. 実際に運用する際の課題
- ルールそのものを整理するコスト(ここが最も大変)
- 記述スキルが必要
- 運用チームに“宣言的ロジックの読み方”を理解してもらう必要
とはいえ、制度改定や例外処理が多い領域ほど構造化のメリットが大きいため、中長期的には十分投資価値があると感じています。
また、実際の業務ルールには“語彙の揺れ”や“例外の重複”が多く、ルール同士が衝突することがあります。ロジックとして表現する前に、項目化・正規化で語彙や条件を整理しておくことが安定運用の鍵になります。
まとめ
- 社内申請フローの判断には、人間固有の“あいまいさ”が多く含まれる
- 生成AIは文書の要点抽出に優れるが、説明責任が必要な判定は苦手
- 論理プログラミング(特に Prolog/Picat/Mercury など)は複雑なルール管理が得意
- AI × ロジック × ワークフローの補完関係が有効
ビジネスルール管理システム(BRMS)や DMN も選択肢になりますが、業務ルールが“例外だらけ”で「後から条件を職人的に足していく」性質が強い領域では、宣言的に記述できる Prolog のほうが変更の局所性を保ちやすいと感じました。
なお、今回は単純な if/else 相当の判定のみ扱いましたが、本来 Prolog は CLP(FD) などの制約ソルバと統合することで、また Mercury は言語として制約解決機構を組み込むことで、「日程調整」「最適化」「数値制約」などの高度な問題も解けます。
業務フローの領域においても、承認者のリソース制約や同時処理制限などに応用できます。
おわりに
本記事では、社内業務と技術アプローチの観点から、ロジックベースのアプローチや生成AIの活用可能性を自分なりに整理してみました。