AI API کی ناکامیاں عام API ناکامیوں سے مختلف ہوتی ہیں۔ 200 ریسپانس اس بات کی ضمانت نہیں کہ آپ کی جنریشن کامیاب ہوئی۔ ایک null content فیلڈ ہمیشہ خرابی نہیں ہوتا۔ اور وہی پرامپٹ جو کل کام کر رہا تھا، آج کسی پرووائیڈر کی کنٹینٹ پالیسی اپ ڈیٹ کے باعث ناکام ہو سکتی ہے۔
یہ گائیڈ بتاتی ہے کہ AI API ایررز کو کیسے پڑھیں، ہر فیلئر موڈ کا مطلب کیا ہے، اور ایسا ایرر ہینڈلنگ کیسے بنائیں جو یہ بتائے کہ کیا ٹوٹا ہے، صرف یہ نہیں کہ کچھ ٹوٹ گیا ہے۔
نوٹ: اس مضمون میں استعمال ہونے والے ماڈل نام جیسے gpt-5.4 اور gpt-5.4-mini CometAPI کے پلیٹ فارم شناخت کار ہیں۔ یہ صرف https://api.cometapi.com/v1 کے ذریعے کام کرتے ہیں — براہ راست OpenAI یا Anthropic کی APIs کے ذریعے نہیں۔ مکمل ماڈل فہرست دیکھیں۔
کیوں AI API ڈیبگنگ عام API ڈیبگنگ سے زیادہ مشکل ہے
ایک عام REST API میں، 200 کا مطلب کامیابی اور 4xx کا مطلب آپ کی غلطی۔ AI APIs ایک تیسری قسم کا اضافہ کرتی ہیں: نرم ناکامیاں — ایسی جو 200 لوٹائیں لیکن قابلِ استعمال مواد نہ ہو۔
تین چیزیں غلط ہو سکتی ہیں:
- سخت ناکامی — HTTP ایرر (4xx، 5xx)۔ ریکویسٹ مکمل نہیں ہوئی۔
- نرم ناکامی — HTTP 200، لیکن
finish_reasoncontent_filterیاlengthہو، یاcontentnullہو۔ - خاموش ناکامی — HTTP 200، مواد ٹھیک دکھتا ہے، مگر آؤٹ پٹ معنوی طور پر غلط ہو جسے صرف ایپلیکیشن لیئر پر پکڑا جا سکتا ہے۔
زیادہ تر ایرر ہینڈلنگ صرف کیس 1 کو کور کرتی ہے۔ کیس 2 اور 3 میں زیادہ تر پراڈکشن بگز ہوتے ہیں۔
ایرر ریسپانس فارمیٹ کو سمجھیں
ٹیکسٹ کمپلیشنز اینڈ پوائنٹ ایک یکساں ایرر اسٹرکچر لوٹاتا ہے:
{ "error": { "message": "human-readable description (often includes request id)", "type": "comet_api_error", "param": "the_problematic_parameter_or_null", "code": "error_code_or_null" }}
امیج اور ویڈیو اینڈپوائنٹس مختلف ایرر فارمیٹس لوٹاتے ہیں — اینڈپوائنٹس کے پار ایک مقررہ اسٹرکچر فرض کرنے کے بجائے ہمیشہ را بڈی کو پارس کریں۔
message فیلڈ عموماً آپ کو عین مسئلہ بتا دیتی ہے۔ param فیلڈ بتاتی ہے کہ کون سا پیرامیٹر وجہ بنا۔ دونوں کو ہمیشہ لاگ کریں۔
ہر HTTP اسٹیٹس کوڈ کا مطلب جانیں
| Status | Meaning | Common cause | Fix |
|---|---|---|---|
| 400 | خراب ریکویسٹ | ماڈل غائب، اس ماڈل کے لیے غلط پیرامیٹر | ریسپانس میں error.param چیک کریں |
| 401 | غیر مجاز | غلط یا غائب API کلید | Authorization: Bearer |
| 429 | ریٹ لمٹ | بہت زیادہ ریکویسٹس | ایکسپونینشل بیک آف (قدم 4 دیکھیں) |
| 500 | سرور ایرر | پرووائیڈر سائیڈ مسئلہ، یا خراب ریکویسٹ باڈی | بیک آف کے ساتھ دوبارہ کوشش؛ ریکویسٹ فارمیٹ چیک کریں |
| 504 | گیٹ وے ٹائم آؤٹ | پرووائیڈر نے بہت دیر لگا دی | دوبارہ کوشش؛ تیز تر ماڈل پر غور کریں |
ماخذ**: CometAPI chat completions docs
400 بمقابلہ 500 کا فرق ریٹری لاجک کے لیے اہم ہے۔ 400 کا مطلب آپ کی ریکویسٹ غلط ہے — وہی ریکویسٹ دوبارہ بھیجنا مدد نہیں کرے گا۔ 500 یا 504 کا مطلب سرور کا مسئلہ — دوبارہ کوشش کرنا مناسب ہے۔
finish_reason چیک کریں — سب سے نظر انداز کیا جانے والا فیلڈ
finish_reason: "content_filter" کے ساتھ 200 ریسپانس کا مطلب ہے آپ کی جنریشن بلاک ہو گئی۔ content فیلڈ null یا خالی ہوگی۔ اگر آپ یہ چیک نہیں کرتے تو آپ کی ایپ خاموشی سے کچھ نہیں لوٹائے گی۔
| finish_reason | Meaning | What to do | Fix |
|---|---|---|---|
| stop | معمول کے مطابق تکمیل | کچھ نہیں — یہ کامیابی ہے | ریسپانس میں error.param چیک کریں |
| length | ٹوکن حد لگ گئی | max_tokens بڑھائیں یا پرامپٹ مختصر کریں | Authorization: Bearer |
| content_filter | سیفٹی پالیسی نے بلاک کر دیا | پرامپٹ کو نئے انداز میں لکھیں؛ مخصوص نام/موضوعات سے پرہیز کریں | ایکسپونینشل بیک آف (قدم 4 دیکھیں) |
| tool_calls | ماڈل نے ٹیکسٹ دینے کے بجائے ٹول کال کی | ٹول کال ہینڈل کریں؛ content null ہوگا | بیک آف کے ساتھ دوبارہ کوشش؛ ریکویسٹ فارمیٹ چیک کریں |
| 504 | گیٹ وے ٹائم آؤٹ | پرووائیڈر نے بہت دیر لگا دی | دوبارہ کوشش؛ تیز تر ماڈل پر غور کریں |
ماخذ**: CometAPI chat completions docs
import osimport loggingfrom openai import OpenAI, APIStatusError, APIConnectionError, APITimeoutErrorfrom dotenv import load_dotenvload_dotenv()api_key = os.environ.get("COMETAPI_KEY")if not api_key: raise ValueError("COMETAPI_KEY is not set")client = OpenAI( base_url="https://api.cometapi.com/v1", api_key=api_key,)def safe_complete(messages: list, model: str = "gpt-5.4-mini", **kwargs) -> dict: """ Complete a chat request with full error and finish_reason handling. Returns {"content": str, "finish_reason": str, "tool_calls": list | None} Raises on API errors. """ try: response = client.chat.completions.create( model=model, messages=messages, **kwargs ) except APIStatusError as e: error_body = {} try: error_body = e.response.json().get("error", {}) except Exception: pass logging.error( f"API error status={e.status_code} " f"message={error_body.get('message')} " f"param={error_body.get('param')}" ) raise except (APIConnectionError, APITimeoutError) as e: logging.error(f"Network/timeout error: {e}") raise choice = response.choices[0] finish_reason = choice.finish_reason if finish_reason == "content_filter": raise ValueError( f"Generation blocked by content filter. " f"Model: {model}. Rephrase the prompt." ) if finish_reason == "length": used = response.usage.completion_tokens if response.usage else "unknown" logging.warning(f"Output truncated at token limit. Used {used} tokens.") # Return structured result so callers can handle tool_calls explicitly return { "content": choice.message.content or "", "finish_reason": finish_reason, "tool_calls": choice.message.tool_calls, }# Usageresult = safe_complete( messages=[{"role": "user", "content": "Summarize this article: [text]"}], model="gpt-5.4-mini")if result["finish_reason"] == "tool_calls": # Handle tool call — content will be empty print("Model wants to call a tool:", result["tool_calls"])else: print(result["content"])
ایپلیکیشن لیئر پر خاموش ناکامیوں کا پتہ لگائیں
خاموش ناکامیاں پکڑنا سب سے مشکل ہے۔ API 200 لوٹاتی ہے، finish_reason stop ہوتا ہے، مگر آؤٹ پٹ معنوی طور پر غلط ہے۔ آپ انہیں صرف ایپلیکیشن لیئر پر پکڑ سکتے ہیں۔
عام پیٹرنز:
def validate_completion(result: dict, task: str) -> str: """ Application-layer validation for silent failures. Raises ValueError if the output doesn't meet basic expectations. """ content = result["content"].strip() # Empty output that isn't a tool call if not content and result["finish_reason"] != "tool_calls": raise ValueError(f"Empty output for task '{task}' with finish_reason='{result['finish_reason']}'") # Task-specific checks if task == "classify": valid_labels = {"positive", "negative", "neutral"} if content.lower() not in valid_labels: logging.warning( f"Unexpected classification output: '{content}'. " f"Expected one of {valid_labels}. " f"Model may have returned explanation instead of label." ) if task == "json_extract": import json try: json.loads(content) except json.JSONDecodeError: raise ValueError( f"Expected JSON output but got: '{content[:100]}...'. " f"Try adding 'respond with valid JSON only' to the prompt, " f"or use response_format={{\"type\": \"json_object\"}}." ) if task == "summarize" and len(content.split()) < 10: logging.warning( f"Suspiciously short summary ({len(content.split())} words). " f"Check if the input was too short or the model misunderstood the task." ) return content# Full flow with silent failure detectionresult = safe_complete( messages=[{"role": "user", "content": "Classify as positive/negative/neutral: 'Great product!'"}], model="claude-haiku-4-5")label = validate_completion(result, task="classify")
خاموش ناکامیاں عموماً تین ذرائع سے آتی ہیں: پرامپٹ مبہم ہے، ماڈل نے آپ کی فارمیٹ ہدایات نظر انداز کر دیں، یا ان پٹ اس ٹاسک کے لیے بہت چھوٹا/طویل تھا۔ جب ویلیڈیشن ناکام ہو تو پورا آؤٹ پٹ لاگ کرنا سب سے تیز تشخیص ہے کہ کون سا مسئلہ تھا۔
ریٹ لمٹس کے لیے ایکسپونینشل بیک آف شامل کریں
ریٹ لمٹ ایررز (429) عارضی ہوتے ہیں۔ درست ردِعمل یہ ہے کہ بڑھتے وقفوں سے انتظار کریں اور دوبارہ کوشش کریں — یہ کسی بھی ریٹ لمٹ والی API کے لیے معیاری عمل ہے:
import timeimport randomfrom openai import RateLimitErrordef complete_with_retry( messages: list, model: str = "gpt-5.4-mini", max_retries: int = 3, **kwargs) -> dict: """Retry on rate limits and server errors with exponential backoff.""" last_error = None for attempt in range(max_retries): try: return safe_complete(messages, model=model, **kwargs) except APIStatusError as e: if e.status_code < 500: raise # 4xx: don't retry, request is wrong last_error = e except RateLimitError as e: last_error = e except (APIConnectionError, APITimeoutError) as e: last_error = e if attempt < max_retries - 1: wait = (2 ** attempt) + random.random() # jitter prevents thundering herd logging.warning(f"Attempt {attempt + 1} failed. Waiting {wait:.1f}s before retry.") time.sleep(wait) raise RuntimeError(f"All {max_retries} attempts failed") from last_error
400 یا 401 پر دوبارہ کوشش نہ کریں — یہ کلائنٹ ایررز ہیں جو خود بخود درست نہیں ہوں گے۔
امیج جنریشن ناکامیوں کو ڈیبگ کریں
امیج جنریشن کے اپنے فیلئر موڈز ہوتے ہیں، معیاری HTTP ایررز کے علاوہ:
import base64import requestsdef generate_image_safe(prompt: str, model: str = "dall-e-3") -> dict: """ Generate an image with full error handling. Returns {"url": str | None, "bytes": bytes | None, "blocked": bool} """ api_key = os.environ.get("COMETAPI_KEY") if not api_key: raise ValueError("COMETAPI_KEY is not set") BASE64_MODELS = {"gpt-image-2", "qwen-image"} headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } payload = {"model": model, "prompt": prompt, "size": "1024x1024"} if model in BASE64_MODELS: payload["output_format"] = "png" else: payload["response_format"] = "url" try: response = requests.post( "https://api.cometapi.com/v1/images/generations", json=payload, headers=headers, timeout=60 ) response.raise_for_status() except requests.exceptions.HTTPError as e: logging.error(f"Image generation HTTP error: {e.response.status_code} {e.response.text}") raise except requests.exceptions.Timeout: logging.error("Image generation timed out after 60s") raise data = response.json().get("data", []) if not data: logging.warning("Image generation returned empty data — prompt may have been filtered.") return {"url": None, "bytes": None, "blocked": True} item = data[0] if "revised_prompt" in item: logging.info(f"Provider revised prompt to: {item['revised_prompt']}") if "url" in item: return {"url": item["url"], "bytes": None, "blocked": False} return { "url": None, "bytes": base64.b64decode(item["b64_json"]), "blocked": False }
امیج سے متعلق مخصوص مسائل:
| Symptom | Cause | Fix |
|---|---|---|
| خالی data ارے | پرامپٹ فلٹر ہو گیا | revised_prompt چیک کریں؛ دوبارہ لکھیں |
| GPT Image 2 پر response_format ایرر | پیرامیٹر سپورٹ نہیں | output_format استعمال کریں |
| Qwen Image پر n > 1 ایرر | ماڈل کی حد | ریکویسٹس کو لوپ میں بھیجیں |
| بعد میں URL کا 403 لوٹانا | URL کی معیاد ختم | جنریشن کے فوراً بعد ڈاؤن لوڈ کریں |
ماخذ**: CometAPI image generation docs
ویڈیو جنریشن ناکامیوں کو ڈیبگ کریں
ویڈیو جنریشن مختلف انداز سے ناکام ہوتی ہے کیونکہ یہ async ہے۔ ٹائم آؤٹ ایرر میسج کو ہمیشہ درست رکھنے کے لیے لوپ سے پہلے اسٹیٹس ویری ایبلز initialize کریں:
def submit_and_poll_video( prompt: str, model: str = "veo3-fast", max_wait: int = 600) -> str: """Submit video task and poll to completion. Returns video URL.""" api_key = os.environ.get("COMETAPI_KEY") if not api_key: raise ValueError("COMETAPI_KEY is not set") headers = {"Authorization": f"Bearer {api_key}"} try: response = requests.post( "https://api.cometapi.com/v1/videos", headers=headers, files={ "prompt": (None, prompt), "model": (None, model), "size": (None, "16x9") }, timeout=30 ) response.raise_for_status() except requests.exceptions.HTTPError as e: logging.error(f"Video submit failed: {e.response.status_code} {e.response.text}") raise task_id = response.json()["id"] logging.info(f"Video task submitted: {task_id}") poll_url = f"https://api.cometapi.com/v1/videos/{task_id}" elapsed = 0 interval = 10 status = "unknown" # initialize before loop progress = 0 # initialize before loop while elapsed < max_wait: try: poll_response = requests.get(poll_url, headers=headers, timeout=30) poll_response.raise_for_status() except requests.exceptions.HTTPError as e: logging.error(f"Poll request failed: {e.response.status_code}") raise result = poll_response.json() status = result.get("status", "unknown") progress = result.get("progress", 0) logging.info(f"Task {task_id}: status={status} progress={progress}%") if status == "succeeded": return result["output"][0] elif status in ("failed", "cancelled"): error_detail = result.get("error", "no error detail returned") raise RuntimeError(f"Video task {task_id} failed: {error_detail}") time.sleep(interval) elapsed += interval raise TimeoutError( f"Video task {task_id} did not complete within {max_wait}s. " f"Last status: {status}, progress: {progress}%" )
ویڈیو سے متعلق مخصوص مسائل:
| Symptom | Cause | Fix |
|---|---|---|
| ٹاسک 10+ منٹ تک queued میں پھنسا ہوا | سرور لوڈ | مختلف ماڈل کے ساتھ ریٹری کریں |
| failed اور کوئی ایرر تفصیل نہیں | پرامپٹ فلٹر یا ماڈل ایرر | پرامپٹ دوبارہ لکھیں |
| ویڈیو URL 403 لوٹاتا ہے | URL کی معیاد ختم | فوراً ڈاؤن لوڈ کریں |
| Runway کی پہلی پول پر task_not_exist | ٹاسک ابھی initialize ہو رہا ہے (CometAPI کی دستاویز شدہ رویہ) | 5s انتظار کریں اور ریٹری کریں |
| Kling "succeed" نہ کہ "succeeded" لوٹاتا | Kling کی API غیر معیاری اسٹیٹس سٹرنگ استعمال کرتی ہے | پولنگ لاجک میں دونوں ہینڈل کریں |
ماخذ**: CometAPI video generation docs**, Kling Video docs
Node.js ورژن
import OpenAI from 'openai';const apiKey = process.env.COMETAPI_KEY;if (!apiKey) throw new Error('COMETAPI_KEY is not set');const client = new OpenAI({ baseURL: 'https://api.cometapi.com/v1', apiKey,});async function safeComplete(messages, model = 'gpt-5.4-mini', options = {}) { let response; try { response = await client.chat.completions.create({ model, messages, ...options }); } catch (err) { if (err.status && err.status < 500) { console.error(`Client error ${err.status}: ${err.message}`); } else { console.error(`Server/network error: ${err.message}`); } throw err; } const choice = response.choices[0]; const finishReason = choice.finish_reason; if (finishReason === 'content_filter') { throw new Error(`Generation blocked by content filter. Model: ${model}`); } if (finishReason === 'length') { console.warn(`Output truncated. Used ${response.usage?.completion_tokens ?? 'unknown'} tokens.`); } return { content: choice.message.content ?? '', finishReason, toolCalls: choice.message.tool_calls ?? null, };}async function completeWithRetry(messages, model = 'gpt-5.4-mini', maxRetries = 3) { let lastError; for (let attempt = 0; attempt < maxRetries; attempt++) { try { return await safeComplete(messages, model); } catch (err) { // Don't retry 4xx client errors if (err.status && err.status < 500) throw err; lastError = err; if (attempt < maxRetries - 1) { const wait = (2 ** attempt + Math.random()) * 1000; console.warn(`Attempt ${attempt + 1} failed. Retrying in ${(wait / 1000).toFixed(1)}s`); await new Promise(r => setTimeout(r, wait)); } } } throw new Error(`All ${maxRetries} attempts failed: ${lastError?.message}`);}// Usageconst result = await safeComplete( [{ role: 'user', content: 'Classify as positive/negative/neutral: "Great product!"' }], 'claude-haiku-4-5');if (result.finishReason === 'tool_calls') { console.log('Tool call requested:', result.toolCalls);} else { console.log(result.content);}
ایک ڈیبگنگ چیک لسٹ
جب جنریشن ناکام ہو اور آپ کو سمجھ نہ آئے کہاں سے شروع کریں:
ٹیکسٹ جنریشن کے لیے:
- کیا API کلید سیٹ ہے اور
Authorization: Bearer <key>فارمیٹ میں ہے؟ - کیا
finish_reasonstopکے علاوہ کچھ ہے؟ - کیا
contentnull ہے؟ چیک کریں کہfinish_reasontool_callsتو نہیں - کیا آؤٹ پٹ تراش دیا گیا؟
finish_reason: "length"اورusage.completion_tokensدیکھیں - کیا ایرر 4xx ہے (ریکویسٹ درست کریں) یا 5xx (دوبارہ کوشش کریں)؟
- کیا آؤٹ پٹ آپ کی ایپلیکیشن لیئر ویلیڈیشن پر پورا اترتا ہے؟ (خاموش ناکامی)
امیج جنریشن کے لیے:
- کیا
dataارے خالی ہے؟ (کنٹینٹ فلٹر) - کیا آپ نے GPT Image 2 پر
response_formatاستعمال کیا؟ (سپورٹ نہیں —output_formatاستعمال کریں) - کیا آپ نے Qwen Image پر
n > 1سیٹ کیا؟ (سپورٹ نہیں) - کیا آپ نے URL کے ایکسپائر ہونے سے پہلے امیج ڈاؤن لوڈ کیا؟
ویڈیو جنریشن کے لیے:
- کیا ٹاسک
queuedمیں پھنسا ہوا ہے؟ (مختلف ماڈل آزمائیں) - کیا آپ نے ناکام ٹاسک ریسپانس میں
errorفیلڈ چیک کی؟ - کیا آپ نے URL کے ایکسپائر ہونے سے پہلے ویڈیو ڈاؤن لوڈ کی؟
- کیا آپ
"succeed"(Kling) اور"succeeded"(Veo، Runway) دونوں کو ہینڈل کر رہے ہیں؟
سوالاتِ متداولہ (FAQ)
سوال: میری ریکویسٹ 200 لوٹاتی ہے مگر کوئی مواد نہیں۔ کیا ہوا؟
finish_reason چیک کریں۔ اگر content_filter ہے تو جنریشن بلاک ہو گئی — ریکویسٹ کامیاب ہوئی مگر آؤٹ پٹ کو دبا دیا گیا۔ اگر tool_calls ہے تو ماڈل نے ٹیکسٹ کے بجائے ٹول کال کی، اور content ڈیزائن کے مطابق null ہے۔ اگر finish_reason stop ہے لیکن مواد پھر بھی خالی ہے، یہ خاموش ناکامی ہے — پورا ریسپانس لاگ کریں اور اپنا پرامپٹ چیک کریں۔
سوال: مجھے کیسے معلوم ہو کہ میرا پرامپٹ فلٹر ہو رہا ہے؟
ٹیکسٹ کے لیے: چیک کریں finish_reason === "content_filter"۔ امیجز کے لیے: دیکھیں data ارے خالی ہے یا نہیں۔ ویڈیو کے لیے: دیکھیں ٹاسک سبمٹ کرنے کے فوراً بعد failed پر پہنچتا ہے اور کوئی ایرر تفصیل نہیں ملتی۔ ہر صورت میں، پرامپٹ کو زیادہ غیر جانب دار انداز میں دوبارہ لکھنے کی کوشش کریں۔
سوال: مجھے کب ناکام ریکویسٹ کو دوبارہ آزمانا چاہیے؟
429 اور 5xx پر ایکسپونینشل بیک آف کے ساتھ ریٹری کریں۔ 4xx پر ریٹری نہ کریں — خراب ریکویسٹ خود ٹھیک نہیں ہوگی۔ استثنا 401 ہے اگر آپ API کیز گھما رہے ہیں۔
سوال: ایکسپونینشل بیک آف کیا ہے اور یہ کیوں اہم ہے؟
فوراً دوبارہ کوشش کرنے کے بجائے، آپ بتدریج زیادہ انتظار کرتے ہیں: 1s، 2s، 4s۔ رینڈم جِٹر (+ random.random()) اس بات کو روکتا ہے کہ کئی کلائنٹس ایک ساتھ ریٹری نہ کریں۔ یہ کسی بھی ریٹ لمٹ والی API کے لیے معیاری عمل ہے — خاص طور پر CometAPI تک محدود نہیں۔
سوال: ویڈیو ٹاسک 10 منٹ سے queued میں پھنسا ہے۔ کیا یہ ناکام ہو گیا؟
ضروری نہیں — لوڈ کے تحت قطاریں بڑھ سکتی ہیں۔ اپنے max_wait تک انتظار کریں، پھر TimeoutError اٹھائیں اور مختلف ماڈل کے ساتھ ریٹری کریں۔ ٹاسک آئی ڈی لاگ کریں تاکہ ضرورت پڑنے پر دستی طور پر اسٹیٹس چیک کیا جا سکے۔
سوال: میں خاموش ناکامیوں کو کیسے پکڑوں؟
خاموش ناکامیوں کے لیے ایپلیکیشن لیئر ویلیڈیشن درکار ہے — API آپ کو نہیں بتائے گی کہ آؤٹ پٹ معنوی طور پر غلط ہے۔ چیک کریں کہ آؤٹ پٹ متوقع فارمیٹ سے میل کھاتا ہے (valid JSON، متوقع لیبل، کم از کم طوالت)۔ جب ویلیڈیشن ناکام ہو تو پورا آؤٹ پٹ لاگ کریں۔ سب سے عام وجوہات ہیں مبہم پرامپٹس، فارمیٹ ہدایات کو نظر انداز کرنا، یا ٹاسک کے لیے ان پٹ کا بہت چھوٹا یا بہت طویل ہونا۔
