Kimi K2.7 Code is now on CometAPI — Kimi's most intelligent coding model to date, reliably follows instructions in long contexts and completes programming tasks with a higher success rate. Try it now

Сәтсіз аяқталған AI API генерацияларын қалай дебагтау

CometAPI
AnnaJun 4, 2026
Сәтсіз аяқталған AI API генерацияларын қалай дебагтау

AI API істен шығулары кәдімгі API істен шығуларынан өзгеше. 200 жауабы генерацияның сәтті өткенін білдірмейді. null content өрісі әрдайым қате емес. Кеше жұмыс істеген дәл сол prompt бүгін провайдердің контент саясаты жаңарғандықтан сәтсіз болуы мүмкін.

Бұл нұсқаулық AI API қателерін қалай оқу керегін, әрбір істен шығу режимінің нені білдіретінін және “бірдеңе бұзылды” деп қана айтпай, нақты қай жерде бұзылғанын көрсететін қате өңдеуді қалай құруды қамтиды.

Note: Бұл мақалада қолданылған gpt-5.4 және gpt-5.4-mini сияқты модель атаулары CometAPI платформасының идентификаторлары. Олар тек https://api.cometapi.com/v1 арқылы жұмыс істейді — OpenAI немесе Anthropic API-лары арқылы тікелей емес. Толық модель тізімін қараңыз.

Неліктен AI API диагностикасы кәдімгі API-ға қарағанда қиынырақ

Әдеттегі REST API-де 200 — сәтті, ал 4xx — сіздің қатеңіз. AI API-ларда үшінші санат бар: жұмсақ сәтсіздіктер — 200 қайтарады, бірақ қолдануға болатын мазмұн жоқ.

Үш нәрсе қате кетуі мүмкін:

  1. Қатаң сәтсіздік — HTTP қатесі (4xx, 5xx). Сұраныс аяқталмады.
  2. Жұмсақ сәтсіздік — HTTP 200, бірақ finish_reason content_filter немесе length, не content null.
  3. Үнсіз сәтсіздік — HTTP 200, контент қалыпты сияқты, бірақ нәтиже қолданба деңгейінде ғана байқалатын түрде қате.

Қате өңдеудің көпшілігі тек 1-жағдайды қамтиды. Нақты өндірістік ақаулардың көбі 2 және 3-жағдайларда болады.

Қате жауап форматын түсіну

Text completions endpoint-і тұрақты қате құрылымын қайтарады:

{  "error": {    "message": "human-readable description (often includes request id)",    "type": "comet_api_error",    "param": "the_problematic_parameter_or_null",    "code": "error_code_or_null"  }}

Сурет және видео endpoint-тері басқа қате форматтарын қайтарады — endpoint-тер арасында тұрақты құрылымға сүйенбей, әрқашан бастапқы жауап денесін талдаңыз.

message өрісі әдетте нақты не қате екенін айтады. param өрісі қандай параметр себеп болғанын көрсетеді. Екеуін де әрқашан логтаңыз.

Әрбір HTTP мәртебе кодын нені білдіретінін біліңіз

StatusМағынаЖиі себепШешім
400Bad requestМодель жоқ, осы модельге тән емес параметрЖауаптағы error.param-ды тексеріңіз
401UnauthorizedAPI кілті қате немесе жоқAuthorization: Bearer форматын тексеріңіз
429Rate limitedӨте көп сұраныстарЭкспоненциалды backoff (4-қадамды қараңыз)
500Server errorПровайдер жағындағы мәселе немесе қате денеBackoff-пен қайталап көріңіз; форматты тексеріңіз
504Gateway timeoutПровайдер тым ұзақ жауап бердіҚайта көріңіз; жылдамырақ модельді қарастырыңыз

Source**: CometAPI chat completions docs

400 мен 500 айырмашылығы retry логикасы үшін маңызды. 400 — сіздің сұранысыңыз қате — дәл сол сұранысты қайталау көмектеспейді. 500 немесе 504 — сервер жағындағы мәселе — қайталап көру орынды.

Ең көп еленбейтін өріс — finish_reason-ды тексеріңіз

