Tabelog Tech Blog

食べログの開発者による技術ブログです

生成AIを使ったらAPIの開発が捗った話

この記事は 食べログアドベントカレンダー2024 の6日目の記事です🎅🎄

はじめに

こんにちは。2022年に入社し、飲食店システム開発部の予約サービスチームに所属している @aaknsk です。

当社では、業務効率化のため社内向けに生成AIを活用したチャットボットを導入しています。
この記事では、オンライン台帳の「食べログノート」で分析機能を開発したときにチャットボットを活用して効率が上がった事例について紹介します。

食べログノートとは

食べログノートはオンライン予約台帳サービスです。
食べログネット予約はもちろん、電話予約や他社ネット予約、ウォークイン(ご予約無し来店)も全て統合管理できます。

2022年4月にリリースされ現在では多くの店舗で導入されています。

食べログノートの分析機能とは

機能の目的

食べログノートの分析機能は、店舗が日々の業務で収集するデータを視覚的に分析することで、
適切な施策を講じるための意思決定を行いやすくすることを目的としています。

こんなことができる

  • 当月の総客数やキャンセル率・平均人数など予約に関するデータが一目で分かるダッシュボード
  • どんな経路から登録された予約なのかがわかる予約経路の分析
  • 予約が入ってから来店するまでに何日かかっているかがわかるリードタイム分析

他にも分析できる項目があり、分析機能の画面だけで 9 つあります。

▼ダッシュボードの画面イメージです
食べログノート分析機能のダッシュボード画面

分析機能を開発するときに困ったこと

食べログノートでは、PC/iPad用のWeb(Next.js)・iOSアプリ・Androidアプリが共通のGraphQLから情報を取得しています。GraphQLからは、Ruby on RailsのAPIを呼び出す構成になっています。

食べログノートの開発は、GraphQLのスキーマに基づいて進められています。GraphQLのスキーマには、クライアントがどのようなデータを取得できるかが分かる型情報が記載されています。

私はバックエンドの担当で、集計結果を返却するRuby on RailsのAPI開発を担当しました。 今回はスキーマの項目が非常に多く、ネストも深いため、スキーマ形式に沿って集計データを作成することが大変でした。

▼スキーマを見える化したイメージの簡略版
※ダッシュボード画面用APIではこちらの図のような構造で、さらに多くの項目がありました。
ダッシュボード画面のGraphQLスキーマの見える化イメージ

項目がとても多かったので、このままではどんなレスポンスの形になるかイメージがつきにくい状況でした。

そうだ、チャットボットを活用してみよう!

開発を進めていたときに、GPT-4oを利用する社内チャットボットが利用可能になったよというアナウンスがありました。
プライベートでも生成AIを利用していたので、開発の効率を上げるために上手く使えないかな?と思い、試してみました。

どんなレスポンスを返却すればいいのかイメージをつけたかったので、まずはGraphQLスキーマからレスポンスのサンプルを作成してみました。

▼スキーマのサンプルコード
※実際のスキーマを真似た簡略版です。このコードもチャットボットで生成しました。

type Query {
  reservationAnalysisDashboard: ReservationAnalysisDashboard!
}
 
type ReservationAnalysisDashboard {
  totalReservations: Int!
  totalVisitors: Int!
  comparisonWithLastMonth: ComparisonResult!
  comparisonWithLastYear: ComparisonResult!
  reservationSourceDetails: ReservationSourceDetail!
}
 
type ComparisonResult {
  percentageChange: Float!
  difference: Int!
}
 
type ReservationSourceDetail {
  online: Int!
  phone: Int!
  walkIn: Int!
}

スキーマをチャットボットに渡し、APIのサンプルJSONを作成してみました。
チャットボットにJSONのサンプル生成依頼をしたスクリーンショット

スキーマの型通りのJSONのサンプルが出来上がりました!
▼生成されたJSON

{
  "reservationAnalysisDashboard": {
    "totalReservations": 150,
    "totalVisitors": 400,
    "comparisonWithLastMonth": {
      "percentageChange": 10.5,
      "difference": 15
    },
    "comparisonWithLastYear": {
      "percentageChange": 25.0,
      "difference": 30
    },
    "reservationSourceDetails": {
      "online": 90,
      "phone": 40,
      "walkIn": 20
    }
  }
}

簡略版のスキーマを利用しましたが、実際のスキーマでもいい感じのJSONのサンプルが作成できました。
型情報があるため、文字列や日付を入れたい項目にもきちんと期待通りの値が入っていました。

スキーマからJbuilderのコードを作成

食べログノートでは、Ruby on RailsのAPI開発時にJbuilderというJSONを生成するためのテンプレートエンジンを利用しています。

サンプルのレスポンスがいい感じに作成できたので、次はJbuilderのコードを作成しました。

▼最初の依頼で生成したコード

# app/views/reservations/reservation_analysis_dashboard.json.jbuilder
 
json.reservationAnalysisDashboard do
  json.totalReservations 150
  json.totalVisitors 400
 
  json.comparisonWithLastMonth do
    json.percentageChange 10.5
    json.difference 15
  end
 
  json.comparisonWithLastYear do
    json.percentageChange 25.0
    json.difference 30
  end
 
  json.reservationSourceDetails do
    json.online 90
    json.phone 40
    json.walkIn 20
  end
