TL;DR
- OpenRouter の
:freeモデルは商用利用可能・レート制限あり・品質差大 - Claude Code の
ANTHROPIC_BASE_URLを差し替えるだけで切り替え可能 - 用途別モデル選定・ローテーション・フォールバック設計の3本柱でコスト0運用
背景
Claude Code は強力なAIコーディング支援ツールだが、フル活用するとAPIコストが積み上がりやすい。一方、OpenRouter は2024年末以降、google/gemini-flash-1.5, meta-llama/llama-3.3-70b-instruct, qwen/qwen3-235b-a22b などの高品質モデルを :free サフィックス付きで提供している。
本記事では「Claude Code + OpenRouter :free モデルで品質を落とさずコストを下げる実践設計」を解説する。
前提知識
OpenRouter :free モデルとは
OpenRouter が提供するプロキシ経由で、無料枠内で利用できるモデル群。
- URLは
https://openrouter.ai/api/v1 - APIスキーマは OpenAI 互換
-
:free付きモデルは 1分あたりのリクエスト数 に制限がある(RPM上限はモデルにより異なる) - 商用利用可否はモデルごとのライセンスに依存(Llama 3.3: Meta Llama 3.3 Community License, Qwen3: Apache 2.0 など)
Claude Code のモデル設定
Claude Code は環境変数 ANTHROPIC_BASE_URL と ANTHROPIC_API_KEY で接続先を差し替えられる。ただし、以下の制約がある。
- Claude Code はデフォルトで
claude-3-5-sonnet/claude-3-5-haiku等のAnthropicモデル名を送信する - OpenRouterはモデル名を
--modelフラグ または リクエストボディのmodelフィールドで受け取る - そのため「Anthropicモデル名 → OpenRouterモデル名のマッピング」が必要になる
設定1: 環境変数の差し替え
.env または シェル設定に記述する。
# OpenRouter エンドポイントに差し替え
export ANTHROPIC_BASE_URL="https://openrouter.ai/api/v1"
export ANTHROPIC_API_KEY="sk-or-v1-xxxxxxxxxxxxxxxxxxxxxxxx"
Claude Code 起動時にこれらが読み込まれると、以降のAPIコールはOpenRouter経由になる。
⚠️ APIキーは
.gitignore済みの.envにのみ記述し、リポジトリにコミットしないこと。
設定2: 用途別モデル選定
すべてのタスクに同じモデルを使うのは非効率。2026年5月時点の :free モデルを用途別に整理する。
| 用途 | 推奨モデル | 理由 |
|---|---|---|
| コード補完・短い変換 | google/gemini-flash-1.5:free |
速度最優先・レイテンシ低 |
| 設計レビュー・ロジック相談 | meta-llama/llama-3.3-70b-instruct:free |
70B規模・文脈保持力高 |
| 長文ドキュメント要約 | qwen/qwen3-235b-a22b:free |
長コンテキスト・多言語対応 |
| ユニットテスト生成 | microsoft/phi-4:free |
推論精度・コンパクト |
| 英語コメント翻訳・日本語補完 | qwen/qwen3-14b:free |
日英混在コードに強い |
選定基準:
- コンテキスト長 — 大きなファイルを渡す場合は128k以上必須
- RPM上限 — 連続リクエスト多発タスクでは高RPMモデルを選ぶ
- ライセンス — 商用プロダクトのコード生成に使う場合はApache 2.0 or MITを優先
設定3: ローテーション設計(RPM制限の回避)
:free モデルは RPM 上限に達すると 429 Too Many Requests を返す。これを回避する最もシンプルな方法がモデルローテーション。
Python での実装例(最小構成)
import anthropic
import time
import random
FREE_MODELS = [
"google/gemini-flash-1.5:free",
"meta-llama/llama-3.3-70b-instruct:free",
"qwen/qwen3-14b:free",
]
def call_with_rotation(prompt: str, max_retries: int = 3) -> str:
models = FREE_MODELS.copy()
random.shuffle(models) # ローテーションを均等化
for model in models:
for attempt in range(max_retries):
try:
client = anthropic.Anthropic(
base_url="https://openrouter.ai/api/v1",
# api_key は環境変数 ANTHROPIC_API_KEY から自動読み込み
)
message = client.messages.create(
model=model,
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
)
return message.content[0].text
except Exception as e:
if "429" in str(e):
wait = 2 ** attempt # exponential backoff
time.sleep(wait)
continue
raise e # 429以外は再試行しない
raise RuntimeError("All free models rate-limited. Try again later.")
ポイント:
-
random.shuffleでモデルへの負荷を分散 -
429のみ exponential backoff・それ以外は即時 raise - Anthropic Python SDK の
base_urlパラメータで OpenRouter に向ける(OpenAI互換エンドポイントを使う場合はopenaiライブラリも同様に対応可)
設定4: フォールバック設計(有料 → 無料の逆引き)
開発初期は無料モデル優先、品質が足りない場合のみ有料モデルにフォールバックする戦略が費用対効果が高い。
from enum import Enum
class ModelTier(Enum):
FREE = "free"
PAID = "paid"
FALLBACK_CHAIN = {
"code_review": [
("qwen/qwen3-235b-a22b:free", ModelTier.FREE),
("meta-llama/llama-3.3-70b-instruct:free", ModelTier.FREE),
("anthropic/claude-3-5-sonnet", ModelTier.PAID), # 最終手段
],
"quick_completion": [
("google/gemini-flash-1.5:free", ModelTier.FREE),
("microsoft/phi-4:free", ModelTier.FREE),
("anthropic/claude-3-5-haiku", ModelTier.PAID),
],
}
def get_model_for_task(task: str, prefer_free: bool = True):
chain = FALLBACK_CHAIN.get(task, FALLBACK_CHAIN["quick_completion"])
if prefer_free:
return [m for m, tier in chain if tier == ModelTier.FREE]
return [m for m, _ in chain]
設定5: コスト可視化ログ(無料 vs 有料の呼び出し比率トラッキング)
どのモデルが何回呼ばれたかをローカルログに残すだけで、コスト最適化の改善サイクルが回せる。
import json
import os
from datetime import datetime
LOG_PATH = "./llm_usage_log.jsonl" # .gitignore に追加推奨
def log_call(model: str, input_tokens: int, output_tokens: int, task: str):
entry = {
"ts": datetime.utcnow().isoformat(),
"model": model,
"task": task,
"input_tokens": input_tokens,
"output_tokens": output_tokens,
"is_free": ":free" in model,
}
with open(LOG_PATH, "a") as f:
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
JSONL形式にしておくと、後から pandas や jq で集計できる。
# 無料モデル呼び出し数の確認
grep '"is_free": true' llm_usage_log.jsonl | wc -l
# モデル別集計 (jq)
jq -r '.model' llm_usage_log.jsonl | sort | uniq -c | sort -rn
注意点まとめ
ライセンス確認は必須
| モデル | ライセンス | 商用利用 |
|---|---|---|
| Llama 3.3 70B | Meta Llama 3.3 Community License | 月間アクティブユーザー 7 億人超のサービスは別途ライセンス契約が必要 |
| Qwen3 (全サイズ) | Apache 2.0 | ✅ 商用利用可 |
| Phi-4 | MIT | ✅ 商用利用可 |
| Gemini Flash 1.5 | Google利用規約 | 利用規約に準拠 |
:free モデルの品質制約
- プロンプトが長くなるほど品質差が顕在化する(特に複雑な推論・多ステップのコード変換)
- 日本語の精度は
Qwen3系が最も安定している - ストリーミング(
stream=True)は:freeモデルでも基本サポートされているが、RPM制限に引っかかりやすくなる
OpenRouter のキャッシュ活用
OpenRouter は同一プロンプトに対するキャッシュ(Prompt Cache)を自動適用する。長いシステムプロンプトを繰り返し送る設計にしておくとトークン消費を削減できる(無料モデルでもキャッシュは効く)。
まとめ
| 設定 | 効果 |
|---|---|
| 環境変数差し替え | ゼロコード変更でOpenRouterに切り替え |
| 用途別モデル選定 | 品質×速度×コストの最適バランス |
| ローテーション設計 | RPM制限によるダウンタイムを回避 |
| フォールバック設計 | 本当に必要なときだけ有料モデル利用 |
| コスト可視化ログ | 改善サイクルをデータドリブンに |
OpenRouter :free モデルは「タダだから品質が低い」という思い込みを捨てると、開発・研究フェーズのコストを大幅に削減できる実用的な選択肢になる。まずは gemini-flash-1.5:free と llama-3.3-70b:free の2本立てから試してみてほしい。
参考リンク
- OpenRouter Docs — Free Models
- Claude Code Documentation
- Anthropic Python SDK (Apache 2.0)
- Meta Llama 3.3 Community License
- Qwen3 Technical Report
✍️ 本記事の著者: 合同会社ジモラボ
ジモラボは、八王子を拠点に AI を活用した SaaS を多数開発しています。本記事の技術検証もそうした開発過程の副産物です。
- 🌐 公式サイト: https://locallab.jp
- 🔍 AI SEO 最適化 SaaS: lookupai.jp
- 📺 YouTube: @locallab_llc
- ✉️ お問い合わせ: info@locallab.jp
興味を持っていただけたら、ぜひ各 SNS のフォローもお願いします!