finish_reason: "content_filter" бар 200 жауабы генерацияның бұғатталғанын білдіреді. content өрісі null немесе бос болады. Мұны тексермесеңіз, қолданбаңыз үн-түнсіз ештеңе қайтаруы мүмкін.

finish_reasonМағынаНе істеу керекШешім
stopҚалыпты аяқталуЕштеңе — бұл сәтті аяқталуЖауаптағы error.param-ды тексеріңіз
lengthТокен шегіне жеттіmax_tokens-ты ұлғайтыңыз немесе prompt-ты қысқартыңызAuthorization: Bearer форматын тексеріңіз
content_filterҚауіпсіздік саясаты бұғаттадыPrompt-ты қайта тұжырымдаңыз; нақты есім/тақырыптардан аулақ болыңызЭкспоненциалды backoff (4-қадам)
tool_callsМодель мәтін орнына құралды шақырдыҚұрал шақыруын өңдеңіз; content null боладыBackoff-пен қайталап көріңіз; форматты тексеріңіз
504Gateway timeoutПровайдер тым ұзақ жауап бердіҚайта көріңіз; жылдамырақ модельді қарастырыңыз

Source**: CometAPI chat completions docs

import osimport loggingfrom openai import OpenAI, APIStatusError, APIConnectionError, APITimeoutErrorfrom dotenv import load_dotenv​load_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_reasonstop, бірақ нәтиже семантикалық тұрғыдан қате. Мұны тек қолданба деңгейінде ғана анықтауға болады.

Жиі үлгілер:

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")

Үнсіз сәтсіздіктер әдетте үш себептің бірінен болады: prompt екіұшты, модель формат нұсқауларын елемеді немесе енгізу тапсырма үшін тым қысқа/ұзын болды. Валидтеу сәтсіз болғанда толық output-ты логтау қай себеп екенін анықтаудың ең жылдам жолы.

Rate limit үшін экспоненциалды backoff қосыңыз

Rate limit қателері (429) уақытша. Дұрыс әрекет — кідірістерді біртіндеп ұзартып, қайта әрекет ету — rate limit бар кез келген API үшін стандартты тәжірибе:

import timeimport randomfrom openai import RateLimitError​def 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 requests​def 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    }

Суретке тән мәселелер:

БелгіСебепШешім
Бос data массивіPrompt сүзгіден өттіrevised_prompt-ты тексеріңіз; қайта жазыңыз
GPT Image 2-де response_format қатесіПараметр қолдау таппайдыОның орнына output_format қолданыңыз
Qwen Image-те n > 1 қатесіМодель шектеуіЦиклмен жеке сұраныстар жіберіңіз
URL кейінірек 403 қайтарадыURL мерзімі өттіГенерациядан кейін бірден жүктеңіз

Source**: CometAPI image generation docs

Видео генерациясы ақауларын түзету

Видео генерациясы асинхронды болғандықтан, басқаша сәтсіздікке ұшырайды. Таймаут хабарламасы әрдайым дұрыс қалыптасуы үшін циклге дейін статус айнымалыларын инициализациялаңыз:

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}%"    )

Видеге тән мәселелер:

БелгіСебепШешім
Тапсырма 10+ минут бойы queued күйіндеСервер жүктемесіБасқа модельмен қайталап көріңіз
failed және error detail жоқPrompt сүзгіден өтті немесе модель қатесіPrompt-ты қайта жазыңыз
Видео URL 403 қайтарадыURL мерзімі өттіДереу жүктеп алыңыз
Runway бірінші polling-де task_not_existТапсырма әлі инициализацияда (CometAPI құжатталған)5с күтіп, қайталаңыз
Kling "succeed", ал басқалары "succeeded"Kling API стандарттан тыс статус жолын қолданадыPolling логикасында екеуін де өңдеңіз

Source**: 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);}

Ақауды түзетуге арналған чек-парақ

Генерация сәтсіз болып, неден бастарыңызды білмесеңіз:

