ผมเคยคิดว่าตัวเองฉลาดมาก ผมเขียนฟังก์ชัน helper ที่จองพื้นที่ 30% ของ context window ไว้เป็น thinking budget สำหรับ AI pipeline ของเรา มันดูสะอาด คาดเดาได้ และทำงานได้อย่างยอดเยี่ยมบน Opus 4.5 แต่พอผมเปลี่ยนมาใช้ Opus 4.8 ทุกคำขอ (request) ก็ตายสนิทด้วย error 400 การคำนวณ token ที่ผมบรรจงสร้างมาอย่างดีกลับกลายเป็นขยะเพียงชั่วข้ามคืน
รูปแบบเดิมนั้นเรียบง่าย คุณแค่กำหนดค่า budget_tokens แล้วโมเดลจะจัดสรรการคิดให้อยู่ภายใต้เพดานนั้น หากผมส่ง context ขนาด 128K ไป โค้ดของผมจะแบ่งประมาณ 38,000 tokens ไว้สำหรับการใช้เหตุผล (reasoning) และเหลือส่วนที่เหลือไว้สำหรับคำตอบ มันให้ความรู้สึกที่รับผิดชอบ เหมือนกับการขับรถไม่ให้เกินความเร็วที่กำหนด
โมเดลนั้นไม่อยู่แล้ว เวอร์ชันใหม่อย่าง Opus 4.7 และ 4.8 ใช้ adaptive thinking คุณไม่ต้องเลือกตัวเลขอีกต่อไป แต่คุณต้องส่ง "effort knob" (ปุ่มปรับระดับความพยายาม) เข้าไปแทน ฟังดูเหมือนแค่การเปลี่ยนชื่อ แต่การควบคุมทั้งสองแบบนี้ต่างกันอย่างสิ้นเชิง budget_tokens คือการตั้งเพดานที่ตายตัวว่าโมเดลได้รับอนุญาตให้คิดได้มากแค่ไหน ส่วน effort คือการควบคุมว่าโมเดลจะคิดและแสดงออกอย่างไรตั้งแต่แรก อย่างแรกเหมือนมิเตอร์ปั๊มน้ำมัน ส่วนอย่างหลังเหมือน engine map
การจับคู่ระดับ Effort กับการใช้งานจริง
เมื่อการควบคุมเปลี่ยนไป สัญชาตญาณเดิมของผมก็ใช้ไม่ได้ผล ผมต้องเรียนรู้ใหม่ว่าการตั้งค่าแต่ละแบบให้ผลลัพธ์ที่แตกต่างกันอย่างไร ผมได้ทำการทดสอบกับ traffic ภายในของเราเพื่อดูว่าระดับ effort แต่ละระดับให้ผลลัพธ์อย่างไรในทางปฏิบัติ
Classification and routing ควรใช้ effort ระดับ low เกือบจะเสมอ งานเหล่านี้เป็นการตัดสินใจที่รวดเร็ว เช่น นี่คือคำขอคืนเงินหรือคำถามด้านการขาย? log entry นี้ต้องส่งต่อ (escalation) หรือไม่? คุณไม่ต้องการการบรรยายยาวเหยียด การใช้ effort ระดับ low จะช่วยรักษา latency ให้ต่ำและทำให้ต้นทุนน้อยจนแทบไม่มีนัยสำคัญ
Traffic ส่วนใหญ่ของแอป ซึ่งเป็นงานประจำวันอย่างการสรุปความ, การเขียนใหม่, การตอบกลับฝ่ายสนับสนุน และการดึงข้อมูล (content extraction) จะเหมาะกับ effort ระดับ medium ถึง high นี่คือจุดสมดุล โมเดลจะมีพื้นที่เพียงพอในการจัดการกับความคลุมเครือที่แท้จริง โดยไม่ต้องเสีย token ไปกับงานที่ไม่จำเป็นต้องใช้ chain of thought ที่ยาวเกินไป
Coding และ agentic loops ต้องการ effort ระดับ xhigh นี่คือจุดที่ความผิดพลาดจะทวีคูณ หากโมเดลเขียนแผนงานที่แย่ในการทำงานรอบแรกของ tool-calling loop มันจะต้องใช้สามขั้นตอนถัดไปเพื่อซ่อมแซมความเสียหาย หรือที่แย่กว่านั้นคือมันจะเรียกใช้เครื่องมือผิด, hallucinate พารามิเตอร์ และปล่อยให้ผู้ใช้จ้องมอง workflow ที่พังทลาย การใช้เหตุผลที่ดีตั้งแต่ต้นจะช่วยป้องกันวงจรความผิดพลาดนี้ได้
งานที่สำคัญ (Critical tasks) ควรได้รับ effort ระดับ max แต่อย่าใช้สิ่งนี้กับทุกอย่าง ให้เก็บไว้ใช้ในจังหวะที่คำตอบที่ผิดพลาดมีมูลค่าความเสียหายมากกว่าค่า token เช่น การกระทบยอดทางการเงิน (financial reconciliations), การตรวจสอบความปลอดภัย, การตัดสินใจด้านสถาปัตยกรรม และการคัดกรองผู้ป่วย (medical triage) หากความผิดพลาดหมายถึงการที่มนุษย์ต้องมานั่งแก้ความวุ่นวายนี้เป็นชั่วโมง ก็จงยอมจ่ายเพื่อการคิดที่มากขึ้น
ความประหลาดใจเรื่องต้นทุน
นี่คือส่วนที่ทำลายโมเดลความคิดของผม ผมทึกทักเอาเองว่า max effort จะทำให้ต้นทุนพุ่งสูงขึ้นเสมอ ในการทำงานรอบเดียว (single turn) มันเป็นเช่นนั้น เพราะ reasoning trace จะยาวขึ้น แต่สำหรับงาน agentic แบบหลายขั้นตอน (multi-step) ยอดรวมมักจะลดลง
โมเดลจะวางแผนได้ดีขึ้นในการลองครั้งแรก มันเรียกใช้เครื่องมือ (tool calls) น้อยลง และหยุดตัวเองไม่ให้หลงทางไปในทางตัน ผมเคยเฝ้าดู agent ดึงข้อมูลที่ปกติจะต้องโต้ตอบไปมาถึงห้าครั้ง แต่กลับเสร็จสิ้นภายในสองครั้ง เพราะโมเดลมีพื้นที่ในการใช้เหตุผลเพียงพอที่จะ parse schema ได้อย่างถูกต้องตั้งแต่เริ่มต้น เมื่อคุณวัดต้นทุน ให้ดูที่การทำงานจนสำเร็จ (job completion) ไม่ใช่ดูที่จำนวน request การมีงบประมาณการคิด (thinking budget) ที่มากขึ้นต่อหนึ่งขั้นตอน อาจหมายถึงจำนวนขั้นตอนที่น้อยลงในภาพรวม
วิธี Migrate โดยไม่ทำให้ส่วนอื่นพัง
หากคุณยังมี budget_tokens หลงเหลืออยู่ใน codebase ของคุณ นี่คือแนวทางที่ชัดเจน อย่าข้ามขั้นตอนที่สามและห้า ผมเคยข้าม และมันทำให้ผมต้องเสียเวลาทั้งบ่ายเพื่อ debug
ค้นหา budget_tokens ในโค้ดของคุณ ทุกจุดต้องถูกลบออก พารามิเตอร์นี้ใช้ไม่ได้แล้วในโมเดลรุ่นใหม่และจะทำให้เกิด error 400
แทนที่ budget object ด้วย adaptive thinking block โดยใช้ thinking: { type: "adaptive" }
เพิ่ม output_config พร้อมระบุระดับ effort ที่ชัดเจนสำหรับการเรียกแต่ละครั้ง อย่าปล่อยให้เป็นค่า default ส่วนกลางหาก traffic ของคุณมีความหลากหลาย endpoint สำหรับการจำแนกประเภทที่เบาบางของคุณไม่ควรได้รับค่า effort เดียวกันกับ coding agent โดยไม่ได้ตั้งใจ จงระบุให้ชัดเจน ณ จุดที่เรียกใช้งาน (call site)
ลบ helper function ที่ใช้คำนวณ budget ทิ้งไป ผมรู้ มันอาจจะมี unit tests ของมัน ของผมก็มี แต่ตอนนี้มันคือส่วนเกินที่ไม่มีประโยชน์แล้ว แพลตฟอร์มไม่ต้องการการคำนวณ token ของคุณ โมเดลจะจัดการจังหวะของมันเอง
ตัด temperature, top_p, และ top_k ออก ใน Opus 4.7 และ 4.8 พารามิเตอร์การสุ่ม (sampling parameters) เหล่านี้จะทำให้เกิดข้อผิดพลาด 400 แพลตฟอร์มได้นำพารามิเตอร์เหล่านี้ออกจากโมเดลรุ่นนี้แล้ว เทคนิคการปรับจูน temperature แบบเดิมของคุณใช้ไม่ได้กับที่นี่ และการปล่อยทิ้งไว้จะทำให้การย้ายระบบ (migration) ของคุณพังโดยไม่แจ้งเตือน
ทดสอบแต่ละโมเดลแยกกัน Opus 4.5 และ 4.8 นั้นแตกต่างกันอย่างสิ้นเชิง การตั้งค่า (config) ที่ใช้ได้กับตัวหนึ่ง ไม่จำเป็นต้องใช้ได้กับอีกตัวหนึ่งเสมอไป หากคุณรองรับหลายเวอร์ชัน ให้แยกตรรกะ (logic) ออกจากกัน หรือจัดการพวกมันในฐานะ backend ที่แยกจากกัน
การแก้ไขปัญหา UI ค้าง
มีพฤติกรรมการสตรีม (streaming behavior) อย่างหนึ่งที่จะทำให้ผู้ใช้สับสนหากคุณไม่จัดการมัน ในโมเดลรุ่นใหม่ thinking blocks จะถูกสตรีมออกมา แต่โดยค่าเริ่มต้นแล้วข้อความจะว่างเปล่า ในอินเทอร์เฟซของคุณ สิ่งนี้จะดูเหมือนการหยุดชะงักที่ยาวนานและน่าอึดอัดโดยไม่มีความคืบหน้าที่มองเห็นได้ ผู้ใช้จะคิดว่าแอปค้าง
เพื่อแก้ไข ให้ส่งค่า thinking: { type: "adaptive", display: "summarized" } วิธีนี้จะทำให้คุณมีตัวบ่งชี้ความคืบหน้าที่มองเห็นได้ โดยไม่ต้องเทข้อมูลกระบวนการคิดดิบๆ (raw thought stream) ลงในหน้าต่างแชท หน้าบ้าน (frontend) ของคุณจะยังคงตอบสนองได้ และผู้ใช้จะรู้ว่ามีบางอย่างกำลังทำงานอยู่เบื้องหลัง
บทเรียนที่แท้จริง
ผมสร้างเลเยอร์การแยกส่วน (abstraction layer) ทั้งหมดขึ้นมาบนพารามิเตอร์ที่ผู้ให้บริการไม่เคยตั้งใจจะให้ใช้งานได้ในระยะยาว ผมห่อหุ้มการตั้งค่าของพวกเขาไว้ในตรรกะของผมเอง เพราะผมคิดว่าผมเข้าใจเรื่องการแลกเปลี่ยน (tradeoff) ได้ดีกว่าแพลตฟอร์ม แต่ผมคิดผิด Adaptive thinking เป็นทางเลือกที่ดีกว่า เพราะโมเดลจะเป็นผู้ตัดสินใจเองว่าเมื่อใดที่ต้องใช้การใช้เหตุผลอย่างหนัก และเมื่อใดที่สามารถทำงานแบบปกติได้ โค้ดเบส (codebase) ของผมเล็กลง ผลลัพธ์ที่ได้ก็เฉียบคมขึ้น บางครั้ง การตัดสินใจทางวิศวกรรมที่ถูกต้องคือการลบโค้ดที่ดูฉลาดทิ้งไป แล้วปล่อยให้แพลตฟอร์มทำหน้าที่ของมัน
หากคุณต้องการอ่านบันทึกการย้ายระบบต้นฉบับ คุณสามารถอ่านได้ ที่นี่ สำหรับการพูดคุยเชิงปฏิบัติแบบนี้เพิ่มเติม เข้าร่วม ชุมชน GyaanSetu AI บน Telegram
