Prompt caching ลดค่า LLM ได้ แต่ต้นพรอมป์ที่เปลี่ยนอาจทำให้พลาดแคช

|ผู้เขียน: กองบรรณาธิการ QUASA|3 นาทีในการอ่าน| 1
Prompt caching ลดค่า LLM ได้ แต่ต้นพรอมป์ที่เปลี่ยนอาจทำให้พลาดแคช

Prompt caching ช่วยลดต้นทุนโทเค็นขาเข้าของ LLM API และลดเวลารอก่อนคำตอบเริ่มมาได้ เมื่อคำขอซ้ำใช้ต้นพรอมป์เดียวกันที่ยาวพอและยังอยู่ในแคช วิธีจัดคือคงคำสั่ง นิยามเครื่องมือ ตัวอย่าง และข้อมูลอ้างอิงที่ใช้ร่วมกันไว้ก่อน แล้ววางคำถามหรือข้อมูลเฉพาะครั้งไว้ท้ายสุด การเปลี่ยนข้อความตั้งแต่ช่วงต้นทำให้ส่วนที่ตามมาจับคู่กับแคชเดิมไม่ได้ แม้ข้อความช่วงหลังจะเหมือนกันก็ตาม

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

วางขอบเขตส่วนคงที่ในพรอมป์อย่างไร

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

  1. นิยามเครื่องมือ: คงชื่อ คำอธิบาย พารามิเตอร์ และลำดับเครื่องมือที่ส่งให้โมเดลเหมือนเดิมในกลุ่มคำขอเดียวกัน
  2. คำสั่งและบริบท: วางกติกาภาษา รูปแบบคำตอบ ข้อจำกัด และข้อความจากคู่มือที่ใช้ซ้ำไว้ก่อนข้อมูลของแต่ละคน
  3. ตัวอย่าง: ต่อคู่คำถามกับคำตอบที่ใช้สอนรูปแบบงานเดียวกัน โดยไม่สอดคำถามปัจจุบันเข้าไปกลางชุดตัวอย่าง
  4. ขอบเขตแคช: หาก API และรุ่นโมเดลที่ใช้กำหนด breakpoint ได้ ให้วางหลังบล็อกคงที่สุดท้าย
  5. ส่วนท้ายที่เปลี่ยน: ใส่คำถามใหม่ ข้อมูลเฉพาะลูกค้า ผลเครื่องมือที่เพิ่งได้ และบทสนทนาที่เพิ่มเข้ามาหลังขอบเขตนั้น

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

ตัวอย่างเชิงโครงสร้างคือคำขอ ก และ ข เริ่มด้วยกติกาตอบภาษาไทย ชุดเครื่องมือ และคู่มือฉบับเดียวกัน ก่อนแยกเป็นคำถามเกี่ยวกับการคืนสินค้าและคำถามเกี่ยวกับการรับประกัน ส่วนต้นที่เหมือนกันมีโอกาสอ่านจากแคช ส่วนคำถามปลายทางแต่ละคำขอยังคงประมวลผลใหม่ หากนำคำถามของ ก ไปแทรกระหว่างกติกากับคู่มือ คำขอ ข จะต่างจาก ก ตั้งแต่จุดนั้น คู่มือที่อยู่ด้านหลังจึงไม่เป็น prefix เดิมต่อเนื่อง แม้คู่มือจะเหมือนกันทุกตัวอักษร

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

ตำแหน่ง breakpoint มีผลต่อสิ่งที่ระบบเขียนด้วย หากปล่อยให้จุดคั่นอัตโนมัติอยู่หลังคำถามที่เปลี่ยนทุกครั้ง ระบบอาจเขียนส่วนท้ายใหม่ซ้ำ แม้ยังอ่านส่วนต้นเดิมได้ การกำหนดจุดคั่นหลังเนื้อหาคงที่เมื่อรุ่นโมเดลรองรับ ทำให้ขอบเขตที่ตั้งใจจ่ายค่าเขียนชัดเจนขึ้น แต่จุดคั่นที่วางไว้ก่อนเนื้อหาคงที่บางส่วนก็ทำให้ส่วนนั้นพลาดโอกาสอ่านแคช

เหตุใดคำขอที่ดูเหมือนเดิมยังพลาดแคช

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

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

สำหรับ Claude ลำดับ prefix ที่ใช้พิจารณาคือ tools แล้ว system แล้ว messages การเปลี่ยนนิยามเครื่องมือกระทบส่วนที่ตามมาทั้งหมด ส่วนการปรับ tool_choice หรือการเพิ่มภาพอาจกระทบบล็อกข้อความ ข้อแตกต่างเชิงลำดับนี้ทำให้การเลื่อนข้อมูลที่เปลี่ยนออกไปหลังบล็อกคงที่ช่วยรักษาส่วนร่วมได้ แต่ไม่แก้กรณีที่เครื่องมือระดับต้นเปลี่ยนในทุกคำขอ หากต้องใช้เครื่องมือหลายชุดตามงาน การแยกวัดแต่ละรูปแบบพรอมป์จะอธิบายยอดอ่านได้ชัดกว่าการรวมทุกชุดเป็นอัตราเดียว

