Gemini API の請求額、先月と比べてじわじわ上がっていませんか。
LLMをプロダクトに組み込んだ直後は「自動化最高!」と盛り上がるんですが、ユーザーが増えるほどAPIコストも比例して膨らんでいく。動いてるから触りたくない。でも請求書は毎月届く。 あの微妙な緊張感、薄々気づいているけど見て見ぬふりしていませんか。
ある採用管理システムで Gemini 2.5 Flash を使っていたとき、まさにその状態でした。そこで gemini-3.1-flash-lite-preview に切り替えたところ、出力コスト40%削減、応答速度2.5倍。しかも変更は実質15分で終わりました。
この記事では、モデル選定の判断軸から実際のコード変更まで、やったことをそのまま共有します。
前提:どんなシステムで使っていたか
以前の記事で紹介した採用管理ダッシュボードの話です。Cistree社向けに開発したこのシステムでは、Gemini API を4つの機能で使っています。
| AI機能 | やっていること | 呼び出し頻度 |
|---|---|---|
| テキスト抽出 | 履歴書・職務経歴書のPDF/Wordからテキストを取り出す | 候補者登録ごと |
| 書類選考 | 経歴サマリ・定量スコア・合否推奨を自動生成 | 候補者ごと |
| 合否判断支援 | 面接情報から合否判断の推奨と理由を生成 | 面接ステージごと |
| 連絡文案生成 | 候補者・エージェントへの連絡テンプレートを生成 | 都度 |
全部 gemini-2.5-flash で動かしていました。動くには動く。精度も十分。でも...
「このモデル、オーバースペックでは?」
ある日、APIのレスポンスタイムを眺めていて気づいたんです。書類選考のスコアリング、1リクエストあたり3〜5秒かかっている。採用担当者は候補者一覧を開いて「AIスクリーニング実行」ボタンを押すわけですが、5秒って体感だと結構長い(スマホの3秒ルールを思い出してください)。
そして料金表を見直すと、2.5 Flash は高性能な分、出力トークンの単価もそれなりにかかる。
ここで考えたのが、「このタスクに2.5 Flashの推論能力は本当に必要か?」 という問い。
タスクの性質を分解してみた
テキスト抽出 → 推論不要。パターンマッチ寄り
書類選考 → 構造化JSON出力。定型的な評価軸
合否判断支援 → 文脈理解は必要だが、創造性は不要
連絡文案生成 → テンプレート的な文章生成
どれも 「賢さ」より「速さと安さ」が求められるタスクでした。2.5 Flash の高い推論能力は、数学の証明問題や複雑なコード生成には強いけど、定型的なJSON出力には正直もったいない(高級レストランでカップ麺を食べてる感じ)。
モデル選定:3つの軸で比較
Gemini のモデルラインナップを改めて整理してみました。
| 比較軸 | gemini-2.5-flash | gemini-3.1-flash-lite-preview |
|---|---|---|
| 出力コスト | ベースライン | 約40%安い |
| 応答速度 | 標準 | 約2.5倍速い |
| 推論能力 | 高い(思考モデル) | 標準(軽量モデル) |
| 構造化出力 | 対応 | 対応 |
| マルチモーダル | 対応 | 対応 |
選定の決め手はもうひとつあります。ちょうど Gemini 3.1 ファミリーがリリースされた直後で、上位モデルの 3.1 Pro がベンチマークでかなり好成績を出していた。「Pro がこれだけ強いなら、同世代の Lite も基礎能力が底上げされているはず」——この読みが移行を後押ししました。
ポイントはトレードオフの見極めです。
4機能すべてが「高度な推論は不要、構造化出力で十分」に該当した。ここまで分析して、移行しない理由がなくなったわけです。
移行の実際:変更したのは1行だけ
大げさなリファクタリングは不要でした。gemini.ts の4箇所で、モデル名を書き換えるだけ。
// Before
const model = genAI.getGenerativeModel({
model: "gemini-2.5-flash",
});
// After
const model = genAI.getGenerativeModel({
model: "gemini-3.1-flash-lite-preview",
});
「え、それだけ?」って思いますよね。それだけです。 プロンプトの変更なし、バリデーションロジックの変更なし、レスポンス形式の変更なし。
なぜスムーズだったのか
これには理由があります。設計段階で以下をやっていたから。
- Zodによる出力バリデーション: AIの出力を
screeningResultSchema.safeParse()で検証していた。モデルが変わっても、期待するJSON構造が返ってくれば問題なし - プロンプトの明示性: 「以下のJSON形式で回答してください」と構造を明示していたので、モデルの推論能力に依存していなかった
- エラーハンドリング: パース失敗時に再試行を促すメッセージを出す設計になっていた
つまり、モデルに依存しないアーキテクチャを(たまたま)作っていたんです。結果論ですが、AIを組み込むときの設計原則として覚えておく価値はあります。
移行前後の比較
定量的な成果
| 指標 | Before(2.5 Flash) | After(Flash Lite) | 改善 |
|---|---|---|---|
| 出力トークン単価 | ベースライン | 40%削減 | コスト減 |
| 書類選考の応答時間 | 3〜5秒 | 1〜2秒 | 約2.5倍速 |
| テキスト抽出の応答時間 | 2〜3秒 | 1秒未満 | 体感激変 |
| 書類選考の精度 | 実用十分 | 実用十分 | 変化なし |
| 移行にかかった時間 | — | 約15分 | — |
15分の作業で月々のAPI費用が40%減る。ROIで考えたら、コーヒーを淹れるより効率が良い。
品質への影響
一番気になるのは「安くなった分、精度が落ちたのでは?」というところ。
結論:このユースケースでは品質低下は確認されませんでした。
書類選考のスコアリング結果を移行前後で比較してみると、同じ候補者に対してほぼ同じ評価が返ってきます。理由は明確で、タスクが「決まった評価軸に沿ってJSONを出力する」という構造化タスクだから。Flash Lite でも十分にこなせる処理だったわけです。
ただし、これは「このタスクでは」という条件付きです。複雑な推論が必要なタスク(例えば、候補者の経歴から将来のキャリアパスを予測する、みたいな)では、モデルの能力差が出るかもしれません。
LLMモデル選定の判断フレームワーク
今回の経験を一般化すると、こんなフレームワークになります。
1. タスクの「知性レベル」を分類する
| レベル | タスク例 | 適するモデル |
|---|---|---|
| 抽出・変換 | テキスト抽出、フォーマット変換 | 軽量モデル |
| 分類・スコアリング | 感情分析、カテゴリ分類 | 軽量〜中量モデル |
| 要約・生成 | 文章要約、テンプレ文生成 | 中量モデル |
| 推論・分析 | 複雑な判断、コード生成 | 高性能モデル |
2. 「最小十分モデル」を選ぶ
必要十分な能力のモデルを選ぶ。「念のため高性能モデル」は、保険料としてのAPI費用を毎月払い続けることになります。
3. 移行可能な設計にしておく
- 出力をスキーマで検証する(Zodなど)
- プロンプトでフォーマットを明示する
- モデル名を設定ファイルや環境変数で管理する(今回はハードコードでしたが...)
注意点と学び
preview モデルのリスク
gemini-3.1-flash-lite-preview は名前の通りプレビュー版です。GA(一般提供)になるタイミングでモデル名が変わる可能性があります。本番環境で使う場合は、モデル名の変更に追従できる仕組み(環境変数化など)を入れておくのが安全です。
全タスク一律移行は危険
今回は4機能すべてを移行しましたが、それは全タスクが「軽量モデルで十分」だったから。タスクごとに判断するのが原則です。「書類選考はFlash Lite、キャリア分析は2.5 Flash」という使い分けも全然アリ。
計測してから判断する
「たぶん大丈夫」で移行するのではなく、同じ入力に対して両モデルの出力を比較してから判断しましょう。私たちも実際の候補者データ(もちろん匿名化済み)で比較検証してから本番に切り替えました。
まとめ
LLM APIのコスト最適化は、モデルを下げるのではなく、タスクに合ったモデルを選ぶという発想の転換です。
今回の Gemini 2.5 Flash → 3.1 Flash Lite 移行では、出力コスト40%削減・応答速度2.5倍という成果を、わずか15分の作業で実現できました。タスクの性質を見極めて「最小十分モデル」を選ぶ。AIをプロダクトに組み込む上で、地味だけど確実に効くプラクティスです。



