DEV Community

Cover image for วิธีทดสอบและแก้จุดบกพร่องคำขอ API ของ Grok 4.6 (การสตรีม, การเรียกใช้เครื่องมือ และข้อผิดพลาด)
Thanawat Wongchai
Thanawat Wongchai

Posted on Originally published at apidog.com

วิธีทดสอบและแก้จุดบกพร่องคำขอ API ของ Grok 4.6 (การสตรีม, การเรียกใช้เครื่องมือ และข้อผิดพลาด)

Grok 4.6 ถูกสร้างขึ้นสำหรับเอเจนต์ที่ทำงานต่อเนื่องเป็นเวลานาน ซึ่งหมายความว่าโหมดความล้มเหลวของการผสานรวมของคุณอยู่ในจุดที่ยากที่สุดในการดีบัก: การตอบสนองแบบสตรีมมิ่งที่หยุดชะงักกลางโทเค็น, เพย์โหลดการเรียกใช้เครื่องมือที่เกือบจะแยกวิเคราะห์ได้, และอัตราการจำกัดที่เกิดขึ้นภายใต้โหลดการผลิตเท่านั้น เอกสารของ xAI บอกคุณว่า API ยอมรับอะไร แต่ไม่ได้บอกวิธีทดสอบการผสานรวมอย่างเป็นระบบ คู่มือนี้ครอบคลุมเวิร์กโฟลว์สำหรับตรวจสอบคำขอ, ตรวจสอบสตรีม, ดีบักการเรียกใช้เครื่องมือ, จัดการข้อผิดพลาด, และจำลองการตอบสนองของ Grok เพื่อไม่ให้ CI ของคุณเผาโทเค็น

ลองใช้ Apidog วันนี้

ทุกอย่างในบทความนี้ใช้ Apidog เป็นสภาพแวดล้อมการทำงาน เพราะรวมเครื่องมือที่จำเป็นสำหรับดีบัก LLM API ไว้ในที่เดียว เช่น การเรนเดอร์ SSE, ความลับที่อยู่ในขอบเขตสภาพแวดล้อม, การยืนยันการตอบสนอง และเซิร์ฟเวอร์จำลอง แนวคิดเหล่านี้ใช้ได้กับเครื่องมืออื่นเช่นกัน แต่ขั้นตอนในบทความจะอ้างอิง Apidog

TL;DR

  • ตั้งค่าสภาพแวดล้อม Apidog ด้วย https://api.x.ai/v1 และ XAI_API_KEY เป็นตัวแปร อย่าฮาร์ดโค้ดคีย์ลงในคำขอที่บันทึกไว้
  • ดีบักการสตรีมด้วยภาพ: Apidog เรนเดอร์ SSE แบบเรียลไทม์ ทำให้เห็นการหยุดชะงักและการตัดทอนได้ชัดเจน
  • การเรียกใช้เครื่องมือล้มเหลวบ่อยกว่าข้อความ: ตรวจสอบว่า tool_calls[].function.arguments แยกวิเคราะห์เป็น JSON และตรงกับ schema ทุกครั้ง
  • จัดการ 429 ด้วย exponential backoff และ 5xx ด้วย bounded retries พร้อมบันทึก usage ในทุกการตอบสนอง
  • จำลองปลายทาง Grok ใน CI วงจรเอเจนต์อาจเรียก API หลายสิบครั้งต่องาน การทดสอบกับ API จริงช้า ไม่เสถียร และมีค่าใช้จ่าย
  • เปลี่ยนคำขอดีบักให้เป็นสถานการณ์ทดสอบอัตโนมัติ แล้วรันในการปรับใช้ทุกครั้ง

ตั้งค่าพื้นที่ทำงานที่เหมาะสมก่อน

คำสั่ง curl แบบเฉพาะกิจใช้ได้ดีสำหรับการทดสอบครั้งแรก แต่จะเริ่มจัดการยากทันทีที่ต้องเปรียบเทียบคำขอที่ล้มเหลวหลายรูปแบบ ตั้งค่าพื้นที่ทำงานให้พร้อมตั้งแต่ต้น:

  1. ใน Apidog สร้างโปรเจกต์ เช่น Grok 4.6 Integration และสร้างสภาพแวดล้อมชื่อ xai-dev
  2. เพิ่มตัวแปรสภาพแวดล้อม:
   base_url = https://api.x.ai/v1
   api_key = <your key>
Enter fullscreen mode Exit fullscreen mode

ทำเครื่องหมาย api_key เป็นความลับ

  1. สร้างคำขอ POST ไปยัง:
   {{base_url}}/chat/completions