อีกสาเหตุคือแคชอาจไม่พร้อมแม้ข้อความเหมือนเดิม ช่วงเวลาที่รายการยังใช้ได้ขึ้นกับระบบและรุ่นโมเดล การส่งคำขอ Claude พร้อมกันก่อนคำตอบแรกเริ่มอาจยังไม่มีรายการให้คำขออื่นอ่าน ส่วนการจัดเส้นทางของ OpenAI ก็มีผลต่อการพบรายการบนเครื่องที่ให้บริการ คำขอที่ไม่อ่านแคชครั้งเดียวจึงยังแยกไม่ได้ว่าเพราะข้อความต่าง เกณฑ์ความยาว อายุแคช หรือเส้นทางให้บริการ ต้องดูองค์ประกอบเหล่านี้ร่วมกับยอด usage ของคำขอที่เทียบกันได้

ในบทสนทนายาว การเพิ่มข้อความใหม่ต่อท้ายช่วยรักษาประวัติช่วงต้นที่เหมือนเดิม แต่การสรุปประวัติเก่าใหม่ การสลับลำดับข้อความ หรือการแทนที่ผลเครื่องมือเดิมอาจเปลี่ยน prefix ตั้งแต่ก่อนจุดคั่นได้ งานที่อัปเดตเอกสารอ้างอิงเป็นระยะจึงควรมองแต่ละฉบับเป็นกลุ่มการใช้ซ้ำของตัวเอง ยอดอ่านแคชที่ลดลงทันทีหลังอัปเดตอาจเป็นผลตามโครงสร้างของงาน ไม่จำเป็นต้องหมายถึงบริการแคชขัดข้อง

ขั้นต่ำและอายุแคชต่างกันตรงไหน

คู่มือแคชของ OpenAI ระบุว่า GPT-5.6 และรุ่นหลังต้องมี prefix ที่มีสิทธิ์เก็บยาวอย่างน้อย 1,024 โทเค็นที่มองเห็นได้ และรายการมีอายุขั้นต่ำ 30 นาทีหลังการเขียนหรืออ่านครั้งล่าสุด; ค่าเขียนของรุ่นกลุ่มนี้อยู่ที่ 1.25 เท่าของขาเข้าปกติ ส่วนค่าอ่านของรุ่นใหม่ส่วนใหญ่อยู่ที่ 0.1 เท่า รุ่นก่อนหน้านั้นมีเกณฑ์ขั้นต่ำ อัตรา และตัวเลือกการคงแคชที่ต่างออกไป จึงต้องใช้อัตราของรุ่นที่เรียกจริงในการคำนวณ

รุ่นใหม่ของ OpenAI วาง breakpoint อัตโนมัติได้ และรองรับการเลือกจุดคั่นหลังเนื้อหาคงที่เมื่อส่วนท้ายเปลี่ยนบ่อย การมีข้อความคงที่ยาวถึงขั้นต่ำยังไม่รับประกันยอดอ่าน เพราะคำขอถัดไปต้องมี prefix ที่ตรงกันและพบรายการที่ยังพร้อมใช้งานด้วย สำหรับรุ่นก่อน GPT-5.6 การใช้ prompt_cache_key ที่คงที่กับกลุ่มคำขอที่เกี่ยวข้องช่วยเรื่องการจัดเส้นทาง แต่คีย์เดียวกันเพียงอย่างเดียวไม่รับประกันการพบแคช

คู่มือ prompt caching ของ Claude ระบุว่า Claude Sonnet 5.5 ต้องมีส่วนที่เก็บอย่างน้อย 512 โทเค็น, Claude Sonnet 4.6 ต้องมี 1,024 โทเค็น และ Claude Haiku 4.5 ต้องมี 4,096 โทเค็น; อายุเริ่มต้นคือ 5 นาที ส่วนตัวเลือก 1 ชั่วโมงมีค่าเขียนเพิ่ม โดยสำหรับ Claude Sonnet 5.5 ค่าเขียนสองแบบอยู่ที่ 1.25 และ 2 เท่าของขาเข้าปกติ ขณะที่ค่าอ่านอยู่ที่ 0.1 เท่า Claude รองรับทั้ง cache_control แบบอัตโนมัติและ breakpoint บนบล็อกที่เลือกเอง

