← Context Engineering Handbook
LEVEL 1 · ใช้ทุกวัน
เงินอยู่ที่ต้นแถว — cache กับกฎอย่าขยับของที่อยู่ต้นก้อน
ถึงเวลาไขคำถามที่ปลูกไว้ในบทที่ 1 แล้วครับ: ถ้าทุกรอบส่งประวัติทั้งก้อนไปใหม่ ทำไมค่าใช้จ่ายไม่ระเบิด
คำตอบคือ ระบบไม่ได้อ่านทั้งก้อนใหม่จริง ๆ ทุกรอบ — มันจำผลการอ่าน "ท่อนหน้า" ที่เหมือนเดิมเอาไว้ วงการเรียกกลไกนี้ว่า prompt caching และมันเป็นเหตุผลว่าทำไมบทนี้ถึงเป็นบทที่มีผลต่อบิลมากที่สุดในเล่ม
6.1 กลไก — มันจำเป็น "คำนำหน้า" ไม่ใช่จำเป็นชิ้น
หัวใจอยู่ที่คำเดียว: prefix (คำนำหน้า)
ก้อนข้อความถูกประกอบตามลำดับตายตัวเสมอ: นิยามเครื่องมือ → คำสั่งประจำตัว → ประวัติการคุย · ระบบจะจำผลการอ่าน "ตั้งแต่ต้นก้อนถึงจุดที่เรากำหนด" ไว้เป็นก้อนเดียว รอบต่อไปถ้าท่อนนั้น เหมือนเดิมทุกไบต์ มันหยิบของที่จำไว้มาใช้เลย
หนึ่งไบต์ที่เปลี่ยนต้นแถว ล้างทุกอย่างที่อยู่หลังมัน
นี่ไม่ใช่คำเปรียบ — มันคือกฎตรงตัว ถ้าไบต์ที่ตำแหน่งกลางก้อนเปลี่ยน ของที่จำไว้ทั้งหมดตั้งแต่ตำแหน่งนั้นไปจนสุดใช้ไม่ได้อีกเลย
6.2 ราคาจริง และจุดคุ้มทุน
- อ่านจากของที่จำไว้ ≈ 0.1 เท่า ของราคาปกติ
- เขียนของลงไปจำ = 1.25 เท่า (อายุ 5 นาที) หรือ 2 เท่า (อายุ 1 ชั่วโมง)
คิดจุดคุ้มทุนง่าย ๆ:
| อายุ · จำนวนรอบ | เขียน | อ่าน | รวม | ไม่ใช้ cache |
|---|---|---|---|---|
| 5 นาที · 2 รอบ | 1.25 | 0.1 | 1.35 | 2 → คุ้ม |
| 1 ชม. · 2 รอบ | 2 | 0.2 | 2.2 | 2 → ไม่คุ้ม |
| 1 ชม. · 3 รอบ | 2 | 0.2 | 2.2 | 3 → คุ้ม |
แปลว่า อายุ 5 นาทีคุ้มตั้งแต่คำขอที่สอง · อายุ 1 ชั่วโมงต้องใช้อย่างน้อยสามรอบถึงจะคุ้ม — เลือกอายุยาวเมื่อทราฟฟิกมาเป็นช่วง ๆ มีช่องว่างเกินห้านาที ไม่ใช่เลือกเพราะฟังดูดีกว่า
6.3 ตัวการเงียบที่ทำให้ไม่มีอะไรถูก cache เลย
ทั้งหมดนี้พังด้วยเรื่องเดียวกัน — มีของที่เปลี่ยนทุกรอบไปนั่งอยู่ต้นแถว:
# ❌ ต้นแถวเปลี่ยนทุกครั้ง — ไม่มีอะไรถูก cache เลยสักไบต์
system = f"วันนี้คือ {datetime.now()}. คุณคือผู้ช่วย..."
# ✅ ต้นแถวนิ่ง — ย้ายวันที่ไปไว้ท้ายสุด
system = "คุณคือผู้ช่วย..."
messages = [..., {"role": "user", "content": f"(วันนี้ {today}) ช่วย..."}]รายชื่อตัวการที่เจอบ่อยที่สุด:
- เวลา / วันที่ / เลขสุ่ม ใน system prompt
- แปลง JSON โดยไม่เรียงคีย์ — ได้ผลลัพธ์คนละลำดับทุกครั้ง ทั้งที่ข้อมูลเหมือนกัน
- เปลี่ยนชุดเครื่องมือกลางทาง — เครื่องมืออยู่ตำแหน่งแรกสุด เพิ่มหรือถอดตัวเดียวล้างหมดทั้งก้อน
- สลับรุ่นโมเดลกลางบทสนทนา — ของที่จำไว้ผูกกับรุ่น
6.4 ลองพิสูจน์ด้วยตาเอง
ทุกคำตอบที่ระบบส่งกลับมามีตัวเลขสามตัวติดมาด้วย:
| ตัวเลข | แปลว่า |
|---|---|
cache_read_input_tokens | โทเคนที่หยิบจากของที่จำไว้ (จ่าย 0.1 เท่า) |
cache_creation_input_tokens | โทเคนที่เพิ่งเขียนลงไปจำ (จ่ายแพงกว่าปกติ) |
input_tokens | โทเคนที่ต้องอ่านใหม่จริง ๆ (จ่ายเต็ม) |
ยิงคำขอเดิมสองรอบติดกันแล้วดูตัวที่หนึ่ง — ถ้ารอบสองยังเป็นศูนย์ทั้งที่ท่อนหน้าไม่ควรเปลี่ยน แปลว่ามีตัวการเงียบซ่อนอยู่ ไปไล่หาตามรายชื่อข้างบน
6.5 สั้นเกินไปก็ไม่ถูก cache — และไม่มีใครบอก
มีขั้นต่ำอยู่ · ท่อนหน้าที่สั้นกว่าประมาณ 512 ถึง 4,096 โทเคน แล้วแต่รุ่น จะไม่ถูก cache เลย และ ไม่มี error ไม่มีคำเตือน — เงียบสนิท ตัวเลขก็แค่เป็นศูนย์