ความล้มเหลวของ AI API แตกต่างจากความล้มเหลวของ API ทั่วไป คำตอบสถานะ 200 ไม่ได้แปลว่าการสร้างผลลัพธ์ของคุณสำเร็จเสมอไป ฟิลด์ content ที่เป็น null ก็ไม่ใช่ความผิดพลาดเสมอ และพรอมป์เดียวกันที่ใช้ได้เมื่อวานอาจใช้ไม่ได้วันนี้เพราะผู้ให้บริการอัปเดตนโยบายเนื้อหา
คู่มือนี้อธิบายวิธีอ่านข้อผิดพลาดของ AI API ความหมายของโหมดความล้มเหลวแต่ละแบบ และวิธีสร้างการจัดการข้อผิดพลาดที่บอกคุณได้อย่างชัดเจนว่าอะไรเสีย แทนที่จะบอกแค่ว่ามีบางอย่างเสีย
หมายเหตุ: ชื่อโมเดลอย่าง gpt-5.4 และ gpt-5.4-mini ที่ใช้ในบทความนี้คือไอดีของแพลตฟอร์ม CometAPI ใช้งานผ่าน https://api.cometapi.com/v1 เท่านั้น — ไม่สามารถใช้ผ่าน API ของ OpenAI หรือ Anthropic โดยตรง ดู รายชื่อโมเดลทั้งหมด
ทำไมการดีบัก AI API จึงยากกว่า API ทั่วไป
กับ REST API ทั่วไป สถานะ 200 หมายถึงสำเร็จ และ 4xx หมายถึงคุณทำผิดพลาดเอง AI API เพิ่มหมวดที่สามคือความล้มเหลวแบบนุ่มนวล — ตอบกลับด้วย 200 แต่ไม่มีเนื้อหาที่ใช้งานได้
สามอย่างที่อาจผิดพลาด:
- ความล้มเหลวแบบแข็ง — ข้อผิดพลาด HTTP (4xx, 5xx) คำขอไม่สำเร็จ
- ความล้มเหลวแบบนุ่มนวล — HTTP 200 แต่
finish_reasonเป็นcontent_filterหรือlengthหรือcontentเป็นnull - ความล้มเหลวแบบเงียบ — HTTP 200 เนื้อหาดูเหมือนปกติ แต่ผลลัพธ์ผิดในเชิงความหมาย ซึ่งจะจับได้ที่ชั้นแอปพลิเคชันเท่านั้น
การจัดการข้อผิดพลาดส่วนใหญ่มักครอบคลุมเฉพาะกรณีที่ 1 กรณี 2 และ 3 คือที่มาของบั๊กในการผลิตส่วนใหญ่
ทำความเข้าใจรูปแบบการตอบกลับข้อผิดพลาด
ปลายทาง text completions ส่งคืนโครงสร้างข้อผิดพลาดที่สม่ำเสมอ:
{ "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 แต่ละตัว
| สถานะ | ความหมาย | สาเหตุที่พบบ่อย | วิธีแก้ |
|---|---|---|---|
| 400 | คำขอไม่ถูกต้อง | ไม่มีโมเดลหรือใช้พารามิเตอร์ไม่ตรงกับโมเดลนี้ | ตรวจสอบ error.param ในการตอบกลับ |
| 401 | ไม่มีสิทธิ์ | คีย์ API ไม่ถูกต้องหรือไม่ได้ส่งมา | ตรวจสอบรูปแบบ Authorization: Bearer |
| 429 | เกินขีดจำกัดอัตรา | ส่งคำขอมากเกินไป | ใช้ Exponential backoff (ดูขั้นตอนที่ 4) |
| 500 | ข้อผิดพลาดเซิร์ฟเวอร์ | ปัญหาฝั่งผู้ให้บริการ หรือโครงสร้างคำขอไม่ถูกต้อง | ลองใหม่พร้อม backoff; ตรวจสอบรูปแบบคำขอ |
| 504 | เกตเวย์หมดเวลา | ผู้ให้บริการใช้เวลานานเกินไป | ลองใหม่; พิจารณาใช้โมเดลที่เร็วกว่า |
ที่มา**: เอกสาร CometAPI chat completions
ความแตกต่างระหว่าง 400 กับ 500 สำคัญต่อการตัดสินใจ retry 400 หมายถึงคำขอของคุณผิด — ส่งซ้ำแบบเดิมไม่ช่วย 500 หรือ 504 หมายถึงปัญหาที่ฝั่งเซิร์ฟเวอร์ — ควรลองใหม่
ตรวจสอบ finish_reason — ฟิลด์ที่มักถูกมองข้าม
การตอบกลับ 200 พร้อม finish_reason: "content_filter" หมายความว่าการสร้างผลลัพธ์ถูกบล็อก ฟิลด์ content จะเป็น null หรือว่าง หากคุณไม่ตรวจสิ่งนี้ แอปของคุณอาจคืนค่าว่างโดยเงียบๆ
| finish_reason | ความหมาย | ควรทำอย่างไร | วิธีแก้ |
|---|---|---|---|
| stop | เสร็จสิ้นตามปกติ | ไม่ต้องทำอะไร — ถือว่าสำเร็จ | ตรวจสอบ error.param ในการตอบกลับ |
| length | แตะขีดจำกัดโทเคน | เพิ่ม max_tokens หรือย่อพรอมป์ | ตรวจสอบรูปแบบ Authorization: Bearer <key> |
| content_filter | ถูกบล็อกโดยนโยบายความปลอดภัย | เขียนพรอมป์ใหม่; หลีกเลี่ยงชื่อ/หัวข้อเฉพาะ | Exponential backoff (ดูขั้นตอนที่ 4) |
| tool_calls | โมเดลเรียกเครื่องมือแทนการส่งข้อความกลับมา | จัดการคำเรียกใช้เครื่องมือ; content จะเป็น null | ลองใหม่พร้อม backoff; ตรวจสอบรูปแบบคำขอ |
| 504 | เกตเวย์หมดเวลา | ผู้ให้บริการใช้เวลานานเกินไป | ลองใหม่; พิจารณาใช้โมเดลที่เร็วกว่า |
ที่มา**: เอกสาร CometAPI chat completions
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")
ความล้มเหลวแบบเงียบมักเกิดจากสามสาเหตุ: พรอมป์คลุมเครือ โมเดลไม่ทำตามคำสั่งรูปแบบผลลัพธ์ หรืออินพุตสั้น/ยาวเกินไปสำหรับงาน บันทึกผลลัพธ์ทั้งหมดเมื่อการตรวจสอบไม่ผ่านเป็นวิธีที่เร็วที่สุดในการหาสาเหตุ
เพิ่ม exponential backoff สำหรับข้อผิดพลาดอัตราจำกัด
ข้อผิดพลาดอัตราจำกัด (429) เป็นแบบชั่วคราว วิธีแก้ที่ถูกต้องคือรอแล้วลองใหม่ด้วยการหน่วงเวลาที่เพิ่มขึ้น — เป็นแนวปฏิบัติมาตรฐานสำหรับ API ที่มี rate limit:
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 — เป็นข้อผิดพลาดฝั่งไคลเอนต์ที่ไม่หายเอง ข้อยกเว้นคือ 401 เมื่อคุณหมุนเวียนคีย์ API
ดีบักปัญหาการสร้างภาพ
การสร้างภาพมีโหมดความล้มเหลวเฉพาะ นอกเหนือจากข้อผิดพลาด 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 }
ปัญหาเฉพาะของภาพที่ควรระวัง:
| อาการ | สาเหตุ | วิธีแก้ |
|---|---|---|
| อาร์เรย์ data ว่างเปล่า | พรอมป์ถูกกรอง | ตรวจสอบ revised_prompt; เขียนใหม่ |
| ข้อผิดพลาด response_format บน GPT Image 2 | พารามิเตอร์ไม่รองรับ | ใช้ output_format แทน |
| ข้อผิดพลาด n > 1 บน Qwen Image | ข้อจำกัดของโมเดล | ส่งคำขอแบบวนลูปแทน |
| URL ส่งกลับ 403 ในภายหลัง | URL หมดอายุ | ดาวน์โหลดทันทีหลังสร้าง |
ที่มา**: เอกสาร CometAPI image generation
ดีบักปัญหาการสร้างวิดีโอ
การสร้างวิดีโอมีรูปแบบความล้มเหลวต่างออกไปเพราะเป็นแบบอะซิงก์ กำหนดค่าเริ่มต้นของตัวแปรสถานะก่อนลูปเพื่อให้ข้อความ timeout error ถูกต้องเสมอ:
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}%" )
ปัญหาเฉพาะของวิดีโอ:
| อาการ | สาเหตุ | วิธีแก้ |
|---|---|---|
| งานค้างที่ queued เกิน 10 นาที | โหลดเซิร์ฟเวอร์สูง | ลองใหม่ด้วยโมเดลอื่น |
| ล้มเหลวโดยไม่มีรายละเอียดข้อผิดพลาด | พรอมป์ถูกกรองหรือข้อผิดพลาดของโมเดล | เขียนพรอมป์ใหม่ |
| URL วิดีโอส่งกลับ 403 | URL หมดอายุ | ดาวน์โหลดทันที |
| task_not_exist เมื่อโพลครั้งแรกกับ Runway | งานยังอยู่ระหว่างเริ่มต้น (พฤติกรรมตามเอกสารของ CometAPI) | รอ 5 วินาทีแล้วลองใหม่ |
| Kling ส่งกลับ "succeed" ไม่ใช่ "succeeded" | API ของ Kling ใช้สตริงสถานะที่ไม่เป็นมาตรฐาน | รองรับทั้งสองค่าในตรรกะการโพล |
ที่มา**: เอกสาร CometAPI video generation (veo3)**, เอกสาร Kling Video
เวอร์ชัน 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 key แล้วหรือยัง และอยู่ในรูปแบบ
Authorization: Bearer <key>หรือไม่? finish_reasonเป็นอย่างอื่นที่ไม่ใช่stopหรือไม่?contentเป็น null หรือไม่? ตรวจสอบว่าfinish_reasonเป็นtool_callsหรือเปล่า- ผลลัพธ์ถูกตัดทอนหรือไม่? ตรวจสอบ
finish_reason: "length"และusage.completion_tokens - เป็นข้อผิดพลาด 4xx (แก้คำขอ) หรือ 5xx (ลองใหม่) ?
- ผลลัพธ์ผ่านการตรวจสอบระดับแอปพลิเคชันหรือไม่? (ความล้มเหลวแบบเงียบ)
สำหรับการสร้างภาพ:
- อาร์เรย์
dataว่างหรือไม่? (พรอมป์ถูกกรอง) - คุณใช้
response_formatกับ GPT Image 2 หรือไม่? (ไม่รองรับ — ใช้output_format) - ตั้ง
n > 1กับ Qwen Image หรือไม่? (ไม่รองรับ) - ดาวน์โหลดภาพก่อนที่ URL จะหมดอายุแล้วหรือยัง?
สำหรับการสร้างวิดีโอ:
- งานค้างอยู่ที่
queuedหรือไม่? (ลองโมเดลอื่น) - ตรวจสอบฟิลด์
errorในคำตอบของงานที่ล้มเหลวแล้วหรือยัง? - ดาวน์โหลดวิดีโอก่อนที่ URL จะหมดอายุหรือไม่?
- คุณรองรับทั้ง
"succeed"(Kling) และ"succeeded"(Veo, Runway) หรือยัง?
คำถามที่พบบ่อย
Q: คำขอของฉันตอบกลับ 200 แต่ไม่มีเนื้อหา เกิดอะไรขึ้น?
ตรวจสอบ finish_reason หากเป็น content_filter การสร้างถูกบล็อก — คำขอสำเร็จแต่ผลลัพธ์ถูกระงับ หากเป็น tool_calls โมเดลเรียกเครื่องมือแทนที่จะส่งข้อความกลับมา และ content เป็น null ตามการออกแบบ หาก finish_reason เป็น stop แต่เนื้อหายังว่าง นั่นคือความล้มเหลวแบบเงียบ — บันทึกคำตอบเต็มและตรวจสอบพรอมป์ของคุณ
Q: ฉันจะรู้ได้อย่างไรว่าพรอมป์ของฉันถูกกรอง?
สำหรับข้อความ: ตรวจสอบว่า finish_reason === "content_filter" สำหรับภาพ: ตรวจสอบว่าอาร์เรย์ data ว่าง สำหรับวิดีโอ: ตรวจสอบว่างานเข้าสู่สถานะ failed ไม่นานหลังส่งโดยไม่มีรายละเอียดข้อผิดพลาด ในทุกกรณี ลองเขียนพรอมป์ใหม่ให้เป็นกลางมากขึ้น
Q: ควรลองใหม่เมื่อคำขอล้มเหลวตอนไหน?
ลองใหม่เมื่อ 429 และ 5xx โดยใช้ exponential backoff อย่าลองใหม่เมื่อ 4xx — คำขอที่ไม่ถูกต้องจะไม่หายเอง ข้อยกเว้นคือ 401 หากคุณกำลังหมุนเวียนคีย์ API
Q: exponential backoff คืออะไร และสำคัญอย่างไร?
แทนที่จะลองใหม่ทันที คุณรอเป็นช่วงเวลาที่ยาวขึ้นเรื่อยๆ: 1s, 2s, 4s การเพิ่ม jitter แบบสุ่ม (+ random.random()) ช่วยป้องกันการ retry พร้อมกันของไคลเอนต์หลายตัว นี่เป็นแนวปฏิบัติมาตรฐานสำหรับ API ที่มี rate limit — ไม่ได้เฉพาะกับ CometAPI
Q: งานวิดีโอติดอยู่ที่ queued นาน 10 นาที ถือว่าล้มเหลวหรือไม่?
ไม่เสมอไป — คิวอาจหนาแน่นภายใต้โหลด รอจนถึงเกณฑ์ max_wait ของคุณ จากนั้นส่ง TimeoutError และลองใหม่ด้วยโมเดลอื่น บันทึก task ID เพื่อให้คุณตรวจสอบสถานะด้วยมือได้หากต้องการ
Q: จะแก้ความล้มเหลวแบบเงียบได้อย่างไร?
ความล้มเหลวแบบเงียบต้องตรวจสอบระดับแอปพลิเคชัน — API จะไม่บอกว่าผลลัพธ์ผิดในเชิงความหมาย ตรวจสอบว่าผลลัพธ์ตรงตามรูปแบบที่คาดหวัง (JSON ถูกต้อง ป้ายกำกับที่คาดไว้ ความยาวขั้นต่ำ) บันทึกผลลัพธ์ทั้งหมดเมื่อการตรวจสอบไม่ผ่าน สาเหตุที่พบบ่อยที่สุดคือพรอมป์คลุมเครือ ไม่ทำตามคำสั่งรูปแบบ หรืออินพุตสั้น/ยาวเกินไปสำหรับงาน
