मुख्य बिंदु
- यह टेक्स्ट क्लाइंट से आता है, इसलिए असली त्रुटि बॉडी और स्टेटस देखने के लिए curl के साथ कॉल को पुनः बनाएं।
- HTTP 429, जिसका कोड rate_limited या concurrency है, व्यस्त खाते पर सबसे आम कारण है, और एक स्ट्रीम अंत तक अपनी स्लॉट बनाए रखती है।
- कुछ भी करने से पहले बेस यूआरएल, कुंजी, मॉडल ID uncensored, बॉडी साइज (8 MB) और कुल टोकन (100,000) की जांच करें।
- केवल 429 और नेटवर्क ड्रॉप के लिए रीट्राई करें, Retry-After का इंतजार करें, और कन्करेंसी को कुंजी लिमिट के अंदर रखें।
संदेश वास्तव में आपको क्या बताता है
यदि आप अज्ञात त्रुटि खोज रहे हैं, तो आप संभवतः किसी टोस्ट, चैट फ्रंट-एंड, एडिटर प्लगइन या एजेंट फ्रेमवर्क में एक लाल रेखा देख रहे हैं। यह शब्दावली उस क्लाइंट से आती है। इसका अर्थ है कि ऐप ने स्ट्रीम किए गए उत्तर के लिए अनुरोध किया, स्ट्रीम से पहले या दौरान कुछ गलत हो गया, और ऐप को यह वर्णित करना नहीं आता था। API स्वयं HTTP स्थिति और JSON त्रुटि बॉडी के साथ समस्याओं की रिपोर्ट करता है, और क्लाइंट ने उस विवरण को खारिज कर दिया है।
यह अच्छी खबर है, क्योंकि इसका अर्थ है कि आप विवरण वापस प्राप्त कर सकते हैं। उसी अनुरोध को क्लाइंट के बाहर भेजें, स्टेटस लाइन और बॉडी पढ़ें, और कारण आमतौर पर एक या दो प्रयासों में स्पष्ट हो जाता है। इस पृष्ठ का शेष भाग इस API पर उन कारणों की जाँच करता है जो आमतौर पर होते हैं, और फिर आपको एक छोटा स्ट्रीमिंग क्लाइंट देता है जो उसे छिपाने के बजाय वास्तविक त्रुटि प्रिंट करता है।
शुरुआत से एक बात ध्यान में रखें: एक स्ट्रीम किए गए अनुरोध में दो विफलता बिंदु होते हैं। यह पहले बाइट से पहले विफल हो सकता है, जब सर्वर अनुरोध को अस्वीकार कर दे (बुरी कुंजी, बुरा URL, एक लिमिट)। या यह बीच में विफल हो सकता है, जब कुछ टेक्स्ट आने के बाद कनेक्शन टूट जाए। समाधान अलग-अलग होते हैं, इसलिए नोट करें कि आपको कौन सा दिख रहा है। यदि उत्तर कभी शुरू नहीं होता, तो खंड दो से चार देखें। यदि यह शुरू होता है और फिर रुक जाता है, तो प्रॉक्सी और टाइमआउट्स वाले खंड को देखें।
सबसे पहले बेस यूआरएल, कुंजी और मॉडल की जांच करें
नई सेटअप पर अधिकांश स्ट्रीम त्रुटियां तीन छोटी गलतियों से आती हैं। उन्हें खारिज करने में एक मिनट लगता है।
- बेस URL. यह
https://api.uncensoredllmhub.com/v1होना चाहिए, जिसमें/v1शामिल है और अंत में/chat/completionsनहीं होना चाहिए। क्लाइंट पथ स्वयं जोड़ते हैं। यदि आप पूरा एंडपॉइंट किसी ऐसे फ़ील्ड में पेस्ट करते हैं जो बेस URL की उम्मीद करता है, तो क्लाइंट एक ऐसे पथ का अनुरोध करेगा जो मौजूद नहीं है और एक अस्पष्ट त्रुटि रिपोर्ट करेगा। - कुंजी। हेडर
Authorization: Bearer YOUR_KEYहै। एक अकेला स्थान, कुंजी के साथ कॉपी किया गया नया लाइन, या किसी अन्य सेवा से कुंजी — तीनों एक ही तरह से विफल होते हैं। यदि आपको शक है, तो API कुंजी पृष्ठ से कुंजी फिर से बनाएं या कॉपी करें। - मॉडल ID। एकमात्र मॉडल
uncensoredहै। जो क्लाइंट ड्रॉपडाउन प्रदान करते हैं, वे अक्सर किसी अन्य प्रदाता का नाम पहले से भर देते हैं। ID को हाथ से टाइप करें, और यदि सर्वर द्वारा सूचीबद्ध चीज की पुष्टि करनी हो तोGET /v1/modelsकॉल करें।
तीनों एक साथ परीक्षण करने का एक तेज़ तरीका मॉडल्स कॉल है। यह स्ट्रीम नहीं करता, इसलिए यह कनेक्शन या कुंजी की समस्या को स्ट्रीमिंग की समस्या से अलग करता है:
curl -i https://api.uncensoredllmhub.com/v1/models -H "Authorization: Bearer $API_KEY"
यदि यह एक सामान्य सूची लौटाता है, तो URL और कुंजी ठीक हैं और आप उन्हें संदिग्ध मानना बंद कर सकते हैं। यदि यह विफल होता है, तो स्ट्रीमिंग से पहले उसकी मरम्मत करें। साथ ही, जांचें कि आपके खाते में क्रेडिट है: API प्रतिक्रियाओं पर X-Balance-USD हेडर में आपका शेष बैलेंस भेजता है, जो तब उपयोगी होता है जब भारी उपयोग के बाद एक कुंजी अचानक काम करना बंद कर दे। मूल्य निर्धारण पृष्ठ टॉप-अप की व्याख्या करता है, और नए खातों की कुंजी पृष्ठ से $0.50 का ट्रायल क्रेडिट दावा कर सकते हैं।
रेट लिमिट और वह स्ट्रीम जो अपना स्लॉट रखती है
अगला सबसे आम कारण HTTP 429 है। इसके तीन प्रकार हैं, और आपका क्लाइंट उन सभी को एक ही असहायक संदेश में बदल देगा।
| संकेत | अर्थ | क्या करना है |
|---|---|---|
429, कोड rate_limited | कुंजी के लिए प्रति मिनट बहुत अधिक अनुरोध | गति कम करें; एक पूर्ण कुंजी प्रति मिनट 300 की अनुमति देती है, एक ट्रायल कुंजी 60 |
429, कोड concurrency | एक साथ बहुत सारे अनुरोध चल रहे हैं | उनकी कतार बनाएं; एक पूर्ण कुंजी एक साथ 8 की अनुमति देती है, एक ट्रायल कुंजी 2 |
429 के साथ Retry-After: 5 | सर्विस साइड पर अस्थायी ओवरलोड | 5 सेकंड प्रतीक्षा करें, फिर पुनः प्रयास करें |
कॉन्करेंसी लिमिट वह है जो लोगों को हैरान करती है, क्योंकि स्ट्रीमिंग कैसे काम करती है। एक स्ट्रीम किए गए अनुरोध का स्लॉट तब तक घिरे रहता है जब तक स्ट्रीम खत्म न हो जाए, न कि जब तक पहला टोकन न आए। यदि आपकी ऐप हर संदेश के लिए एक स्ट्रीम खोलती है और पुरानी स्ट्रीम को कभी बंद नहीं करती, उदाहरण के लिए क्योंकि उपयोगकर्ता ने नेविगेशन छोड़ दिया और UI ने अनुरोध रद्द करना भूल गया, तो वे स्लॉट लिए रहते हैं। 2 की सीमा वाली ट्रायल कुंजी पर, दो छोड़ी गई स्ट्रीम तीसरे संदेश को विफल करने के लिए पर्याप्त हैं।
लक्षण संगत हैं। पहले कुछ संदेश काम करते हैं, फिर त्रुटियां शुरू होती हैं, और फिर कुछ देर की प्रतीक्षा के बाद सब कुछ फिर से काम करने लगता है। यदि यह मेल खाता है, तो उन स्ट्रीम को रद्द करें जिनकी आपको अब आवश्यकता नहीं है (ब्राउज़र में एक AbortController, सर्वर पर प्रतिक्रिया बंद करना), और अपने कोड में समानांतर कॉल की संख्या को सीमित करें। एजेंट आमतौर पर दोषी होते हैं: एक प्लानर जो एक साथ दस फ़ंक्शन कॉलिंग भेजता है, वह तुरंत ट्रायल कुंजी पर रेट लिमिट पर पहुंच जाएगा।
रिस्पॉन्स हेडर आपको अपनी स्थिति देखने में मदद करते हैं। X-RateLimit-Limit-Requests और X-RateLimit-Limit-Concurrency उस कुंजी पर लागू सीमाएं दिखाते हैं जिसे आपने उपयोग किया, और X-Request-Id कॉल की पहचान करता है यदि आपको इसके बारे में सहायता से पूछना हो।
अनुरोध का आकार और कॉन्टेक्स्ट विंडो
एक अनुरोध बहुत बड़ा होने के कारण भी अस्वीकृत हो सकता है। दो संख्याएँ महत्वपूर्ण हैं। बॉडी अधिकतम 8 MB हो सकती है, और प्रॉम्प्ट और पूरक टोकन 100,000 टोकन की कॉन्टेक्स्ट विंडो में फिट होने चाहिए। चैट फ्रंट-एंड जो हर चरण पर पूरी बातचीत फिर से भेजते हैं, इन सीमाओं को धीरे-धीरे और फिर अचानक छूते हैं: चैट एक घंटे तक काम करता है, फिर एक लंबा संदेश या पेस्ट किया गया फ़ाइल इसे बढ़ा देता है, और हर बाद के चरण में इतिहास अनुरोध में होने के कारण विफलता आती है।
यदि त्रुटि एक लंबे सत्र के बाद शुरू होती है, तो एक छोटे नए संवाद के साथ परीक्षण करें। यदि वह काम करता है, तो इतिहास ही कारण है। पुराने टर्न को छोड़कर, उन्हें एक संदेश में सारांशित करके, या एक नई चैट शुरू करके उसे कम करें। बड़े पेस्ट किए गए दस्तावेज़ दूसरा ट्रिगर हैं। कुछ सौ किलोबाइट का टेक्स्ट फ़ाइल ठीक है, लेकिन बेस64 ब्लॉब या बहुत बड़े लॉग 8 MB तक तेज़ी से पहुंच सकते हैं।
आपको max_tokens सेट करने की आवश्यकता नहीं है, क्योंकि पूरक टोकन विंडो के बचे हुए हिस्से का उपयोग कर सकता है। यदि आप इसे सेट करते हैं, तो सुनिश्चित करें कि प्रॉम्प्ट टोकन और max_tokens का योग 100,000 से कम रहे। एक क्लाइंट जो लंबे इतिहास के ऊपर एक बड़ा max_tokens हार्ड-कोड करता है, वह प्रॉम्प्ट अकेले ठीक दिखने पर भी योग को विंडो से अधिक कर सकता है।
प्रॉक्सी, बफ़रिंग और टाइमआउट
स्ट्रीमिंग सर्वर-सेंट इवेंट्स का उपयोग करता है: एक लंबे समय तक चलने वाला HTTP रिस्पॉन्स जो उत्पादन के रूप में छोटे चंक भेजता है। आप और API के बीच कुछ भी जो पूरे रिस्पॉन्स का इंतज़ार करता है और फिर आगे बढ़ाता है, वह उसे तोड़ देगा। परिणाम या तो एक लंबी खामोशी के बाद एक बर्स्ट, या एक टाइमआउट और सामान्य त्रुटि है।
अपने सेटअप में इनकी तलाश करें:
- रिवर्स प्रॉक्सी। यदि आप API को nginx या किसी समान प्रॉक्सी के माध्यम से रूट करते हैं, तो उस स्थान के लिए रिस्पॉन्स बफरिंग बंद करें, और अपनी अपेक्षित सबसे लंबे जवाब से ऊपर रीड टाइमआउट बढ़ाएं। 100,000 टोकन विंडो से आने वाले लंबे जवाबों में कुछ समय लग सकता है।
- कॉर्पोरेट या एंटीवायरस प्रॉक्सी। कुछ HTTPS ट्राफिक की जाँच करते हैं और बॉडी को रोकते हैं। इसे बाहर करने के लिए फोन हॉटस्पॉट से परीक्षण करें।
- सर्वरलेस फंक्शन्स। कई प्लेटफॉर्म एक्जीक्यूशन टाइम को सीमित करते हैं या प्रतिक्रियाओं को बफर करते हैं जब तक कि आप स्ट्रीमिंग को ऑप्ट इन न करें। यदि स्ट्रीम हर बार एक ही सेकंड की संख्या पर मर जाती है, तो प्लेटफॉर्म टाइम लिमिट संभावित कारण है।
- ब्राउज़र एक्सटेंशन और VPN। दुर्लभ, लेकिन वे आइडल कनेक्शन काट सकते हैं।
जो संकेत यहाँ इशारा करता है, वह एक उत्तर के बीच में त्रुटि है, हर प्रयास पर समान कट-ऑफ टाइम के साथ। एक रेट लिमिट अनुरोध को शुरुआत में अस्वीकार कर देगा, इसलिए एक मध्य-स्ट्रीम कट ऑफ जो हमेशा, उदाहरण के लिए, 30 सेकंड पर होता है, लगभग कभी एक लिमिट नहीं होता।
एक क्लाइंट जो असली त्रुटि दिखाता है
इसका उपयोग तब करें जब आप दोस्ताना संदेश के बजाय सत्य चाहते हों। यह OpenAI SDK अपवादों को पकड़ता है, स्थिति और त्रुटि बॉडी प्रिंट करता है, और यदि कोई पुनः प्रयास संकेत हो तो उसे पढ़ता है।
import time
from openai import OpenAI, APIConnectionError, APIStatusError, RateLimitError
client = OpenAI(
base_url="https://api.uncensoredllmhub.com/v1",
api_key="YOUR_API_KEY",
)
def stream_once(messages):
stream = client.chat.completions.create(
model="uncensored",
messages=messages,
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if getattr(chunk, "usage", None):
print("\n[usage]", chunk.usage)
messages = [{"role": "user", "content": "Write two sentences about harbours."}]
for attempt in range(4):
try:
stream_once(messages)
break
except RateLimitError as e:
wait = int(e.response.headers.get("retry-after", 5))
print("429:", e.body, "- waiting", wait, "s")
time.sleep(wait)
except APIStatusError as e:
print("status", e.status_code, e.body)
print("request id:", e.response.headers.get("x-request-id"))
break
except APIConnectionError as e:
print("connection problem:", e)
time.sleep(2)
Node में एक ही विचार, एक एबॉर्ट सिग्नल के साथ ताकि छोड़े गए स्ट्रीम अपने स्लॉट रिलीज कर सकें:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.uncensoredllmhub.com/v1",
apiKey: process.env.API_KEY,
});
const controller = new AbortController();
try {
const stream = await client.chat.completions.create(
{
model: "uncensored",
messages: [{ role: "user", content: "Write two sentences about harbours." }],
stream: true,
},
{ signal: controller.signal }
);
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
} catch (err) {
console.error("status:", err.status, "body:", err.error);
}
// call controller.abort() when the user leaves the page
और एक कच्चा curl कॉल, जो हर क्लाइंट को दृश्य से हटा देता है। -N curl के अपने बफरिंग को बंद कर देता है और -i स्थिति पंक्ति और हेडर प्रिंट करता है, जिसमें X-Request-Id भी शामिल है:
curl -N -i https://api.uncensoredllmhub.com/v1/chat/completions -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" -d '{"model":"uncensored","stream":true,"messages":[{"role":"user","content":"Say hello."}]}'
यदि curl टेक्स्ट को ठीक से स्ट्रीम करता है और आपका ऐप नहीं करता है, तो API स्वस्थ है और समस्या ऐप, उसके प्रॉक्सी या उसकी सेटिंग्स में है। यदि curl 429 या कोई अन्य स्थिति दिखाता है, तो आपके पास अब सटीक कारण है।
नियम जो चीजों को खराब नहीं करते
पुनः प्रयास अस्थायी समस्याओं में मदद करते हैं और स्थायी समस्याओं में नुकसान पहुँचाते हैं। एक छोटी नीति आपको मुसीबत से बचाती है।
- 429 और टूटे कनेक्शन के लिए पुनः प्रयास करें। जब
Retry-Afterमौजूद हो तो प्रतीक्षा करें, अन्यथा कुछ सेकंड के लिए बैकऑफ़ करें और कुछ यादृच्छिक ज़िटर जोड़ें ताकि समानांतर वर्कर एक साथ पुनः प्रयास न करें। - प्रमाणीकरण विफलताओं या अत्यधिक बड़े अनुरोधों को पुनः प्रयास न करें। परिणाम नहीं बदलेगा, और हर पुनः प्रयास केवल शोर जोड़ता है।
- प्रयासों को तीन या चार तक सीमित करें, फिर उपयोगकर्ता को असली त्रुटि पाठ दिखाएं।
- अपने समानांतरता को कुंजी लिमिट से नीचे कैप करें। एक पूर्ण कुंजी पर 6 का सेमाफोर उसी कुंजी का उपयोग कर रही दूसरी टूल के लिए जगह छोड़ देता है।
- यदि एक स्ट्रीम आधे में टूट जाती है, तो आंशिक टेक्स्ट रखें। मॉडल को जारी रखने के लिए उस टेक्स्ट को एक असिस्टेंट मैसेज के रूप में फिर से भेजें, बजाय शून्य से पुनः उत्पन्न करने के।
असफल या अस्वीकृत अनुरोधों के लिए चार्ज नहीं किया जाता है, इसलिए बार-बार टेस्ट कॉल से आपका क्रेडिट खत्म नहीं होता। सफल कॉल के लिए 1M इनपुट टोकन के लिए $0.15 और 1M आउटपुट टोकन के लिए $0.50 की वसूली होती है, और एक आंशिक स्ट्रीम जो सामान्य रूप से पूर्ण होती है, वह बस एक छोटा उत्तर है। अनुरोध प्रारूप पर अधिक विवरण API दस्तावेज़ीकरण में है।
यदि आपने ऊपर दिए गए सभी कदम उठाए हैं और फिर भी संदेश दिख रहा है, तो एक विफल कॉल का X-Request-Id सपोर्ट पेज पर भेजें, प्रयास का समय और विफलता पहले टोकन से पहले या बाद में आई थी, यह बताते हुए। यह जानकारी पर्याप्त है कि पता लगाया जा सके कि क्या हुआ।
