الخدمة التي تنتمي إليها الحدود
الأسماء سهلة الخلط. Groq هي شركة تستضيف النماذج على عتادها الخاص. Grok هو عائلة النماذج من xAI. هذا الموقع ليس أيًا منهما: إنه واجهة برمجة تطبيقات متوافقة مع OpenAI لنموذج واحد مفتوح الأوزان (معرف النموذج uncensored)، وتشغله جهة مستقلة. لذا، فيما يخص حدّ المعدل الخاص بواجهة groq api نفسه، مثل عدد الطلبات أو الرموز في الدقيقة على خطة معينة، افتح لوحة تحكم Groq أو وثائقه واقرأ الأرقام لحسابك. هي تتغير، ولن أخمن.
ما يلي دقيق لواجهة برمجة التطبيقات الخاصة بنا، وتنطبق العادات على أي مزود: احترم رؤوس حدّ المعدل، وأعد المحاولة فقط عند الأخطاء الصحيحة، وحدّ من التزامن الخاص بك قبل أن يفعله الخادم لك. إذا كنت قد جئت هنا لإعداد Grok NSFW، فإن دليل التكامل الخاص بنا يغطي الأخطاء المحيطة أيضًا.
الحدود بإيجاز
| الحد | مفتاح كامل | مفتاح التجربة |
|---|---|---|
| طلبات متزامنة | 8 | 2 |
| الطلبات في الدقيقة | 300 | 60 |
| جسم الطلب | 8 MB | 8 MB |
| نافذة السياق (الموجّه بالإضافة إلى الإكمال) | 100,000 رمز (token) | 100,000 رمز (token) |
اثنان من هذه الحدود هما حدود معدل بالمعنى الدقيق للكلمة، الطلبات في الدقيقة والتزامن. النوعان الآخران هما حدود الحجم على طلب واحد، وهي مستقلة عن حدود المعدل. الطلب الذي يحتوي على موجّه بحجم 90,000 رمز يُحسب كطلب واحد ضد حد 300 في الدقيقة، تمامًا مثل الموجّه ذو السطر الواحد، على الرغم من أنه سيستغرق وقتًا أطول ويحتفظ بمكانه لفترة أطول.
يُحصل على رصيد التجربة بقيمة $0.50 بنقرة واحدة على صفحة مفتاح API بعد تسجيل الدخول، ويخضع لحدود التجربة. تنطبق حدود المفتاح الكامل بمجرد شحن الرصيد.
أنواع 429 الثلاثة
تصل جميع أخطاء الحدود بصيغة HTTP 429، لكنها تعني أشياء مختلفة وتتطلب تفاعلات مختلفة.
rate_limited: لقد أرسلت أكثر من حصة الطلبات في الدقيقة المسموحة لك. قلل السرعة؛ النافذة هي دقيقة، لذا فإن توزيع الطلبات بالتساوي يساعد أكثر من التوقف الطويل.concurrency: كان هناك الكثير من الطلبات قيد التنفيذ في وقت واحد. انتظر انتهاء طلب سابق. هذا شائع مع البث المتدفق، حيث يعيش كل طلب طوال مدة التوليد.- حمل زائد مؤقت: هو أيضًا خطأ 429، مع رأس
Retry-After: 5. ليس خطأ منك ولا مرتبط بحدود مفتاحك. انتظر 5 ثوانٍ المحددة وأعد المحاولة.
الطلبات الفاشلة لا تُحسب، لذا فإن حلقة إعادة المحاولة تكلف فقط الطلب الذي ينجح أخيرًا. تحمل الاستجابات أيضًا رؤوس X-RateLimit-Limit-Requests و X-RateLimit-Limit-Concurrency بحيث يمكن لعميلك قراءة حدوده الخاصة بدلاً من برمجتها بشكل ثابت، بالإضافة إلى X-Balance-USD للرصيد المتبقي و X-Request-Id، والتي يجب أن تسجلها وتذكرها إذا تواصلت مع الدعم.
رياضيات الإنتاجية: لماذا من الصعب الوصول إلى 300 في الدقيقة
يتفاعل الحدّان مع بعضهما البعض. مع 8 فتحات متزامنة، فإن أقصى ما يمكنك إكماله في الدقيقة هو 8 × 60 مقسومًا على متوسط مدة الطلب بالثواني. للوصول فعليًا إلى 300 طلب في الدقيقة، تحتاج إلى طلبات تنتهي في 8 × 60 / 300 = 1.6 ثانية في المتوسط. الطلبات الأبطأ تحدّها قيود التزامن أولاً.
| متوسط وقت الطلب | الحد الأقصى في الدقيقة، المفتاح الكامل (8 فتحات) | الحد الأقصى في الدقيقة، التجربة (فتحتان) |
|---|---|---|
| 2 ثانية | 240 | 60 |
| 10 ثوانٍ | 48 | 12 |
| 20 ثانية | 24 | 6 |
هذه حدود حسابية لوقت طلب افتراضي، وليست قياسات لخدمتنا؛ قس وقت طلباتك الخاصة. الخلاصة هي أن التوليد الإبداعي الطويل الذي يستغرق 20 ثانية على مفتاح كامل يصل إلى حد أقصى هو 24 طلبًا في الدقيقة، وهو أقل بكثير من الـ 300 المسموح بها. إذا كنت بحاجة إلى إنتاجية أعلى، فاقصر الردود باستخدام max_tokens أو اطلب نصًا أقل لكل استدعاء بدلاً من الأمل في الحصول على حد طلب أعلى.
عميل يتعامل مع الحالات الثلاث
يحدّ هذا العميل بلغة Python من التزامنه الخاص باستخدام سيمافور (semaphore)، ويقرأ Retry-After عند وجوده، ويتراجع مع تأخير عشوائي صغير (jitter) في الحالات الأخرى. يستخدم حزمة openai الرسمية.
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))
نفس الفكرة في Node هي قائمة انتظار صغيرة تسمح بحد أقصى 8 Promises معلقة، وطريقة التحقق عبر curl أدناه تطبع رؤوس الحدود حتى تتمكن من تأكيد حدود مفتاحك:
curl -s -D - -o /dev/null https://api.groknsfw.top/v1/models \
-H "Authorization: Bearer YOUR_KEY" | grep -i "x-"البث المتدفق، الموجّهات الطويلة والسياق
يحتفظ الطلب الذي يتم بثّه مع stream: true بخانة التزامن الخاصة به حتى وصول الحدث الأخير. وهذا يعني أن القارئ البطيء يُحسب عليك: إذا توقف الكود الخاص بك أثناء معالجة كل قطعة، تظل الخانة مشغولة. استهلك البث على الفور.
تتفاعل الموجّهات الطويلة مع الحدود بطريقتين. أولاً، تستغرق وقتاً أطول للمعالجة، مما يقلل من معدل الإنتاجية وفقاً للصيغة أعلاه. ثانياً، يجب أن تتسع نافذة الـ 100,000 رمز مع الرد، لذا حافظ على هامش. يساعد اختصار أجزاء الدردشة القديمة في حلّ المشكلتين، ويقلل الفاتورة أيضاً: عند $0.15 لكل مليون رمز مدخل، يكلف سجل بطول 20,000 رمز $0.003 في كل مرة تعيد إرساله.
تفاصيل تنسيق الطلب موجودة في دليل البدء السريع، والأسعار في صفحة الأسعار.
عرض الحدود على مستخدميك
حدّ المعدل هو أيضاً قرار منتج. إذا كان تطبيقك يعمل كوسيط بين المستخدمين النهائيين وAPI، فيجب ألا يصل 429 الخام إليهم. قرر مسبقاً ما الذي سيرونه بدلاً من ذلك.
- لتطبيقات الدردشة، اعرض حالة "الكتابة" القصيرة وضع الرسالة في الطابور. انتظار بضع ثوانٍ يكون غير مرئي لمعظم المستخدمين إذا كان هناك شيء يحدث على الشاشة.
- لأدوات الدفعات، اعرض التقدم بعدد العناصر المكتملة واترك المهمة تعمل في الخلفية. عمليات إعادة المحاولة داخلية ولا ينبغي أن تظهر كأخطاء.
- للنشر المشترك، امنح كل مستخدم حصة صغيرة لكل مستخدم في كودك الخاص حتى لا يأخذ مستخدم واحد كثيف الاستخدام كل الـ 8 خانات من الآخرين.
سجّل ثلاثة أشياء لكل فشل: X-Request-Id، ورمز الخطأ، وعدد الطلبات التي كان تطبيقك يعالجها في تلك اللحظة. بهذه البيانات، يمكنك التمييز بين العميل الذي لا يعمل بشكل صحيح والحمل الحقيقي في بضع دقائق. إذا بدا أن المشكلة من جانب الخادم، فإن معرف الطلب هو ما سيطلبه الدعم أولاً.
أخيراً، اختبر مسار الفشل عن قصد. شغّل العميل الخاص بك بحدّ تزامن منخفض عمداً ثم بحدّ عالٍ، وانظر ما تظهره السجلات. حلقة إعادة المحاولة التي لم تنفجر من قبل هي حلقة لا يمكنك الوثوق بها. المفتاح التجريبي مكان مريح لهذا، لأنه مع طلبين متزامنين فقط، من السهل الوصول إلى خطأ concurrency باستخدام نص برمجي قصير ورؤية كيف يتفاعل الكود الخاص بك، بتكلفة بضعة أعشار من السنت لكل طلب.
الأخطاء الشائعة
تسبب بعض الأنماط معظم مشاكل 429 التي يبلغ عنها الناس.
- إعادة المحاولة فورًا. الحلقة التي تعيد الإرسال عند كل فشل تحول لحظة تجاوز الحد إلى عاصفة. انتظر، أضف تأخيراً عشوائياً (jitter)، وحدّد عدد المحاولات.
- إعادة المحاولة لكل شيء. فقط 429 وأخطاء الخادم العابرة تستحق إعادة المحاولة. الطلب غير الصحيح أو المفتاح الخاطئ سيفشل بنفس الطريقة في كل مرة.
- نسيان البث في العد. عشر نوافذ دردشة مفتوحة على مفتاح كامل يمكن أن تكون عشرة تدفقات، وهذا يزيد بمقدار 2 على الـ 8 خانات.
- عدم تعيين مهلة زمنية. الاتصال المعلق يظل خانة مشغولة. امنح كل طلب مهلة زمنية معقولة في عميل HTTP الخاص بك.
- تحديد الحجم بناءً على المتوسط. الحركة تأتي على شكل دفعات. خطط لأكثر دقيقة ازدحاماً لديك، وليس متوسطك اليومي.
تخطيط السعة قبل الإطلاق
اعمل بالرجوع من ذروة الاستخدام. إذا كنت تتوقع 30 مستخدمًا دردشة في وقت واحد وكل رد يبث لمدة 15 ثانية تقريبًا، فأنت تحتاج إلى 30 فتحة في اللحظة التي يرسلون فيها جميعًا، والمفتاح الكامل يحتوي على 8. ضع الباقي في طابور في تطبيقك الخاص، وأظهر انتظارًا قصيرًا، وعالجها عندما تتحرر الفتحات. مع 8 فتحات وردود تستغرق 15 ثانية، يمكنك إنهاء 8 x 60 / 15 = 32 ردًا في الدقيقة.
لأعمال الدفعات، شغّل مجموعة عمالة ثابتة تساوي حدّ التزامن الخاص بك واترك منطق إعادة المحاولة يتعامل مع الحمل الزائد العرضي. بدلاً من العمل حول الحدود، ابنِ الطابور: فهو يمنحك سلوكاً قابلاً للتنبؤ ويسمح لك بإظهار أوقات الانتظار الحقيقية لمستخدميك.
