เอเจนต์เขียนโค้ดของคุณกำลังจ่ายแพงหูฉี่ให้กับคำถามแบบตัวเลือก
ควรโหลดโน้ตไหน? ขั้นตอนนี้ควรส่งไปให้โมเดลใหญ่หรือเล็กดี? เครื่องมือเพิ่งทำงานล้มเหลว จะลองใหม่ แก้ไข หรือยอมแพ้? ควรรันเทสต์ตัวไหนก่อน?
ทุกข้อที่ว่ามาคือคำถามที่มีคำตอบให้เลือกแค่สี่หรือห้าข้อ และในการตั้งค่าเอเจนต์ส่วนใหญ่ในปัจจุบัน ทุกคำถามจะถูกตอบโดยโมเดลที่แพงที่สุดที่คุณมี พร้อมเปิดโหมด thinking อ่านบริบททั้งหมด แล้วเขียนอธิบายเป็นย่อหน้าก่อนจะตัดสินใจทำอะไรสักอย่าง
นั่นแหละคือจุดที่เงินรั่วไหล
บทความนี้จะบอกวิธีอุดรอยรั่วนั้น ให้ Opus 5.5 รับหน้าที่ใช้เหตุผลในเรื่องยากๆ อย่างการวางแผน เขียนโค้ด และดีบัก ส่วน Jev จะรับหน้าที่ตัดสินใจสี่อย่างที่แทบจะต้องทำในทุกขั้นตอน ขณะที่ harness ของคุณจะเป็นคนเตรียมตัวเลือก ตรวจคำตอบ และฟันธงในท้ายที่สุด
ในตัวอย่างการใช้งานด้านล่าง เซสชันพัฒนาฟีเจอร์หนึ่งรายการลดต้นทุนจาก $6.42 เหลือ $2.00 ซึ่งถูกลงถึง 69% และเราแสดงวิธีคิดคำนวณทุกบรรทัดไว้ในบทความนี้ เพื่อให้คุณนำไปเทียบกับตัวเลขของตัวเองได้
บทความนี้เขียนขึ้นสำหรับทุกคนที่รัน coding agent กับงานจริง ไม่ว่าจะเป็น Claude Code, harness ที่คุณสร้างเองบน API หรืออะไรที่อยู่ระหว่างกลาง คุณไม่ต้องเขียนเอเจนต์ใหม่เลย ทุกส่วนในบทความนี้สามารถแทรกเข้าไปในลูปเดิมได้เลยในรูปแบบของ function call ที่มี flag สำหรับปิดการทำงานได้ทันที ถ้าคุณเคยอ่านบทความเรื่อง Jev + Claude Code ของผมมาแล้ว นี่คือเวอร์ชันอัปเกรด: แนวคิดเดิม แต่ใช้ reasoning model ที่ใหม่กว่า และเจาะจงไปที่การตัดสินใจ 4 จุด แทนที่จะเป็นหลักการกว้างๆ
สิ่งที่คุณต้องมีคือ Jev API key, Anthropic API key และ log ของเอเจนต์ตัวเองประมาณหนึ่งสัปดาห์เพื่อใช้เป็นตัวเปรียบเทียบ
มาเริ่มลงมือกันเลย

