ข้ามไปยังเนื้อหา
Tayakorn
Context Engineering Handbook

Context Engineering Handbook

LEVEL 1 · ใช้ทุกวัน

เงินอยู่ที่ต้นแถว — cache กับกฎอย่าขยับของที่อยู่ต้นก้อน

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

คำตอบคือ ระบบไม่ได้อ่านทั้งก้อนใหม่จริง ๆ ทุกรอบ — มันจำผลการอ่าน "ท่อนหน้า" ที่เหมือนเดิมเอาไว้ วงการเรียกกลไกนี้ว่า prompt caching และมันเป็นเหตุผลว่าทำไมบทนี้ถึงเป็นบทที่มีผลต่อบิลมากที่สุดในเล่ม

6.1 กลไก — มันจำเป็น "คำนำหน้า" ไม่ใช่จำเป็นชิ้น

หัวใจอยู่ที่คำเดียว: prefix (คำนำหน้า)

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

รอบที่ 2 · ต้นแถวเหมือนเดิมทุกไบต์นิยามเครื่องมือคำสั่งประจำตัวประวัติเก่าข้อความใหม่อ่านจากแคช ≈ 0.1 เท่าจ่ายเต็มรอบที่ 2 · แก้คำสั่งประจำตัวไปหนึ่งไบต์นิยามเครื่องมือคำสั่งประจำตัวแก้ตรงนี้ประวัติเก่าข้อความใหม่รอดแค่ท่อนก่อนจุดที่แก้ที่เหลือจ่ายเต็มทั้งหมด
FIG 6.1 แคชจับที่ คำนำหน้า ไม่ใช่จับเป็นชิ้น — ไบต์เดียวที่เปลี่ยนตรงกลาง ทำให้ทุกอย่างหลังจากจุดนั้นใช้ของเดิมไม่ได้อีก ต่อให้เนื้อหาที่เหลือเหมือนเดิมเป๊ะ

หนึ่งไบต์ที่เปลี่ยนต้นแถว ล้างทุกอย่างที่อยู่หลังมัน

นี่ไม่ใช่คำเปรียบ — มันคือกฎตรงตัว ถ้าไบต์ที่ตำแหน่งกลางก้อนเปลี่ยน ของที่จำไว้ทั้งหมดตั้งแต่ตำแหน่งนั้นไปจนสุดใช้ไม่ได้อีกเลย

6.2 ราคาจริง และจุดคุ้มทุน

  • อ่านจากของที่จำไว้0.1 เท่า ของราคาปกติ
  • เขียนของลงไปจำ = 1.25 เท่า (อายุ 5 นาที) หรือ 2 เท่า (อายุ 1 ชั่วโมง)

คิดจุดคุ้มทุนง่าย ๆ:

อายุ · จำนวนรอบเขียนอ่านรวมไม่ใช้ cache
5 นาที · 2 รอบ1.250.11.352 → คุ้ม
1 ชม. · 2 รอบ20.22.22 → ไม่คุ้ม
1 ชม. · 3 รอบ20.22.23 → คุ้ม

แปลว่า อายุ 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 ไม่มีคำเตือน — เงียบสนิท ตัวเลขก็แค่เป็นศูนย์

อ่านแบบเต็มเล่ม