Enter fullscreen mode Exit fullscreen mode

พร้อม header:

   Authorization: Bearer {{api_key}}
Enter fullscreen mode Exit fullscreen mode
  1. ทำซ้ำสภาพแวดล้อมเป็น xai-prod โดยใช้คีย์สำหรับการผลิต

คำขอควรเหมือนกัน แต่ต้องแยกขอบเขตสภาพแวดล้อมให้ชัดเจน เพื่อไม่ให้การทดลองของนักพัฒนาไปกระทบโควต้าการผลิตโดยไม่ตั้งใจ

หากคุณยังไม่ได้สร้างคีย์ คู่มือเริ่มต้นใช้งาน Grok 4.6 API ของเราจะแนะนำการตั้งค่า console.x.ai และคำขอแรกด้วย curl, Python และ JavaScript

ตรวจสอบคำขอก่อนที่จะโทษโมเดล

เมื่อคำขอทำงานผิดปกติ ให้ตรวจสอบสาเหตุพื้นฐานตามลำดับนี้ก่อน:

  • ID ของโมเดล: ใช้ grok-4-6 บน API ดั้งเดิม แต่ตัวแทนจำหน่ายอาจใช้ชื่อไม่เหมือนกัน เช่น OpenRouter ใช้ x-ai/grok-4.6 หากได้ 404 ในกรณีนี้ ปัญหาคือ ID ไม่ใช่โมเดลขัดข้อง
  • ช่วงพารามิเตอร์: temperature ที่อยู่นอกช่วง หรือ max_tokens ที่เกินบริบทที่เหลือ จะส่ง 400 พร้อมข้อความข้อผิดพลาดที่มักระบุสาเหตุชัดเจน อ่านข้อความนั้นก่อนเปลี่ยนค่าอื่น
  • โครงสร้างข้อความ: อาร์เรย์ messages ต้องเรียงลำดับอย่างมีเหตุผล ข้อความว่างในตำแหน่งผิด หรือ system prompt ที่ซ้ำกัน อาจทำให้เอาต์พุตแย่ลงโดยไม่มีข้อผิดพลาด
  • การคำนวณบริบท: หน้าต่างบริบทของ Grok 4.6 คือ 500K โทเค็น แม้จะกว้าง แต่ก็มีขีดจำกัด ประวัติเอเจนต์ที่ยาวร่วมกับ max_tokens ที่จองไว้มากเกินไปอาจทำให้บริบทล้น และแสดงผลเป็นการตัดทอนแบบเงียบ ๆ

บันทึกจำนวนโทเค็นของพรอมต์จาก usage และตั้งการแจ้งเตือนเมื่อการใช้งานมีแนวโน้มเข้าใกล้ขีดจำกัด

การตรวจสอบคำขอของ Apidog ช่วยจับข้อผิดพลาดเชิงโครงสร้าง เช่น ชนิดข้อมูลผิดหรือฟิลด์บังคับหายไป ก่อนส่งคำขอออกจากเครื่อง ทำให้ตัดรอบการตรวจสอบที่ไม่จำเป็นได้

ดีบักการสตรีมโดยไม่ตาบอด

การตอบกลับของ Grok 4.6 สตรีมผ่าน Server-Sent Events (SSE) และคำตอบจากเอเจนต์มักยาวหลายพันโทเค็น ปัญหาการสตรีมส่วนใหญ่เข้ากับหนึ่งในสามรูปแบบนี้:

  1. สตรีมหยุดชะงักกลางคำตอบ โทเค็นหยุดมาถึงกลางการตอบสนอง ในเทอร์มินัล คุณอาจแยกไม่ออกว่าโมเดลกำลังประมวลผลหรือสตรีมเสียหาย

ในมุมมอง SSE ของ Apidog ให้ดูว่า:

  • ชิ้นส่วนหยุดมาถึงจริงหรือไม่ — ปัญหาฝั่งเซิร์ฟเวอร์หรือเครือข่าย
  • ชิ้นส่วนยังมาถึง แต่แอปหยุดเรนเดอร์ — ปัญหาฝั่งไคลเอนต์
  1. สตรีมจบเร็วเกินไป ตรวจสอบ finish_reason ของชิ้นส่วนสุดท้าย:
   {
     "finish_reason": "length"
   }
Enter fullscreen mode Exit fullscreen mode

