【ITニュース解説】How We Built Real-Time Booking System with Symfony. #Part 1
2025年09月25日に「Dev.to」が公開したITニュース「How We Built Real-Time Booking System with Symfony. #Part 1」について初心者にもわかりやすく解説しています。
ITニュース概要
SymfonyとLLMを組み合わせ、リアルタイム予約システムを構築した。空き状況の即時表示と、自然な会話形式のチャット予約を実現する。`symfony/ai-agent`コンポーネントがLLM連携を担い、ユーザーの要望に応じて予約や空き確認などの処理を自動実行する。非同期処理で快適な操作性も確保し、データベースのデータ構造も紹介した。
ITニュース解説
現代のサービス提供企業にとって、顧客が利用可能な時間枠を即座に把握し、素早く予約できる機能は、ビジネスを差別化する上で極めて重要となる。この記事では、Symfonyフレームワークと大規模言語モデル(LLM)を組み合わせ、このようなリアルタイム予約システムを構築した経緯と、その主要な技術要素について解説する。
従来の予約方法は、ウェブサイト上の複雑なフォーム入力や、電話での問い合わせによる時間的制約といった問題点を抱えていた。そこで、顧客がより自然で直感的にサービスを予約できるよう、チャットインターフェースを通じた予約システムが構想された。このシステムの開発にあたり、以下の主要な要件が設定された。第一に、空き時間枠を常に最新の状態で表示する「リアルタイム性」。第二に、ユーザーが会話の流れで簡単に予約できる「直感的なチャットインターフェース」。第三に、多数のユーザーが同時にアクセスしても対応できる「拡張性」。第四に、予約データの正確性と整合性を保証する「信頼性」。最後に、既存のサービス管理システムとのスムーズな「統合性」である。
チャットを通じた予約体験は、非常にシンプルで自然な会話の流れで行われる。例えば、ユーザーが「予約したい」とメッセージを送ると、チャットボットが「どのようなサービスをご希望ですか?」と尋ね返す。ユーザーが「ヘアカット」と答えると、チャットボットは続けて「いつ頃がよろしいですか?」と問いかける。ユーザーが「明日」と返答すると、チャットボットは明日の空き時間枠をいくつか提示し、ユーザーが「11:00 AM」といった具体的な時間を選ぶことで、その時間帯が仮予約される。その後、システムから確認のメッセージが送られるという流れである。
このチャットシステムを支えるのは、大規模言語モデル(LLM)を中心とした複雑なアプリケーションフローである。ユーザーがチャットインターフェースからメッセージを送信すると、そのメッセージはまずシステムへの唯一の入り口となるSymfonyのコントローラーに到達する。コントローラーはメッセージを受け取ると、すぐにそれをSymfony AI Agent(エージェント)というサービスに渡す。このAI Agentは外部のLLMと連携するように設定されており、ユーザーのメッセージと、システム内で実行可能な特定の操作(これを「ツール」と呼ぶ)のリストをLLMに送る。
LLMはユーザーのリクエストを分析し、単にテキストで応答を生成するか、あるいは提供されたツールの中から適切なもの(例えば、サービスの有効性を確認するツールなど)を呼び出すかを判断する。もしLLMがツールを呼び出すと判断した場合、ツールの名前と必要な引数(パラメーター)をAI Agentに伝える。AI Agentはその指示に基づいて、ReservationToolsというサービス内の対応するメソッドを実行する。ReservationToolsサービス内のメソッドは、その中で、データベースに問い合わせて空き時間枠を確認したり、外部のサービスシステムに対してAPI(アプリケーション・プログラミング・インターフェース)呼び出しを行ったりといった具体的な処理を実行する。ツールの実行結果はAI Agentに戻され、さらにLLMにフィードバックされる。LLMはこの結果を受けて、最終的な、ユーザーにとって分かりやすい自然言語の応答を生成し、その応答がAI Agent経由でSymfonyコントローラーに戻され、最終的にユーザーのチャットインターフェースに表示されるのである。
このシステムでは、ユーザーに即座に返答する必要のない、時間のかかる処理を効率的に行うための工夫もされている。例えば、予約の確定、確認メールの送信、支払い処理といったタスクは、非同期処理と呼ばれる方法で実行される。これは、Symfony Messengerというコンポーネントを利用して、これらの処理をメッセージとしてバックグラウンドで処理させることで実現される。ユーザーからのリクエストはすぐに完了したかのように見せかけ、重い処理は裏側で進められるため、ユーザーは常にシステムが素早く反応していると感じられる。Messengerコンポーネントは、予約の詳細をデータベースに保存したり、外部のサービスシステムに最終的な予約確定を通知するAPI呼び出しを行ったりする。このように、ユーザーに直接対面する部分、ビジネスロジックを処理する部分、そして時間のかかるタスクをバックグラウンドで処理する部分が明確に分離されている。
システムのデータの持ち方についても理解が重要である。サービス予約の最小単位である特定の時間ブロックは「Slot(スロット)」というエンティティ(データ構造)で表現される。Slotエンティティは、一意のID、関連するサービスの種類(ServiceType)、予約の開始時刻と終了時刻、予約済みであるかどうかの真偽値、そして予約した顧客を識別する情報といった属性を持つ。一方、「ServiceType(サービスタイプ)」エンティティは、ヘアカットやマニキュアといった提供されるサービスの種類を管理する。ServiceTypeは複数のSlotエンティティと関連付けられ、特定のサービスに紐づくすべてのSlotを容易に検索できる。データベースからSlotエンティティの情報を取得したり、更新したりするためのロジックは「SlotRepository(スロットリポジトリ)」というクラスに集約されている。このリポジトリには、特定のサービス名と日時範囲で空いているSlotを探すためのデータベースクエリ(データ問い合わせ)が記述されている。
大規模言語モデルをアプリケーションに統合する上で、symfony/ai-agentコンポーネントが最適なツールとして選定された。これはSymfonyフレームワークの公式コンポーネントであり、既存のサービスや設定とスムーズに統合できる点が大きな利点である。また、OpenAIやGoogle AIなど様々なLLMプロバイダーと柔軟に連携できるAPIを提供し、APIキーの管理やリクエスト・レスポンス処理といったAI連携の複雑な部分を効率的に処理するように設計されている。公式コンポーネントであるため、Symfonyコミュニティからの強力なサポートと定期的な更新も期待できる。このコンポーネントはComposerというPHPのパッケージ管理ツールを使ってcomposer require symfony/ai-agentというコマンド一つで簡単にインストールできる。ただし、このコンポーネントはまだ開発段階にあるため、Composerの設定ファイルであるcomposer.jsonにおいて、minimum-stabilityをdevに、prefer-stableをtrueに設定することで、開発版のパッケージを他の安定版の依存関係と共存させながらインストールすることが可能になる。
リアルタイム予約システムを実現するために不可欠なのが「ツール」の構築である。これらのツールは、LLMがシステム内部で具体的なアクションを実行するための通信手段として機能する。symfony/ai-agentコンポーネントのツーリングシステムは、LLMがどの機能を呼び出せるか、その機能の実行に必要なデータ、そしてその機能が返す情報を、構造化された方法でLLMに理解させる。この構造化された通信方法は、モデルコンテキストプロトコル(MCP)とも呼ばれる。予約システムにおいては、例えばユーザーID、サービス名、希望日時を受け取って予約を作成する「予約ツール」、特定のサービスと日時における空き状況をデータベースに問い合わせる「空き確認ツール」、ユーザーの過去の予約情報などを取得する「ユーザー情報取得ツール」などが具体的に構築される。これらの明確に定義された単一目的のツールを構築することで、LLMはアプリケーションのバックエンドと連携し、その動作は予測可能で安全なものとなり、既存のビジネスロジックと完全に統合されるのである。
本記事では、リアルタイム予約システムの基本的な構築思想、大規模言語モデルとの統合アプローチ、そしてこれを支えるSymfonyの主要なコンポーネントとデータ構造について解説した。特に、symfony/ai-agentコンポーネントとその「ツール」の概念が、LLMにシステムを操作させる上でいかに重要であるかを説明した。次回の記事では、これらのツールを実際にどのように構築し、LLMにシステムを動かすための具体的な実装方法をさらに詳しく掘り下げていく予定である。