開発部の國分です。
この記事は、先日公開した『「こんなのあったら便利かも」をすぐ形にできる、チャレンジラボ制度でレシピアプリを作ってみた』
の続編となります。
前回の記事では、我が社の「チャレンジラボ」制度を利用して、「冷蔵庫管理&レシピ提案アプリ」を作った経緯をご紹介しました。その記事の最後で「チームメンバーからフィードバックをもらってブラッシュアップする楽しさ」について触れましたが、実はこのアプリが抱えていた「写真をアップロードして解析結果が返ってくるまでが遅い」という課題について、社内のメンバーからこんなアドバイスをもらっていました。
「画像が大きいから遅いのでは? 送信前にリサイズしてみたら速くなるかも!」
「なるほど、API側の処理速度ばかり気にしていて、送るデータサイズを見落としていた・・・」と気づかされる的確なアドバイス!ということで、早速検証と実装を進めてみました。
結果としてアドバイス通り処理時間を大幅にカットできただけでなく、そこからさらに深掘りして「AIの思考時間」の調整、そして「速度の最適解だと思ったものが、実は精度とのトレードオフだった」という落とし穴まで発見したので、調べた結果を共有します。
※なお、使用モデルは gemini-3.1-pro-preview です。
※すべての計測は、条件を固めて順番に測ると外部要因(時間帯やサーバー負荷)の影響を受けやすいことが分かったため、各条件をランダムな順番で混ぜながら10回ずつ試行し、平均を取っています。
計測範囲について
※「Gemini呼び出し時間」= Laravel側で Http::post() を呼んでからレスポンスを受け取るまで(Google側の推論時間+Laravel⇄Google間の通信時間を含む)。本記事の数値は基本的にこれを指します。
※ユーザーが実際に体感する「ボタンを押してから結果が返るまで」の時間は、これに数十〜百数十ms程度(Canvasリサイズ処理・ブラウザ⇄Laravel間の通信)が上乗せされますが、秒単位の議論には影響しない程度の差でした。
まずはアドバイス通り画像リサイズを導入!
蓋に賞味期限がくっきりと印字されているプリンの写真をそのままAPIに投げると、1回の処理に約7.9秒かかっていました。
「リサイズ処理をどこに挟むか」を考えた結果、サーバーへの送信データそのものを減らして通信時間を削るため、フロントエンド(Vue.js / HTML5 Canvas)で送信前に縮小するアプローチを採用しました。
解像度ごとの速度比較(各10回試行の平均)
| 解像度 | ファイルサイズ | Gemini呼び出し時間(平均) | 変化率 |
|---|---|---|---|
| リサイズなし | 1,282.7 KB | 7,944.7 ms | ベースライン |
| 1200px | 353.6 KB | 6,156.5 ms | -22.5% |
| 800px | 170.9 KB | 5,352.2 ms | -32.6% |
| 400px | 51.5 KB | 5,093.5 ms | -35.9% |
→ 400pxまで縮小しても、賞味期限の数字は十分判読できるレベルを保っています。
アドバイス通り、7.9秒 → 5.1秒(約36%短縮)という成果が出ました!
データサイズが1,282.7KB→51.5KBに激減したことで、「ネットワーク通信にかかる待ち時間がごっそり削られたのだろう」と考えました。
意外な事実。Geminiの「Promptトークン」は変わっていない?
通信が速くなったのは間違いないですが、「Gemini API自体の処理も軽くなったのかな?」とレスポンスのトークン情報(usageMetadata)を覗いてみたところ、不思議な現象に気づきました。
なんと、リサイズ前とリサイズ後(400px)で、Geminiが受け取ったPrompt(入力)トークンの数が「1182」のまま変わっていなかったのです。画像を96%も軽くしたのに、Gemini側での処理負荷は完全に同じでした。
つまり、約2.8秒(7.9秒→5.1秒)も高速化できた正体は、APIの処理が速くなったわけではなく、純粋に「画像をGoogleのサーバーへ送信(アップロード)するのにかかっていたネットワーク通信時間がごっそり削られただけ」だと推測できました。
通信のボトルネックが解消されたのは大成功ですが、裏を返せば「Gemini API自体の処理時間はまだ全く削れていない」ということです。
「じゃあ画像側のトークンを直接コントロールできれば、もっと速くなるのでは?」と思い、Gemini 3の正式な画像トークン制御パラメータ media_resolution を low に指定して試してみました。
| 条件 | Promptトークン | Gemini呼び出し時間(平均) |
|---|---|---|
| 未指定 | 1,182 | 7,986.4 ms |
| media_resolution: low | 384(-67.5%) | 6,431.9 ms |
トークンを大幅に削った割には「そこまで速くならなかったな」というのが正直なところです。「画像トークンを単体で削るだけでは、劇的な速度改善には繋がらない」という結果になりました。
「では、時間は何に使われているのか?」と内訳をさらに分析してみます。
- Prompt(入力): 1182
- Thoughts(思考プロセス): 約400〜500(試行によりばらつき)
- candidates(最終結果): 30
こうなると、処理時間の大部分は画像そのものではなく、AIが裏側で考えている「Thoughts(思考トークン)」の生成時間が占めていたと推測しました。通信時間を削った今、さらに高速化を狙うなら「AIの思考時間(Thoughts)を削る」という2つ目のアプローチが見えてきました。
thinking_level も調整してダブルで高速化!
Gemini 3シリーズには、AIの思考量そのものをコントロールできる thinking_level というパラメータが存在します。これを low に設定し、リサイズと組み合わせてみました。
| ステップ | 実施した工夫 | Gemini呼び出し時間 | 削減率 |
|---|---|---|---|
| ベースライン | なし | 7,986.4 ms | - |
| 単体検証 | thinking_level: low のみ | 5,905.2 ms | -26.1% |
| 組み合わせ | リサイズ(400px) + thinking_level: low | 4,008.5 ms | -49.8% |
「通信量の削減」と「AI思考量の削減」が掛け合わさり、約8秒 → 約4秒(約50%カット)まで縮めることができました。
他の食品でも試してみた
「プリンの蓋のように、条件が良い画像だから成功したのではないか?」という疑問が残ります。実運用において賞味期限の読み取り失敗は致命的な問題になるため、印字の見え方が異なる難しい食品でも、この 400px + thinking_level: low が通用するか検証してみました。
| 食品 | 特徴 | 賞味期限の正答率 | Gemini呼び出し時間(平均) |
|---|---|---|---|
| 乳酸菌飲料のボトル | 曲面に直接印字、背景の文字も紛らわしい | 100%(10/10) | 4,637.1 ms |
| 卵パック | 透明な樹脂パック越しの反射・グレアあり | 90%(9/10) | 5,001.9 ms |
→ 曲面のボトルに直接印字されています。
→ 透明な樹脂パック越しに撮影しているため、もともとピントが合いにくく、印字の輪郭が甘くなりやすかったです。
曲面や反射といった「見た目の難しさ」があっても、この設定なら精度・速度ともにおおむね安定していることが確認できました。プリンの検証(50回近く)も含め、実用には十分なパフォーマンスです。
「全部乗せ」の落とし穴と、精度とのトレードオフ
もう一段速くならないかと欲を出し、ここに media_resolution: low まで足してみたところ、思わぬ落とし穴がありました。
プリンでは 3,738.9ms(-53.2%)とさらに速くなったのですが、先ほど9割正解できていた「卵パックの画像」で事情が一変したのです。
| 設定(卵パック) | 賞味期限の正答率 | Gemini呼び出し時間(平均) | thoughtsトークン(平均) |
|---|---|---|---|
| リサイズ(400px) + thinking_level: low | 90%(9/10) | 5,001.9 ms | 349.2 |
| さらに media_resolution を追加 | 30%(3/10) | 6,285.5 ms(悪化) | 475.7(増加) |
media_resolution: low を足すと、正答率が90% → 30%まで急落し、しかも処理時間はむしろ悪化してしまいました。
原因は thoughts トークンの増加(349.2 → 475.7)に表れています。media_resolution: low は画像の情報量そのものを削るパラメータなので、もともと反射やグレアで読みにくい画像だと、情報がさらに不足してAIが判断に迷い、長く考えた末に間違えるという悪循環が起きていたようです。
プリンのように情報に余裕がある画像では実害が出ませんでしたが、卵パックのように情報がギリギリの画像では逆効果になる、ということです。
おわりに
チームメンバーからの「画像をリサイズしてみたら?」という一言のおかげで、まずは通信時間を大幅に短縮することができました。
さらに、そのアドバイスを起点に検証を深めたことで、「リサイズしてもAPI側のトークンは同じ」「本当のボトルネックは思考時間」という面白い事実に気づき、「リサイズ+thinking_level: low」で約50%の高速化を実現できました。
ただ、そこで欲を出して「もう一段速くならないか」と media_resolution: low まで足してみたところ、プリンでは効果があったものの、印字が読みにくい別の画像では精度が90% → 30%まで落ち、しかも速度も悪化するという、良いことが何もない結果に遭遇しました。
もし「プリンで一番速かったから」という理由だけでこの設定を採用していたら、実運用では誤読を量産していたかもしれません。1枚の画像だけで判断せず、複数の画像で検証し直したからこそ気づけた落とし穴でした。
一つのアドバイスをきっかけに検証を重ねるうちに、速度の最適解を見つけたと思ったら、実はそれが精度とのトレードオフだったという、一筋縄ではいかない発見にたどり着けたのは、今回とても面白い経験でした。
チャレンジラボは「一人で技術を触って終わり」ではなく、こうやってチームからのフィードバックを起点に、みんなで深掘りし、時には自分の仮説が覆されるところまで検証し尽くせる場になっているのが、うちの会社の良いところだと改めて感じています。
もし私たちのカルチャーや開発環境に少しでも興味を持っていただけたら、ぜひ採用ページをのぞいてみてください。
https://www.key-p.com/recruit/