หากเป็น length หมายความว่าถึงขีดจำกัด max_tokens แล้ว ให้เพิ่มค่าเพดานนั้น หากเป็น stop หมายความว่าโมเดลจบคำตอบตามปกติ

  1. ปัญหาจาก reverse proxy หากใช้งานได้ในเครื่องแต่สตรีมค้างใน staging ให้ตรวจสอบ proxy ก่อน โดยเฉพาะ nginx ที่อาจบัฟเฟอร์ SSE ตามค่าเริ่มต้น:
   proxy_buffering off;
Enter fullscreen mode Exit fullscreen mode

ทดสอบคำขอเดียวกันผ่าน Apidog กับทั้งสองสภาพแวดล้อม หากสตรีมจากเครื่องได้แต่ผ่าน gateway ไม่ได้ ปัญหาอยู่ที่โครงสร้างพื้นฐาน ไม่ใช่ xAI

การเรียกใช้เครื่องมือ: จุดที่การผสานรวมเอเจนต์มักจะพังทลาย

การเรียกใช้ฟังก์ชันเป็นส่วนสำคัญของเอเจนต์ Grok 4.6 และเป็นจุดที่เกิดเหตุการณ์ในระบบจริงบ่อยที่สุด โหมดความล้มเหลวหลักมีดังนี้:

  • อาร์กิวเมนต์แยกวิเคราะห์ไม่ได้ tool_calls[].function.arguments มาถึงในรูปแบบสตริง JSON ซึ่งบางครั้งอาจเกือบถูกต้องแต่ยังไม่สมบูรณ์ เช่น มี comma ท้ายข้อความหรือมี quote ที่ไม่ escape โดยเฉพาะเมื่อบริบทยาว

ห่อการแยกวิเคราะห์ด้วย try/catch และนับจำนวนความล้มเหลว:

  let args;

  try {
    args = JSON.parse(toolCall.function.arguments);
  } catch (error) {
    logger.error("tool_arguments_parse_failed", {
      tool: toolCall.function.name,
      arguments: toolCall.function.arguments,
      error: error.message,
    });

    throw error;
  }
Enter fullscreen mode Exit fullscreen mode

หากอัตราความล้มเหลวเพิ่มขึ้น นั่นอาจเป็นสัญญาณว่าพรอมต์หรือ schema มีการเปลี่ยนแปลง

  • JSON ถูกต้อง แต่รูปร่างไม่ตรง schema อาร์กิวเมนต์อาจ parse ได้ แต่ขาดฟิลด์บังคับ หรือส่งสตริงในฟิลด์ที่ต้องเป็นตัวเลข ตรวจสอบ schema ทุกครั้ง ไม่ใช่เฉพาะตอนพัฒนา
  const result = toolSchema.safeParse(args);

  if (!result.success) {
    throw new Error(`Invalid tool arguments: ${result.error.message}`);
  }
Enter fullscreen mode Exit fullscreen mode
  • เครื่องมือที่ไม่ได้กำหนดไว้ อาจเกิดการเรียกใช้ฟังก์ชันที่คุณไม่ได้ประกาศไว้ ปฏิเสธชื่อเครื่องมือที่ไม่รู้จักอย่างชัดเจน แทนที่จะปล่อยให้ KeyError หรือข้อผิดพลาด runtime ทำให้วงจรล้มเหลว
  if (!allowedTools.has(toolCall.function.name)) {
    throw new Error(`Unknown tool: ${toolCall.function.name}`);
  }
Enter fullscreen mode Exit fullscreen mode
  • การประกอบข้อมูลสตรีมไม่สมบูรณ์ ในการตอบสนองแบบสตรีมมิ่ง อาร์กิวเมนต์การเรียกใช้เครื่องมืออาจมาถึงเป็นส่วนย่อยจากหลาย chunk ต้องประกอบให้ครบก่อนค่อย parse
  let argumentBuffer = "";

  for await (const chunk of stream) {
    const delta = chunk.choices?.[0]?.delta;
    const fragment = delta?.tool_calls?.[0]?.function?.arguments;

    if (fragment) {
      argumentBuffer += fragment;
    }
  }

  const args = JSON.parse(argumentBuffer);
Enter fullscreen mode Exit fullscreen mode

ใน Apidog ให้บันทึกคำขอที่ทำให้เกิด tool call แล้วเพิ่ม assertions ดังนี้:

  • ชื่อเครื่องมืออยู่ในรายการที่อนุญาต
  • สตริงอาร์กิวเมนต์ parse เป็น JSON ได้
  • ออบเจ็กต์ที่ parse แล้วตรงตาม schema

รันซ้ำอย่างน้อย 10 ครั้ง เพราะผลลัพธ์ของ LLM ไม่กำหนดตายตัว และอัตราความล้มเหลว 10% อาจไม่ปรากฏในการทดสอบครั้งเดียว

