Tabelog Tech Blog

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

工数6割削減! 生成AIとOCRを組み合わせ、店舗毎に形式が異なるレストランメニューを読み取らせてみた

目次

1. はじめに

初めまして。食べログ開発本部 技術部のデータサイエンスチームに所属する河村です。
データサイエンスチームは、データとAIを活用してビジネス成長に貢献することをミッションとしており、生成AI技術の事業活用や業務活用に取り組んでいます。

今回の活動では、レストランメニューのデータ入稿業務の効率化を行い作業工数を6割削減することに成功しました。 効率化のポイントとしては、OCR技術の活用やUIの徹底的な作り込みなど、生成AIの範囲にとどまらず、幅広い技術を総動員して一つのツールを作り上げたことにあると考えています。

本ブログでは、この活動の内容と、成功の要因となったポイントについてご紹介できればと思います。

2. プロジェクトの内容と成果

2.1. メニュー入稿業務の説明

食べログをご利用いただいたことがある方であれば、食べログの飲食店ページの中にメニュー画面があることをご存知の方も多いのではないでしょうか。料理名と価格が一覧表示されている画面です。

食べログでは、飲食店様からご依頼をいただいた場合、飲食店ページを作成する支援作業を行なっています。メニュー画面もその対象となっており、飲食店様からメニューの写真などのデータをいただき、それをもとに入稿作業を行っています。
実際にどのように作業しているのかというと、いただいた写真を見ながら一つ一つ料理名と価格を登録しています。手作業で入力していますのでかなりの時間がかかっていました。

より詳細に分析すると、作業工程としては、準備作業、文字起こし作業、確認作業の3工程です。

入稿作業の作業工程

やはり時間がかかっているのは文字起こし作業で、工数削減という意味ではここにフォーカスを当てる必要がありそうです。
一方で、確認作業に多くの時間を費やしていることが判明しました。 ここで入力した内容が食べログの画面に表示されるわけですから、間違いは許されません。 当然と言えば当然かもしれませんが、一つ一つ指差し確認するという作業を慎重かつ丁寧に行っています。   

2.2. 作業効率化のためのツール開発

これらの状況を踏まえ、作業効率化のためのツール開発に取り組みました。

生成AIの文字認識能力を活用しようと考えましたが、生成AIのクオリティは100%には程遠い状況でした。 前述した通り、食べログ画面に表示される内容ですので、100%のクオリティが必須です。 このため、確認・修正作業を支援する機能が必須であると考えました。
しかし、その際に問題となったのは、生成AIが出力した料理名や価格の元となる情報が、画像内のどこにあるのかわからない事でした。

そこで目をつけたのがOCR技術です。
OCR技術とは、画像内の文字情報を読み取る技術ですが、読み取った文字の位置情報も取得できます。 生成AIにメニュー情報を抽出させる際に、OCRの結果とのマッピング作業も併せて行わせることで、生成AIのアウトプットが画像内のどの位置にあるかを特定できるようになりました。

この抽出処理の詳細については、3章にて詳細に説明します。
まずは開発したツールをご覧いただければと思います。

youtu.be

  • Point1. 入力作業はAIが担当し、確認作業を人が実施
    このツールの画面構成は、右側に飲食店様からいただいたメニュー画像が表示されています。 左側に最終的に出力するためのデータを格納するための入力フォームが配置されており、長めのフィールドが料理名、短めのフィールドが価格入力欄です。
    見ていただきたいのは真ん中のエリアですが、この入力フォームへのデータ入力はすべて生成AIが行っています。 その生成AIが入力したデータを順次、確認・修正し、確定(左のパネルに移す)作業を行うのが人の作業となります。
  • Point2. 人による確認・修正作業を徹底的に支援
    このツールでは確認作業、修正作業を少しでも効率的に作業できるように色々工夫をしています。生成AIとOCRを組み合わせる事で、 場所が特定できる様になりましたので、これをフル活用して下記の機能を開発しました。
    • 確認対象となるメニューにフォーカスをあてると、画像内の該当箇所が黄色くなるハイライト機能
    • 一番左のエリアにあるものは、画像内の該当箇所を赤く塗りつぶす消し込み機能
    • OCRで取得した文字情報をマウス操作のみで活用できる入力支援機能

AIが高速に入力し、人がしっかりと確認するという 「AIと人間それぞれの強みを活かし、お互いを補完するツール」が開発できました。

2.3. 成果

ツール導入前とツール導入後の、作業時間を分析した図が下記となります。
作業時間を6割削減することに成功しました。

ツールの効果分析