Text generation үшін:

  • API кілті орнатылған ба және Authorization: Bearer <key> форматында ма?
  • finish_reason stop емес пе?
  • content null ма? finish_reason tool_calls екенін тексеріңіз
  • Шығыс қысқарып қалды ма? finish_reason: "length" және usage.completion_tokens-ты тексеріңіз
  • Қате — 4xx (сұранысты түзету) әлде 5xx (қайта көру)?
  • Нәтиже қолданба деңгейіндегі валидациядан өтті ме? (үнсіз сәтсіздік)

Image generation үшін:

  • data массиві бос па? (контент сүзгісі)
  • GPT Image 2-де response_format қолдандыңыз ба? (қолдау жоқ — output_format қолданыңыз)
  • Qwen Image-те n > 1 қойдыңыз ба? (қолдау жоқ)
  • URL мерзімі өтпей тұрып суретті жүктеп алдыңыз ба?

Video generation үшін:

  • Тапсырма queued күйінде тұрып қалды ма? (басқа модельді көріңіз)
  • Сәтсіз тапсырма жауаптан error өрісін тексердіңіз бе?
  • URL мерзімі өтпей тұрып видеоны жүктеп алдыңыз ба?
  • "succeed" (Kling) және "succeeded" (Veo, Runway) екеуін де өңдеп жатырсыз ба?

Жиі қойылатын сұрақтар

Q: Сұраныс 200 қайтарады, бірақ контент жоқ. Не болды?

finish_reason-ды тексеріңіз. Егер content_filter болса, генерация бұғатталды — сұраныс сәтті өтті, бірақ шығыс басылды. Егер tool_calls болса, модель мәтін орнына құралды шақырды және content әдейі null. Егер finish_reason stop, бірақ контент әлі де бос болса — бұл үнсіз сәтсіздік — толық жауапты логтап, prompt-ты тексеріңіз.

Q: Prompt-ым сүзгіден өтіп жатқанын қалай білемін?

Мәтін үшін: finish_reason === "content_filter" екеніне қараңыз. Суреттер үшін: data массиві бос па, тексеріңіз. Видео үшін: жібергеннен көп ұзамай failed күйіне түсіп, error detail бермесе, ықтимал сүзгі. Барлық жағдайда prompt-ты бейтарап етіп қайта жазыңыз.

Q: Қашан сәтсіз сұранысты қайта көру керек?

429 және 5xx үшін экспоненциалды backoff-пен қайталаңыз. 4xx үшін қайталамаңыз — қате сұраныс өздігінен түзелмейді. Ерекше жағдай — 401, егер API кілттерін ауыстырып жатсаңыз.

Q: Экспоненциалды backoff деген не және неге маңызды?

Дереу қайталамай, кідірісті біртіндеп ұзартасыз: 1с, 2с, 4с. Кездейсоқ jitter (+ random.random()) бірнеше клиенттің бір сәтте қайталап жіберуін болдырмайды. Бұл кез келген rate limit бар API үшін стандартты тәжірибе — CometAPI-ға ғана тән емес.

Q: Видео тапсырма queued күйінде 10 минут тұр. Бұл сәтсіздік пе?

Әрқашан емес — жүктеме кезінде кезек ұзауы мүмкін. Өз max_wait шегіңізге дейін күтіңіз, содан кейін TimeoutError тастап, басқа модельмен қайталап көріңіз. Қолмен тексеру үшін task ID-ны логтаңыз.

Q: Үнсіз сәтсіздіктерді қалай ұстауға болады?

Үнсіз сәтсіздіктер үшін қолданба деңгейінде валидация қажет — API шығудың семантикалық тұрғыдан дұрыс еместігін айтпайды. Шығыс күтілетін форматқа сай ма (валид JSON, күтілетін белгі, минималды ұзындық) тексеріңіз. Валидация сәтсіз болса, толық шығуды логтаңыз. Ең жиі себептер: екіұшты prompt, формат нұсқауларын елемеу немесе тапсырмаға сай емес өте қысқа/ұзын енгізу.

AI әзірлеу шығындарын 20%-ға қысқартуға дайынсыз ба?

Минуттар ішінде тегін бастаңыз. Тегін сынақ кредиттері қосылған. Банк картасы талап етілмейді.

Толығырақ оқу