ローカルLLM (Ollama) を活用した、APIコストを抑えるプロンプト開発ワークフローと運用の勘所
はじめに
SecureNaviでFit&Gapと2線の匠クラウドの開発エンジニアとして業務を行っているKandaです。
最近はプロダクトにLLM(大規模言語モデル)を組み込む機会が増えています。
一方で、LLM機能を開発するフェーズのボトルネックの1つが、APIコスト(=試行回数に比例して増える課金)です。
本記事では、この課題に対してローカルの開発環境でLLMを動かせるOllamaを導入し、プロンプトの変更などを含めたアプリケーション開発における試行錯誤を、課金を気にせず回せる状態にした所感や学びをまとめます。
LLMを使った機能開発で詰まりやすい点
LLMを使った機能開発では、実装だけでなく、システムプロンプトやユーザプロンプトの調整に時間を使うことがあります。
例えば以下のような点を確認するには、細かなプロンプトの表現を変えながら何度もLLMを呼び出して期待値の調整を行う必要があります。
- 期待するデータ構造(JSONなど)で返ってくるか
- ユーザプロンプトの文脈を正しく汲み取れているか
- 制約(禁止事項・形式・トーンなど)にきちんと従うか
- 例外ケース(入力が短い、曖昧、攻撃的など)で破綻しないか
GeminiやOpenAI、Azure OpenAIなどのAPIでこの試行回数を増やしていくと、1回あたりは少額でも、数百〜数千回と繰り返すうちに課金が積み上がります。
その結果、APIの使用コストに関心が向き、開発者体験に悪影響を与える可能性があります。
Azure OpenAIの料金の例
Azure OpenAIを利用する場合、基本的にはトークン量に応じた従量課金になります。
詳細は下記の公式ページを参照してください。
一例として、公式ページに掲載されている価格表の形式に合わせて例を載せます。
| モデル | 価格 (100 万トークン) |
|---|---|
| GPT-5.1 Global | 入力: ¥194.94 |
| キャッシュされた入力: ¥19.50 | |
| 出力: ¥1,559.51 |
トークン課金は使った分だけでAPIコールの回数の従量課金よりも安心感はありますが、ちょっとした改修で気軽に回す用途で使用するには心理的負担になりやすいと感じました。
他にも、Azure OpenAI Batchを利用してコストを抑える選択肢もあります。
ただし一括実行が前提になるため、用途によっては合わないケースもあります。
ローカル開発でOllamaを選んだ理由
そこで、ローカル環境でLLMを動かせるOllamaを採用し、検証フェーズをAPIの費用をかけずに実験・開発ができる運用にしました。
Ollamaの詳細は公式サイトにてご確認ください。
ローカルで実行する目的は、プロンプトの試行回数を増やしても課金が増えないところでした。
🦙Ollamaのセットアップ🦙
brewを経由してインストールします。
brew install ollama
下記コマンドでOllamaが起動します。
ollama serve
上記の状態で、ヘルプは以下のように確認できます。
ollama -h
モデルのダウンロードは次のように行います。
ollama pull llama3
Ollamaへのリクエスト例
OllamaへのリクエストはHTTPで実行できます(指定がなければポートは11434)。
curl http://localhost:11434/api/chat -d '{
"model": "llama3",
"messages": [
{"role": "system", "content": "日本語で、1文で回答してください"},
{"role": "user", "content": "日本の首都は?"}
],
"stream": false
}'
返ってくるレスポンスは概ね次の形式です(見やすさのため一部省略しています)。
{
"model": "llama3",
"created_at": "2026-01-20T08:58:46.843566Z",
"message": {
"role": "assistant",
"content": "日本の首都は東京です。"
},
"done": true
}
使い分けの前提
本記事の前提として、次のような使い分けを想定していました。
- 開発・検証(プロンプトの試行錯誤、仕様の探索):Ollamaでローカル実行
- 本番運用(ユーザ向け機能として提供):GCP/Azure/OpenAIなどのAPIを利用
ローカルである程度形を作ってから本番APIに寄せることで、課金を抑えて検証ができる運用を考えました。
開発環境スペック
今回の検証に使用した端末はM3のMacBook Proです。
軽量モデルの限界
最初に躓いたのはモデル選定でした。
実行速度を優先して軽量モデルを試しましたが、次のような課題に直面しました。
- 回答の不安定さ:プロンプトを無視して、文脈が崩れることがある、文脈が支離滅裂になる
- 出力の非一貫性:同じプロンプトでも結果がぶれる
- 指示追従性の低さ:複雑な制約を与えると、一部を無視することがある
プロダクトに組み込む機能を想定して検証する場合、軽量モデルは動作確認には便利でも、プロンプトの微調整には不十分に感じる場面がありました。
そのため、ローカル検証でもある程度パラメータ数の大きいモデルを選ぶ必要がありました。
ローカル検証から本番APIへ切り替えたときに起きたこと
ローカルで調整したプロンプトを、そのままクラウドAPIへ切り替えた際に、出力が想定より変わってしまう問題がありました。
具体的には次の2点です。
- 出力の差異:同じプロンプトでも、モデルが違うとアウトプットが若干変わる
- 再調整の必要性:本番モデルで改めてチューニングが必要になり、手戻りが発生する
ローカルで完璧に作り上げると、クラウドAPIに移行した際に手戻りが発生しました。
今回の経験からは、下記のように試行することが大事だと感じました。
- ローカルは仕様の探索プロンプトの方向性固めを高速に回す場所
- 最終的な詰めは本番で使うモデルに寄せて行う(評価用プロンプトセットを作ると楽)
若干の手戻りはありましたが、初期段階の試行錯誤を課金ゼロでトライアンドエラーができたことで、開発に専念できました。
推論スピードと心理的安全性
M3 Mac上の推論は、APIコールに比べると遅いです。内容によっては数十秒〜数分待つこともありました。
とはいえ、検証を回すたびに課金が増えない安心感が大きく、結果として試行錯誤できたのは価値がありました。
プロンプトのパターンを何通りも試しながら、プロダクトのロジックを深掘りできました。
本番運用にあたり考えたこと
LLM機能を本番で提供する場合、各ベンダーのエンドポイントには次のような制限が入ることがあります。
- 時間あたりのトークン量の上限
- APIコール回数(レート制限)
- 同時実行数などの制限
また、悪意のあるプロンプトによるプロンプトインジェクションや想定外入力による事故も考えられるため、ガードレール設計が必要になります。
今回は、OWASP Top 10 for Large Language Model Applications をベースに、自分の中で実装方針に落とし込みました。
例えば考慮したのは次のような点です。
- 入出力のバリデーション(形式が崩れたら受け入れない)
- 重要な指示(ルール)とユーザ入力を明確に分離する
- レート制限、タイムアウト、最大トークンなどで過負荷を防ぐ
おわりに
LLMを使った機能を開発する際、Ollamaをローカル検証に使うのは有効な選択肢だと感じました。
推論速度はAPIより遅くなる場合がありますが、初期段階のトライアンドエラーを料金を気にせず回せるメリットがありました。
開発で試行錯誤して機能をトライアンドエラーする環境では、心理的負担は低かったです。
Ollamaによる検証を経て、安定して開発できる環境では、ローカルの開発環境から直接LLMのAPIをコールしても良いかもしれません。
Discussion