opus ใช้เหตุผล jev ตัดสินใจ
ปัญหา: โมเดลเดียวรับสองงาน
ลองนั่งดู coding agent ทำงานสักสิบนาที แล้วคุณจะเห็นว่ามันทำงานสองประเภทที่แตกต่างกันอย่างสิ้นเชิง
งานแรกคือการคิดวิเคราะห์ (reasoning) เช่น การวางแผนฟีเจอร์ การเขียนฟังก์ชัน การอ่าน stack trace เพื่อหาสาเหตุว่าทำไม date parser ถึงพังตอนเจอปีอธิกสุรทิน งานพวกนี้เป็นปลายเปิด คำตอบไม่มีอยู่ในลิสต์ คุณจึงต้องใช้โมเดลที่ฉลาดที่สุดเท่าที่งบจะอำนวย และ Opus 5.5 ก็เก่งเรื่องนี้มาก
งานที่สองคือการตัดสินใจ (deciding) เช่น การเลือกโน้ตโปรเจกต์ที่สำคัญจริงๆ 3 รายการจากทั้งหมด 40 รายการ การตัดสินใจว่าการเปลี่ยนชื่อตัวแปรส่งไปให้โมเดลราคาถูกทำได้ การเลือกว่าจะทำอะไรต่อเมื่อ npm test หมดเวลา หรือการเลือกว่าจะรันไฟล์เทสต์ 12 ไฟล์ไหนก่อนจากรายการเต็ม 1,400 ไฟล์ คำตอบของงานพวกนี้มีอยู่ในลิสต์ ลิสต์นั้นสั้น และโค้ดของคุณสามารถนำคำตอบไปใช้งานต่อได้โดยตรง
เอเจนต์ส่วนใหญ่รันทั้งสองงานผ่านโมเดลเดียวกัน เพราะมันเป็นค่าเริ่มต้น ลูปจะเรียก Opus, Opus คิด, Opus ตอบ, แล้วลูปก็ทำงานต่อไป
มันใช้งานได้จริง แต่มันช้าและแพงในแบบที่สังเกตได้ยาก เพราะการเรียกใช้เพื่อตัดสินใจแต่ละครั้งไม่ได้ดูแพงเลย การเรียกถามว่า "ฉันต้องใช้โน้ตไหน" หนึ่งครั้งอาจเสียแค่ไม่ถึงเซ็นต์ แต่มันเกิดขึ้นในทุกขั้นตอน และต้องแบกบริบททั้งหมดไปด้วยทุกครั้ง
แล้วยังมีต้นทุนที่สองที่มองข้ามได้ง่ายยิ่งกว่า: เมื่อเอเจนต์ตัดสินใจไม่ได้ว่าจะโหลดอะไร มันก็จะโหลดทุกอย่างเข้ามา โน้ตโปรเจกต์ทุกฉบับ เอกสาร convention ทุกชิ้น การตัดสินใจในอดีตทุกรายการ ถูกยัดเข้าไปในทุกการเรียกใช้ Opus 5.5 ทำให้การอ่าน cache ถูกลงเหลือ $0.20 ต่อล้านโทเคน แต่ "ของถูกคูณหกสิบขั้นตอนคูณโฟลเดอร์โน้ตทั้งหมดของคุณ" ยังไงก็รวมกันเป็นเงินก้อนโตอยู่ดี
ทางแก้: Opus วิเคราะห์, Jev ตัดสินใจ, Harness ของคุณคุมเกม
Jev คือโมเดลจาก TypeSafe ที่สร้างมาเพื่องานที่สองโดยเฉพาะ มันไม่เขียนข้อความ คุณแค่ป้อนบริบทและคำถามแบบ typed ที่มีชุดตัวเลือกตายตัวให้มัน แล้วมันจะคืนค่าความน่าจะเป็นของทุกตัวเลือกกลับมา มันตอบกลับภายในหน่วยมิลลิวินาที ต้นทุน input อยู่ที่ $0.042 ต่อล้านโทเคน และ output ฟรี
นั่นทำให้สถาปัตยกรรมนี้อธิบายได้ง่ายๆ ว่า:
Opus 5.5 รับหน้าที่คิดวิเคราะห์ การวางแผน เขียนโค้ด ดีบัก หรืออะไรก็ตามที่คำตอบไม่มีอยู่ในลิสต์
Jev รับหน้าที่ตัดสินใจเล็กๆ น้อยๆ โดยเลือกจากตัวเลือกที่ harness ของคุณเตรียมไว้ให้
Harness ของคุณยังคงเป็นคนคุมเกม เป็นคนสร้างลิสต์ตัวเลือก อ่านค่าความน่าจะเป็น กำหนดเกณฑ์ threshold และส่งกลับไปหา Opus เมื่อ Jev ไม่มั่นใจ
ข้อสามนี่แหละคือสิ่งที่คนมักข้ามไป แต่มันคือสิ่งที่ทำให้ระบบทั้งหมดปลอดภัย Jev จะไม่มีวันสร้างตัวเลือกขึ้นมาเอง Jev จะไม่มีสิทธิ์ขาดในการตัดสินใจเรื่องที่คุณย้อนกลับไม่ได้ โค้ดของคุณเป็นคนกำหนดว่าแค่ไหนถึงเรียกว่า "มั่นใจพอ"
นี่คือ helper function ที่ทุกส่วนของบทความนี้สร้างขึ้นมาจากมัน:
from dataclasses import dataclass
class Decision:
answer: str
prob: float
probs: dict
confident: bool
def jev_choice(context: str, question: str, options: list[str]):
เชื่อมต่อกับ Jev client ของคุณ: TypeSafe SDK, Vercel AI Gateway,
หรือแพ็กเกจ LangChain มันต้องคืนค่า {option: probability}
สำหรับทุกตัวเลือกที่คุณส่งเข้าไป
raise NotImplementedError
def decide(context: str, question: str, options: list[str], threshold: float):
probs = jev_choice(context, question, options)
answer = max(probs, key=probs.get)
return Decision(answer, probs[answer], probs, probs[answer] >= threshold)
สังเกตว่ามีอะไรหายไปบ้าง: ไม่มีคำถามที่ถาม Jev ว่ามันมั่นใจแค่ไหน คุณแค่อ่านค่าความน่าจะเป็นที่มันคืนกลับมา การถามโมเดลใดๆ ว่า "แน่ใจนะ?" จะได้คำตอบว่า "ใช่" แทบทุกครั้ง ค่าความน่าจะเป็นต่างหากคือสัญญาณที่ซื่อสัตย์ที่สุด
ทีนี้มาดูการตัดสินใจทั้งสี่ข้อกัน