さらに詳細に分析してみます。
ツールの使用前後で、必ずしも同じ作業にはならないため少し補正をしています。 準備作業は台形補正などツール固有の作業があり、少し時間が増えています。 また、ツール使用後の修正作業と確認作業は、メニューごとに順番に進める方が多く、明確に工程が分けられなくなってしまったのですが、"確認作業の時間はツール使用前と同じ時間がかかる"という前提を置いて、修正作業の時間を算出しています。
このような前提のもとで計算した結果、文字起こし作業にかかっていた時間は、約1/5の修正時間に短縮ができました。

また、参考データとして、AIの得意な形式である横書きのメニューに絞った場合のグラフも載せています。 この場合、全体としては7割削減、文字起こし部分については約1/9の時間短縮ができました。
現状は、縦書きなど苦手なフォーマットの場合に修正作業が多く必要となってしまっており、平均値を悪化させています。 もし今後、AIの精度が上がれば、全体の平均時間が参考データと同じぐらいまで改善できる余地はあると考えています。

いかがでしょうか。アウトプット品質を担保したまま大幅な工数削減を実現できました。

3. メニュー抽出処理の詳細

この章ではメニュー抽出作業の実装についてより深掘りして説明します。

メニュー抽出処理の概要

メニュー抽出作業は上の図の様な流れで行われますが、この中の下記の5つの要素について詳細に説明します。

  • 3.1. OCR技術
  • 3.2. 生成AIとOCRを用いたメニューデータ抽出方法
  • 3.3. ストリーミング対応
  • 3.4. 斜め画像への対応
  • 3.5. メニュー画像タイプごとの抽出精度

3.1. OCR技術

OCR技術というと、画像から文字情報を読み取る技術であると言うことはよく知られていますが、読み取った文字の位置情報も得られることをご存知の方は少ないのではないでしょうか。
今回、Google社のDocument AIのOCR機能を利用しているのですが、Block,Paragraph,Line,Tokenと言う複数の単位で文字列と座標情報が得られます。
今回はTokenの文字・位置情報を活用しているのですが、これは日本語の場合数文字程度に区切られたデータで、料理名と一致するものではありません。 例えば「唐揚げ定食」は「唐」「揚げ」「定食」という3つのTokenで構成されています。 今回必要な情報は料理名ですので、これらを適切に組み合わせる必要があるのですが、その作業を生成AIに任せています。

Google以外のOCR技術としては、Azure AI Document Intelligenceも良さそうです。 特徴的な機能としてOCRした結果をMarkdown形式に構造化して出力する機能があります。生成AIとの親和性も高いです。
メニューデータを構造化してくれるのではと思い試してみたのですが、メニュー画像のレイアウトは様々なため、構造化した結果も表形式になったり箇条書きになったりとバラバラになってしまいました。 このため、今回の用途では利用できませんでした。

3.2. 生成AIとOCRを組み合わせたメニューデータ抽出方法

生成AIとOCRを組み合わせてデータを抽出する際に、生成AIにどういう依頼をしているのかをサンプルデータなども用いて説明します。
ポイントとしては、画像からメニューを抽出させる際に、抽出した料理名や価格がどのOCRデータの文字列を用いて構成されているかという情報を、IDの配列という形で返却させていることです。

ツールの効果分析

少し複雑な依頼となるため、うまくいくかどうか不安でしたが、やってみるとある程度正確なデータが返却されることがわかりました。 正確でないケースとして、同じ文字列が複数箇所にある場合に、別の場所のIDを返してしまうケースがありました。ハイライトする場所がずれてしまうのですが、頻度としてあまり高くないことと、確認作業に不都合ではあるものの致命的なエラーではないため、そのまま本番運用しています。

実は、プロジェクト開始当初は生成AIの文字認識精度が低かったこともあり、 上記の様に画像とOCRデータを渡すのではなく、OCRデータのみを渡す形で検証を進めていました。 この方式の場合、先ほど述べた様な料理名とハイライトがずれることは全くありませんでした。
しかしこのOCRデータのみを渡す方式では、グループ名をメニューと解釈して価格をつけてしまうことがあるという課題がありました。 これは実はかなり大きな課題で、下の図の様にメニューと価格が全部ずれてしまうことがあり、全メニューの修正が必要となるため、大きな課題となっていました。

OCRと画像の組み合わせによる効果

ちょうどこの課題で悩んでいる時にGPT-4oがリリースされ、上の図で説明した画像とOCRデータの両方を生成AIに渡す形の検証を行ったのですが、文字列だけでなく、色やサイズなどの情報も用いて判断している様で、グループ名と料理名の判別精度が格段に上がり、この課題が解消されました。

先ほど、OCRと画像を組み合わせた場合にハイライトがずれるケースがあるとお話ししましたが、ハイライトがずれるデメリットより、グループ名と料理名がうまく判別できるメリットの方が断然大きかったため、OCRと画像を組み合わせる方式を採用しています。

3.3. ストリーミング対応

今回のメニュー画像読み込みでは、メニュー画像1画面分を抽出する処理を行うと、数分以上かかってしまいます。 作業者に処理完了まで待ってもらうとなると、かなりのタイムロスです。

