✂️

Geminiを使ったら、レシート表記のカバー率が20ポイント向上した話

2025/01/10に公開

はじめに

WED株式会社でMLエンジニアをしている catabon です。WEDでは、ユーザーの方々からレシートを買い取るアプリ「ONE」を開発運用しています。レシート画像からOCRによって文字列を取得し、それらをより有用な情報になるよう抽出・集積しています。その精度を向上させるために、新しい商品名からレシート表記をGeminiを用いて作成してみました。

レシート表記の生成

レシートに記載されている商品名は、正式な商品名より短縮されているものがほとんどです。現在我々が利用しているJANコード統合商品情報データベース(JICFS)には、正式な商品名に加えてレシート表記も(任意の項目ではありますが)登録されているのですが、レシート表記は店舗によって異なる場合もあります。また、プライベートブランドの商品など、データベース(JICFS)に記載されていない商品もあります。これらの商品については、正式な商品名はWebページなどに記載されていることもありますが、レシート表記に相当する表現は分かりません。チェーンによっては、正式な商品名の平均の長さ20.7文字に対してレシート表記の平均の長さが9.4文字と、半分以下に短くなる場合もあります:

#例えば
-クラフトスパイスソーダ 旬の彩り 缶 500ml
+クラフトSソーダ彩り5

-アルフォートミニチョコプレミアム宇治玉露 12個
+アルフォートミニ宇治玉

このようなデータでも先日紹介したようなベクトル検索である程度JANコードとの紐付けはできるのですが、正式名称とかなり字面が異なるレシート表記を精度良く把握するのはやはり難しい場合があります。この問題を軽減する方法として、正式な商品名から事前にレシート表記を自動生成することを考えました。生成する手法としては、単純に先頭または末尾の部分文字列を取る方法や、形態素解析などを用いて単語分割してその単語列を用いて短縮する方法が考えられますが、ここでは、Geminiを使ってレシート表記の候補を生成してもらうことを考えます。
Geminiは、ご存知の方も多いと思いますがGoogleが提供しているLLM:(大規模言語モデル)で、自然言語で指示することで、様々な作業を行わせることができます。自然言語文の指示だけでも結果を生成してくれますが、入力と出力の例をいくつか指示に追加することで(few-shot prompting)、更に出力の精度を高めることができます。ここでは、正式な商品名とそれに対応するレシート表記が分かっているペアをいくつか事前に与えることにしました。元々短い商品名もあるので、その場合にはそのまま出力するようにしました。

prompt = f"""
与えられた商品名を11文字以内に短くしてください。
レシートに商品を印刷するように、できるだけ11文字に近い文字列に変更してください。
与えられた商品名がすでに11文字以内の場合はそのままの文字列を出力してください。
入力は商品名のリストです。入力として与えられた個々の商品名に対し、
以下の例のように出力として短くした商品名とペアにしたリストをjson形式で出力してください。

<EXAMPLE>
  INPUT: "おむすび 手巻シーチキンマヨネーズ",”鶏つくね串", "クリスピーチキン(プレーン)", ...

  OUTPUT:
  [
      {"original": "おむすび 手巻シーチキンマヨネーズ",
       "shortened": "手巻シーチキンマヨネー"},
      {"original": "鶏つくね串",
       "shortened": "鶏つくね串"},
      {"original": "クリスピーチキン(プレーン)",
       "shortened": "クリスピープレー"},
      ...
  ]
  </EXAMPLE>
"""

ただ、生成された表記がそれらしく見えるとしても、それらが実際にレシートに現われるかどうかを確かめる必要があります。そのため、生成されたレシート画像からOCRされた文字列と照合して、それらが実際にレシートに現れるかどうかを調べました。

実験の概要

あるチェーンのプライベートブランド商品名1267個を対象にして、レシート表記を生成して評価します。レシート表記の生成には最初gemini-2.0-flash-expを用いてみたのですが、生成結果が安定しなかったので最終的にgemini-1.5-flash-002によるものを用いました。

正解例として、任意に抽出した40個の商品名に対してレシート表記を人手で調べたペアを入力に与えて、その例を含んだプロンプトを用いて対象のプライベートブランド商品に対しレシート表記を生成しました。比較のために、より単純な手法4つ(先頭11文字を取る、末尾11文字を取る、形態素解析後先頭11文字以内に収まる単語を取る、形態素解析後末尾11文字以内に収まる単語を取る)でもレシート表記を生成しました。形態素解析にはMeCabUniDicと共に用いました。

次に、これらのレシート表記が実際に存在するか、2024年12月の1ヶ月分のレシートデータに対し検索を行いました。その結果、1267個の商品名に対して、単純な手法4つを総合した結果得られた545個に加えて、Geminiによって新たに261個のレシート表記を取得できました。これにより、レシート表記のカバー率をGeminiを用いず単純な手法のみを用いた場合の43.0%(545/1267)から63.6%(806/1267)にまで向上させることができました。

手法 取得した表記数(手法間の重複あり) その手法単独で取得した表記数
短縮なし 219
先頭11文字 293 24
末尾11文字 248 5
先頭11文字(単語毎) 435 28
末尾11文字(単語毎) 412 25
Geminiによる生成 546 261
未取得 461
合計 1267

Geminiによって新たに取得できたレシート表記は、多くは係り受けの構造に沿って、複数ある修飾語句(の一部)を除いて被修飾語となる名詞を残すものでしたが、以下のように必ずしも文法にこだわらない短縮表記も取得できました。このような表記を作り出せるのは生成AIならではかもしれません。

正式名称 Geminiの出力(=実際のレシート表記)
豆パン(マーガリンサンド) 豆パンマーガリン
贅沢チョコプレッツェル 贅沢チョコプレ
香ばしく炒めたナポリタン 香ばしナポリタン

一方で、先の表に示したように、Geminiでもレシート表記を取得できなかった商品名も461個ありました。これらの多くは、以下に示すように短縮する際に助詞を除いて名詞の羅列にしたり、語順を前後させたり、また商品を区別できる最小限の文字列を残して切ったりなど、より複雑な操作が必要なものでした。これらに対応するには、更に正解例を増やしてGeminiに生成する表記の候補をより多く示す必要がありそうです。

正式名称 Geminiの出力 実際のレシート表記
オクラと長芋のネバネバサラダ ネバネバサラダ オクラ長芋ネバネバサラ
ポテトチップス堅揚げの絶品うすしお味 ポテトチップス堅揚げ 堅あげポテトうすしお味
トマトソースのミートボール トマトソースミート ミートボールトマトソ

おわりに

今回のGeminiを利用したタスクは比較的単純なものでしたが、それでもGeminiのようなLLMを用いた手法をタスクに組み入れる利点を感じることができました。生成AIの発展は昨今特に目覚しいものがありますし、今後も解決したいタスクに取り入れていきたいと考えています。

WED Engineering Blog

Discussion