はじめに
一時期、私はGenerative AIによって、システムやワークフローの作り方が大きく変わるのではないかと考えていました。
もちろん、「AIが開発者を置き換える」というような極端な話ではありません。もう少し現実的な意味です。これまでは、業務課題を解決するために、多くのコードを書き、ルールを設計し、細かなケースを処理し、何度もテストしながら、ようやく安定したワークフローを作っていました。
ところがAIが登場してから、特に大規模言語モデルを使えるようになってから、「ワークフローの多くの部分をAIに任せられるのではないか」と感じるようになりました。
顧客からのメールを分類したい。AIに渡す。
業務文書から必要な情報を抽出したい。AIに渡す。
ニュース記事やブログをクロールして要約したい。それもAIに渡す。
最初は、この考え方はとても魅力的でした。AIは従来のコードでは扱いづらかったことを自然にこなせます。自然言語を理解し、非構造化データを読み取り、曖昧な文脈から推論し、それらしい回答を生成できます。
しかし、実際のワークフローにAIを組み込んで使っていくうちに、少しずつ考え方が変わりました。
AIは非常に強力です。ただし、ワークフロー全体をAIに任せるべきではありません。
より現実的で効果的なのは、「AIに全部やらせる」ことではなく、安定して制御可能なワークフローを設計したうえで、AIが本当に価値を出せる部分にだけAIを配置することでした。
この記事は、AIが良いか悪いかを証明するものではありません。AIをシステム内の1つの技術コンポーネントとして見たときに、強み、弱み、コスト、レイテンシ、安定性、そして適切な使いどころがある、という話です。
AI以前:ワークフローはコードとルールと細かな処理の積み重ねだった
Generative AIが一般的になる前、業務プロセスを自動化しようとすると、だいたい次のような作業から始めていました。
- 入力と出力を定義する
- データを読み取るパーサーを書く
- 分類用のルールを書く
- データ検証のロジックを書く
- 次に進むべき処理を決める
- 状態をデータベースに保存する
- 件数が多ければキューを用意する
- エラー時のリトライを設計する
- システムの状態を監視できるようにする
- 必要に応じてダッシュボードやレポートを作る
構造化データであれば、このやり方はとても有効です。たとえば入力がJSON、CSV、フォーム送信、データベースのレコードであれば、スキーマも型もルールも明確にできます。
status = pending ならAの処理を行う。amount > 1000 なら承認が必要。customer_id がなければリジェクトする。
このような処理は、従来のコードが非常に得意とする領域です。速く、安く、安定していて、テストもしやすいです。一度正しく書いたルールは、今日も明日も同じように動きます。
しかし、データがきれいではない場合、話は難しくなります。
たとえば顧客からの問い合わせを処理するワークフローでは、入力は次のようなものになります。
- 自由形式で書かれたメール
- スキャンされたPDF
- チャットメッセージ
- 営業担当者のメモ
- 決まった形式のない障害報告
- 自然言語で書かれた変更依頼
このような入力に対してルールを書くのはかなり大変です。正規表現、キーワードマッチ、ヒューリスティック、マッピングテーブルなどを使うことはできます。ただ、作れば作るほど例外が増えていきます。
- 表現は違うが意味は同じ
- 必要な情報が明示されていないが文脈から推測できる
- 1つの依頼に複数の意図が含まれている
- 重要な情報が複数の文に分散している
- 人によって書き方がまったく違う
AI以前でも、もちろんこうした問題を解決することはできました。ただし、ワークフローを構築するコストは高くなりがちでした。
コードを書くコストだけではありません。ドメインエキスパートとルールを詰める時間、何十・何百もの分岐を保守するコスト、入力形式が変わったときの修正コスト、例外処理のコストもあります。
よいワークフローを作るには、曖昧な業務課題を、機械が実行できる明確な手順に落とし込む必要があります。
このやり方には大きな利点があります。システムが安定し、予測可能で、監査もしやすいことです。
一方で、初期コストが高いため、小さな自動化は後回しになりがちでした。数週間かけて作っても、月に数時間しか削減できないなら、作らないという判断になることも多かったと思います。
Generative AIの登場:すべてが速く作れるように見えた
Generative AIを使い始めたとき、最初に感じたのは「速さ」でした。
これまでなら、入力を分析し、パーサーを書き、ルールを作り、ケースごとにテストしていたような処理が、まずは1つのプロンプトで試せるようになりました。
この顧客メールを読み取り、意図を分類し、会社名、緊急度、関連製品、次に取るべき対応を抽出してください。
するとAIは、かなり整ったJSONを返してくれます。
しかも、なぜそのように分類したのかまで説明できます。決まった形式ではない文章を読み取り、異なる表現を理解し、日本語、英語、ベトナム語、あるいは複数言語が混ざった内容にも対応できます。
プロトタイプ段階では、これは非常に強力です。
数日かかっていた検証を、数時間で形にできます。少量のサンプルを用意し、プロンプトを調整し、出力スキーマを整えれば、それらしく動くワークフローをすぐに見せられます。
これまで「作るほどの価値があるか微妙」と判断されていた自動化も、試しやすくなりました。
AIは開発プロセスでも役に立ちます。
- ボイラープレートコードを生成する
- パイプライン設計の案を出す
- 初期のテストケースを書く
- 要件を要約する
- 業務説明をチェックリスト化する
- 社内向けドキュメントを作る
- ログやエラーの内容を分析する
こうした能力を見ていると、自然と次のように考えてしまいます。
AIが業務を理解し、データを読み取り、判断までできるなら、ワークフロー全体をAIに任せてもよいのではないか。
たとえば、顧客対応ワークフローは次のように単純化できます。
- 顧客からのメールを受け取る
- 内容をすべてAIに渡す
- AIが依頼種別を判断する
- AIが必要な情報を抽出する
- AIが次の処理を決める
- AIが返信文を作る
- システムが結果を送信する
スライド上では非常にきれいです。
しかし、実際の運用に近づくほど、問題が見えてきます。
現実とのギャップ:AIは強いが、コードほど安定していない
最初に気になったのは安定性です。
同じ入力を渡しても、AIは毎回少し違う出力を返すことがあります。表現だけが違う場合もありますが、入力が曖昧なときには判断自体が少し変わることもあります。
チャットボットや個人用の補助ツールであれば、それでも問題にならない場合があります。しかし、業務ワークフロー、特に大量のデータを処理するシステムでは、この不安定さは無視できません。
業務システムには、一般的に次のような性質が求められます。
- 同じ入力に対して同じ出力を返す
- エラーを明確に分類できる
- リトライしても予期しない結果にならない
- なぜその判断になったかを監査できる
- 回帰テストを書ける
- コストと処理時間をある程度予測できる
AIは、これらを自然に満たすわけではありません。
temperatureを下げたり、スキーマを強制したり、function callingを使ったり、validationやguardrailを追加したりすることで改善はできます。それでも、AIは従来の決定的な関数とは異なります。
AIは確率的なコンポーネントです。曖昧なものを扱うのが得意である一方、その曖昧さゆえに制御が難しくなる場面があります。
次に問題になるのは速度です。
コード上のルールは数ミリ秒で実行できます。データベースクエリも最適化できます。単純なロジックであれば、バッチ処理で大量のレコードを処理できます。
一方で、AI呼び出しにはそれなりのレイテンシがあります。ワークフロー内の複数のステップでAIを呼ぶと、全体の処理時間はすぐに増えていきます。
さらにコストの問題もあります。
1回のAI呼び出しは安く見えるかもしれません。しかし、継続的に動くワークフローで、各アイテムごとに複数回AIを呼び、長いプロンプトと長い出力を扱うようになると、コストは無視できなくなります。
特に、コードで簡単に処理できる部分までAIに任せると、そのコストはあまり価値を生みません。
たとえば次のような処理です。
- 必須フィールドが存在するか確認する
- 明確なenumにマッピングする
- 金額を計算する
- 日付フォーマットを検証する
- 既知のルールでルーティングする
- 既存キーで重複判定する
これらはAIに任せる必要がありません。コードの方が速く、安く、安定していて、テストもしやすいです。
もう1つの問題は、制御しづらさです。
AIに多くの処理をまとめて任せると、最終結果が間違っていたときに、どこで失敗したのか分かりにくくなります。
原因は次のどれかかもしれません。
- プロンプトが曖昧だった
- 入力に十分な文脈がなかった
- モデルの推論が間違っていた
- 出力がスキーマに合っていなかった
- 分類ミスが後続のルーティングに影響した
- 入力にない情報をAIが補ってしまった
- validationが緩すぎて検出できなかった
ワークフロー全体が1つの大きなプロンプトになっていると、デバッグはかなり難しくなります。各ステップの境界が見えず、すべてが大きなブラックボックスになります。
重要なワークフローほど、すべての判断を1つのプロンプトに閉じ込めるべきではありません。プロンプトはシステムの一部にはなりますが、システム設計そのものを置き換えるものではありません。
AIが本当に強いところ
何度か試していくうちに、AIが最も価値を出すのは、従来のコードではコストが高かった部分だと感じるようになりました。
つまり、非構造化データと自然言語の処理です。
業務ワークフローであれば、AIは次のようなステップに向いています。
- メールやチャットから意図を分類する
- 自由記述から必要な情報を抽出する
- 表記ゆれを正規化する
- 長い文章を要約する
- 感情や緊急度を推定する
- 文脈に基づいてアクション候補を提案する
- 人間が確認する返信文のドラフトを作る
- 非構造化テキストをスキーマ付きJSONに変換する
これらの共通点は、入力が曖昧で、すべてのルールを手で書くのが難しいことです。ただし、AIが出した結果は、コードや人間によって検証できます。
一方で、AIを最初に使うべきではない処理もあります。
- 単純なvalidation
- 計算
- 明確なルールによるマッピング
- 認可
- idempotency
- transaction
- audit log
- retry policy
- state machine
- 既知条件によるrouting
言い換えると、AIは「曖昧な部分」を処理し、ワークフローは「確実な部分」を処理するべきだと思います。
Hybrid workflow:ワークフローを骨格にし、AIを価値の高いノードに置く
「AIに全部やらせる」という考えから少し距離を置くと、より現実的なのはhybrid workflowだと感じるようになりました。
このモデルでは、ワークフロー自体はコードやworkflow engineで明確に設計します。ステップ、状態、ルール、リトライ、validation、storage、monitoringはワークフロー側が持ちます。
AIは、その中で本当に価値を出せるノードとして使います。
顧客リクエスト処理の例であれば、次のような流れです。
ここで重要なのは、AIがすべてを決定するわけではないということです。
AIは「これはキャンセル依頼の可能性が高い」「緊急度は高そう」「注文番号はABC123のようです」と提案できます。
しかし、システム側では次を確認する必要があります。
- 注文番号が存在するか
- 顧客にキャンセル権限があるか
- 注文がどの状態にあるか
- 承認が必要か
- 手動レビューが必要なリスクがあるか
AIの抽出結果が不足している場合や不確実な場合、ワークフローはレビューに回せます。AIの出力がスキーマに合わなければrejectできます。confidenceが低ければ、自動で危険なアクションを実行しないようにできます。
このモデルは、1つのプロンプトで何でもこなすデモほど派手ではありません。しかし、長期的に運用するにはこちらの方が信頼できます。
3つのアプローチの比較
私がよく考える比較は、次の3つです。
| 観点 | コード中心のワークフロー | AIにすべて任せる | Workflow + AI |
|---|---|---|---|
| プロトタイプ速度 | 遅め | とても速い | 速い |
| 安定性 | 高い | 低〜中程度 | 設計次第で高い |
| 実行コスト | 低く予測しやすい | 高くなりやすい | 制御しやすい |
| 非構造化データ処理 | 難しく、ルールが増える | 得意 | 必要な箇所で得意 |
| デバッグ | 比較的容易 | 大きなブラックボックスになりやすい | ステップごとに追いやすい |
| 回帰テスト | 書きやすい | 難しい | レイヤーごとに書ける |
| 大量処理 | 得意 | cost/latencyが課題 | AI呼び出しを絞れば対応しやすい |
| 監査・制御 | しやすい | 弱くなりやすい | ログ設計次第で可能 |
| 重要な判断への適用 | ルールが明確なら可能 | リスクが高い | AI単独判断にしなければ可能 |
| 初期構築コスト | 高め | 低い | 中〜低程度 |
どれか1つが常に正解というわけではありません。
ルールが明確でデータが構造化されているなら、コード中心のワークフローは今でも非常に有効です。AIにすべて任せる方法は、プロトタイプや小さな内部ツール、リスクの低いタスクには向いています。
しかし、安定して動かす必要がある業務システムでは、hybrid approachが最もバランスがよいと感じています。
具体例:顧客問い合わせの処理
たとえば、顧客からのメールを受け取り、適切なチームに振り分けるシステムを考えます。
メール本文は自由形式です。目的は、依頼内容を分類し、正しいキューに入れることです。
AIにすべて任せるなら、次のようなプロンプトを書けます。
このメールを読み、問題を特定し、担当チームを決め、チケットを作成し、顧客への返信文を作成してください。
デモとしては非常に速いです。
しかしproductionではリスクがあります。AIが担当チームを誤るかもしれません。自信過剰な返信を作るかもしれません。重要な情報を見落とすかもしれません。社内ポリシーに合わない対応を提案する可能性もあります。
一方で、完全にコードだけで処理する場合は、多くのルールを書く必要があります。
-
refundを含むならbillingへ -
cannot loginを含むならsupportへ -
invoiceを含むならfinanceへ -
urgentを含むならpriority highへ
単純なケースではこれで十分です。しかし、顧客の表現が少し変わるだけで取りこぼしが発生します。
hybrid approachでは、次のように分けます。
- コードがメールを受け取り、raw inputとrequest idを保存する
- コードが署名、過去メールの引用、attachment metadataを整理する
- AIがintent分類とfield抽出を行う
- コードが出力を検証する
- 既知のルールでチケットをルーティングする
- confidenceが低い場合や必須情報が欠ける場合はhuman reviewに回す
- 安全な場合のみ、AIが返信ドラフトを作成する
- 人間が確認するか、low-riskなtemplateに限って自動送信する
- すべてのdecisionをaudit logに残す
ここでAIは最も難しい部分、つまり自由形式のメール理解を担当します。一方で、状態管理、ルール、権限、最終アクションはワークフロー側が制御します。
1つのプロンプトだけで動くデモほど派手ではありませんが、実運用には向いています。
Case study:URLからニュースやブログを要約する
もう1つ、AIにすべて任せる場合とworkflow + AIの違いが分かりやすい例があります。
ニュース記事やブログを収集し、内容を要約するワークフローです。
一見すると、やることは単純です。
- URLの一覧を受け取る
- 各ページの内容を取得する
- 内容を要約する
- タグやカテゴリを付ける
- レポートやdigestとして保存する
しかし、crawlerやscraperを書いたことがある人なら分かると思います。難しいのは「ページを取得する」ことではありません。難しいのは、WebサイトごとにHTML構造が違い、その構造が時間とともに変わることです。
AI以前:固定parserは速いが壊れやすい
AI以前の一般的な方法は、ソースごとにscraperを書くことでした。
たとえば、あるブログでは本文が次のXPathにあるとします。
//article
別のサイトでは、次のような場所かもしれません。
//*[@id="main-content"]
あるいはCSS selectorで次のように指定することもあります。
.article-body .content
本文部分を取得したら、title、author、published date、tag、main imageなどを取り出して保存します。
この方法は、サイト構造が安定していれば非常に有効です。速く、安く、deterministicです。selectorが正しければ、数千ページでも低コストで処理できます。
しかし弱点も明確です。
HTMLが変わると壊れます。
サイト側がclass名を変えた。wrapperを1つ追加した。server-renderedからclient-renderedに変わった。記事レイアウトを変更した。titleの位置が変わった。cookie bannerや広告、paywallが追加された。
こうした変更で、昨日まで動いていたparserが突然空文字を返したり、sidebarを本文として取得したり、commentやrelated postsまで拾ってしまうことがあります。
対象サイトが3つ程度ならまだ管理できます。しかし、50や100の情報源を扱うようになると、サイトごとのselectorを保守するコストはかなり大きくなります。
コード中心の方法は安定していますが、その安定性には保守コストが伴います。
AIにすべて任せる:プロトタイプは速いがscaleしにくい
AIが使えるようになると、最初に考えるのはとても自然です。
URLをAIに渡して、ページを読ませ、本文を抽出し、要約してもらえばよいのではないか。
または、AIが直接URLにアクセスできない場合、システム側でHTMLをfetchし、raw HTML全体をAIに渡す方法もあります。
これは記事ページのHTMLです。menu、広告、footer、commentを無視して、本文だけを抽出し、要約してください。
この方法は、デモではとても速く動きます。数個のURLなら、AIはかなりうまく処理できます。どこがtitleで、どこが本文で、どこがノイズなのかをある程度判断できます。そのまま要約もできます。
しかし、実際のworkflowに入れると問題が出てきます。
Webページのraw HTMLには多くのノイズが含まれています。
scriptstyle- inline CSS
- tracking code
- JSON-LD
- navigation
- footer
- sidebar
- related posts
- comment
- ads
- cookie banner
- hidden HTML
- frontend frameworkのhydration data
1つのraw HTMLでも、ページによっては数万token、あるいはそれ以上になることがあります。そのままAIに渡すと、必要のない情報に対してもコストを払うことになります。
問題はコストだけではありません。
- promptが長くなり処理が遅くなる
- noiseが多く、本文の特定が不安定になる
- sidebarや関連記事を要約してしまう可能性がある
- 大量URLのbatch処理では費用が読みにくい
- fetchの問題なのかHTML noiseなのかAIの推論ミスなのか切り分けにくい
- table、list、headingなどの構造を保ちづらい
つまり、AIにすべて任せる方法は、prototypeには向いています。しかしproductionや大量処理では、tokenを無駄に使い、制御しづらいシステムになりがちです。
crawlや要約の文脈では、「raw HTMLをそのままAIに渡す」のが最速のデモになりがちです。ただし、productionや大規模batchのデフォルト設計にはしない方がよいと思います。
Workflow + AI:必要な部分だけを抽出してからAIに渡す
より現実的なのは、機械的な処理をworkflowに任せ、言語理解をAIに任せることです。
raw HTML全体をAIに渡す代わりに、workflow側で次のような前処理を行います。
- URLを受け取る
- HTTP request、必要であればheadless browserでHTMLを取得する
- XPath/CSS selector、またはreadability heuristicで本文領域を抽出する
-
script、style、不要なclass/css、tracking、nav、footer、commentを削除する -
h1、h2、p、ul、ol、table、blockquote、codeなどのsemantic HTMLは残す - cleanされたHTMLをAIに渡す
- AIに要約、tag付け、要点抽出を行わせる
- 出力をvalidationして保存する
流れとしては次のようになります。
ここで重要なのは、workflowがAIの代わりに内容を理解しようとしているわけではないことです。
workflowの役割はノイズを減らし、価値のある部分だけをAIに渡すことです。
AIは、raw HTMLの中を泳ぐ必要がなくなります。小さく、きれいで、構造が残った入力を読み、本文の理解と要約に集中できます。
この設計にはいくつかの利点があります。
- tokenを大きく削減できる
- batch処理時のコストを抑えやすい
- promptが短くなりlatencyも下がりやすい
- 記事の構造を保ちやすい
- table、list、headingを扱いやすい
- ステップごとにdebugしやすい
- extractionに失敗したときfallbackしやすい
たとえばXPathがmatchしなかった場合、workflowはすぐにそれを検知できます。その場合は次のようなfallbackを選べます。
- 別のselectorを試す
- readability algorithmを使う
- headless browserでrenderしてから再抽出する
- review queueに送る
- そのdomainのextraction ruleを更新対象として記録する
一方、raw HTMLをAIに渡して要約だけが間違っていた場合、原因の切り分けはかなり難しくなります。
固すぎるXPathにも注意する
ただし、ここで昔ながらの壊れやすいscraperに戻ってしまうのもよくありません。
たとえば、次のようにDOM階層に強く依存するXPathは壊れやすいです。
//*[@id="__next"]/div/div[3]/main/div[2]/article/div[1]
サイト側がwrapperを1つ追加しただけで壊れる可能性があります。
そのため、できるだけ相対的でsemanticな方法を優先した方がよいと思います。
-
articleを探す - paragraphが連続している領域を探す
-
h1に近いcontent containerを探す - navigationやfooterらしいblockを除外する
- XPath/CSS selectorとreadability heuristicを組み合わせる
- 重要なdomainについてはdomain別設定を持つ
目的は完璧なparserを作ることではありません。
目的は、AIを呼ぶ前に不要な入力を減らしつつ、fallback可能な形で処理することです。
Dynamic HTMLは別の難しさがある
すべてのページがHTTP responseに完全な本文を含んでいるわけではありません。多くのページはJavaScriptで内容をrenderします。scrollが必要なものもあれば、client-side APIを呼ぶものもあります。
このようなdynamic HTMLでは、Playwrightのようなheadless browserでrenderしてから抽出する必要があるかもしれません。
これはHTTP requestだけで処理するより遅くなります。それでも、すべてをAIに丸投げするよりは制御しやすいです。
重要なのは、AIはfetchやrenderの工程を置き換えるものではないということです。workflowにrepeatabilityやauditが必要であれば、AIに渡したraw inputまたはclean inputを保存しておくべきです。
なぜ構造を残すことが重要なのか
crawl後にHTMLをすべてplain textにしてしまうこともあります。これは単純ですが、情報を落とす場合があります。
たとえば、記事内に比較表があるとします。
| Tool | 長所 | 短所 |
|---|---|---|
| A | 速い | 柔軟性が低い |
| B | 柔軟 | setupが難しい |
これを雑にtext化すると、列同士の関係が失われることがあります。list、heading、code block、quote、section hierarchyも同じです。
そのため、class、style、scriptは削除しても、semantic tagは残した方がよいケースがあります。
<h1>...</h1>
<h2>...</h2>
<p>...</p>
<ul>...</ul>
<table>...</table>
<blockquote>...</blockquote>
この形式は、raw HTMLより短く、plain textより構造が豊かです。
これもhybrid approachの良い例です。workflowが入力を整え、AIが意味を処理します。
AIはワークフローを置き換えない。ワークフローを作りやすくする
ここで重要なのは、AIがワークフローを不要にするわけではないということです。
むしろ、AIによってワークフローを作るコストが下がったと考えています。
以前は、多くの自動化が初期コストの高さによって見送られていました。多くのcaseを分析し、多くのparserを書き、多くのruleを作る必要があったからです。入力が非構造化データであれば、さらにコストは高くなります。
AIがあると、開始しやすくなります。
- AIを使ってサンプルデータを探索する
- intentの分類案を出してもらう
- 情報抽出用のpromptを作る
- schema draftを作る
- validation codeを速く書く
- 実データからtest caseを作る
- workflowの説明ドキュメントを作る
- business側に見せるprototypeを早く作る
AIはruntime componentであるだけではありません。workflowを設計し、構築するプロセス自体も速くしてくれます。
以前なら「作るほどではない」と判断していたautomationでも、短時間で試し、価値を確認してから安定化に投資できます。
つまり、AIは試行錯誤のコストを下げます。
試行錯誤のコストが下がると、自動化できる対象も広がります。大きなROIが見える業務だけではなく、社内の小さなワークフローにも適用しやすくなります。
- ticketの分類
- 手入力データの正規化
- reportの要約
- document reviewの補助
- 返信draftの作成
- 異常ケースの検出
- 社内向けニュースdigest
- 技術ブログの定期収集と要約
こうした小さなworkflowは、以前なら後回しにされがちでした。しかし積み重なると、運用時間を大きく削減できます。
私がよく使う判断基準
AIを含むworkflowを設計するとき、私はよく次のように考えます。
このステップからAIを外した場合、従来のコードの方がうまく処理できるか?
答えがyesなら、基本的にはコードを優先します。
schema validation、計算、明確なルールによるrouting、permission check、logging、HTML fetch、script/style の除去、navigation/footerの削除などは、コードの方が得意です。
次に考えるのは、次の問いです。
このステップでAIが間違えた場合、影響はどの程度か?
影響が小さいなら、AIにより多く任せてもよいかもしれません。たとえば、draft作成、参考用の要約、tag候補の提案などです。
影響が大きい場合は、validation、人間によるreview、またはAIに最終判断をさせない設計が必要です。
もう1つの問いはこれです。
AIの出力をコードで検証できるか?
検証できるなら、システムはかなり安定します。AIは曖昧な入力から候補を作り、コードはその候補をチェックします。
schema validation、enum validation、range check、consistency check、database lookup、duplicate detectionなどは非常に有効です。
個人的には、次の考え方がしっくりきます。
AI proposes, workflow disposes.
AIは提案する。ワークフローがその提案をどう使うかを決める。
プロンプトにすべての業務ロジックを詰め込まない
よくある失敗の1つは、プロンプトに多くのロジックを詰め込みすぎることです。
最初はintent分類だけだったプロンプトに、特別なルールを追加する。例外を追加する。policyを追加する。出力形式の指示を追加する。few-shot exampleを追加する。
しばらくすると、プロンプトが巨大な業務ロジックファイルになります。読みにくく、テストしにくく、reviewもしづらくなります。
これは、巨大な1ファイルにすべてのロジックを詰め込むのと似ています。ただし、promptの方がさらに制御しづらい場合があります。
プロンプトはシステムの一部として扱うべきです。しかし、すべてのロジックを置く場所ではありません。
明確なルールはcodeやconfigに置く。重要なpolicyはvalidationで確認する。リスクのあるdecisionはaudit logに残す。
プロンプトは、AIが得意な部分に集中させた方がよいと思います。つまり、自然言語理解、抽出、要約、分類などです。
crawlerでも同じです。
プロンプトに「menuを無視して、footerを無視して、scriptを無視して、adsを無視して、本文を見つけて、tableは維持して、commentは取らないで」と全部書くより、workflow側でできるだけ前処理した方がよいです。
AIには、きれいで構造化された入力を渡すべきです。
振り返り
振り返ると、私のAIに対する考え方は3段階で変わりました。
最初は、ほどよい懐疑でした。AI以前は、すべてをコードで明確に定義することに慣れていました。良いシステムとは、ルールが明確で、テストがあり、挙動が予測できるものだと考えていました。
次に、期待が大きくなりました。AIは、これまで扱いづらかった曖昧な入力をかなりうまく処理できました。inputを読み、業務を理解し、判断し、outputを生成する。demoはすぐに動き、非常に強力に見えました。
そして最後に、より現実的になりました。
AIはシステムから消えるわけではありません。しかし、すべての運転席に座るものでもありません。AIはarchitectureの中の1つのcomponentです。非常に強力ですが、boundary、validation、fallback、logging、cost controlが必要です。
この経験によって、私の問いは変わりました。
以前はこう考えていました。
このworkflowをAIで作れるか?
今はこう考えます。
このworkflowの中で、AIが価値を出すほど曖昧な部分はどこか。逆に、コードが担当すべき明確な部分はどこか。
後者の問いの方が難しいですが、実運用ではずっと役に立ちます。
まとめ
AIはワークフローを置き換えるものではありません。むしろ、ワークフローをより速く、より安く作れるようにするものだと思います。
ただし、AIにシステム全体を依存させると、安定性、速度、コスト、制御性の問題が出やすくなります。特に業務ワークフローでは、出力が予測可能で、監査可能であることが重要です。
私が今のところ実用的だと感じている方針は次の通りです。
- deterministicな部分はworkflow/codeに任せる
- 自然言語や非構造化データの処理にAIを使う
- AIの出力はschemaやruleで検証する
- input、output、decisionをログに残す
- 不確実な場合はhuman reviewにfallbackする
- コードの方が得意な処理ではAIを呼ばない
- AIに渡す前にnoiseを減らす
- raw dataをそのまま投げるのではなく、重要な構造を残す
- AIをcost、latency、failure modeを持つcomponentとして扱う
最後に、重要な問いは「AIは開発者を置き換えるのか」ではないと思います。
より実用的な問いは、こちらです。
業務課題を正しく解決しながら、システムをより安定させ、より速く、より安くするために、AIをworkflowのどこに置くべきか。
業務自動化にAIを使ってみて、私の考え方はそこに落ち着きました。