การลดต้นทุนคู่มือ
ตัดประวัติแชทเพื่อลดต้นทุน: sliding window หรือสรุป
จำกัดสิ่งที่คุณส่งซ้ำในแต่ละเทิร์น: เก็บไม่กี่ข้อความล่าสุดหรือสรุปสั้น ๆ การคำนวณโทเคนสำหรับแชท 50 เทิร์นและตัวช่วย Python

ในหน้านี้
บอทซัพพอร์ตของคุณแชทมาแล้ว 50 เทิร์น และทุกข้อความใหม่มีต้นทุนสูงกว่าข้อความก่อนหน้า API ไม่จดจำอะไรเลย โค้ดของคุณจึงส่งบทสนทนาทั้งหมดซ้ำทุกครั้ง วิธีแก้คือจำกัดสิ่งที่คุณส่ง: เก็บ system prompt กับไม่กี่เทิร์นล่าสุด (sliding window) หรือแทนที่เทิร์นเก่าด้วยสรุปสั้น ๆ ด้านล่างคือการคำนวณสำหรับแชท 50 เทิร์นและตัวช่วยที่คุณคัดลอกได้
คู่มือ multi-round chat ของ DeepSeek (api-docs.deepseek.com ตรวจสอบเมื่อ 1 พฤศจิกายน 2026) ระบุชัดเจนว่าเซิร์ฟเวอร์ไม่บันทึก context ของคำขอก่อนหน้า ไคลเอนต์จึงต้องส่งรายการ messages ทั้งหมดทุกครั้งที่เรียก รูปแบบที่เข้ากันได้กับ OpenAI บน CheapTokens ทำงานแบบเดียวกัน หากคุณเพิ่งรู้จักเรื่องนี้ เริ่มจาก ทำไมแชทยาวจึงมีต้นทุนสูงขึ้น และ อาร์เรย์ messages ทำงานอย่างไร
เทิร์นที่ 50 ส่งอะไรจริง ๆ#
สมมติคุณรันบอทซัพพอร์ตที่มี system prompt 400 โทเคน ในเทิร์นทั่วไปผู้ใช้เขียนราว 60 โทเคน และบอทตอบราว 190 โทเคน หนึ่งเทิร์นเต็มเพิ่ม 250 โทเคนเข้าประวัติ นี่คือสมมติฐาน: แทนที่ด้วยตัวเลขจากฟิลด์ usage ของคำตอบคุณเอง
ที่เทิร์น 50 คำขอมี system prompt, 49 เทิร์นก่อนหน้า และข้อความใหม่: 400 + 49 × 250 + 60 = 12,710 input tokens เพื่อให้ได้คำตอบ 190 โทเคน รวมทั้งแชท system prompt และข้อความใหม่ถูกส่งทุกครั้ง: 50 × 460 = 23,000 ประวัติที่ส่งซ้ำเพิ่ม 250 × 1,225 = 306,250 รวมกัน: 23,000 + 306,250 = 329,250 input tokens เทียบกับ 50 × 190 = 9,500 output tokens
ประวัติในแต่ละคำขอเพิ่มขึ้นหนึ่งเทิร์น ยอดรวมจึงโตตามกำลังสองของความยาวแชท จาก 50 เป็น 100 เทิร์น ส่วนประวัติที่ส่งซ้ำจะเพิ่มขึ้นราวสี่เท่า
ลองด้วยตัวเองลองดู: ถ้าคุณส่งเฉพาะ system prompt, 4 เทิร์นล่าสุด และข้อความใหม่ เทิร์นที่ 50 จะมี input tokens เท่าไร?แสดงคำตอบ
1,460 (400 + 4 × 250 + 60) เทียบกับ 12,710 เมื่อส่งประวัติเต็ม คำถามเดิม ความยาวคำตอบเดิม แต่ใช้ input เพียงเศษเสี้ยว
ตัวเลือกที่ 1: sliding window#
แนวคิด: ส่ง system prompt เสมอ ตัดทุกอย่างยกเว้น N เทิร์นล่าสุด คุณเก็บประวัติเต็มในที่จัดเก็บของคุณเองและตัดเฉพาะสำเนาที่ส่ง
def trim_history(messages, keep_pairs=4):
"""System prompt + the last keep_pairs turns + the new user message."""
system = [m for m in messages if m["role"] == "system"]
rest = [m for m in messages if m["role"] != "system"]
return system + rest[-(keep_pairs * 2 + 1):]เรียกมันหลังคุณต่อท้ายข้อความใหม่ของผู้ใช้ ด้วย keep_pairs=4 นั่นคือ 4 คู่ user/assistant บวกข้อความใหม่ รวม 9 ข้อความ และ slice จะเริ่มที่ข้อความของผู้ใช้เสมอ นี่คือการต่อเข้ากับการเรียกจริง:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
MODEL = "deepseek-ai/DeepSeek-V4-Flash-0731"
history = [{"role": "system", "content": "You are a concise support assistant."}]
def ask(text):
history.append({"role": "user", "content": text})
resp = client.chat.completions.create(
model=MODEL,
messages=trim_history(history),
max_tokens=500,
)
answer = resp.choices[0].message.content
history.append({"role": "assistant", "content": answer})
print(resp.usage.prompt_tokens, resp.usage.completion_tokens)
return answerบรรทัด print คือบรรทัดที่มีประโยชน์: จับตาดูตัวเลขแรก หากไม่ตัด มันจะเพิ่มขึ้นทุกเทิร์น ด้วย window มันจะหยุดโตเมื่อแชทผ่านเทิร์นที่ 4