การตัดสินใจสี่อย่างภายในขั้นตอนของเอเจนต์
การตัดสินใจที่ 1: เลือกโน้ตโปรเจกต์ที่เกี่ยวข้องก่อนโหลด Context
นี่คือคานงัดที่ใหญ่ที่สุด และเป็นสิ่งที่แทบไม่มีใครสร้างขึ้นมาใช้
เอเจนต์ของคุณมีโฟลเดอร์เก็บโน้ต มี AGENTS.md, เอกสาร architecture, conventions, การตัดสินใจในอดีต, คำเตือนประเภท "ห้ามแตะ billing module ถ้าไม่มี migration" รวมๆ อาจถึง 30,000 โทเคน เอเจนต์ส่วนใหญ่โหลดทั้งหมดนี้ในทุกการเรียกใช้ เพราะไม่มีใครอยากเป็นคนลืมใส่โน้ตสำคัญ
ดังนั้นแทนที่จะโหลดทุกอย่าง คุณแค่ถาม Jev ด้วยคำถามง่ายๆ เกี่ยวกับโน้ตแต่ละชิ้นแบบขนานกันไปเลยว่า: เอเจนต์ต้องใช้โน้ตนี้สำหรับงานนี้ไหม?
ขั้นแรก แบ่งโน้ตของคุณออกเป็น chunk ตามหัวข้อ แต่ละ section ใน AGENTS.md จะกลายเป็น chunk ของตัวเอง เอกสาร architecture แต่ละฉบับจะกลายเป็นหนึ่ง chunk หรือมากกว่า
import re
def chunk_notes(markdown: str, source: str):
parts = re.split(r"
(?=## )", markdown)
return [{"source": source, "text": p.strip()} for p in parts if p.strip()]
จากนั้นให้คะแนนทุก chunk เทียบกับงานปัจจุบัน:
from concurrent.futures import ThreadPoolExecutor
def pick_notes(task: str, notes: list[dict], keep: int = 6, floor: float = 0.55):
def score(note):
probs = jev_choice(
context=f"TASK:
{task}
NOTE ({note['source']}):
{note['text']}",
question="Would an engineer need this note to do the task correctly?",
options=["needed", "not_needed"],
)
return probs["needed"], note
with ThreadPoolExecutor(max_workers=16) as pool:
scored = sorted(pool.map(score, notes), key=lambda s: s[0], reverse=True)
picked = [n for p, n in scored[:keep] if p >= floor]
return picked or [n for _, n in scored[:2]]
มีรายละเอียดสามจุดที่สำคัญตรงนี้
โหลดสิ่งที่ต่อรองไม่ได้เสมอ โน้ตบางชิ้นควรอยู่ในการเรียกใช้ทุกครั้งไม่ว่าจะเกิดอะไรขึ้น เช่น กฎด้านความปลอดภัย, "ห้าม force push เด็ดขาด", บรรทัดที่บอกว่า database ไหนคือ production ให้แท็กสิ่งเหล่านี้ว่า always แล้วข้ามการให้คะแนนไปเลย
ตั้งเกณฑ์ขั้นต่ำและแผนสำรองไว้เสมอ ถ้าไม่มีอะไรผ่านเกณฑ์ 0.55 เลย คุณก็ยังต้องโหลดสองอันดับแรกเข้ามา เอเจนต์ที่ไม่มี context เลยแย่กว่าเอเจนต์ที่มี context มากเกินไปนิดหน่อย
บันทึก log ว่าอะไรถูกตัดทิ้งไป เวลาเอเจนต์ทำพลาด สิ่งแรกที่คุณต้องเช็กคือโน้ตที่ควรจะป้องกันความผิดพลาดนั้นถูกตัดทิ้งไปจากการให้คะแนนหรือไม่ log นี้แหละคือวิธีที่คุณจะใช้ปรับค่า keep และ floor
ในตัวอย่างการใช้งาน การเปลี่ยนแปลงเพียงจุดนี้ช่วยลดสัดส่วนโน้ตในแต่ละการเรียกใช้จาก 30,000 โทเคนเหลือ 6,000 โทเคน แค่จุดเดียวก็ลดต้นทุนเซสชันไปได้ประมาณ 24% แล้ว
การตัดสินใจที่ 2: ส่งงานที่เหมาะสมไปให้ Worker ที่เร็วกว่า
ไม่ใช่ทุกขั้นตอนที่ต้องใช้ Opus
การเปลี่ยนชื่อฟังก์ชันในแปดไฟล์ไม่ต้องใช้ การเพิ่มฟิลด์ลงในฟอร์มที่มีอีกเก้าฟิลด์หน้าตาเหมือนกันเป๊ะอยู่แล้วก็ไม่ต้องใช้ การอัปเดต import path ก็ไม่ต้องใช้ พวกนี้คือการแก้ไขที่ทำตามแพตเทิร์นที่มีอยู่ใน codebase แล้ว
ดังนั้นก่อนที่แต่ละขั้นตอนจะรัน Jev จะจัดประเภทของขั้นตอนนั้น และ harness ของคุณจะแมปประเภทนั้นไปยัง worker:
ROUTES = {
"rename_or_move": "fast",
"small_edit_following_existing_pattern": "fast",
"new_logic": "opus",
"debugging": "opus",
"design_decision": "opus",
}
def route(step: str, recent_diff: str):
d = decide(
context=f"STEP:
{step}
RECENT CHANGES:
{recent_diff}",
question="What kind of work is this step?",
options=list(ROUTES),
threshold=0.8,
)
if not d.confident:
return "opus"
return ROUTES[d.answer]
ลองดูวิธีเขียนตัวเลือกสิ มันไม่ใช่คำว่า "ง่าย" กับ "ยาก" และแน่นอนว่าไม่ใช่ "โมเดลเล็กจัดการอันนี้ได้ไหม" แต่มันคือประเภทงานที่เป็นรูปธรรมซึ่งโค้ดของคุณสามารถแปลงเป็นการกระทำได้ นี่คือกฎเหล็กสำหรับทุกคำถามที่ถาม Jev: ทุกตัวเลือกต้องเป็นสิ่งที่ harness ของคุณรู้วิธีจัดการ
และสังเกตค่า default ไว้ด้วย ถ้าต่ำกว่า 0.8 ขั้นตอนนั้นจะถูกส่งไปหา Opus ความผิดพลาดในการ route ที่นี่ไปในทิศทางเดียวเท่านั้น: งานยากที่ถูกส่งไปให้ fast worker จะทำให้คุณเสียขั้นตอนนั้นไปและต้องลองใหม่ แต่งานง่ายที่ถูกส่งไปให้ Opus แค่ทำให้เสียเงินเพิ่มนิดหน่อย ดังนั้นถ้าลังเล ส่งขึ้นไปข้างบนไว้ก่อน
สำหรับ fast worker ผมใช้ Haiku 4.5 ที่ราคา $1 ต่อล้าน input tokens และ $5 ต่อล้าน output ในตัวอย่างการใช้งาน 12 จาก 36 ขั้นตอนที่เป็นงานจริงถูกส่งไปที่นี่
การตัดสินใจที่ 3: เลือกเส้นทางกู้คืนเมื่อเครื่องมือล้มเหลว
เครื่องมือล้มเหลวเป็นเรื่องปกติ เทสต์หมดเวลา file path ผิด แพ็กเกจยังไม่ได้ติดตั้ง shell command เจอ permission error linter บ่นเรื่องที่ไม่เกี่ยวข้อง
เอเจนต์ส่วนใหญ่จัดการเรื่องนี้ด้วยวิธีที่แพงที่สุดเท่าที่จะเป็นไปได้: พวกมันโยน error ทั้งหมดกลับไปให้โมเดลใหญ่แล้วปล่อยให้มันคิดว่าควรทำอะไรต่อ บางครั้งนั่นก็ถูกต้อง แต่บ่อยครั้งที่คำตอบชัดเจนอยู่แล้ว และ Opus ต้องเสีย 1,500 โทเคนเพื่อค้นพบใหม่ว่า ENOENT แปลว่าไฟล์ไม่ได้อยู่ตรงนั้น
ที่แย่กว่านั้นคือเอเจนต์ติดอยู่ในลูป ลองใหม่ ล้มเหลว ลองใหม่ ล้มเหลว โดยต้องจ่ายค่าขั้นตอนการคิดวิเคราะห์เต็มรูปแบบทุกครั้ง
ดังนั้นคุณจึงส่งความล้มเหลวนั้นให้ Jev พร้อมกับชุดเส้นทางกู้คืนที่ตายตัว:
from collections import deque
def tail(text: str, n: int = 4000):
return "".join(deque(text, maxlen=n)) # ตัวอักษร n ตัวสุดท้ายของ error
def recover(tool: str, command: str, error: str, attempt: int):
if attempt >= 3:
return "stop_and_report"
d = decide(
context=f"TOOL: {tool}
COMMAND: {command}
ATTEMPT: {attempt}
ERROR:
{tail(error)}",
question="What is the best next move after this failure?",
options=RECOVERY,
threshold=0.8,
)
return d.answer if d.confident else "escalate_to_opus"
1RECOVERY = [2 "retry_unchanged", # เน็ตเวิร์กไม่นิ่งหรือ timeout3 "retry_after_install", # แพ็กเกจหรือเครื่องมือหาย4 "fix_path_and_retry", # file path หรือ cwd ผิด5 "switch_tool", # เครื่องมือนี้ทำไม่ได้ แต่อันอื่นทำได้6 "escalate_to_opus", # ต้องอาศัยการ debug จริงจัง7 "stop_and_report", # ต้องให้คนมาจัดการ8]
ขีดจำกัดสูงสุดของความพยายามถูกฝังไว้ในโค้ด ไม่ใช่ในโมเดล ไม่มีโมเดลใด ไม่ว่าจะราคาถูกแค่ไหน ที่ควรถูกปล่อยให้ลองใหม่ไปเรื่อยๆ ตลอดกาล
เส้นทางกู้คืนแต่ละเส้นจะแมปกับฟังก์ชันเล็กๆ ใน harness ของคุณ retry_after_install จะอ่านชื่อแพ็กเกจที่หายไปจาก error ด้วย regex แล้วติดตั้งมัน fix_path_and_retry จะเช็ก path ที่มีอยู่และแนะนำตัวที่ใกล้เคียงที่สุด มีแค่ escalate_to_opus เท่านั้นที่ใช้เงินจริง และมันจะทำงานเฉพาะเมื่อความล้มเหลวนั้นต้องอาศัยการคิดวิเคราะห์จริงๆ
ในตัวอย่างการใช้งาน วิธีนี้ช่วยตัดขั้นตอนการลองใหม่ที่สูญเปล่าออกไป 6 ขั้นตอนจากเซสชัน
การตัดสินใจที่ 4: รันเทสต์แบบเจาะจงก่อนรัน Test Suite ทั้งหมด
ข้อนี้ช่วยประหยัดเวลามากกว่าเงิน และเวลาคือสิ่งที่ทำให้เอเจนต์รู้สึกว่ามันเร็ว
หลังจากแก้ไขโค้ดทุกครั้ง เอเจนต์ส่วนใหญ่จะรัน test suite ทั้งหมด ถ้า suite ของคุณใช้เวลาสี่นาที เอเจนต์ก็ต้องรอสี่นาทีหลังการแก้ไขทุกครั้ง แล้วก็มานั่งอ่าน output หลายร้อยบรรทัดเพื่อหาความล้มเหลวเพียงจุดเดียวที่สำคัญ
วิธีแก้ใช้แพตเทิร์นเดียวกับเรื่องโน้ต: ให้คะแนนไฟล์เทสต์แต่ละไฟล์เทียบกับ diff, รันไฟล์ที่เกี่ยวข้องที่สุดก่อน, และรัน suite ทั้งหมดเฉพาะเมื่อเทสต์แบบเจาะจงผ่านแล้วเท่านั้น
1def pick_tests(diff: str, test_files: list[str], keep: int = 12):2 def score(path):3 probs = jev_choice(4 context=f"DIFF:\n{diff[:12000]}\n\nTEST FILE: {path}",5 question="Could this change break tests in this file?",6 options=["likely", "unlikely"],7 )8 return probs["likely"], path910 with ThreadPoolExecutor(max_workers=16) as pool:11 scored = sorted(pool.map(score, test_files), key=lambda s: s[0], reverse=True)12 return [p for _, p in scored[:keep]]1314def check(diff: str, test_files: list[str]):15 focused = pick_tests(diff, test_files)16 if not run_tests(focused):17 return False # fail fast, แก้ให้เสร็จก่อนทำอย่างอื่น18 return run_tests(test_files) # full suite ยังคงเป็นตัวตัดสินก่อน commit
อ่านบรรทัดสุดท้ายซ้ำอีกรอบ test suite ทั้งหมดยังคงต้องรันก่อนที่อะไรจะถูก commit การเทสต์แบบเจาะจงเป็นแค่สัญญาณเตือนล่วงหน้า ไม่ใช่ตัวแทนทดแทน คุณจะจับข้อผิดพลาดส่วนใหญ่ได้ในหลักวินาทีแทนที่จะเป็นนาที และจะไม่เผลอปล่อยโค้ดที่ full suite น่าจะจับได้หลุดออกไป
เพิ่มการตรวจสอบราคาถูกๆ เข้าไปก่อนด้วย: type check และ lint เฉพาะไฟล์ที่ถูกแก้ไข มันใช้เวลาแค่เสี้ยววินาทีแต่จับข้อผิดพลาดได้เยอะอย่างน่าประหลาดใจก่อนจะเริ่มรันเทสต์ใดๆ เสียอีก
ประกอบร่างเข้าด้วยกัน: Harness Loop
นี่คือภาพรวมของการตัดสินใจทั้งสี่ที่อยู่ในหนึ่งขั้นตอนของลูป:
def run_step(task: str, step: str, state):
1. context: โหลดเฉพาะโน้ตที่ขั้นตอนนี้ต้องการ
notes = state.always_notes + pick_notes(step, state.notes)
2. routing: เลือก worker สำหรับขั้นตอนนี้
worker = state.workers[route(step, state.recent_diff())]
result = worker.run(step, notes=notes, history=state.history)
3. recovery: จัดการความล้มเหลวของเครื่องมือในขั้นตอนนี้
for failure in result.failures:
action = recover(failure.tool, failure.command, failure.error, failure.attempt)
state.apply_recovery(action, failure)
4. checks: รันเทสต์แบบเจาะจงก่อน แล้วค่อยรัน suite ทั้งหมดก่อน commit
if result.diff:
state.log_check(check(result.diff, state.test_files))
และนี่คือฝั่ง Opus: มันก็คือการเรียกใช้ Opus 5.5 แบบปกติของคุณ วาง context ที่คงที่ไว้ก่อน (system prompt, tool definitions, โน้ตกลุ่ม "always") เพื่อให้มันอยู่ใน cache ข้ามขั้นตอนได้ แล้ววางเนื้อหาเฉพาะของขั้นตอนนั้นไว้ท้ายสุด
import os
import anthropic
client = anthropic.Anthropic()
OPUS = os.environ["OPUS_MODEL"] # model id ของ Opus 5.5 ที่คุณใช้
def opus_step(system: str, notes: list[dict], history: list, step: str):
notes_text = "
".join(n["text"] for n in notes)
return client.messages.create(
model=OPUS,
max_tokens=8000,
system=[{"type": "text", "text": system, "cache_control": {"type": "ephemeral"}}],
messages=history + [{"role": "user", "content": f"NOTES:
{notes_text}
STEP:
{step}"}],
)
ไม่มีอะไรพิสดาร การประหยัดต้นทุนมาจากสิ่งที่คุณหยุดส่งไปหามัน ไม่ใช่มาจาก prompt ที่ชาญฉลาดอะไร
แกะรอยหนึ่งขั้นตอน
นี่คือหน้าตาของหนึ่งขั้นตอนใน log เมื่อการตัดสินใจทั้งสี่ทำงานจริง งานคือ: เพิ่ม rate limiting ให้กับ public signup endpoint เทรสนี้เป็นตัวอย่างประกอบ แต่มันคือรูปแบบที่คุณจะเห็นใน log ของตัวเอง
step 14 "add a per IP rate limit to POST /signup"
[notes] ให้คะแนน 41 chunks แบบขนานกัน
kept: api/middleware.md (0.94), conventions/errors.md (0.88),
infra/redis.md (0.81), decisions/2025_auth.md (0.62)
dropped: 37 chunks รวมถึง billing, email templates, CI
[route] new_logic (0.91) → opus
[opus] วางแผนการเปลี่ยนแปลง เขียน middleware + config + handler edit
[tool] npm test FAILED "Cannot find module 'bottleneck'"
[recover] retry_after_install (0.97) → npm install, rerun
[checks] typecheck changed files: pass
focused tests (12 of 1,388): pass
full suite: pass
ลองอ่านจากบนลงล่างแล้วนับดูว่ากี่บรรทัดที่เคยต้องเรียกใช้ Opus เต็มรูปแบบ การเลือกโน้ต: เคยเป็นการเรียกใช้ครั้งใหญ่ หรือไม่เลือกเลยแล้วโหลดโน้ต 30,000 โทเคนเข้ามาแบบหลับหูหลับตา การ route: ไม่เคยมี ทุกขั้นตอนส่งไป Opus หมด แพ็กเกจที่หายไป: เคยต้องใช้ขั้นตอนการคิดวิเคราะห์เต็มรูปแบบเพื่อหาว่าโมเดลที่หายไปแปลว่า "ต้องติดตั้งโมเดลนั้น" การเลือกเทสต์: ไม่เคยมี รัน suite ทั้งหมดทุกครั้งที่แก้ไข
ตอนนี้เหลือแค่บรรทัดเดียวในเทรสนั้นที่ใช้ Opus และเป็นบรรทัดที่ต้องการ frontier model จริงๆ นั่นคือการวางแผนและเขียน rate limiter
นั่นคือแนวคิดทั้งหมดในภาพเดียว โมเดลราคาแพงใช้เวลาไปกับส่วนที่มันเท่านั้นที่ทำได้
ตัวอย่างการใช้งาน: 69% มาจากไหน
นี่คือวิธีคิดคำนวณทั้งหมดสำหรับหนึ่งเซสชันพัฒนาฟีเจอร์: 60 ขั้นตอนของเอเจนต์บวกกับการลองใหม่ที่สูญเปล่าอีก 6 ครั้งที่เอเจนต์ทั่วไปมักจะสะสมมาระหว่างทาง ราคาทั้งหมดคือราคาสาธารณะ ณ ปัจจุบัน
ก่อนปรับปรุง: Opus 5.5 ทำทุกอย่าง
ทุกขั้นตอนโหลด context 70,000 โทเคน: 15,000 สำหรับ system prompt และ tools, 30,000 สำหรับโฟลเดอร์โน้ตทั้งหมด, และ 25,000 สำหรับการสนทนาที่ผ่านมา ผมสมมติว่า 80% ของจำนวนนั้นคือ cache hit ทุกขั้นตอนสร้าง output ประมาณ 1,500 โทเคน เพราะ thinking เปิดอยู่เสมอใน Opus 5.5
cache reads: 56,000 × $0.20/M = $0.0112
fresh input: 14,000 × $4.00/M = $0.0560
output: 1,500 × $20.00/M = $0.0300
per step = $0.0972
66 steps × $0.0972 = $6.42
หลังปรับปรุง: มี decision layer
Context ลดลงเหลือ 46,000 โทเคนต่อขั้นตอน เพราะ Jev เลือกโน้ตมาแค่ 6,000 โทเคนแทนที่จะโหลดทั้งหมด 30,000 โทเคน ขั้นตอนที่เป็น pure decision 24 ขั้นตอนถูกย้ายไปให้ Jev ลูปการลองใหม่ 6 ครั้งหายไป และ 12 จาก 36 ขั้นตอนการทำงานที่เหลือถูกส่งไปให้ Haiku 4.5
Opus 5.5: 24 steps × $0.0742 = $1.78
Haiku 4.5: 12 steps × $0.0169 = $0.20
Jev: 102 calls × 5,000 tokens
× $0.042/M, output free = $0.02
total = $2.00
จาก $6.42 เหลือ $2.00 ถูกลง 68.8% สำหรับฟีเจอร์เดียวกัน

ตั้ง threshold จากต้นทุนของคำตอบที่ผิด
และนี่คือสัดส่วนที่คานงัดแต่ละตัวช่วยประหยัดได้ เรียงตามลำดับ:
notes selection only $4.89 ประหยัดได้ 23.7%
- decisions moved to Jev $3.13 ประหยัดได้ 51.2%
- recovery paths $2.69 ประหยัดได้ 58.1%
- routing to a fast worker $2.00 ประหยัดได้ 68.8%
มีข้อเท็จจริงสองอย่างเกี่ยวกับตัวเลขเหล่านี้ที่ต้องบอกกันตรงๆ
อย่างแรก ตัวเลขเหล่านี้เป็นการจำลองจากสมมติฐานที่ตั้งไว้ชัดเจน ไม่ใช่การวัดจากระบบของคุณ ขนาด context, อัตรา cache hit และจำนวนการตัดสินใจของคุณจะต่างออกไป เหตุผลที่แสดงวิธีคิดทุกบรรทัดคือเพื่อให้คุณเอาตัวเลขของตัวเองมาสลับใส่ได้ เมื่อคุณวัดผลลัพธ์ก่อนและหลังของระบบจริงได้แล้ว ให้ใช้ตัวเลขของคุณ ไม่ใช่ของผม
อย่างที่สอง ลองดูว่าเงินจริงๆ ไปอยู่ที่ไหน การเรียกใช้ Jev 102 ครั้งเสียเงินรวมกันแค่สองเซ็นต์ การประหยัดไม่ได้มาจาก Jev ราคาถูกต่อการเรียกใช้ แต่มันมาจากทุกสิ่งที่ไม่ต้องเกิดขึ้นอีกต่อไปเมื่อ Jev เป็นผู้ตัดสินใจ: context ที่พองโตเกินจำเป็น, ขั้นตอนการคิดวิเคราะห์เต็มรูปแบบสำหรับคำถามแบบตัวเลือก, ลูปการลองใหม่, และการเรียกใช้โมเดลใหญ่ในงานเปลี่ยนชื่อตัวแปร
แล้วทำไมไม่ใช้ Haiku ตัดสินใจไปเลยล่ะ?
เป็นคำถามที่ดี Haiku 4.5 ทั้งถูกและเร็ว จะเพิ่มโมเดลใหม่เข้ามาทำไม?
มีสามเหตุผล
มันยังคงเขียนข้อความ Haiku ตอบกลับเป็นข้อความ คุณต้องเขียน prompt สั่งให้มันตอบด้วยหนึ่งในตัวเลือกของคุณ จากนั้นต้อง parse คำตอบ แล้วต้องคอยจัดการกรณีที่มันเติมคำอธิบายเข้ามา เลือกสิ่งที่ไม่มีในลิสต์ หรือห่อคำตอบไว้ในประโยคยาวๆ แต่ Jev คืนค่าความน่าจะเป็นของทุกตัวเลือกที่คุณส่งเข้าไป ไม่ต้อง parse อะไรเลย และไม่มีอะไรหลุดออกนอกลิสต์
คุณได้เห็นการกระจายตัวทั้งหมด ไม่ใช่แค่คำตอบ เมื่อ Jev บอกว่า needed: 0.52, not_needed: 0.48 คุณจะรู้ทันทีว่ามันเหมือนโยนเหรียญเสี่ยงทาย และ harness ของคุณสามารถ escalate ได้ แต่เมื่อโมเดลข้อความบอกว่า "needed" คุณไม่มีทางรู้เลยว่ามันมั่นใจแค่ไหน Threshold จะใช้ได้ผลก็ต่อเมื่อคุณมองเห็นค่าความน่าจะเป็นเท่านั้น
คณิตศาสตร์เรื่องต้นทุนต่างกัน Output ของ Jev ฟรี และ input อยู่ที่ $0.042 ต่อล้านโทเคน การให้คะแนน 41 note chunks ทุกขั้นตอนหมายถึงการเรียกใช้ขนาดเล็ก 41 ครั้งต่อขั้นตอน ด้วย Jev มันคือเศษเสี้ยวของเซ็นต์ แต่ด้วยโมเดลข้อความใดๆ แม้แต่ตัวที่ถูกที่สุด มันคือการ generate 41 ครั้งที่มีต้นทุน output และ latency ของตัวเอง
ใช้ Haiku กับงานแก้ไขเล็กๆ ที่มันต้องเขียนโค้ดจริงๆ ใช้ Jev สำหรับการเลือกจากรายการ และใช้ Opus สำหรับการคิดวิเคราะห์ ให้แต่ละโมเดลทำหน้าที่ที่มันถูกสร้างมา
วิธีทยอยใช้งานโดยไม่พังระบบเดิม
อย่าเปิดการตัดสินใจทั้งสี่พร้อมกันในทีเดียว นี่คือลำดับที่ผมแนะนำ
สัปดาห์ที่ 1: shadow mode เก็บเอเจนต์ปัจจุบันของคุณไว้เหมือนเดิมทุกประการ สำหรับการตัดสินใจแต่ละครั้งที่มันทำ ให้ถาม Jev ด้วยคำถามเดียวกันแล้ว log ทั้งสองคำตอบพร้อมค่าความน่าจะเป็นของ Jev ไว้ อย่าเพิ่งทำตามคำตอบของ Jev เด็ดขาด
1def shadow(decision_name, context, question, options, current_answer):2 probs = jev_choice(context, question, options)3 jev_answer = max(probs, key=probs.get)4 log_row(5 decision=decision_name,6 current=current_answer,7 jev=jev_answer,8 prob=probs[jev_answer],9 agree=(jev_answer == current_answer),10 )
สัปดาห์ที่ 2: อ่านจุดที่เห็นไม่ตรงกัน ดูเฉพาะแถวที่ Jev และเอเจนต์ปัจจุบันของคุณตอบไม่เหมือนกัน เรียงลำดับตามค่าความน่าจะเป็นของ Jev ปกติคุณจะเห็นเส้นแบ่งที่ชัดเจน: เหนือระดับความน่าจะเป็นหนึ่ง Jev จะตอบถูกบ่อยพอๆ กับ Opus เส้นนั้นแหละคือ threshold ของคุณ และแถวที่เห็นไม่ตรงกันเหล่านั้นจะกลายเป็น test set ของคุณที่ได้มาฟรีๆ จาก traffic จริง
สัปดาห์ที่ 3: เปิดใช้ notes selection มันเป็นคานงัดที่ใหญ่ที่สุดและย้อนกลับได้ง่ายที่สุด เพราะโน้ตที่ตกหล่นจะปรากฏให้เห็นใน log อย่างรวดเร็ว
สัปดาห์ที่ 4: เปิดใช้ recovery และ tests ทั้งสองอย่างมีขีดจำกัดและ fallback ฝังอยู่ในโค้ด ดังนั้นกรณีที่แย่ที่สุดคือการกลับไปใช้วิธีที่คุณทำอยู่ทุกวันนี้
สุดท้าย: routing ความผิดพลาดในการ route เป็นสิ่งที่ผู้ใช้สังเกตเห็นได้ชัดที่สุด เพราะงานยากที่ถูกส่งไปให้ fast worker จะผลิตโค้ดคุณภาพต่ำออกมา เปิดใช้เป็นอย่างสุดท้าย ตั้ง threshold แบบระมัดระวัง และคอยดูอัตราความล้มเหลวของขั้นตอนที่ส่งไปให้ fast worker
ซ่อนการตัดสินใจทุกอย่างไว้หลัง on/off flag เพื่อให้คุณย้อนกลับได้ด้วยโค้ดบรรทัดเดียว
การตั้ง Threshold ตามระดับความเสี่ยง
การใช้ threshold เดียวกับทุกอย่างเป็นความผิดพลาด ให้ตั้งตามผลกระทบที่เกิดขึ้นเมื่อคำตอบผิด

หนึ่งเซสชันพัฒนาฟีเจอร์ ผลลัพธ์เดียวกัน จาก $6.42 สู่ $2.00
ความเสี่ยงต่ำ ย้อนกลับง่าย: 0.55 ถึง 0.65 การเลือกโน้ต การจัดลำดับเทสต์ คำตอบที่ผิดแลกมาด้วย context นิดหน่อยหรือเวลาไม่กี่วินาที
ความเสี่ยงปานกลาง: 0.8 การ route และการกู้คืน คำตอบที่ผิดแลกมาด้วยขั้นตอนที่ล้มเหลว ซึ่ง harness ของคุณตรวจจับได้
ความเสี่ยงสูง ย้อนกลับยาก: 0.9 หรือห้ามใช้เด็ดขาด การลบไฟล์ การ force push การแตะ production config การรัน migration คำแนะนำจากใจจริงของผม: อย่าปล่อยให้โมเดลใดๆ ตัดสินใจเรื่องพวกนี้ตามลำพัง ส่งไปให้คนจัดการ หรืออย่างน้อยที่สุดส่งไปให้ Opus พร้อมขั้นตอนยืนยัน
อะไรก็ตามที่ต่ำกว่า threshold ให้ส่งขึ้นบันได: ไปหา Opus ถ้ามันต้องใช้เหตุผล ไปหาคนถ้ามันต้องใช้วิจารณญาณ
กรณีไหนที่วิธีนี้ช่วยไม่ได้
สถาปัตยกรรมนี้ไม่ใช่ตัวคูณวิเศษสำหรับทุก workload
งานที่เน้น generation แทบไม่เปลี่ยน ถ้าเอเจนต์ของคุณใช้เวลาส่วนใหญ่ไปกับการเขียนโค้ดใหม่จำนวนมากจาก spec ที่ชัดเจน มันก็ไม่มีการตัดสินใจมากนักให้ย้ายที่ คุณยังจะได้ประโยชน์จากการเลือกโน้ต แต่ไม่ค่อยได้อะไรอื่น
โปรเจกต์จิ๋วไม่จำเป็นต้องใช้ ถ้าโฟลเดอร์โน้ตทั้งหมดของคุณมีแค่ 2,000 โทเคน และ suite รันเสร็จในแปดวินาที แรงที่ต้องใช้ในการสร้างระบบนี้ยังไม่คุ้มค่าในตอนนี้
Jev ไม่เก่งเรื่องการฟันธงคนเดียว มันเก่งมากในการสังเกตสิ่งต่างๆ และเลือกจากรายการสั้นๆ แต่มันไม่ใช่โมเดลที่คุณอยากให้ตัดสินคำถามใหญ่ๆ อย่าง "pull request นี้พร้อม merge หรือยัง?" เพียงคำถามเดียว ให้แตกคำถามใหญ่ออกเป็นคำถามเล็กๆ ให้คะแนนแต่ละข้อ แล้วนำผลลัพธ์มารวมกันในโค้ดของคุณด้วยน้ำหนักที่คุณกำหนดเอง
ถ้าคุณมี labelled data สำหรับคำถามที่ตายตัวอยู่แล้ว โมเดลเล็กที่คุณ host เองอาจเอาชนะ Jev เรื่องราคาได้ Jev จะเฉิดฉายเมื่อคำถามเปลี่ยนไปเรื่อยๆ และคุณไม่มี training data ซึ่งเป็นลักษณะของ coding agent ส่วนใหญ่
ข้อผิดพลาดที่ควรหลีกเลี่ยง
ปล่อยให้โมเดลเขียนลิสต์ตัวเลือก สถาปัตยกรรมทั้งหมดพึ่งพาตัวเลือกที่โค้ดของคุณจัดการต่อได้ ถ้าโมเดลเป็นคนสร้างตัวเลือก คุณก็ต้องกลับไปนั่ง parse ข้อความอิสระเหมือนเดิม
ถาม Jev ว่ามันมั่นใจไหม ให้อ่านค่าความน่าจะเป็นแทน การรายงานตัวเองมักจะได้คำตอบว่า "ใช่" แทบทุกครั้ง
ไม่มี fallback การตัดสินใจของ Jev ทุกครั้งต้องมีเส้นทางสำหรับ "ไม่แน่ใจ" และเส้นทางนั้นคือ Opus หรือคน ไม่ใช่การเดา
จำกัดจำนวนการลองใหม่ใน prompt แทนที่จะเป็นในโค้ด โมเดลที่ถูกสั่งว่า "ลองใหม่ได้แค่ 3 ครั้ง" บางครั้งจะลองใหม่ 30 ครั้ง แต่โค้ดไม่ทำแบบนั้น
ตัด test suite ทั้งหมดทิ้ง การเทสต์แบบเจาะจงช่วยให้คุณเร็วขึ้น แต่ suite ทั้งหมดช่วยให้คุณซื่อสัตย์ต่อคุณภาพ เก็บไว้ทั้งคู่
ไม่วัดอะไรเลย ถ้าคุณไม่บันทึกต้นทุนต่อเซสชันไว้ก่อนเริ่ม คุณจะไม่มีทางรู้เลยว่าประหยัดไปได้ 20% หรือ 70% ดึงข้อมูลการใช้งานในช่วงสัปดาห์ที่ทำงานปกติออกมาก่อน ใช้เวลาแค่สิบนาที และนั่นคือตัวเลขเดียวที่สำคัญจริงๆ
สิ่งที่ต้องทำในสัปดาห์นี้
นี่คือเช็กลิสต์ฉบับเต็ม:
- บันทึกข้อมูลเซสชันของ agent ตลอดหนึ่งสัปดาห์: จำนวนขั้นตอน, tokens, ต้นทุน และความล้มเหลว
- หาการตัดสินใจที่ซ่อนอยู่ในลูปของคุณให้เจอ: notes, routing, recovery, tests
- เขียนแต่ละรายการให้อยู่ในรูปคำถาม พร้อมตัวเลือกที่กำหนดไว้ตายตัว
- รัน Jev ในโหมด shadow คู่กับ agent ตัวปัจจุบันของคุณเป็นเวลาหนึ่งสัปดาห์
- กำหนดเกณฑ์จากบันทึกความขัดแย้ง โดยแบ่งตามระดับความเสี่ยง
- เปิดใช้งานการเลือก notes ก่อน จากนั้นตามด้วย recovery และ tests แล้วค่อยเปิด routing
- เปรียบเทียบต้นทุนต่อเซสชันก่อนและหลัง นั่นแหละคือตัวเลขของคุณ
Opus 5.5 คือโมเดล reasoning ที่ดีที่สุดเท่าที่ผมเคยใช้กับงานเขียนโค้ด แต่ความผิดพลาดคือการเอามันไปทำอย่างอื่นทั้งหมดด้วย
ปล่อยให้มันคิด ปล่อยให้ Jev ตัดสินใจ และปล่อยให้โค้ดของคุณเป็นผู้กำหนดกฎ
ถ้าบทความนี้มีประโยชน์ กดติดตาม @cyrilXBT ผมจะมาเจาะลึกวิธีสร้างงานด้วย AI โมเดลใหม่ๆ ทุกสัปดาห์ พร้อมตัวเลขจริงให้เห็นกันจะๆ
บุ๊กมาร์กหน้านี้เก็บไว้ จะได้หยิบมาใช้ตอนที่คุณเริ่มลงมือสร้าง