生成AIはほとんどのモデルでストリーミング出力が可能です。 ストリーミング出力を利用し、取得できた内容を順次画面表示すると、部分的ではあるものの読み始めることができるため、体感速度としてはものすごく早くなります。
今回も同様に、処理できたメニューから順次表示できれば、その分の確認作業を始められるため、実質的な待ち時間をゼロにできるのではと考えました。

ただ、今回は生成AIの戻り値はJSON形式ですので、これをストリーミングで処理するのはかなり大変です。 XMLにおけるSAXライブラリの様な、ストリームを読み込みながらイベント駆動で処理が実行できるライブラリを探してみたところ、@streamparser/jsonというパッケージがあり、これを利用しています。 ストリームパーサのパッケージはいくつかあったのですが、フロントエンド側で動作可能なものは少なく、私が探した限りはこのライブラリしか見つけられませんでした。

このライブラリでは、JSON形式のkey=value形式のvalueが確定したタイミングと、配列の一要素分のオブジェクトが確定したタイミングの2つのタイミングでイベントを発生してくれます。今回はメニューデータを配列で返却する形にしていましたので、後者のイベントを活用して、メニューデータが一つ確定するごとにその画面に追加するという処理を実装しています。

ストリーミング対応のイメージ

今回の様に、生成AIをシステムの一部に組み込むような使い方は今後増えると思います。 JSON形式のアウトプットをストリーミング処理する技術は、今後必須であると言えるかもしれません。

3.4. 斜め画像への対応

メニュー画像が綺麗に真っ直ぐ撮られておらず斜めになっている場合、OCRやAIの精度がかなり落ちてしまいます。 実際に運用を始めたところ、このようなケースは少なくないことがわかり、何らかの対応が必要でした。
このために、アプリ内に台形補正機能を実装することを考えたのですが、JavaScriptは遅いという先入観があり、実運用に耐える速度が出せるかどうかが懸念でした。 そんな中、glfx.jsというライブラリを使って実装したのですが、このライブラリは裏でGPUを活用しており、マウス操作に合わせてリアルタイムで変換できるUIが作れてしまいました。今時のフロントエンドはこんなこともできるのかと正直びっくりしました。

外部ツールを使って変換してもらう事も考えていたのですが、同一ツール内で完結することで無駄な工数もかからず、操作性も良かったため、好評でした。

ツール内に作成した台形補正機能

3.5. メニュー画像タイプごとの抽出精度

開発を行い様々な画像を用いて試した結果、メニュー画像のタイプごとにかなり得意不得意があることがわかりました。

画像タイプごとの抽出精度

横書きで料理名と価格が整然と並んでいる様なメニュー画像の場合は、かなり精度高く抽出でき、場合によっては修正不要というケースもあるのですが、他のタイプにおいては、なんらか修正が発生してしまうのが現状です。 どれぐらい修正が発生するかはメニュー画像ごとにばらばらであるため、数値化しにくいのですが、傾向としてまとめてみました。

また、Claude 3.5 Sonnetについて検証したところ、縦書きの精度がGPT-4oより高い結果が出ました。 生成AIのモデルによっても精度の差がかなりあります。今後、新しいモデルを採用したら劇的に改善するということもあるかもしれません。

4. 成功の要因となったポイント

ここでは、プロジェクト全体を振り返ってみて、成功の要因と言える重要なポイントを整理してみます。

  • 4.1. 生成AI領域だけでなく、幅広く解決案を模索したこと。
  • 4.2. 作業効率化に直結するUIは徹底的な作り込みを実施したこと。
  • 4.3. 最新動向を常にウォッチし、柔軟な方針転換ができたこと。
  • 4.4. 作業の完全自動化を目指さなかったこと。

4.1. 生成AI領域だけでなく、幅広く解決案を模索したこと。

前章にて説明した通り、今回実装したメニュー抽出処理は生成AIとOCR機能を組み合わせる事で実現しています。 今回のポイントとなったハイライト機能や消し込み機能はこのアイディアがなければ実現できませんでした。

偶然ですが、私が以前にOCRを使った開発を行ったことがあったため、その様なアイディアが思いついたのですが、 生成AIに限らず、広い視野・知見をもって解決案を模索したことが、本プロジェクト最大の成功要因だったと言えます。

4.2. 作業効率化に直結するUIは徹底的な作り込みを実施したこと。

ユーザビリティについては徹底的にこだわりました。

今回Webシステムで構築していますが、Next.jsを用いて実装しており、クライアントアプリに近い作り込みを行なっています。 検証過程で使ってみて感じた改善要望は要望一覧というシートで管理していましたが、3ヶ月で100以上にもなりました。
想定以上にソートが必要となるケースが多く、ドラッグ&ドロップでできるソート機能を作成したり、3章で述べた台形補正機能やストリーミング対応も、ユーザからの要望をもとに実装した機能です。