ความยาวขั้นต่ำต้องพิจารณาที่เนื้อหาก่อนขอบเขตแคช ไม่ใช่จำนวนโทเค็นทั้งคำขอ หากคู่มือและกติกาที่คงที่สั้นกว่าขั้นต่ำ แต่คำถามท้ายคำขอยาวมาก การเพิ่มคำถามไม่ได้ทำให้ prefix คงที่ยาวขึ้น การเติมตัวอย่างที่เกี่ยวกับงานจริงอาจทำให้ถึงเกณฑ์ ทว่าแต่ละตัวอย่างเพิ่มค่าเขียนและเพิ่มอินพุตในครั้งที่พลาดแคช จึงต้องดูทั้งผลต่อคุณภาพคำตอบและต้นทุนรวม

อายุแคชเป็นเงื่อนไขสำคัญเมื่อคำขอมีช่วงเว้นห่าง ระบบที่เรียกซ้ำถี่อาจอ่านรายการเดิมและต่ออายุได้หลายครั้ง ส่วนงานที่เรียกเป็นรอบห่างอาจจ่ายค่าเขียนใหม่แทบทุกครั้ง สำหรับ Claude ระยะเวลานับจากเริ่มคำขอที่เขียนหรืออ่านรายการ ไม่ได้นับจากเวลาที่คำตอบเสร็จ หากคำตอบใช้เวลานาน ช่วงที่เหลือให้คำขอถัดไปอ่านรายการเดิมย่อมสั้นลง การเลือกอายุยาวขึ้นจึงควรอิงจังหวะเรียกจริงและจำนวนครั้งที่คาดว่าจะอ่านซ้ำ

อ่าน usage เพื่อแยกการอ่านออกจากการเขียนใหม่

OpenAI แสดงยอดโทเค็นขาเข้าทั้งหมดใน usage.input_tokens และแยกยอดอ่านกับเขียนใน usage.input_tokens_details.cached_tokens กับ cache_write_tokens สำหรับรุ่นที่รายงานการเขียน ช่อง cached_tokens เป็นศูนย์หมายความว่าคำขอนั้นไม่ได้อ่านจากแคช ส่วน cache_write_tokens บอกปริมาณที่ถูกเขียนใหม่ ค่าอินพุตปกติจึงคำนวณจาก input_tokens ลบสองช่องดังกล่าว แล้วคูณแต่ละส่วนกับอัตราอ่าน เขียน และปกติของรุ่นที่ใช้อยู่ตามลำดับ

Claude รายงาน usage.cache_read_input_tokens และ usage.cache_creation_input_tokens แยกกัน ส่วน usage.input_tokens เป็นโทเค็นขาเข้าที่ไม่ได้อ่านหรือเขียนเป็นแคช ผลรวมของทั้งสามช่องคือขาเข้าทั้งหมดที่ต้องใช้คำนวณ หากใช้อายุแคชสองแบบร่วมกัน ให้ดูรายละเอียด cache_creation.ephemeral_5m_input_tokens กับ ephemeral_1h_input_tokens เพื่อคูณอัตราเขียนของแต่ละแบบ การเอา input_tokens ช่องเดียวไปเทียบกับพรอมป์ทั้งฉบับจะทำให้ประเมินต้นทุนผิด เพราะช่องนี้ไม่รวมส่วนที่อยู่ในสองช่องแคช

สมมติให้ส่วนคงที่ยาว 2,000 โทเค็นและคำถามใหม่ยาว 300 โทเค็น โดยกำหนด breakpoint หลังส่วนคงที่และสมมติว่าคำขอถัดไปอ่านได้ครบ ครั้งแรกควรเห็นการเขียนส่วนคงที่ ส่วนครั้งถัดไปควรเห็นยอดอ่านของส่วนเดิมพร้อมยอดขาเข้าปกติของคำถามใหม่ ตัวเลขนี้เป็นเพียงแบบจำลองสำหรับอ่านช่อง usage; ยอดที่รายงานจริงอาจขึ้นกับวิธีเลือก breakpoint และวิธีนับของรุ่นโมเดล

หากครั้งถัดไปกลับมียอดเขียน ให้ดูตำแหน่งแรกที่อินพุตต่างกันและเวลาระหว่างคำขอ หากทั้งยอดเขียนและอ่านเป็นศูนย์ ให้ดูเกณฑ์ขั้นต่ำและตำแหน่ง breakpoint ก่อน การวินิจฉัยจากคู่คำขอที่รู้ว่าควรใช้ prefix เดียวกันชัดกว่าการมองค่าเฉลี่ยของทุกงานที่ปะปนกัน คำขอสั้นที่ไม่มีสิทธิ์เก็บไม่ควรถูกรวมกับงานคู่มือยาวแล้วใช้ค่าเฉลี่ยเดียวตัดสินว่าการจัดพรอมป์ล้มเหลว

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

