【ITニュース解説】Sorting website form enquiries with an LLM that can only answer from a list
2026年10月29日に「Dev.to」が公開したITニュース「Sorting website form enquiries with an LLM that can only answer from a list」について初心者にもわかりやすく解説しています。
ITニュース概要
ウェブサイトのお問い合わせをLLMで自動分類するシステムを構築した。LLMが自由な回答ではなく、事前に定義されたカテゴリリストからのみ選ぶように制御することで、分類の一貫性を保ち、データ管理を容易にする。不適切な回答やAPIエラーの際は、人間が確認する仕組みも備えている。
ITニュース解説
ウェブサイトの問い合わせフォームには、日々様々なメッセージが届く。商品やサービスに関する営業問い合わせ、技術的なサポート質問、提携の提案、採用応募、そして迷惑メール(スパム)など、内容は多岐にわたる。これらのメッセージは、誰かが一つひとつ内容を確認し、適切な担当者や部署に振り分ける必要がある。この手作業は時間と労力がかかり、特に問い合わせ数が多い企業にとっては大きな負担となっていた。
このような課題を解決するために、近年注目されているのが大規模言語モデル(LLM)の活用だ。LLMは人間が書いた文章を理解し、その内容に基づいて分類する能力を持っているため、問い合わせの自動分類に適していると考えられる。しかし、LLMを単純に使うだけでは問題が生じる場合がある。たとえば、LLMに問い合わせを読ませて自由に分類カテゴリを答えさせると、「潜在的な営業案件(高価値)」と回答した翌日には「営業リード」と答えるなど、表現が揺らぐ可能性がある。このようにカテゴリ名が安定しないと、後からスプレッドシート(表計算ソフト)でデータを絞り込んだり、集計したりする際に、正確な結果が得られなくなってしまう。
この問題を解決するために考え出されたのが、LLMに「決められたリストの中からしか回答できない」という制約を与える方法だ。この方法では、LLMはあらかじめ定義されたカテゴリID(例:sales_inquiry, support, partnershipなど)の中から一つを選択して回答するか、あるいは分類できなかった場合は「null」(何もなし)を返すようにする。これによって、LLMがどのような表現をしようとも、最終的な分類結果は常に一貫した形式に保たれる。もしLLMがリストにないIDを答えたり、文章で回答したりした場合は、エラーとして処理し、人間の確認が必要な「needs_human」カテゴリに振り分ける。
具体的な仕組みは、n8nというワークフロー自動化ツールを使って構築されている。このワークフローは次のような流れで動作する。
まず、ウェブサイトの問い合わせフォームからデータが送信されると、それは「Webhook」と呼ばれる仕組みでワークフローに受け取られる。このデータには、氏名、メールアドレス、会社名、そして問い合わせメッセージが含まれる。
次に、受け取ったデータに対して「正規化」の処理が行われる。ここでは、特にメールアドレスが有効かどうかをチェックする。もしメールアドレスが無効であったり、全く含まれていなかったりした場合は、その問い合わせは不正なものとみなし、それ以降の処理は行わずに、送信元にHTTP 400(不正なリクエスト)というエラーを返す。この際、ログにも記録しないため、無駄なデータが残らず、セキュリティ面でも望ましい。
メールアドレスが有効であった場合、いよいよLLMが問い合わせを分類する段階に移る。LLMには、あらかじめ定義されたカテゴリIDとその簡単な説明文、そしてユーザーからの実際の問い合わせメッセージが与えられる。LLMはこの情報をもとに、最も適切なカテゴリIDを一つ選択して回答を生成する。
LLMからの回答は、すぐに最終的なカテゴリとして採用されるわけではない。その回答は「Codeノード」と呼ばれる部分で厳密にチェックされる。まず、LLMの回答から余分な空白を削除し、すべて小文字に変換し、引用符や末尾の句読点なども取り除く。「Partnership.」のような回答でも、最終的には「partnership」として認識されるように調整される。この処理の後、LLMの回答が、事前に定義されたカテゴリIDのいずれかと「完全に一致するか」が確認される。
このチェックが非常に重要だ。たとえLLMが「これはパートナーシップのリクエストのようです」のように、カテゴリIDを含む文章を返したとしても、それは有効な回答とはみなされない。なぜなら、LLMが何を意図したのかをシステム側で推測してしまうと、分類の一貫性が損なわれる可能性があるからだ。あくまで厳密に定義されたIDと一致することだけが許容される。もしLLMの回答がnullであったり、未知のIDであったり、あるいは文章であったりした場合は、すべて「needs_human」(人間の確認が必要)カテゴリに分類される。この際、チェックに失敗した理由も記録されるため、後から確認する際に役立つ。
また、もしLLMを提供するAPI自体がエラー(例えばHTTP 500などのサーバーエラー)を返した場合でも、その問い合わせが失われることはない。この場合も「needs_human」として処理され、最終的にはスプレッドシートに記録されるため、APIの一時的な不調によって重要な問い合わせが失われるリスクを防ぐことができる。
最終的な分類結果(またはneeds_human)は、Google Sheets(Googleが提供する表計算サービス)に新しい行として追加される。これには、元の問い合わせ内容や分類カテゴリ、そして必要に応じてエラー理由なども含まれる。Google Sheetsへの記録が完了すると、ワークフローは問い合わせの送信元に対してHTTP 200(成功)という応答を返し、その応答には分類されたカテゴリ情報も含まれる。
このワークフローでは、カテゴリリストの管理にも工夫が凝らされている。カテゴリID(sales_inquiry, supportなど)とそれぞれの短い説明、そして優先順位は、「Settings」という名前のCodeノードで一元的に定義されている。LLMに送るプロンプト(指示文)も、LLMの回答をチェックするコードも、この「Settings」ノードからカテゴリ情報を読み込む。これにより、プロンプトでLLMに伝えたカテゴリと、システムが認識するカテゴリに食い違いが生じる事態を防ぎ、常に整合性が保たれるようになっている。
もう一つ、技術的な注意点として、問い合わせメッセージに波括弧({})が含まれる場合の対処がある。n8nのようなワークフローツールの中には、LLM連携のために「LangChain」というライブラリを使用しているものがあり、LangChainは波括弧をテンプレート構文(例えば、メッセージ内に変数名を埋め込むための特殊な記号)として扱うことがある。そのため、問い合わせメッセージにたまたま波括弧が含まれていると、システムがそれをテンプレートと誤認識してしまい、正しく処理できない問題が発生する可能性があった。このワークフローでは、問い合わせメッセージをLLMに渡す前に適切にエスケープ(特殊な意味を持たない普通の文字として扱わせる処理)することで、この問題を回避している。これにより、ユーザーが入力したメッセージがそのままの形でスプレッドシートに保存されることが保証される。
このワークフローは、n8nの実際のインスタンス上でテストされている。テストでは、正しいカテゴリが記録されるか、無効なメールアドレスが適切に処理されHTTP 400エラーとなるか、LLMの無効な回答やAPIエラーが「needs_human」として処理されるか、波括弧が正しく処理されるかなど、計17項目が検証され、すべてパスした。これにより、ワークフローの基本的な機能とエラーハンドリングが意図通りに動作することが確認できた。
ただし、これらのテストは実際のLLMモデルの分類性能や、実際のGoogle Sheetsへの書き込み、そしてウェブフックへの認証機能や重複する問い合わせを排除する機能については検証されていない。本番環境でこのワークフローを一般公開する前には、セキュリティ強化のために認証メカニズムを追加したり、同じ問い合わせが複数回送信された場合に重複を排除する機能(重複排除)を追加したりすることが強く推奨される。
このワークフローは、LLMの強力なテキスト処理能力を、ワークフロー自動化ツールによる厳格な制御と組み合わせることで、実用的な問い合わせ分類システムを構築できることを示している。システム開発において、予測できない入力やエラーに対してどのように対処するか(エラーハンドリング)や、結果の一貫性をどう保つか(入力の制約)が非常に重要であることがわかる事例だ。