ユーザと連携を密にしつつ、どうすれば工数削減につながるかを考えながら徹底的に作り込みを行い、生産性を向上しました。

4.3. 最新動向を常にウォッチし、柔軟な方針転換ができたこと。

3章で述べた内容となりますが、プロジェクト開始当初は、生成AIの文字認識機能は使わず、OCRのみを利用して行っていたのですが、GPT-4oがリリースされたタイミングで、方針転換を行い、大きな改善が実現できました。

また、これも3章で述べた内容となりますが、 GPT-4oで本番運用を開始したところ、縦書きメニューの認識精度が弱く、工数削減の足枷になっているという課題がありました。 Anthropic社のClaude 3.5 Sonnetがリリースされたタイミングで評価を行ったのですが、偶然、縦書きの認識性能が高いことが判明し、現在はこのモデルを利用してます。

生成AIは動きが早く、新しいモデルや、機能がどんどん出てきます。 課題を最新モデルが解決してくれるということも多いので、常に動きをキャッチアップし、必要であれば方針転換する柔軟性が必要です。

4.4. 作業の完全自動化を目指さなかったこと。

「生成AIを用いることで、人による作業を全て無くそう。」というような、AIによる作業の完全自動化を目標にしたいケースもあると思います。 しかし、既存業務にAI適用する場合は、完全自動化は目指さない方がよいです。

一般に業務というと、「全てのケースで合格点が必要」という場合が多いです。 今回においても、全ての飲食店の全てのメニュー正しく入力する必要があります。 しかし、生成AIのアウトプットはばらつきが大きく、最低点のコントロールがしづらいため、どうしてもたまにNGなアウトプットが出てしまいます。
稀に発生するNGケースがどうしても消せないために、生成AIの適用自体もNGとなる。 と言うような事態になりかねません。

今回は、文字入力を生成AIに処理させ、確認作業は人が行う形としており、その確認作業をいかに効率よく行うかに注力してツールを開発しました。 このため、生成AIのアウトプットがNGな場合も合格点が出せています。
既存業務に生成AIを適用する場合は、生成AIのアウトプットを最終アウトプットとするのではなく、人が介在できる箇所を残す方が現実的です。

生成AIを業務に適用する際の課題

5. 生成AIを業務活用する鍵はフルスタックエンジニアにあり

前章の内容を振り返りながら、生成AIを業務に活用する重要なポイントについて考えてみました。

生成AIの活用方法を考えるにあたり、生成AIエンジニア(のみ)が担当する。で十分でしょうか? 今回のプロジェクトを振り返って、成功ポイントをいくつか上げてみましたが、そのほとんどが生成AIエンジニアと呼ばれる人の担当範囲ではないと思います。

これまで、生成AIの活用というと、チャットシステムを構築してプロンプトを工夫する。 という活用方法が多かったと感じますが、生成AIの活用対象は、チャットシステムにとどまらず、ありとあらゆる領域に広がっています。 活用方法は全くの未知数で、成功例もノウハウもなく、試行錯誤しながら道を切り開いていく必要があります。 これは、ビジネスで例えるなら0→1フェーズのスタートアップと言えます。

この0→1フェーズというのは、幅広い対応ができるゼネラリストが力を発揮できるフェーズです。 生成AIの活用方法の模索においても、幅広く解決案を模索できるゼネラリストが活躍できるフェーズであると言えます。 今回のプロジェクトは、アイディア出しから課題解決方法の検討まで「何でも屋」の形で推進しましたが、いろいろなことが爆速で進められました。

生成AIを用いた業務革新を、生成AIエンジニアのみに任せていないでしょうか。 フルスタックエンジニアを加えてみると、全く異なるソリューションが爆速で誕生する。かもしれません。

6. 食べログの未来を一緒に変えてくれる人募集中!

少し私自身についてもお話しさせてください。
私は今年の2月に入社し、データサイエンス部に所属しております。 カカクコム入社前はSIerとスタートアップの2社の経験があります。 スタートアップの時はフルスタックエンジニアで、小さめのシステムは一人で作り切っていました。
実はデータサイエンス分野の経歴はないのですが、新しい技術に取り組むことが好きで、生成AIについてもかなり早いタイミングから触り始めていました。 ビジネスへの活用も始めており、そのような姿勢、経験が今回、活かせたのかなと思います。

食べログはChatGPTのプラグイン開発を国内最速で行うなど、生成AIを活用していこうという意識はかなり高いです。 実際、生成AIを活用したさまざまなPoCが進んでいますし、食べログがどんどん変わっていくとても面白いタイミングです。 生成AIを用いて食べログの未来を変えていける人を募集しています。一緒に食べログを変えていきましょう!