หากสแตกของคุณใช้ MCP server แทน function calling โดยตรง ให้ใช้วินัยเดียวกัน ดูคู่มือ ทดสอบเซิร์ฟเวอร์ MCP ด้วย Apidog

ข้อผิดพลาด การลองใหม่ และการจำกัดอัตรา

การผสานรวม Grok ที่ใช้งานจริงควรมีนโยบายชัดเจนสำหรับทุกสถานะต่อไปนี้:

สถานะ ความหมาย นโยบาย
400 คำขอผิดรูปแบบ อย่าลองใหม่ บันทึกและแก้ไขคำขอ การลองใหม่คำขอที่ผิดคือการวนลูป
401 คีย์ไม่ถูกต้องหรือไม่พบ อย่าลองใหม่ ตรวจสอบตัวแปรสภาพแวดล้อมและคีย์ในคอนโซล
404 โมเดลหรือปลายทางผิดพลาด อย่าลองใหม่ ตรวจสอบกับ /v1/models
429 ถูกจำกัดอัตรา / โควต้า ลองใหม่ด้วย exponential backoff และ jitter; ใช้ Retry-After หากมี
5xx ข้อผิดพลาดฝั่งเซิร์ฟเวอร์ ลองใหม่ได้สูงสุด 3 ครั้งด้วย backoff จากนั้นให้ล้มเหลวอย่างชัดเจน
Timeout การสร้างคำตอบนานเกินไปหรือปัญหาเครือข่าย ใช้ streaming เพื่อให้โทเค็นแรกมาถึงเร็ว และตั้ง client timeout เป็นระดับนาที ไม่ใช่วินาที สำหรับงานเอเจนต์

