Jsiphon - ตัวแยกวิเคราะห์ JSON สำหรับการสตรีม LLM ที่รองรับการติดตามเดลตาและการตรวจจับความกำกวม
(github.com/webtoon-today)สวัสดีครับ/ค่ะ ขอแนะนำ Jsiphon เครื่องมือนี้ช่วยแก้ปัญหาที่พบบ่อยเมื่อใช้การตอบกลับแบบมีโครงสร้างกับการสตรีมของ LLM
เมื่อใช้การตอบกลับแบบมีโครงสร้าง (โหมด JSON) ของ LLM ร่วมกับการสตรีม ก็มักจะเจอปัญหาการพาร์สคำตอบบางส่วนอยู่บ่อย ๆ ในกรณีแบบนี้จะใช้ JSON.parse() ตรง ๆ ไม่ได้ และมักต้องใช้วิธีพยายามกู้คืน JSON ที่ยังไม่สมบูรณ์ซ้ำ ๆ
แต่ถ้าอาศัยคุณสมบัติของคำตอบจาก LLM ที่เป็นแบบ append-only โดยมีแต่ข้อมูลเพิ่มเข้ามาโดยไม่ย้อนลำดับเดิม ก็จะสามารถแก้ปัญหานี้ได้อย่างสะอาดกว่ามาก และ Jsiphon มี 3 ความสามารถดังต่อไปนี้
-
การพาร์สแบบ append-only — เมื่อมีคำตอบบางส่วนเข้ามา เช่น
{"msg": "Helก็จะคืนค่าคำตอบที่สมบูรณ์ได้ทันทีในรูป{msg: "Hel"}โดยจะถือว่าสคีมาก่อนหน้าฟิลด์msgในตัวอย่างนี้สมบูรณ์แล้ว -
การติดตามเดลตา — ในแต่ละครั้งที่ส่งผลลัพธ์ออกมา นอกจากสแนปช็อตทั้งหมดแล้ว ยังมีข้อมูลที่เพิ่งถูกเพิ่มเข้ามาล่าสุดแยกให้อีกด้วย ตัวอย่างเช่น ถ้าคุณกำลังวาดบอลลูนข้อความของแชตบอตหลายอัน ก็ไม่ต้องวาดทั้งหมดใหม่ แต่สามารถวาดเฉพาะส่วนที่เพิ่มขึ้นของบอลลูนล่าสุดได้ ในตัวอย่างก่อนหน้า หาก LLM ส่งต่อด้วย
lo, World!คุณก็จะพบ{msg: "lo, World!"}ใต้deltaของคำตอบได้ทันที ทำให้ไม่จำเป็นต้องกู้คืนและพาร์ส JSON ใหม่พร้อมทำ diff ทุกครั้งที่ได้รับสแนปช็อต -
การตรวจจับความกำกวม — จะคืนค่า ambiguity tree ที่มีโครงสร้างต้นไม้เหมือนกับคำตอบทุกประการ โดยใช้บอกได้ในหลายระดับชั้นว่าข้อมูลที่อยู่ในสแนปช็อตนั้นยืนยันแล้วหรือยัง หรือยังอยู่ระหว่างการอ่านคำตอบต่อไป ตัวอย่างเช่น ขณะสตรีมข้อมูลต่อไปนี้
{"header":{"title": "abcdefghijk","date": "..."},"body": "..."}
ถ้าใช้
isAmbiguous(ambiguous.header.title)ก็จะสามารถใช้งานtitleได้อย่างปลอดภัยตั้งแต่จังหวะที่titleสมบูรณ์ (คำตอบลำดับที่ 3) โดยไม่ต้องรอให้ฟิลด์ถัดไปสมบูรณ์ทั้งหมด ไม่ได้ให้แค่สถานะว่าทั้งหมดสมบูรณ์หรือไม่ แต่ให้สถานะความสมบูรณ์บางส่วนในทุกระดับชั้นด้วย ดังนั้นisAmbiguous(ambiguous.header)จะคืนค่าisAmbiguous = falseก็ต่อเมื่อทุกลูกหลานของheaderสมบูรณ์แล้ว
แม้ตอนนี้จะมีไลบรารีสำหรับกู้คืน/พาร์ส partial JSON อยู่แล้วหลายตัว (เช่น partial-json, gjp-4-gpt ฯลฯ) และต่างก็ช่วยแก้ปัญหาการพาร์สพื้นฐานได้ดี แต่ Jsiphon ใช้ประโยชน์จากธรรมชาติของการสตรีม LLM ที่เป็นแบบ append-only จึงไม่ได้แค่ให้สแนปช็อตเท่านั้น แต่ยังให้ข้อมูลเพิ่มขึ้นรายฟิลด์ (delta) และช่วยระบุได้ในแต่ละรอบว่าฟิลด์ใดสมบูรณ์แล้ว
ถ้าคุณกำลังแก้ปัญหาแนวนี้อยู่ ก็น่าจะเข้าใจประโยชน์ของมันได้ดี ผม/ฉันเองกำลังผสาน Jsiphon เข้ากับ multi-type SSE เพื่อให้แชตบอตสตรีมข้อความไปพร้อมกับตัดสินหลายแฟลกแบบเรียลไทม์ เช่น is_adult, need_admin เป็นต้น
ในด้านการใช้งานจริง ยังมีความสะดวกเพิ่มเติม เช่น zero dependency, ไม่ throw error แม้คำตอบจะผิดรูป, และการตัดข้อความที่ไม่มีความหมายก่อนหรือหลัง JSON ออก
GitHub: https://github.com/webtoon-today/jsiphon
npm install jsiphon
ถ้าเห็นว่ามีประโยชน์ก็ลองนำไปใช้ดู แล้วช่วยส่งความคิดเห็นกันได้ครับ/ค่ะ
สำหรับ ambiguity tree เองก็ดูเป็นการออกแบบที่ท้าทายพอสมควร จึงอยากรู้เหมือนกันว่ามีวิธีที่ดีกว่านี้ไหม หากมีข้อเสนอแนะเรื่องการออกแบบ API ก็จะขอบคุณมากครับ/ค่ะ
ยังไม่มีความคิดเห็น