end

期待通りのレスポンスを返却するサンプルコードが作成できていました。

期待する形になるまでに、固定値から変数を利用した形に修正をしたり、変数がキャメルケースになっているためスネークケースに修正したりと数回やりとりをしました。
ほんの数分で大量の項目を扱うJbuilderが仕上がりました。

Jbuilderを自分で作成するとどれくらい時間がかかりそうだったか

一般的なタイピング速度は1分間に200〜300文字程度と言われています。

今回取り組んだダッシュボード画面用APIのJbuilderは、約13,000文字の大きなものでした。
※レンダリングで遅くならないようpartialを利用していないのでファイルの文字数が大きくなっています。

単純に文字を打つだけでも、1分間に200文字タイピングするとしたら65分はかかります。

実際はエディターの入力補助やコピペをして省略できることもありますが、コーディングする際に構造を考えたり、デバッグを行ったりする時間を考慮すると、さらに多くの時間がかかりそうです。

チャットボットだと数回のやり取りを実施し、10分程度で仕上げることができました。

分析画面では、ダッシュボード用のAPIを含めて10個のAPIの開発が必要でした。
同じようにチャットボットを活用することで効率的に進めることができました。

分析機能の集計ロジックもチャットボットで作成してみる

Jbuilderがいい感じに作成できたので、集計ロジックも同様に実装できないか試してみましたが、なかなか難しかったです。

分析画面では、毎回リアルタイムで集計をすると時間がかかってしまうため、既に実績が確定している予約の分析結果はデータベースに登録しています。
当月と未来分の予約はまだ変更が可能なため、リアルタイムで集計するようにしています。

複数の月を選択して集計する機能もあるため、作成済みの分析データを保持するテーブルと集計対象の予約のテーブルの定義を入力し、細かい条件を追加しながらの調整が必要でした。

期待通りの集計結果が得られるサンプルコードの作成はできましたが、自分で修正が必要な箇所が多くありました。
複雑な条件を入力し、生成するコードの調整をしていくことに時間がかかったので、ある程度イメージを固めるために利用していく方がいいのかなと感じました。

テストコードもチャットボットに頼ってみる

モデルに実装した集計結果を計算するメソッドのテストコードの実装にもチャットボットを使ってみました。
まずはテストケースを作成しました。

▼円グラフ用のサンプルテストケース
テストケースのスクリーンショット

エクセルにまとめたテストケースとメソッド名を入力し、テストコードを作成してみます。
チャットボットにRSpecの生成依頼をしたスクリーンショット

エクセルにまとめたテストケースの観点に沿って context と it が記述されていました。
後はテストの実行のために必要なテストデータの準備や軽微な修正で済みそうです。

▼チャットボットが生成したコード

# reservation_helper_spec.rb
require 'rails_helper'
 
RSpec.describe ReservationHelper, type: :helper do
  describe '#calculate_pie_chart_rate' do
    context 'ネット予約のみの場合' do
      it 'ネット予約が100%になっていること' do
        result = helper.calculate_pie_chart_rate(100, 0)
        expect(result[:online]).to eq(100.0)
        expect(result[:walk_in]).to eq(0.0)
      end
    end
 
    context 'ウォークインのみの場合' do
      it 'ウォークインが100%になっていること' do
        result = helper.calculate_pie_chart_rate(0, 100)
        expect(result[:online]).to eq(0.0)
        expect(result[:walk_in]).to eq(100.0)
      end
    end
 
    context 'ネット予約・ウォークインが両方ある場合' do
      it 'ネット予約、ウォークインの割合が正しく反映されていること' do
        result = helper.calculate_pie_chart_rate(50, 50)
        expect(result[:online]).to eq(50.0)
        expect(result[:walk_in]).to eq(50.0)
      end
    end
  end
end

チャットボットにテストコードの実行に必要な設定データも作成してもらえたら楽だなと思ったので、テーブル定義や factorybot の指定の仕方など細かい条件を指定してやり取りをしてみましたが、なかなか思うようにいかず、それっぽいけどなんか違うものが出来上がりました。

不要な箇所を消すことも面倒だったので、テスト実行に必要な条件が複雑な場合は、作成したテストケースに沿って context と it だけを書いてねと依頼をして枠組みだけを作るようにしました。

たまに誤字もありますが、全て自分で対応するよりずっと楽にテストコードが書けるようになりました。

まとめ

チャットボットを利用してみて、型に沿ってやればできる単純なことはとても効率化できるなと思いました。
複雑な条件の入力が必要な場合は、期待通りのアウトプットになるよう何度も調整が必要なので、やり方を工夫することが必要そうです。

今回はコード生成をメインに利用したので、今後はテーブル定義や業務知識をインプットして仕様の検討や設計でも活用してみたいです。

最後に

明日は先進技術を活用し、全社の業務生産性向上・サービス改善支援をしている 西本さん の「1000人超えの組織にDifyでチャットボットを導入した話と生成AIアプリで全社の効率化を進めている話」です。お楽しみに!