ตัวอย่าง retry สำหรับ 429 และ 5xx:

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function requestWithRetry(sendRequest, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await sendRequest();
    } catch (error) {
      const status = error.response?.status;
      const retryable = status === 429 || status >= 500;

      if (!retryable || attempt === maxRetries) {
        throw error;
      }

      const retryAfter = Number(error.response?.headers?.["retry-after"]);
      const baseDelay = retryAfter ? retryAfter * 1000 : 1000 * 2 ** attempt;
      const jitter = Math.floor(Math.random() * 250);

      await sleep(baseDelay + jitter);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

ข้อสังเกตสำหรับ Grok มีสองข้อ:

  1. ช่วงหลังการเปิดตัวอาจมีภาระงานสูง ทำให้ 429 และ 5xx แบบชั่วคราวเกิดขึ้นได้บ่อยขึ้น ดังนั้นควรมี backoff ก่อนนำระบบไปสาธิตหรือเปิดให้ผู้ใช้จริง
  2. บันทึกออบเจ็กต์ usage จากทุกการตอบสนอง ราคาอยู่ที่ 2/6 ดอลลาร์ต่อล้านโทเค็น แต่ลูปของเอเจนต์สามารถเพิ่มจำนวนการเรียกได้อย่างรวดเร็ว การเปลี่ยนพรอมต์ที่ทำให้ต้นทุนสูงขึ้นมักเห็นได้จากบันทึกโทเค็นก่อนปรากฏในใบแจ้งหนี้

ดูรายละเอียดเพิ่มเติมใน การวิเคราะห์ราคา Grok

จำลอง Grok ใน CI ทดสอบ API จริงแยกต่างหาก

หลักการสำคัญในการทำให้ชุดทดสอบ LLM รวดเร็วและประหยัดคือ: CI ไม่ควรเรียกโมเดลจริงในทุก commit

การทดสอบการรวมเอเจนต์ที่เรียก Grok จริง 30 ครั้งมีค่าใช้จ่าย ใช้เวลามากกว่าหนึ่งนาที และอาจล้มเหลวแบบสุ่มเมื่อผู้ให้บริการมีปัญหา หากเป็นเช่นนี้บ่อย นักพัฒนาจะเริ่มไม่เชื่อถือผลการทดสอบ

แยกความรับผิดชอบออกเป็นสองระดับ:

  • Mocks สำหรับตรรกะ ใช้ smart mock ของ Apidog เพื่อส่งการตอบสนองในรูปแบบ Grok ที่สมจริง เช่น:
    • การตอบข้อความปกติ
    • การตอบกลับที่มี tool call
    • 429
    • สตรีมที่ถูกตัดทอน

วิธีนี้ทำให้ตรรกะ retry, JSON parsing และโค้ดจบวงจรเอเจนต์ถูกทดสอบในทุก commit ภายในไม่กี่วินาทีและไม่มีค่าใช้จ่าย

  • การทดสอบจริงตามกำหนดเวลา รันชุดทดสอบที่เรียก API จริงทุกคืนหรือก่อนเปิดตัว ไม่ใช่ทุก commit เพื่อจับการเปลี่ยนแปลงจากผู้ให้บริการ เช่น รูปแบบ tool call ที่เปลี่ยนไป, การอัปเดตโมเดล หรือข้อจำกัดอัตราใหม่

สถานการณ์ทดสอบของ Apidog รองรับทั้งสองแบบ: กำหนด scenario เดียวกันให้ใช้ mock environment สำหรับ CI และใช้ xai-dev สำหรับ scheduled run ที่เรียก API จริง

ใช้ assertions ชุดเดิมกับปลายทางสองเป้าหมาย หากคุณรันทดสอบจากเทอร์มินัลหรือ pipeline ให้ใช้ Apidog CLI เพื่อรัน scenario เดียวกันโดยไม่ต้องเปิด GUI

รายการตรวจสอบก่อนการผลิต

ก่อนเปิดใช้ทราฟฟิก Grok 4.6 จริง ควรตอบว่า “ใช่” ได้ครบทุกข้อ:

  • [ ] คีย์ API อยู่ในขอบเขตสภาพแวดล้อม แยก dev และ prod และไม่อยู่ในระบบควบคุมเวอร์ชัน
  • [ ] การสตรีมจัดการ finish_reason: length, การหยุดชะงัก และ proxy buffering ได้
  • [ ] อาร์กิวเมนต์ tool call ถูก parse อย่างรอบคอบและตรวจสอบตาม schema ทุกครั้ง
  • [ ] มีนโยบาย retry สำหรับ 429 และ 5xx และ ทดสอบผ่าน mock แล้ว
  • [ ] บันทึก usage ต่อคำขอ พร้อมแจ้งเตือนเมื่อมีการเปลี่ยนแปลงของต้นทุนต่องาน
  • [ ] CI รันกับ mocks และชุดทดสอบจริงรันตามกำหนดเวลา
  • [ ] ชุดทดสอบทั้งหมดรันซ้ำได้ด้วยคำสั่งเดียวสำหรับการเปิดตัวโมเดลครั้งถัดไป

คำถามที่พบบ่อย

ฉันจะดีบักการตอบกลับแบบสตรีมมิ่งของ Grok 4.6 ที่ค้างได้อย่างไร?

ทำซ้ำปัญหาในมุมมอง SSE ของ Apidog หาก chunk หยุดมาถึง แสดงว่าเป็นปัญหาฝั่งเซิร์ฟเวอร์หรือเครือข่าย ให้ตรวจสอบ proxy และ timeout หาก chunk ยังมาถึง แต่ไคลเอนต์หยุดแสดงผล ให้ตรวจสอบ buffering และการจัดการ asynchronous ในโค้ดของคุณ

ทำไมการเรียกใช้เครื่องมือของ Grok 4.6 จึงล้มเหลวในการแยกวิเคราะห์บางครั้ง?

อาร์กิวเมนต์ฟังก์ชันมาถึงเป็นสตริง JSON ที่บางครั้งอาจผิดรูปแบบ และ tool call แบบสตรีมมิ่งต้องประกอบจากส่วนย่อยหลายส่วนก่อน parse ใช้การ parse แบบรอบคอบร่วมกับ schema validation เพื่อจับทั้งสองกรณี การ parse ก่อนประกอบข้อมูลครบเป็นข้อผิดพลาดที่เกิดจากฝั่งแอปบ่อยที่สุด

การทดสอบของฉันควรเรียก Grok API จริงหรือไม่?

ควรเรียกตามกำหนดเวลา เช่น ทุกคืนหรือก่อนเปิดตัว เพื่อจับการเปลี่ยนแปลงจากผู้ให้บริการ แต่ไม่ควรเรียกทุก commit ให้จำลองปลายทางใน CI เพื่อให้การทดสอบเร็ว กำหนดผลลัพธ์ได้ และไม่มีค่าใช้จ่าย

เวิร์กโฟลว์นี้ใช้กับ LLM API อื่นได้หรือไม่?

ได้ เนื่องจาก API ของ Grok เข้ากันได้กับ OpenAI คุณสามารถใช้โครงสร้างโปรเจกต์ Apidog เดียวกัน และเปลี่ยนเฉพาะสภาพแวดล้อมของแต่ละผู้ให้บริการเพื่อทดสอบ GPT-5.6, Claude และ Grok ควบคู่กันได้

Top comments (0)