ในเชิงตัวเลข: ตั้งแต่เทิร์นที่ 5 เป็นต้นไป แต่ละคำขอคือ 400 + 4 × 250 + 60 = 1,460 input tokens สี่เทิร์นแรกยังโตตามปกติและรวมกันได้ 3,340 ทั้งแชท: 3,340 + 46 × 1,460 = 70,500 input tokens ราวหนึ่งในห้าของ 329,250 ที่คุณส่งเมื่อใช้ประวัติเต็ม Output ยังคงเป็น 50 × 190 = 9,500

ในโค้ด การเปลี่ยนแปลงทั้งหมดคืออาร์กิวเมนต์เดียวในการเรียก:
เปรียบเทียบ
การเปลี่ยนแปลงบรรทัดเดียว
ก่อน
messages=historyหลัง
messages=trim_history(history)ข้อควรระวัง: window จะลืม หากผู้ใช้ถามในเทิร์นที่ 40 ว่า "หมายเลขคำสั่งซื้อของฉันคืออะไร?" และหมายเลขนั้นอยู่ในเทิร์นที่ 3 โมเดลจะไม่เคยเห็นมัน วิธีแก้ราคาถูกสองวิธี ดึงข้อเท็จจริงที่คงที่ (ชื่อ หมายเลขคำสั่งซื้อ แพ็กเกจ) ออกจากแชทในโค้ดของคุณเองและต่อท้ายเข้า system prompt ซึ่ง window จะไม่ตัดมัน หรือเพิ่มสรุป ซึ่งเป็นตัวเลือกถัดไป
ตัวเลือกที่ 2: สรุปเทิร์นเก่า#
แทนที่จะทิ้งเทิร์นเก่า คุณบีบอัดมัน ทุกไม่กี่เทิร์น ส่งเทิร์นที่เพิ่งหลุดออกจาก window พร้อมสรุปปัจจุบันไปยังโมเดลและขอสรุปใหม่ที่สั้น จากนั้นใส่สรุปลงใน system message
def summarize(summary, old_messages):
transcript = "\n".join(f"{m['role']}: {m['content']}" for m in old_messages)
prompt = (
f"Summary so far:\n{summary}\n\nNew turns:\n{transcript}\n\n"
"Rewrite the summary in under 200 words. "
"Keep names, numbers, decisions and open questions."
)
resp = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": prompt}],
max_tokens=400,
)
return resp.choices[0].message.content
def build_messages(history, summary, keep_pairs=4):
system = history[0]["content"]
if summary:
system += "\n\nEarlier in this chat: " + summary
recent = history[1:][-(keep_pairs * 2 + 1):]
return [{"role": "system", "content": system}] + recentสรุปไม่ฟรี: มันคือการเรียกโมเดลเพิ่ม สมมติสรุปยาวราว 300 โทเคน รีเฟรชทุก 5 เทิร์น (9 ครั้งใน 50 เทิร์น) แต่ละครั้งอ่านราว 1,600 โทเคน (สรุปเก่าบวกห้าเทิร์นบวกคำสั่ง) และเขียน 300 เพื่อความปลอดภัย ให้นับสรุปในทุกคำขอตั้งแต่เทิร์นที่ 5 เป็นต้นไป (ในความเป็นจริงมันปรากฏหลังการรีเฟรชครั้งแรก นี่จึงเป็นการประเมินเกินเล็กน้อย): 400 + 300 + 4 × 250 + 60 = 1,760 input tokens
ยอดรวมสำหรับแชท: คำขอหลัก 3,340 + 46 × 1,760 = 84,300 input tokens, การเรียกสรุป 9 × 1,600 = 14,400 input และ 9 × 300 = 2,700 output ทั้งหมด 84,300 + 14,400 = 98,700 input และ 9,500 + 2,700 = 12,200 output tokens
สรุปมีต้นทุนมากกว่า window เปล่าเล็กน้อย และแลกมาด้วยโมเดลที่ยังรู้ว่าเกิดอะไรขึ้นในเทิร์นที่ 3
สามรูปแบบมีต้นทุนเท่าไร#
นี่คือแชท 50 เทิร์นเดียวกันบน DeepSeek-V4-Flash คำนวณสดจากยอดรวมข้างต้น:
ราคามาจากรายการราคาสด ตัวเลขจึงอัปเดตเมื่ออัตราเปลี่ยน ลำดับจะไม่เปลี่ยน: window ส่งน้อยที่สุด สรุปอยู่ตรงกลาง ประวัติเต็มแพงที่สุด
สำหรับแชทแบบนี้ โมเดล CheapTokens ที่ควรเริ่มด้วยคือ DeepSeek-V4-Flash มี context window 380K (แชท 50 เทิร์นใส่ได้แม้ไม่ตัด) output สูงสุด 32,768 โทเคนต่อคำตอบ ราคาคงที่เดียวทุกชั่วโมงของวัน และโดยรวมเมื่อนับ input กับ output รวมกัน ถูกกว่า OpenRouter model id คือ deepseek- หากคุณต้องการเปรียบเทียบโมเดลบนรูปแบบ window (เฉลี่ย 1,410 input tokens ต่อคำขอ, 190 output, 50 คำขอ) นี่คือตารางสด:
| โมเดล | Input $/1M | Output $/1M | ต่อคำขอ | 50 คำขอ | OpenRouter, 50 คำขอ |
|---|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.000036 | $0.0018 | $0.0032 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.00004 | $0.002 | $0.0063 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.000099 | $0.005 | $0.0594 |
1,410 โทเค็นอินพุตและ 190 โทเค็นเอาต์พุตต่อคำขอ ราคาต่อ 1M โทเค็นเป็นราคาปัจจุบันและเปลี่ยนแปลงไปพร้อมกับอัตราค่าบริการของเรา คอลัมน์ OpenRouter แสดงราคาอ้างอิงสำหรับปริมาณงานเดียวกัน
GLM-5.3-Flash มี context 390K และ MiniMax-M2.7 มี 180K ซึ่งเพียงพอสำหรับแชทที่ตัดแล้ว ราคาปัจจุบันอยู่ที่ หน้าราคา และ เอกสาร แสดงวิธีส่งคำขอแรก
เลือกอันไหน#
Window คือค่าเริ่มต้น: สามบรรทัดโค้ด ไม่มีการเรียกเพิ่ม ไม่มีโหมดล้มเหลวเพิ่ม ใช้กับบอทซัพพอร์ต ติวเตอร์ และ role-play ซึ่งไม่กี่เทิร์นล่าสุดแบกบทสนทนาและ system prompt แบกกฎ เพิ่มสรุปเมื่อผู้ใช้ย้อนอ้างถึงสิ่งที่พูดนานแล้ว เช่นผู้ช่วยส่วนตัวที่มีบทสนทนาไม่สิ้นสุด เก็บ window ให้เล็กพอที่โมเดลยังเห็น context ทันที และใหญ่พอที่จะเก็บการถาม-ตอบครบชุด สิ่งที่ใส่ได้ทั้งหมดเป็นขีดจำกัดแยก ครอบคลุมใน context window คืออะไร
เช็กด่วน
ผู้ใช้ถามในเทิร์นที่ 40 เกี่ยวกับหมายเลขคำสั่งซื้อที่ให้ไว้ในเทิร์นที่ 3 คุณใช้ window 4 เทิร์นโดยไม่มีสรุป เกิดอะไรขึ้น?
แสดงคำตอบ
คำตอบ: โมเดลมองไม่เห็น เพราะเทิร์นที่ 3 ถูกตัดออกจากคำขอ
API ไม่มีสถานะ โมเดลเห็นเพียงสิ่งที่อยู่ในคำขอ ข้อเท็จจริงที่คุณยังต้องการจึงต้องอยู่ใน system prompt หรือในสรุป