คำนวณจุดคุ้มทุนจากจำนวนครั้งที่ใช้ซ้ำ

สูตรพื้นฐานใช้เฉพาะส่วนคงที่ที่ยาวเท่ากันและสมมติว่าเขียนครั้งแรกแล้วทุกคำขอที่เหลืออ่านได้ครบ กำหนด B เป็นราคาประมวลผล prefix หนึ่งครั้งในอัตราขาเข้าปกติ, w เป็นตัวคูณค่าเขียน, r เป็นตัวคูณค่าอ่าน และ N เป็นจำนวนคำขอ หากไม่ใช้แคช ต้นทุนส่วนนี้คือ B × N; หากเขียนครั้งเดียวแล้วอ่านอีก N − 1 ครั้ง ต้นทุนคือ B × [w + (N − 1) × r] การใช้แคชคุ้มกว่าประมวลผลใหม่เมื่อ N มากกว่า (w − r) ÷ (1 − r) โดยต้องมี r ต่ำกว่า 1

กรณีตัวอย่างให้ w เท่ากับ 1.25 และ r เท่ากับ 0.1 ซึ่งตรงกับ Claude Sonnet 5.5 แบบ 5 นาทีและ OpenAI รุ่นใหม่ส่วนใหญ่ตามเงื่อนไขข้างต้น หากมีคำขอสองครั้ง ส่วนคงที่หนึ่งชุดมีต้นทุนเทียบเท่า 1.35 เท่าของการประมวลผลปกติหนึ่งครั้ง แทนที่จะจ่าย 2 เท่า การอ่านสำเร็จเพียงหนึ่งครั้งหลังเขียนจึงเริ่มคุ้มสำหรับส่วนคงที่ในแบบจำลองนี้ แต่บิลทั้งคำขอยังรวมข้อมูลท้ายพรอมป์และโทเค็นคำตอบ

หากเลือก Claude Sonnet 5.5 แบบ 1 ชั่วโมง ค่าเขียนในตัวอย่างเป็น 2 เท่าของขาเข้าปกติ ขณะที่ค่าอ่านยังเป็น 0.1 เท่า คำขอสองครั้งจึงมีต้นทุนส่วนคงที่ 2.1 เท่า แพงกว่าการประมวลผลปกติสองครั้ง; ต้องมีคำขอรวมอย่างน้อยสามครั้งโดยอ่านสำเร็จสองครั้งจึงเริ่มคุ้ม การเปรียบเทียบนี้นับจำนวนครั้งภายในรุ่นและผู้ให้บริการเดียวกัน ไม่ได้ถือว่าราคาต่อโทเค็นของ OpenAI กับ Claude เท่ากัน หรือถือว่าทุกรุ่นใช้ตัวคูณค่าอ่านเดียวกัน

หากมีการเขียนใหม่หลายรอบ สูตรที่ใช้ข้อมูลจริงจะตรงกว่า ให้ W เป็นจำนวนโทเค็นที่เขียน, R เป็นจำนวนโทเค็นที่อ่าน และ M เป็นจำนวนโทเค็นขาเข้าปกติในกลุ่มงานเดียวกัน ต้นทุนขาเข้าที่คิดเป็นหน่วยราคาโทเค็นปกติเท่ากับ W × w + R × r + M ส่วนกรณีประมวลผลทั้งหมดแบบปกติเท่ากับ W + R + M ผลประหยัดเกิดเมื่อ R × (1 − r) มากกว่า W × (w − 1) สูตรนี้ทำให้เห็นผลของการหมดอายุหรือการแก้ต้นพรอมป์บ่อย: ยอดเขียนเพิ่มขึ้น แต่ยอดอ่านที่ชดเชยค่าเขียนอาจไม่เพิ่มตาม

การคำนวณทั้งสองแบบยังต้องคิดโทเค็นขาออกแยกตามอัตราขาออก และใช้อัตราของรุ่นที่เรียกจริง หากงานมีปริมาณคำขอไม่สม่ำเสมอ จำนวนการเรียกรวมตลอดวันก็ยังไม่พอบอกความคุ้ม สิ่งที่กำหนดผลของแคชคือแต่ละ prefix ถูกอ่านซ้ำกี่ครั้งก่อนเนื้อหาจะเปลี่ยนหรือรายการจะหมดอายุ ตัวเลขจาก usage จึงตอบได้ตรงกว่าการคาดจากจำนวนคำขอทั้งหมดเพียงอย่างเดียว

แชร์:

สมัครรับจดหมายข่าวของเรา

รับข่าวสารล่าสุดเกี่ยวกับ Web3, AI และคริปโตส่งตรงถึงกล่องจดหมายของคุณ

0