エラー内容
cohere.errors.too_many_requests_error.TooManyRequestsError: status_code: 429, body: You are using a Trial key, which is limited to 10 API calls / minute. Upgrade to a Production key to increase your rate limit.
1分間に10回。これがCohere Trialキーの上限であり、この制限を超えた瞬間にSDKはTooManyRequestsErrorをスローします。自動リトライもなく、猶予期間もなく、ただ429が返るだけです。
原因
Cohere Trialキーは1分間に10回のAPIコールに制限されています。11回目のコールは即座にHTTP 429として返ってきます。よくある原因は次のとおりです:
- 入力リストをループして、遅延なしに
co.embed()やco.chat()を呼び出している asyncioで一斉に発火する並列非同期コール- 開発中にスクリプトを短時間に何度も実行している
- 全アイテムをタイトなループで送るバッチ処理
解決手順
方法1 — コール間に単純なスリープを追加する(最も手軽な修正)
小さなリストで急ぎでなければ、コール間に6秒の遅延を入れましょう。計算すると1分間にちょうど10回のコールになり、Trialキーの上限にぴったり収まります。
import cohere
import time
co = cohere.ClientV2("YOUR_API_KEY")
texts = ["text one", "text two", "text three"] # 入力テキスト
for text in texts:
response = co.embed(
texts=[text],
model="embed-english-v3.0",
input_type="search_document",
)
print(response.embeddings)
time.sleep(6) # 10コール/分 = 1コールあたり6秒
方法2 — 指数バックオフでリトライする(本番に近いコードに推奨)
429でスクリプトをクラッシュさせるのではなく、エラーをキャッチして待機時間を段階的に増やしながらリトライします。10秒から始めて試行ごとに倍増させます:10秒 → 20秒 → 40秒 → 80秒 → 160秒。
import cohere
import time
from cohere.errors import TooManyRequestsError
co = cohere.ClientV2("YOUR_API_KEY")
def embed_with_retry(text: str, max_retries: int = 5) -> list:
wait = 10 # 秒
for attempt in range(max_retries):
try:
response = co.embed(
texts=[text],
model="embed-english-v3.0",
input_type="search_document",
)
return response.embeddings[0]
except TooManyRequestsError:
if attempt == max_retries - 1:
raise
print(f"レート制限に達しました。{wait}秒後にリトライ {attempt + 1}/{max_retries}...")
time.sleep(wait)
wait *= 2 # 指数バックオフ: 10秒 → 20秒 → 40秒
return []
# 使用例
result = embed_with_retry("Hello, world")
print(result)
方法3 — 入力をまとめて1回のコールで送る
最も効果的な方法がこれです:embedエンドポイントはテキストのリストをまとめて受け付けます。50件のテキストを1回のco.embed()コールで渡しても、1件だけ渡す場合と同じクォータ1単位しか消費しません。1件ずつループするのではなく、まとめて送りましょう。
import cohere
co = cohere.ClientV2("YOUR_API_KEY")
texts = [
"First document to embed",
"Second document to embed",
"Third document to embed",
# ... 1回のコールで数百件まで
]
response = co.embed(
texts=texts,
model="embed-english-v3.0",
input_type="search_document",
)
for i, embedding in enumerate(response.embeddings):
print(f"テキスト {i}: {len(embedding)} 次元")
各co.embed()コールは、渡すテキストの数に関わらず(トークン上限まで)APIコール1回分として数えられます。つまり100件のテキストは100クォータ単位ではなく1クォータ単位で済みます。スリープやリトライを検討する前に、まずこの方法を試してください。
方法4 — トークンバケット/レートリミッターを使う
非同期コードや複雑なパイプラインを使っている場合、ratelimitライブラリを使えばデコレーターとして上限を一度宣言するだけで済みます。
pip install ratelimit
import cohere
from ratelimit import limits, sleep_and_retry
co = cohere.ClientV2("YOUR_API_KEY")
CALLS_PER_MINUTE = 9 # 余裕を持たせるため10未満に設定
ONE_MINUTE = 60
@sleep_and_retry
@limits(calls=CALLS_PER_MINUTE, period=ONE_MINUTE)
def rate_limited_chat(message: str) -> str:
response = co.chat(
model="command-r-plus",
messages=[{"role": "user", "content": message}],
)
return response.message.content[0].text
# これでループ内で呼び出しても429を気にしなくて済む
for msg in ["What is Python?", "Explain APIs", "What is embeddings?"]:
print(rate_limited_chat(msg))
方法5 — Productionキーにアップグレードする
本格的なスループットが必要ですか?Trialキーでは対応できません。dashboard.cohere.comにアクセスし、API KeysからProductionキーを作成してください。Productionキーはプランに応じて1分間に数千回のコールをサポートしており、ローカルテスト以外の用途には必須です。
修正の確認
以下のスモークテストを実行して、修正が実際に機能しているか確認してください。1分間の上限を2回超える12回のコールを、6秒間隔で送信します:
# スモークテスト — レートリミッターの動作確認のため10/分の制限を超える12回のコールを実行
import cohere
import time
from cohere.errors import TooManyRequestsError
co = cohere.ClientV2("YOUR_API_KEY")
success = 0
for i in range(12):
try:
co.embed(
texts=[f"test text {i}"],
model="embed-english-v3.0",
input_type="search_document",
)
success += 1
time.sleep(6) # 6秒間隔 = 10コール/分
except TooManyRequestsError as e:
print(f"コール {i} でまだレート制限に達しています: {e}")
break
print(f"{success}/12 コール成功")
12/12 コール成功と表示されれば問題ありません。
ヒント
- まずキーの種類を確認する:
dashboard.cohere.comのAPI Keysを確認してください。Trialキーは「Trial」と表示されています。すでに「Production」と表示されているのに429が発生する場合は、別の原因が考えられます。 - スリープの前にバッチ処理を試す:
time.sleep()を使う前に、必ず複数のテキストを1回のco.embed()コールにまとめることを検討してください。100件のテキストを1回のコールで送る方が、1件ずつ100回コールするより遥かに効率的です。 - 目標は9コール/分、10ではない:クロックのずれやコードが見えないところでトリガーするバックグラウンドリクエストに備えて、1コール分の余裕を持たせてください。
- 開発中はウェイトをログに出力する:
time.sleep()の前に何か出力するようにしましょう。意図しないループがすぐに分かります。スクリプトが無言でハングする代わりに、スロットリングされているタイミングが一目瞭然になります。 - chatエンドポイントが本当に必要か確認する:RerankやChatエンドポイントはコールあたりのコストが高くなります。レート制限に達している場合は、バッチembeddingsで代替できないか検討してください。クォータ1単位で多数のテキストを処理できます。

