Aan welke dienst de limieten toebehoren
De namen zijn makkelijk te verwarren. Groq is een bedrijf dat modellen host op zijn eigen hardware. Grok is de modelfamilie van xAI. Deze site is geen van beide: het is een OpenAI-compatible API voor één open-weight model (model ID uncensored), beheerd door een onafhankelijke provider. Voor de groq api rate limit zelf, zoals verzoeken of tokens per minuut op een bepaald plan, open je de console of documentatie van Groq en lees je de cijfers voor je account. Ze veranderen, en ik gok niet.
Het volgende is exact voor onze API, en de gewoontes zijn overdraagbaar op elke provider: respecteer de limietheaders, probeer alleen opnieuw bij de juiste fouten, en beperk je eigen concurrency voordat de server dat voor je doet. Als je hier bent voor een Grok NSFW-setup, dekt onze integratiegids ook de omliggende fouten.
De limieten in het kort
| Limiet | Volledige sleutel | Proefsleutel |
|---|---|---|
| Gelijktijdige verzoeken | 8 | 2 |
| Verzoeken per minuut | 300 | 60 |
| Verzoeklichaam | 8 MB | 8 MB |
| Contextvenster (prompt plus voltooiing) | 100.000 tokens | 100.000 tokens |
Twee daarvan zijn rate limits in de strikte zin: verzoeken per minuut en concurrency. De andere twee zijn groottelimieten voor een enkel verzoek, en ze zijn onafhankelijk van de rate limits. Een verzoek met een prompt van 90.000 tokens telt als één verzoek tegen de 300 per minuut, hetzelfde als een eenregelige prompt, hoewel het langer duurt en zijn slot langer bezet houdt.
Het proeftegoed van $0,50 claim je met één klik op de API-sleutelpagina na het aanmaken van je account, en het gebruikt de proeflimieten. De limieten van de volledige sleutel gelden zodra je hebt opgewaardeerd.
De drie soorten 429
Alle limietfouten komen als HTTP 429, maar ze betekenen verschillende dingen en vragen om verschillende reacties.
rate_limited: je stuurde meer verzoeken dan je limiet per minuut toestaat. Vertraag; het venster is een minuut, dus verzoeken gelijkmatig verdelen helpt meer dan een lange pauze.concurrency: er waren te veel verzoeken tegelijk actief. Wacht tot een eerder verzoek klaar is. Dit komt veel voor bij streaming, waar elk verzoek de hele generatie duurt.- Tijdelijke overbelasting: ook een 429, met een
Retry-After: 5-header. Het is niet jouw schuld en niet gekoppeld aan de limieten van je sleutel. Wacht de genoemde 5 seconden en probeer opnieuw.
Mislukte verzoeken worden niet in rekening gebracht, dus een retry-loop kost slechts het ene verzoek dat uiteindelijk slaagt. Responsen bevatten ook X-RateLimit-Limit-Requests en X-RateLimit-Limit-Concurrency zodat je client zijn eigen plafonds kan uitlezen in plaats van ze hard te coderen, plus X-Balance-USD voor het resterende tegoed en X-Request-Id, die je moet loggen en citeren als je support contacteert.
Doorvoerwiskunde: waarom 300 per minuut moeilijk te bereiken is
De twee limieten interageren. Met 8 concurrency-slots is het maximum dat je per minuut kunt voltooien 8 x 60 gedeeld door de gemiddelde duur van een verzoek in seconden. Om echt 300 verzoeken per minuut te bereiken, moet je verzoeken hebben die gemiddeld in 8 x 60 / 300 = 1,6 seconden klaar zijn. Langzamere verzoeken worden eerst beperkt door concurrency.
| Gemiddelde verzoektijd | Max per minuut, volledige sleutel (8 slots) | Max per minuut, proef (2 slots) |
|---|---|---|
| 2 seconden | 240 | 60 |
| 10 seconden | 48 | 12 |
| 20 seconden | 24 | 6 |
Dit zijn rekenkundige plafonds voor een hypothetische verzoektijd, geen metingen van onze dienst; meet je eigen verzoeken. De conclusie is dat een lange creatieve generatie van 20 seconden op een volledige sleutel uitkomt op 24 verzoeken per minuut, ver onder de toegestane 300. Als je meer doorvoer nodig hebt, verklein dan de antwoorden met max_tokens of vraag minder tekst per aanroep in plaats van te hopen op een hogere verzoeklimiet.
Een client die alle drie de gevallen afhandelt
Deze Python-client beperkt zijn eigen concurrency met een semaphore, leest Retry-After wanneer aanwezig, en gebruikt anders backoff met een kleine jitter. Het maakt gebruik van het officiële openai-pakket.
import random
import threading
import time
from concurrent.futures import ThreadPoolExecutor
from openai import OpenAI, RateLimitError
client = OpenAI(
base_url="https://api.groknsfw.top/v1",
api_key="YOUR_KEY",
max_retries=0, # we handle retries ourselves
)
slots = threading.BoundedSemaphore(8) # use 2 on the trial key
def ask(prompt, tries=6):
for attempt in range(tries):
with slots:
try:
r = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": prompt}],
max_tokens=400,
)
return r.choices[0].message.content
except RateLimitError as e:
wait = e.response.headers.get("retry-after")
body = e.response.text
# sleep outside the slot so others can proceed
delay = float(wait) if wait else min(2 ** attempt, 30)
if "rate_limited" in body:
delay = max(delay, 5)
time.sleep(delay + random.random())
raise RuntimeError("still rate limited after retries")
with ThreadPoolExecutor(max_workers=8) as pool:
results = list(pool.map(ask, ["Write one line about the sea."] * 20))
print(len(results))
Hetzelfde idee in Node is een kleine wachtrij die maximaal 8 wachtende beloftes toestaat, en de curl-check hieronder print de limietheaders zodat je de plafonds van je sleutel kunt bevestigen:
curl -s -D - -o /dev/null https://api.groknsfw.top/v1/models \
-H "Authorization: Bearer YOUR_KEY" | grep -i "x-"Streaming, lange prompts en context
Een gestreamd verzoek met stream: true houdt zijn concurrency-slot vast tot het laatste event aankomt. Dat betekent dat een trage lezer tegen je aan telt: als je code pauzeert bij het verwerken van elke chunk, blijft het slot bezet. Verbruik de stream tijdig.
Lange prompts interageren op twee manieren met limieten. Ten eerste kosten ze meer tijd om te verwerken, dus ze verlagen je doorvoer volgens de formule hierboven. Ten tweede moeten ze in het 100.000-token venster passen samen met het antwoord, dus houd een marge aan. Oude chatronden bijsnijden helpt beide problemen, en hetzelfde bijsnijden verlaagt je rekening: bij $0,15 per 1M input tokens kost een geschiedenis van 20.000 tokens $0,003 elke keer dat je het opnieuw verstuurt.
Details van het verzoekformaat staan in de quickstart, en tarieven staan op de prijzenpagina.
Limieten tonen aan je eigen gebruikers
Een rate limit is ook een productbeslissing. Als je app tussen eindgebruikers en de API zit, mag een ruwe 429 hen nooit bereiken. Bepaal van tevoren wat ze te zien krijgen.
- Voor chatapps, toon een korte "schrijvend"-status en zet het bericht in een wachtrij. Een wachttijd van een paar seconden is voor de meeste gebruikers onzichtbaar als er iets op het scherm gebeurt.
- Voor batchtools, toon voortgang als een telling van voltooide items en laat de taak op de achtergrond draaien. Retries zijn intern en mogen niet als fouten verschijnen.
- Voor gedeelde implementaties, geef elke gebruiker een klein quotum per gebruiker in je eigen code zodat één zware gebruiker niet alle 8 slots van de anderen kan innemen.
Log drie dingen voor elke fout: de X-Request-Id, de foutcode, en hoeveel verzoeken je app op dat moment actief had. Met die gegevens kun je in een paar minuten een misgedragende client onderscheiden van echte belasting. Als een probleem eruitziet alsof het aan de serverkant zit, is de request ID wat support eerst zal vragen.
Test tot slot het foutpad opzettelijk. Voer je client uit met een bewust lage semaphore en daarna met een hoge, en kijk wat de logs laten zien. Een retry-loop die nog nooit is afgegaan is een retry-loop die je niet kunt vertrouwen. De proefsleutel is een handige plek hiervoor, omdat je met slechts 2 gelijktijdige verzoeken makkelijk de concurrency-fout kunt triggeren met een kort script en kunt zien hoe je code reageert, tegen de kosten van een paar tienden van een cent per verzoek.
Veelgemaakte fouten
Enkele patronen veroorzaken de meeste 429-problemen die mensen melden.
- Opnieuw proberen. Een lus die bij elke fout opnieuw verzendt, verandert één moment van overschrijding in een storm. Wacht, voeg jitter toe en beperk het aantal pogingen.
- Alles opnieuw proberen. Alleen 429-fouten en tijdelijke serverfoutjes verdienen een retry. Een ongeldig verzoek of een verkeerde sleutel faalt elke keer op dezelfde manier.
- Streams vergeten in de telling. Tien open chatvensters op een volledige sleutel kunnen tien streams zijn, en dat zijn er twee meer dan de 8 slots.
- Geen timeout instellen. Een vastgelopen verbinding houdt een slot bezet. Geef elk verzoek een verstandige timeout in je HTTP-client.
- Dimensioneren op het gemiddelde. Verkeer komt in pieken. Plan voor je drukste minuut, niet je dagelijkse gemiddelde.
Capaciteit plannen voordat je lanceert
Werk terug vanuit je piek. Als je verwacht dat 30 gebruikers tegelijk chatten en elk antwoord stroomt ongeveer 15 seconden, heb je 30 slots nodig op het moment dat ze allemaal versturen, en een volledige sleutel heeft er 8. Zet de rest in een wachtrij in je eigen app, toon een korte wachttijd en verwerk ze zodra slots vrijkomen. Met 8 slots en 15-seconden antwoorden kun je 8 x 60 / 15 = 32 antwoorden per minuut voltooien.
Voor batchtaken voer je een vaste worker pool uit die gelijk is aan je gelijktijdigheidslimiet en laat je de retry-logica de af en toe optredende overbelasting afhandelen. In plaats van de limieten te omzeilen, bouw je een wachtrij: dit geeft je voorspelbaar gedrag en stelt je in staat echte wachttijden aan je gebruikers te tonen.
