- ในเครื่องมือ edit ของ Pi พบว่า Claude Opus 4.8 และ Sonnet 5 เพิ่มฟิลด์ที่ไม่มีในสคีมาภายใน
edits[] ทำให้การเรียกถูกปฏิเสธ และสังเกตเห็นว่าโมเดลรุ่นใหม่กลับทำตามสคีมาเครื่องมือบางแบบได้แย่กว่ารุ่นก่อน
- การเรียกเครื่องมือคือกระบวนการที่โมเดล สร้างข้อความ ในรูปแบบมาร์กเกอร์พิเศษและ JSON ดังนั้นเมื่อมีการสุ่มตัวอย่างแบบไม่มีข้อจำกัด ธรรมเนียมที่เรียนรู้มาจากการฝึกอาจมาก่อนสคีมา
- ในกรณีที่ล้มเหลว
oldText และ newText เองถูกต้องอยู่แล้ว แต่กลับมี คีย์ปลอม อย่าง requireUnique, oldText2, matchCase, in_file ถูกแนบมาด้วย และอัตราการเกิดซ้ำก็เปลี่ยนไปตามประวัติของเอเจนต์และการมีหรือไม่มี thinking block
- Claude Code เป็นฮาร์เนสแบบปิด แต่ทำ การแก้ให้หลวม หลายอย่าง เช่น ลองเรียกใหม่เมื่อเรียกผิด, alias ของพารามิเตอร์, ปรับชนิดข้อมูล, กู้คืน Unicode, กรองคีย์ที่ไม่รู้จัก และไม่ได้ใช้โหมด
strict
- การเรียกเครื่องมือแบบ
strict ของ Anthropic แก้ปัญหานี้ได้ และถ้าเมื่อโมเดลเก่งขึ้น สคีมาเครื่องมือทางเลือกกลับเสียเปรียบมากขึ้น ฮาร์เนสก็อาจต้องมีการรับประกันที่แข็งแรงกว่าเดิม เช่น ข้อจำกัดทางไวยากรณ์
Regression ที่เกิดขึ้นในเครื่องมือ edit ของ Pi
- ระหว่างติดตาม Pi issue พบว่าขณะ Claude รุ่นล่าสุดเรียกเครื่องมือ edit ของ Pi จะมีปัญหาเพิ่ม ฟิลด์ที่ไม่มีอยู่จริง เข้าไปในอาร์เรย์
edits[]
- ปัญหานี้ไม่ได้เกิดกับโมเดลเล็ก แต่เกิดกับ Opus 4.8 และพบพฤติกรรมเดียวกันใน Sonnet 5
- ในโมเดล Anthropic รุ่นก่อนหน้าไม่เห็นปัญหาเดียวกันนี้ จึงกลายเป็นว่ารุ่นใหม่ที่ประสิทธิภาพสูงกว่ากลับทำงานแย่ลงกับสคีมาเครื่องมือเฉพาะแบบนี้
- ไม่ได้ทดสอบ Fable เพราะตัวจัดประเภทอาจลดคำขอไปเป็น Opus แบบเงียบ ๆ
การเรียกเครื่องมือใกล้เคียงกับการสร้างข้อความ
- การเรียกเครื่องมือของ LLM คือวิธีที่โมเดลรับประวัติการสนทนา system prompt และรายการเครื่องมือที่ใช้ได้ แล้วสร้าง รูปแบบการเรียก ภายในพรอมป์ขนาดใหญ่ที่มีมาร์กเกอร์พิเศษรวมอยู่ด้วย
- อาร์กิวเมนต์ที่ตั้งใจไว้ของเครื่องมือแก้ไขไฟล์อาจมี
path และอาร์เรย์ edits แบบนี้
{
"path": "some/file.py",
"edits": [
{
"oldText": "text to replace",
"newText": "replacement text"
}
]
}
- ฮาร์เนสจะตรวจสอบอาร์กิวเมนต์และทำการแก้ไข จากนั้นส่งผลลัพธ์กลับเข้าไปให้โมเดลอีกครั้ง และถ้าตรวจสอบไม่ผ่าน โมเดลจะเห็นข้อผิดพลาดและมักจะลองใหม่
- รูปแบบภายในของโมเดล Anthropic ไม่ได้เปิดเผยต่อสาธารณะ แต่เคยมี
ANTML marker หลุดออกมาหรือปรากฏในช่องทางสื่อสารสาธารณะ
- รูปแบบนี้ดูคล้าย XML แต่แท้จริงแล้วใกล้เคียงกับ สัญญาณ in-band ที่เหมาะกับการ tokenize และการฝึกมากกว่าจะเป็น XML จริง
- พารามิเตอร์สตริงระดับบนสุดอาจถูกใส่ inline ได้
- อาร์เรย์ของอ็อบเจ็กต์ดูเหมือนจะถูกใส่มาในรูปแบบ JSON serialization
การสร้างแบบไม่มีข้อจำกัดและการสร้างแบบมีข้อจำกัดทางไวยากรณ์
- โดยใหญ่ ๆ แล้วมีสองวิธีที่โมเดลใช้สร้าง structured output
- ขอให้โมเดลสร้าง JSON ที่ตรงตามสคีมา แล้วค่อยตรวจสอบภายหลัง
- ให้ sampler ป้องกันตั้งแต่ต้นไม่ให้สุ่ม JSON หรือรูปทรงสคีมาที่ผิดออกมาได้
- วิธีที่สองเรียกว่า grammar-aware decoding หรือ constrained decoding โดยจะ mask token ที่ละเมิดไวยากรณ์
- ถ้าสคีมายอมรับแค่
oldText และ newText sampler ก็สามารถกันไม่ให้สร้างคีย์อย่าง "in_file" หรือ "type" ได้
- หากไม่มีข้อจำกัดแบบนี้ โมเดลจะสร้างตามธรรมเนียมที่มันเรียนรู้มา มากกว่าจะยึดตามสัญญาเชิงนามธรรมอย่างเคร่งครัด
รูปแบบความล้มเหลวที่เกิดขึ้นจริง
- เครื่องมือ edit ของ Pi ใช้อาร์เรย์
edits เพราะรองรับการแทนที่สตริงที่ตรงกันหลายจุดภายในการเรียกครั้งเดียว
- ในการเรียกที่ล้มเหลว จะมีฟิลด์ที่ไม่อนุญาตติดมาด้วยแบบนี้
{
"oldText": "...",
"newText": "...",
"requireUnique": true
}
{
"oldText": "...",
"newText": "...",
"oldText2": "",
"newText2": ""
}
- คีย์ปลอมที่พบจากการทดลองซ้ำมีหลากหลาย เช่น
type, id, kind, unique, requireUnique, matchCase, in_file, forceMatchCount, children, notes, cost, oldText2, newText2, oldText_2, newText_2, event.0.additionalProperties
- ในการเรียกที่ผิดซึ่งตรวจพบ ค่า payload ของ
oldText และ newText จริง ๆ แล้ว ถูกต้องระดับไบต์ แต่มีคีย์ไร้ความหมายถูกต่อท้ายที่ท้ายอ็อบเจ็กต์ ทำให้คำสั่งถูกปฏิเสธ
- การทำให้เกิดซ้ำขึ้นอยู่กับบริบทอย่างมาก
- ในพรอมป์แบบ single-turn ใหม่อย่าง “edit this file” จะไม่เกิดซ้ำ
- แต่จะเกิดซ้ำใน ประวัติเอเจนต์ ที่โมเดลอ่านไฟล์ วินิจฉัยปัญหา แล้วจัดชุดการแก้ไขหลายบรรทัด
- ต้องมี transcript ของ Petr Baudis จึงจะทำให้เกิดซ้ำได้
- หากใช้ user session นั้นต่อไป Opus 4.8 จะล้มเหลวด้วยความน่าจะเป็นประมาณ 20%
- ถ้าลบ thinking block ออกจากประวัติ อัตราความล้มเหลวจะลดลงครึ่งหนึ่ง
- หากเปิดการเรียกเครื่องมือแบบ
strict ปัญหาจะหายไปในการรันนั้น
ทำไมมันถึงแย่ลง
- สมมติฐานที่หนักแน่นที่สุดคือ นี่ไม่ใช่การเสื่อมแบบสุ่ม แต่เป็น ผลผลิตจากการฝึก
- โมเดล Anthropic รุ่นก่อนถูกฝึกกับเครื่องมือบางส่วน แต่ยังเป็นช่วงก่อนที่ฮาร์เนสที่ผู้ใช้จัดเตรียมเองอย่าง Claude Code จะกลายเป็นเป้าหมายที่ชัดเจน
- มีความเป็นไปได้สูงว่าโมเดล Anthropic รุ่นล่าสุดได้รับ post-training โดยมี Claude Code หรือฮาร์เนสที่คล้ายกันมากรวมอยู่ด้วย และในสภาพแวดล้อมนั้นอาจเรียนรู้ทั้งการเรียกเครื่องมือที่สำเร็จและความผิดพลาดที่ยังยอมรับได้
- เครื่องมือ edit ของ Claude Code มีโครงสร้าง แบบแบน ใกล้กับ
file_path, old_string, new_string และ replace_all แบบเลือกได้ มากกว่าจะเป็นโครงสร้าง edits[] แบบซ้อนของ Pi
- ไคลเอนต์ Claude Code แก้ข้อผิดพลาดได้มากพอสมควร ทั้งลองใช้เครื่องมือใหม่เมื่อใช้ผิด, alias ของพารามิเตอร์, บังคับแปลงชนิด, กู้คืน Unicode และกรองคีย์ที่ไม่รู้จัก
- หาก reinforcement learning เกิดขึ้นภายในฮาร์เนสแบบนี้หรือการจำลองของมัน การเรียกเครื่องมือที่ผิดเล็กน้อยก็ยังอาจทำงานสำเร็จและได้รับรางวัลได้
- เมื่อฮาร์เนสอื่นให้เครื่องมือแก้ไขที่มีความหมายเหมือนกันแต่ใช้สคีมาต่างออกไป สำหรับโมเดลแล้วเครื่องมือนั้นอาจค่อย ๆ กลายเป็นเครื่องมือ นอก distribution
- ตอนเปิดตัว Opus 4.5 โมเดลยังปรับตัวเข้ากับเครื่องมือ edit แบบอื่นได้ดีมาก แต่สิ่งที่สังเกตตอนนี้ชี้ว่าสคีมาเครื่องมือทางเลือกอาจเสียเปรียบในระบบนิเวศเครื่องมือที่ผ่อนปรนแบบเฉพาะบางชุด
- แม้จะมี text editor tool ที่มีเอกสารกำกับ แต่ Claude Code ไม่ได้ทำตามรูปแบบนั้นตรง ๆ และการทำงานภายในของ Claude Code ก็มองไม่เห็นเพราะเป็นฮาร์เนสแบบปิดซอร์ส
ฮาร์เนสแบบหลวมของ Claude Code
- Claude Code เป็นซอฟต์แวร์ปิดซอร์ส แต่จากโค้ดที่ย่อมาให้ดูจะเห็นว่ามันผ่อนปรนมากกับข้อมูลขาเข้า
- มันตรวจว่ามี
<invoke markup หลุดออกมาในข้อความที่โมเดลมองเห็นหรือไม่ และถ้ามีก็จะส่ง telemetry แล้วลองเรียกที่ผิดใหม่ด้วย state machine ของตัวเอง
- มี การกู้คืน Unicode escape สำหรับแก้ลำดับ
\uXXXX ที่เสียหายและ lone surrogate ในค่าสตริง
- ยังมี alias ของพารามิเตอร์ตามชนิดเครื่องมือด้วย
Edit ยอมรับ old_str, old_string, new_str, new_string
- ยอมรับ
path เป็น alias ของ file_path
- คีย์ที่ไม่คาดคิดจะถูกกรองทิ้งแบบเงียบ ๆ
- ไม่ได้ใช้โหมด
strict
- Anthropic ใช้ข้อจำกัดความซับซ้อนของนิยามเครื่องมือในโหมด
strict ซึ่งอาจทำให้คำขอ API ล้มเหลวได้
- ดูเหมือนว่านี่คือเหตุผลที่ Claude Code ไม่พยายามใช้โหมด
strict
โหมด strict และระบบนิเวศอื่น ๆ
- ทั้งโมเดลและฮาร์เนสของ Anthropic ต่างก็ปิด จึงยากจะบอกได้ว่าปัญหาเดียวกันนี้จะเกิดในฮาร์เนสอื่นด้วยหรือไม่
- โมเดล Codex ก็เป็นแบบปิด แต่ฮาร์เนสไม่ปิด
- gpt-oss ถูกฝึกมาอย่างชัดเจนให้ใช้รูปแบบการตอบกลับ harmony ของ OpenAI และมีเอกสารจำนวนมากที่แสดงแนวคิดของ OpenAI
- harmony ทำให้ channel และ content type ของการเรียกเครื่องมือกลายเป็นส่วนหนึ่งของรูปแบบพรอมป์ และสามารถใส่มาร์กเกอร์อย่าง
<|constrain|>json ไว้ใน body ของการเรียกเครื่องมือได้
<|start|>assistant<|channel|>commentary to=functions.get_weather
<|constrain|>json<|message|>{"location":"San Francisco"}<|call|>
<|constrain|>json ทำให้ reasoning stack หา boundary ที่ต้องสลับไปใช้การสุ่มแบบมีข้อจำกัด JSON สำหรับ body ของการเรียกเครื่องมือได้ง่าย
- สำหรับโมเดล GPT ที่โฮสต์ไว้ ยังมีตัวเลือกให้ส่งไวยากรณ์ LARK สำหรับกำหนด grammar ที่เครื่องมือของผู้ใช้ต้องทำตาม
- ดูเหมือน Anthropic เองก็มีการจัดการคล้ายกันบางส่วนในโหมด
strict แต่สำหรับพารามิเตอร์อาร์เรย์แบบซ้อน โมเดลจำเป็นต้องสร้าง JSON ที่ escape แล้วภายใน string literal สำหรับเนื้อหาไฟล์หลายบรรทัดยาว ๆ
- คีย์ปลอมจะปรากฏหลังจากปิดสตริง
newText ที่ยาวหลายร้อยโทเคนทันที ตรง จุดเอนโทรปีสูง ที่โมเดลต้องเลือกระหว่าง } กับ , "..."
- ดูเหมือน Opus 4.8 และ Sonnet 5 จะมี prior ที่แรงกว่าสำหรับรูปแบบการเรียกเครื่องมือ edit และ prior นั้นใกล้กับสคีมา edit แบบแบนของ Claude Code มากกว่า
- ที่โหมด
strict ของ Anthropic แก้ปัญหาได้ อาจเป็นเพราะฝั่งเซิร์ฟเวอร์ปฏิเสธการสุ่มคีย์ที่ไม่ได้รับอนุญาตตามโครงสร้าง JSON schema
- ในโมเดล Codex ที่ทดสอบ ไม่พบ regression ประเภทนี้ และไม่ได้รวม 5.6 เพราะไม่มีสิทธิ์เข้าถึง
ผลกระทบต่อการออกแบบฮาร์เนส
- สำหรับโมเดล Anthropic สคีมาเครื่องมืออาจไม่ใช่สัญญาเชิงนามธรรมที่เป็นกลาง
- รูปทรงของเครื่องมือบางแบบใกล้กับสิ่งที่เคยเห็นในการ post-training และบางแบบก็ไกลออกไป
- บางรูปทรงอาจง่ายสำหรับ encoding ที่ซ่อนอยู่ของผู้ให้บริการ แต่บางรูปทรงกลับยาก เพราะต้องเขียนอ็อบเจ็กต์ JSON ขนาดใหญ่ที่ escape ไว้ภายในอาร์เรย์ซ้อนหลังสตริงหลายบรรทัดยาว ๆ
- แม้โมเดลจะเข้าใจสคีมา แต่ในสถานการณ์ที่มีแรงกดดัน มันก็อาจสุ่มโครงสร้างที่ถูกต้องออกมาไม่สำเร็จ
- สำหรับ Anthropic ปัญหานี้อาจหายไปได้ถ้าเปิดการสุ่มแบบ
strict
- อย่างไรก็ตาม พฤติกรรมของโมเดลรุ่นล่าสุดแสดงให้เห็นผลกระทบของ reinforcement learning ต่อโมเดล และการพยายามฝืน prior ของฮาร์เนสเฉพาะอาจไม่เป็นผลดีต่อการดึงประสิทธิภาพสูงสุดออกมา
- Claude Code ไม่ได้เป็นโอเพนซอร์ส และก็ไม่รู้ว่ามันทำอะไรในสภาพแวดล้อม RL ดังนั้นจึงยากจะสมมติว่าพฤติกรรมที่ฝึกให้เข้ากับ Claude Code จะถ่ายโอนมายังเครื่องมืออื่นได้อย่างสะอาด
- ยิ่งมี post-training เกิดขึ้นมากภายในฮาร์เนสที่ครองตลาดเพียงชุดเดียว ฮาร์เนสอื่นก็ยิ่งต้องรับช่วง ลักษณะแปลกเฉพาะ ของฮาร์เนสนั้นไปด้วย
- การถอดรหัสแบบมีข้อจำกัดอาจมี trade-off ด้านคุณภาพ แต่ถ้าโมเดลรุ่นใหม่เก่งขึ้นในการแก้งาน ขณะเดียวกันกลับแย่ลงในการปล่อยสคีมาเครื่องมือทางเลือกอย่างซื่อตรง ก็จำเป็นต้องมีการรับประกันที่แข็งแรงขึ้นในบางจุดของฮาร์เนส
1 ความคิดเห็น
ความคิดเห็นบน Lobste.rs
ถ้าสงสัยเกี่ยวกับ Fable เท่าที่เข้าใจ ตอนนี้ Fable จะ แจ้งให้ทราบอย่างชัดเจน เสมอเมื่อมีการดาวน์เกรด
ผมเองก็เคยโดนตัวจำแนกจับเหมือนกัน ดูเหมือนว่า “ช่วยเรียงบั๊กตามระดับความรุนแรงให้หน่อย” ฟังดูเหมือนงานวิจัยด้านความปลอดภัย
รู้ว่าเขาบอกว่าจะไม่ทำลับหลัง แต่ยังไม่ได้ตรวจสอบ กลไก ที่ใช้ในการดาวน์เกรด
ถ้าสมมติฐานนี้ถูกต้อง ผลกระทบอาจไปไกลกว่า coding agent
แอปพลิเคชันใดก็ตามที่พึ่งพา การเรียกใช้เครื่องมือ อย่างเสถียร อาจเจอประสิทธิภาพตกแบบเดียวกันหลังจากโมเดลถูกทำ post-training ให้เข้ากับสภาพแวดล้อมการรันที่ผู้ให้บริการรายหนึ่งชอบเป็นพิเศษ
ขอเสริมว่าโพสต์นี้ผมลงด้วยแท็ก
aiไม่ใช่vibecodingผมเข้าใจยากจริง ๆ ว่าเส้นแบ่งของ
vibecodingบนเว็บนี้อยู่ตรงไหนโพสต์นี้เกี่ยวข้องกับ LLM พื้นฐาน, reinforcement learning และการสร้างสภาพแวดล้อมการรันรอบ ๆ มันมากกว่าเยอะ
ถ้าแม้แต่นี่ก็เป็น
vibecodingแล้วแท็กaiยังเหลือไว้ใช้ตรงไหนกันแน่vibecodingกลายเป็นเหมือน ตราบาปตัวอักษรสีแดง ขนาดใหญ่ที่แปะให้ทุกอย่างที่แตะ generative AI แม้แต่นิดเดียว หรือดูเหมือนจะเคยแตะในช่วงไม่กี่สัปดาห์ที่ผ่านมา ตั้งแต่บทความบล็อกแนวอารมณ์ ๆ, README ของโปรเจกต์ใหญ่ที่ห้ามการมีส่วนร่วมจาก LLM ไปจนถึงบทความที่มีประโยคทำนอง “ไม่ใช่ X แต่เป็น Y” มากเกินไป ล้วนถูกติดแท็ก
vibecodingกันหมดส่วนตัวผมเลิกสนใจแท็กนั้นไปโดยสิ้นเชิงแล้ว เพราะชุมชนติดกันแบบอัตโนมัติเกินไปจนความหมายจริง ๆ หายไป
แต่สำหรับบทความนี้โดยเฉพาะ ถ้าจะพูดให้ชัด มันเกี่ยวกับโมเดลที่ถูกใช้กับงานนั้นจริง ๆ ดังนั้นผมเห็นด้วยที่จะติดแท็ก
vibecodingขณะเดียวกันก็เห็นด้วยตามเหตุผลที่ชี้ไว้ว่า
aiไม่ควรถูกลบออก ด้วย อยากเพิ่มกลับเข้าไป แต่ไม่รู้ทำไมโพสต์นี้ถึงไม่มีตัวเลือกนั้นไม่น่าแปลกใจ vendor lock-in น่าจะเป็นส่วนหนึ่งของแผนอยู่แล้ว
แนวคิดแบบ “ถ้าคุณจ่ายค่าสมัครสมาชิก Claude และส่งโค้ดทั้งหมดมาให้เราอยู่แล้ว ก็ต้องใช้ UI ฟรีของเราด้วย แม้มันอาจไม่ใช่เครื่องมือผูกมัดที่แข็งแรงพอเมื่อแยกจากโมเดล” นั้นค่อนข้างต่างจากวิธีที่ vendor lock-in แบบเพียว ๆ มักทำงาน
มันสมเหตุสมผลที่โมเดลจะทำงานได้ดีที่สุดในสภาพแวดล้อมการรันที่มันถูกฝึกมา นั่นคือสภาพแวดล้อมที่ผู้พัฒนาโมเดลสร้างขึ้น
ถ้ามีการทำ reinforcement learning อย่างหนักกับ trace แบบ Claude Code ผมก็คาดไว้ว่าในสภาพแวดล้อมการรันที่ไม่ทำงานเหมือน Claude Code มันคงแย่ลงพอสมควร
ส่วนตัวกลับแปลกใจกว่าที่มันดูเหมือนทำงานได้ค่อนข้างดีแม้ในสภาพแวดล้อมการรันของบุคคลที่สามอย่าง Pi
การที่บั๊กเกิดขึ้นเฉพาะลึก ๆ ใน trace ของ agent ก็ดูสมเหตุสมผลเช่นกัน
เมื่อต้นปีนี้ ผมเคยปล้ำกับบั๊กในโมเดล GPT 5.2 และ 5.3 ที่ช่วงท้าย ๆ ของ trace agent พิมพ์
ls -ლაออกมาแทนls -laผมจดไว้คร่าว ๆ ที่นี่: https://github.com/openai/codex/issues/7988
จากประสบการณ์ของผม สิ่งนี้ก็เกิดขึ้นหลังจาก trace ลึกขึ้นแล้วเท่านั้น
ในบริบทยาว ๆ โมเดลดูเหมือนไม่สามารถ “คิด” ได้อย่างชัดเจน และถอยกลับไปสู่ สัญชาตญาณ แบบดิบ ๆ
บางที ณ จุดนั้น ความแตกต่างระหว่าง distribution ที่โมเดลถูกฝึกมากับสภาพแวดล้อมการรัน หรือภารกิจที่ผู้ใช้บังคับให้โมเดลทำ อาจส่งผลต่อประสิทธิภาพอย่างรุนแรงที่สุด
ปัญหาคือทำ reinforcement learning มากเกินไปจนมัน ถดถอย ในสภาพแวดล้อมการรันอื่นเมื่อเทียบกับรีลีสก่อนหน้า
มาถึงจุดนี้ควรต้องถามแล้วว่า “overfitting แบบอื่น ๆ กำลังเริ่มเกิดขึ้นด้วยหรือเปล่า?”