[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"academy-blogs-th-1-1-all-golang-prompt-caching-claude-openai-all--*":3,"academy-blog-translations-4gfjbiytxpe8j7c":95,"academy-blog-faqs-4gfjbiytxpe8j7c-th":96},{"data":4,"page":94,"perPage":94,"totalItems":94,"totalPages":94},[5],{"alt":6,"collectionId":7,"collectionName":8,"content":9,"cover_image":10,"cover_image_l_url":11,"cover_image_m_url":12,"cover_image_path":13,"cover_image_s_url":14,"created":15,"created_by":16,"expand":17,"id":88,"keywords":89,"locale":59,"published_at":90,"scheduled_at":75,"school_blog":84,"short_description":91,"status":82,"title":92,"updated":93,"updated_by":16,"slug":85,"views":87},"ปกบทความ Prompt Caching แล็ปท็อปบนโต๊ะทำงานตอนกลางคืน พร้อมการ์ดเทียบค่าใช้จ่ายส่วน system prompt 100 request บน Claude Sonnet 5 ไม่ใช้ cache ประมาณ $2.00 ใช้ cache ประมาณ $0.22","sclblg987654321","school_blog_translations","\u003Cp>เวลามีน้องๆ ที่ต่อ Claude หรือ OpenAI เข้ากับระบบ Go ถามทีมเราว่า \"บิล API เดือนนี้พุ่งขึ้นมาก ต้องเปลี่ยนไปใช้โมเดลถูกลงไหม\" คำตอบที่เราตอบบ่อยที่สุดคือ \"ยังไม่ต้อง ลองดูก่อนว่าส่งอะไรซ้ำไปทุกครั้งบ้าง\" เพราะระบบส่วนใหญ่ส่ง system prompt ยาวๆ นิยาม tools และเอกสารอ้างอิงก้อนเดิมซ้ำไปทุก request แล้วจ่ายเต็มราคาทุกรอบ\u003C\u002Fp>\u003Cp>ทั้งสองค่ายมีวิธีแก้เรื่องนี้แล้ว ชื่อว่า Prompt Caching แต่จากที่เราเห็น หลายระบบเปิดใช้แล้วก็ยังไม่ได้ลดอะไรเลย เพราะ cache ไม่เคย hit จริง\u003C\u002Fp>\u003Cp>บทความนี้จะตอบคำถามเดียวให้ชัด: ต้องจัด request จากฝั่ง Go ยังไงให้ cache hit ทุกครั้งที่ควร hit และจะเช็กจากตัวเลขได้ยังไงว่ามันลดค่าใช้จ่ายได้จริง\u003C\u002Fp>\u003Ch2>Prompt Caching ทำงานยังไง\u003C\u002Fh2>\u003Cp>หลักการมีข้อเดียว คือ \u003Cstrong>prefix match\u003C\u002Fstrong> ผู้ให้บริการจะเก็บผลการประมวลผลของ \"ส่วนต้น\" ของ prompt ไว้ ถ้า request ถัดไปขึ้นต้นเหมือนเดิมทุกตัวอักษร ส่วนนั้นจะไม่ต้องประมวลผลใหม่ และคิดราคาถูกลงมาก\u003C\u002Fp>\u003Cp>คำว่า \"ทุกตัวอักษร\" สำคัญที่สุดในบทความนี้ ถ้าข้อความข้างหน้าต่างไปแม้แต่ตัวเดียว เช่น timestamp ชื่อผู้ใช้ หรือลำดับ field ใน JSON ทุกอย่างที่อยู่หลังจุดนั้นจะ miss ทั้งหมด\u003C\u002Fp>\u003Cp>ฝั่ง Claude เรียงลำดับ prefix ตายตัวเป็น tools แล้วตามด้วย system และ messages (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching\">เอกสาร Claude\u003C\u002Fa>) ถ้าแก้นิยาม tool แม้เล็กน้อย cache ของทุกส่วนที่ตามมาจะหายไปหมด\u003C\u002Fp>\u003Ch2>Claude กับ OpenAI ต่างกันตรงไหน\u003C\u002Fh2>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>วิธีเปิดใช้:\u003C\u002Fstrong> Claude ต้องใส่ \u003Ccode>cache_control\u003C\u002Fcode> เอง ที่ระดับ request หรือราย block ได้สูงสุด 4 จุด ส่วน OpenAI ทำให้อัตโนมัติโดยไม่ต้องแก้โค้ด และมี breakpoint แบบกำหนดเองให้ใช้ด้วย\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>ขนาดขั้นต่ำ:\u003C\u002Fstrong> Claude แล้วแต่รุ่น เช่น Sonnet 5 อยู่ที่ 1,024 tokens และ Opus 5.5 อยู่ที่ 512 tokens ส่วน OpenAI อยู่ที่ 1,024 tokens สำหรับ GPT-5.6 ขึ้นไป\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>ค่าเขียน cache:\u003C\u002Fstrong> Claude คิด 1.25 เท่าของราคา input สำหรับ cache อายุ 5 นาที หรือ 2 เท่าสำหรับอายุ 1 ชั่วโมง ส่วน OpenAI ฟรีสำหรับรุ่นก่อน GPT-5.6 และคิด 1.25 เท่าตั้งแต่ GPT-5.6 ขึ้นไป\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>ค่าอ่าน cache:\u003C\u002Fstrong> Claude คิด 0.1 เท่าของราคา input สำหรับรุ่นส่วนใหญ่ ส่วน OpenAI ลดได้สูงสุดประมาณ 90% แล้วแต่รุ่น\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>อายุ cache:\u003C\u002Fstrong> Claude อยู่ที่ 5 นาทีและต่ออายุฟรีทุกครั้งที่ถูกใช้ หรือเลือกแบบ 1 ชั่วโมงได้ ส่วน OpenAI ระบบจัดการเอง\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>Rate limit:\u003C\u002Fstrong> ฝั่ง Claude cache hit ไม่ถูกหักจาก rate limit ส่วนฝั่ง OpenAI token ที่อ่านจาก cache ยังนับรวมใน tokens-per-minute ถ้าระบบชนโควตาบ่อย ดูวิธีจัดการเพิ่มได้ใน \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fblogs\u002Fgolang-rate-limiting-ai-requests\">EP.164 Rate Limiting AI Requests\u003C\u002Fa>\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>ที่มา: \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching\">เอกสาร Claude\u003C\u002Fa> และ \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fprompt-caching\">เอกสาร OpenAI\u003C\u002Fa> (ข้อมูล ณ กันยายน 2026 ตัวคูณและรุ่นเปลี่ยนได้เมื่อมีโมเดลใหม่ ภาพรวมรุ่นล่าสุดของ Claude ดูได้ใน \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fblogs\u002Fclaude-opus-5-for-devs\">Claude Opus 5 ฉบับสาย Dev\u003C\u002Fa>)\u003C\u002Fp>\u003Cp>สรุปสั้นๆ คือ OpenAI ง่ายกว่าเพราะไม่ต้องทำอะไรก็ได้ cache แต่ Claude ให้ควบคุมได้ละเอียดกว่าว่าจะ cache ตรงไหน ซึ่งมีประโยชน์มากเมื่อ prompt มีหลายส่วนที่เปลี่ยนด้วยความถี่ต่างกัน\u003C\u002Fp>\u003Ch2>เปิด Prompt Caching ของ Claude จาก Go\u003C\u002Fh2>\u003Cp>ตัวอย่างนี้ใช้ net\u002Fhttp กับ struct ตรงๆ เพื่อให้เห็นว่า JSON ที่ส่งออกไปหน้าตาเป็นยังไง ถ้าอยากเทียบกับการเรียกฝั่ง OpenAI ผ่าน SDK ดูได้ใน \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fblogs\u002Fgolang-openai-api-gpt4o-sdk-guide\">EP.144 เชื่อมต่อ OpenAI API ด้วย Go SDK\u003C\u002Fa>\u003C\u002Fp>\u003Cpre>\u003Ccode>package llm\n\nimport (\n\t\"bytes\"\n\t\"encoding\u002Fjson\"\n\t\"fmt\"\n\t\"net\u002Fhttp\"\n\t\"os\"\n)\n\ntype CacheControl struct {\n\tType string `json:\"type\"`          \u002F\u002F \"ephemeral\"\n\tTTL  string `json:\"ttl,omitempty\"` \u002F\u002F \"\" = 5 นาที, \"1h\" = 1 ชั่วโมง\n}\n\ntype TextBlock struct {\n\tType         string        `json:\"type\"`\n\tText         string        `json:\"text\"`\n\tCacheControl *CacheControl `json:\"cache_control,omitempty\"`\n}\n\ntype Message struct {\n\tRole    string `json:\"role\"`\n\tContent string `json:\"content\"`\n}\n\ntype Request struct {\n\tModel     string      `json:\"model\"`\n\tMaxTokens int         `json:\"max_tokens\"`\n\tSystem    []TextBlock `json:\"system\"`\n\tMessages  []Message   `json:\"messages\"`\n}\n\ntype Usage struct {\n\tInputTokens              int `json:\"input_tokens\"`\n\tCacheCreationInputTokens int `json:\"cache_creation_input_tokens\"`\n\tCacheReadInputTokens     int `json:\"cache_read_input_tokens\"`\n\tOutputTokens             int `json:\"output_tokens\"`\n}\n\ntype Response struct {\n\tUsage Usage `json:\"usage\"`\n}\n\n\u002F\u002F systemPrompt ต้องเป็นข้อความคงที่ ห้ามมีเวลา ชื่อผู้ใช้ หรือค่าที่เปลี่ยนทุก request\nfunc Ask(systemPrompt, question string) (*Response, error) {\n\tbody := Request{\n\t\tModel:     \"claude-sonnet-5\",\n\t\tMaxTokens: 1024,\n\t\tSystem: []TextBlock{{\n\t\t\tType:         \"text\",\n\t\t\tText:         systemPrompt,\n\t\t\tCacheControl: &amp;CacheControl{Type: \"ephemeral\"}, \u002F\u002F จุดตัด cache อยู่ท้ายส่วนที่คงที่\n\t\t}},\n\t\tMessages: []Message{{Role: \"user\", Content: question}}, \u002F\u002F ส่วนที่เปลี่ยนอยู่หลังจุดตัด\n\t}\n\n\tb, err := json.Marshal(body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treq, err := http.NewRequest(\"POST\", \"https:\u002F\u002Fapi.anthropic.com\u002Fv1\u002Fmessages\", bytes.NewReader(b))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treq.Header.Set(\"x-api-key\", os.Getenv(\"ANTHROPIC_API_KEY\"))\n\treq.Header.Set(\"anthropic-version\", \"2023-06-01\")\n\treq.Header.Set(\"content-type\", \"application\u002Fjson\")\n\n\tres, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer res.Body.Close()\n\tif res.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"anthropic: status %d\", res.StatusCode)\n\t}\n\n\tvar out Response\n\treturn &amp;out, json.NewDecoder(res.Body).Decode(&amp;out)\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>หัวใจของโค้ดนี้อยู่ที่บรรทัดเดียว คือ CacheControl ต้องอยู่บน \u003Cstrong>block สุดท้ายที่เหมือนเดิมทุก request\u003C\u002Fstrong> ไม่ใช่บน block ที่เปลี่ยนทุกครั้ง\u003C\u002Fp>\u003Ch3>อ่านตัวเลขให้เป็น\u003C\u002Fh3>\u003Cp>ใน usage ของ response มี 3 ค่าที่ต้องดู\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Ccode>cache_creation_input_tokens\u003C\u002Fcode> คือจำนวน token ที่เพิ่งถูกเขียนลง cache ใน request นี้\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Ccode>cache_read_input_tokens\u003C\u002Fcode> คือจำนวน token ที่อ่านจาก cache ใน request นี้\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Ccode>input_tokens\u003C\u002Fcode> คือเฉพาะ token ที่อยู่หลังจุดตัด cache สุดท้าย ไม่ใช่ input ทั้งหมด\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>ถ้าจะหา input ทั้งหมดต้องรวมทั้งสามค่า และถ้า cache_creation_input_tokens กับ cache_read_input_tokens เป็น 0 ทั้งคู่ แปลว่าไม่ได้ cache เลย สาเหตุที่พบบ่อยคือ prompt สั้นกว่าขั้นต่ำของรุ่นนั้น ระบบจะข้ามไปเฉยๆ โดยไม่แจ้ง error (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching\">เอกสาร Claude\u003C\u002Fa>)\u003C\u002Fp>\u003Cp>ฝั่ง OpenAI ดูค่า \u003Ccode>cached_tokens\u003C\u002Fcode> ได้จาก usage.prompt_tokens_details ใน Chat Completions หรือ usage.input_tokens_details ใน Responses API ส่วนรุ่น GPT-5.6 ขึ้นไปจะมี \u003Ccode>cache_write_tokens\u003C\u002Fcode> เพิ่มมาด้วย (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fprompt-caching?prompt-cache-api=chat-completions\">เอกสาร OpenAI\u003C\u002Fa>)\u003C\u002Fp>\u003Ch2>คุ้มแค่ไหน: คำนวณจากราคาจริง\u003C\u002Fh2>\u003Cp>ลองคิดจากราคา Claude Sonnet 5 ต่อ 1 ล้าน token ตามเอกสาร ณ กันยายน 2026: input ปกติ $2 เขียน cache แบบ 5 นาที $2.50 และอ่าน cache $0.20\u003C\u002Fp>\u003Cp>สมมติ system prompt ยาว 10,000 tokens และมี 100 request ที่เข้ามาถี่พอให้ cache ไม่หมดอายุ\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>ไม่ใช้ cache:\u003C\u002Fstrong> 100 x 10,000 x $2 \u002F 1,000,000 = ประมาณ $2.00\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>ใช้ cache:\u003C\u002Fstrong> เขียนครั้งแรก 10,000 x $2.50 \u002F 1,000,000 = $0.025 และอ่านอีก 99 ครั้ง 99 x 10,000 x $0.20 \u002F 1,000,000 = $0.198 รวมประมาณ $0.22\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>ตัวเลขนี้คิดเฉพาะส่วน system prompt ยังไม่รวมคำถามของผู้ใช้และ output ซึ่งราคาเท่าเดิม และเป็นกรณีที่ hit ทุกครั้ง ระบบจริงจะลดได้น้อยกว่านี้ตามอัตรา hit\u003C\u002Fp>\u003Cp>จุดคุ้มทุนมาเร็วมาก เพราะเขียน 1 ครั้งบวกอ่าน 1 ครั้งเท่ากับ 1.25 + 0.1 = 1.35 เท่า ขณะที่ไม่ใช้ cache สองครั้งเท่ากับ 2 เท่า แค่ hit ครั้งเดียวก็คุ้มแล้ว ฟังก์ชันนี้ใช้คำนวณจาก usage จริงได้ และต่อยอดกับระบบบันทึกค่าใช้จ่ายใน \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fblogs\u002Fgolang-the-series-ep149-token-management-api-cost-control\">EP.149 Token Management\u003C\u002Fa> ได้เลย\u003C\u002Fp>\u003Cpre>\u003Ccode>\u002F\u002F ราคาต่อ 1 ล้าน token (USD) ดึงจากหน้าราคาของรุ่นที่ใช้จริง อย่า hardcode ถาวร\ntype Price struct {\n\tInput, CacheWrite5m, CacheRead float64\n}\n\nfunc CostUSD(u Usage, p Price) (withCache, withoutCache float64) {\n\tconst m = 1_000_000.0\n\twithCache = float64(u.InputTokens)*p.Input\u002Fm +\n\t\tfloat64(u.CacheCreationInputTokens)*p.CacheWrite5m\u002Fm +\n\t\tfloat64(u.CacheReadInputTokens)*p.CacheRead\u002Fm\n\n\ttotal := u.InputTokens + u.CacheCreationInputTokens + u.CacheReadInputTokens\n\twithoutCache = float64(total) * p.Input \u002F m\n\treturn\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>ฟังก์ชันนี้คิดเฉพาะ input และสมมติว่าใช้ cache แบบ 5 นาที ถ้าใช้แบบ 1 ชั่วโมงต้องแยกคิดจาก cache_creation.ephemeral_1h_input_tokens\u003C\u002Fp>\u003Cp>นอกจากเงิน ยังได้ความเร็วด้วย OpenAI ทดสอบเองแล้วพบว่า prompt สั้นระดับ 1,024 tokens เร็วขึ้นราว 7% แต่ prompt ยาว 150,000 tokens ขึ้นไปได้ time-to-first-token เร็วขึ้นราว 67% (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fcookbook\u002Fexamples\u002Fprompt_caching_201\">OpenAI Cookbook\u003C\u002Fa>) ยิ่ง prompt ยาว ยิ่งเห็นผลชัด\u003C\u002Fp>\u003Ch2>ใส่ cache_control ทุก request ไปเลยได้ไหม?\u003C\u002Fh2>\u003Cp>จริงๆ ทำได้ และ Claude มีโหมด automatic caching ที่ใส่ cache_control ครั้งเดียวที่ระดับ request แล้วระบบจะเลื่อนจุดตัดไปที่ block สุดท้ายให้เอง เหมาะมากกับแชตหลายรอบที่ประวัติยาวขึ้นเรื่อยๆ\u003C\u002Fp>\u003Cp>แต่ถ้า block สุดท้ายเปลี่ยนทุกครั้ง เช่น แปะเวลาปัจจุบันหรือ context เฉพาะ request ไว้ท้าย prompt ระบบจะเขียน cache ใหม่ทุกรอบโดยไม่เคยได้อ่านเลย เท่ากับจ่ายค่าเขียนแพงขึ้น 25% ทุก request โดยไม่ได้อะไรกลับมา (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching\">เอกสาร Claude\u003C\u002Fa>) กรณีนี้ต้องใช้ breakpoint ราย block และย้ายไปไว้ท้ายส่วนที่คงที่แทน\u003C\u002Fp>\u003Cp>กฎจำง่ายๆ คือ ของที่ไม่เปลี่ยนไว้ข้างหน้า ของที่เปลี่ยนไว้ข้างหลัง ลำดับที่ปลอดภัยคือ tools, คำสั่งหลัก, เอกสารอ้างอิง, ประวัติแชต แล้วจึงเป็นคำถามล่าสุด\u003C\u002Fp>\u003Ch2>กับดักที่คนเขียน Go ต้องรู้\u003C\u002Fh2>\u003Cp>เอกสารของ Claude เตือนไว้ว่าบางภาษา รวมถึง Go อาจสลับลำดับ key ตอนแปลงเป็น JSON ทำให้ cache ไม่ match\u003C\u002Fp>\u003Cp>ต้องแยกให้ชัดตรงนี้ encoding\u002Fjson ของ Go เรียง key ของ map ให้เสมอตอน json.Marshal จึงปลอดภัย ความเสี่ยงจริงอยู่ที่จุดอื่น\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>ประกอบ prompt ด้วยการวน range บน map\u003C\u002Fstrong> ลำดับการวน map ใน Go สุ่มทุกครั้ง ข้อความที่ได้จึงเรียงไม่เหมือนเดิม ควรใช้ slice ที่เรียงลำดับตายตัวแทน\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>ใช้ JSON library ตัวอื่น\u003C\u002Fstrong> ที่ไม่รับประกันลำดับ key\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>input ของ tool_use ที่เก็บแล้วส่งกลับ\u003C\u002Fstrong> ถ้าแปลงผ่าน map แล้วประกอบเองโดยไม่เรียง key\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>วิธีที่ปลอดภัยที่สุดคือใช้ struct เหมือนในตัวอย่างด้านบน เพราะลำดับ field ของ struct ตายตัวเสมอ\u003C\u002Fp>\u003Ch2>Cache ทำให้ AI ตอบเหมือนเดิม หรือใช้ข้อมูลเก่าไหม?\u003C\u002Fh2>\u003Cp>คำถามนี้ควรถามก่อนเปิดใช้ คำตอบคือไม่ Prompt caching ไม่มีผลต่อการสร้างคำตอบ response ที่ได้จะเหมือนกับตอนไม่ใช้ cache ทุกประการ (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching\">เอกสาร Claude\u003C\u002Fa>) สิ่งที่ cache เก็บคือผลการประมวลผล input ไม่ใช่ตัวคำตอบ\u003C\u002Fp>\u003Cp>แต่ caching ก็ไม่ได้ช่วยเรื่องความสดของข้อมูล ถ้าเอกสารอ้างอิงใน prompt เก่า คำตอบก็อิงของเก่าเหมือนเดิม ระบบที่ต้องใช้ข้อมูลล่าสุดจึงยังต้องมีกลไกอัปเดตเนื้อหาของตัวเอง และต้องยอมรับว่าทุกครั้งที่อัปเดต ส่วนนั้นกับทุกอย่างที่ตามมาจะ miss หนึ่งรอบ\u003C\u002Fp>\u003Cp>อีกเรื่องที่ทีมมักถามคือความปลอดภัย cache ของ Claude แยกกันระหว่างองค์กร และบน Claude API ยังแยกระดับ workspace ด้วย ส่วนของ OpenAI แยกกันระดับองค์กร ผู้ใช้ต่างองค์กรจึงไม่ได้ใช้ cache ร่วมกัน\u003C\u002Fp>\u003Cdiv data-type=\"horizontalRule\">\u003Chr>\u003C\u002Fdiv>\u003Ch2>สรุป: เปิด cache อย่างเดียวไม่พอ ต้องออกแบบให้ hit\u003C\u002Fh2>\u003Cp>ตอบแบบตรงๆ ไม่อ้อม\u003C\u002Fp>\u003Cp>\u003Cstrong>ควรทำทันที\u003C\u002Fstrong> ถ้าระบบมี system prompt นิยาม tools หรือเอกสารอ้างอิงยาวเกินขั้นต่ำของรุ่นที่ใช้ และมี request เข้ามาถี่พอให้ cache ไม่หมดอายุ แค่ hit ครั้งเดียวก็คุ้มค่าเขียนแล้ว\u003C\u002Fp>\u003Cp>\u003Cstrong>ยังไม่ต้องรีบ\u003C\u002Fstrong> ถ้า prompt สั้นกว่าขั้นต่ำ หรือแต่ละ request ต่างกันทั้งก้อน กรณีนี้ caching แทบไม่ช่วยอะไร\u003C\u002Fp>\u003Cp>ถ้าจะเริ่มวันนี้ ให้เริ่มจากเรื่องเดียว คือเอา cache_read_input_tokens หรือ cached_tokens ไปใส่ใน log ที่มีอยู่แล้ว ดูสักหนึ่งวันว่าระบบ hit จริงแค่ไหน ตัวเลขนั้นจะบอกเองว่าต้องย้ายอะไรไปไว้หน้า prompt และตรงไหนที่ยังรั่วอยู่\u003C\u002Fp>","cover_cover_9z5thde0yq.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002F8bpeu92yi3yt48w\u002Fl\u002Fcover_cover_9z5thde0yq.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002F8bpeu92yi3yt48w\u002Fm\u002Fcover_cover_9z5thde0yq.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002F8bpeu92yi3yt48w\u002Fcover_cover_9z5thde0yq.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002F8bpeu92yi3yt48w\u002Fs\u002Fcover_cover_9z5thde0yq.webp","2026-09-24 05:18:17.054Z","qym0hub9bm27ns3",{"keywords":18,"locale":53,"school_blog":63},[19,25,31,35,40,44,48],{"collectionId":20,"collectionName":21,"created":22,"created_by":16,"id":23,"name":24,"updated":22,"updated_by":16},"sclkey987654321","school_keywords","2026-09-24 05:18:17.047Z","pvi8p900bsnv9gz","Prompt Caching",{"collectionId":20,"collectionName":21,"created":26,"created_by":27,"id":28,"name":29,"updated":30,"updated_by":27},"2026-03-04 08:20:14.253Z","76qprkevbgfdps8","ah6lvy4x8qe08l5","Golang","2026-06-07 06:45:08.193Z",{"collectionId":20,"collectionName":21,"created":32,"created_by":27,"id":33,"name":34,"updated":32,"updated_by":27},"2026-06-11 16:54:41.946Z","015roiohb99sg77","Claude API",{"collectionId":20,"collectionName":21,"created":36,"created_by":27,"id":37,"name":38,"updated":39,"updated_by":27},"2026-05-11 06:33:36.935Z","xp9ljhapsv79n2f","OpenAI API","2026-06-07 06:49:12.039Z",{"collectionId":20,"collectionName":21,"created":41,"created_by":27,"id":42,"name":43,"updated":41,"updated_by":27},"2026-06-11 16:14:34.250Z","01ajl5eq1joxocg","LLM",{"collectionId":20,"collectionName":21,"created":45,"created_by":16,"id":46,"name":47,"updated":45,"updated_by":16},"2026-09-24 05:18:17.048Z","6spmrq6w10ta0if","ลดต้นทุน API",{"collectionId":20,"collectionName":21,"created":49,"created_by":27,"id":50,"name":51,"updated":52,"updated_by":27},"2026-03-04 08:44:53.062Z","puutdnxuitnxxgq","Backend","2026-06-07 06:46:40.599Z",{"code":54,"collectionId":55,"collectionName":56,"created":57,"flag":58,"id":59,"is_default":60,"label":61,"updated":62},"th","pbc_1989393366","locales","2026-01-22 10:59:55.832Z","twemoji:flag-thailand","s8wri3bt4vgg2ji",true,"Thai","2026-04-10 15:42:46.614Z",{"category":64,"collectionId":65,"collectionName":66,"created":67,"expand":68,"id":84,"slug":85,"updated":86,"views":87},"spm4l1k5bgmhmmt","pbc_2105096300","school_blogs","2026-09-24 05:18:17.049Z",{"category":69},{"blogIds":70,"collectionId":71,"collectionName":72,"created":73,"created_by":27,"id":64,"image":74,"image_alt":75,"image_path":76,"image_s_url":77,"label":78,"name":79,"priority":80,"publish_at":81,"scheduled_at":75,"status":82,"updated":83,"updated_by":27},[],"sclcatblg987654321","school_category_blogs","2026-03-04 08:31:18.590Z","50hyjr6os45_ayazwr5gq7_tqzz9l5y5w.webp","","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclcatblg987654321\u002Fspm4l1k5bgmhmmt\u002F50hyjr6os45_ayazwr5gq7_tqzz9l5y5w.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclcatblg987654321\u002Fspm4l1k5bgmhmmt\u002Fs\u002F50hyjr6os45_ayazwr5gq7_tqzz9l5y5w.webp",{"en":79,"th":79},"Knowledge",0,"2026-03-18 02:25:41.222Z","published","2026-08-18 14:49:11.737Z","4gfjbiytxpe8j7c","golang-prompt-caching-claude-openai","2026-09-24 10:42:49.775Z",119,"8bpeu92yi3yt48w",[23,28,33,37,42,46,50],"2026-09-24 06:42:25.556Z","Prompt Caching ช่วยลดค่า input ของ Claude และ OpenAI API ได้มาก แต่ได้ผลก็ต่อเมื่อ cache hit จริง มาดูวิธีจัด request จากฝั่ง Go ให้ hit และวัดผลจากตัวเลขใน response","Prompt Caching คืออะไร? ลดค่า Claude\u002FOpenAI API ในระบบจริงด้วย Go","2026-09-24 06:42:25.558Z",1,{"th":85,"en":85},[97,101,105,109,113,117],{"answer":98,"id":99,"question":100},"ฝั่ง Claude และ OpenAI รุ่น GPT-5.6 ขึ้นไปคิดค่าเขียน cache แพงกว่า input ปกติ ถ้าเขียนแล้วไม่เคยถูกอ่านก่อนหมดอายุ เช่น ผู้ใช้เว้นช่วงนานเกินอายุ cache หรือจุดตัดอยู่บน block ที่เปลี่ยนทุกครั้ง จะกลายเป็นจ่ายเพิ่มแทนที่จะประหยัด","3wdmp5vmg854enu","Prompt Caching ทำให้ต้องจ่ายเพิ่มในกรณีไหน",{"answer":102,"id":103,"question":104},"ถ้า request เข้ามาถี่กว่าทุก 5 นาที ใช้แบบ 5 นาทีก็พอ เพราะต่ออายุให้ฟรีทุกครั้งที่ถูกใช้ แบบ 1 ชั่วโมงเหมาะกับกรณีที่ผู้ใช้อาจเว้นช่วงเกิน 5 นาทีแต่ไม่เกินชั่วโมง เช่น แชตยาวที่ผู้ใช้หยุดคิด หรือ agent ที่แต่ละขั้นใช้เวลานาน ค่าเขียนแบบ 1 ชั่วโมงแพงกว่า คือ 2 เท่าของราคา input เทียบกับ 1.25 เท่า","e2x54cuxh69x9u8","ควรเลือก cache 5 นาทีหรือ 1 ชั่วโมง",{"answer":106,"id":107,"question":108},"เพราะ OpenAI นับ cache hit เป็นช่วงละ 128 tokens หลังผ่านขั้นต่ำแล้ว ตัวเลขจึงมักน้อยกว่าความยาวส่วนคงที่เล็กน้อย ถือเป็นเรื่องปกติ","dk40qko0i7gcrdf","ทำไม cached_tokens ของ OpenAI ไม่เท่ากับ prompt ส่วนที่คงที่พอดี",{"answer":110,"id":111,"question":112},"ฝั่ง Claude ได้ และตัวคูณราคาของ cache ซ้อนกับส่วนลดของ Batch API ด้วย","g5ok562q5gmd8lz","ใช้ Prompt Caching ร่วมกับ Batch API ได้ไหม",{"answer":114,"id":115,"question":116},"สาเหตุที่พบบ่อยมี 3 อย่าง คือ prompt สั้นกว่าขั้นต่ำของรุ่นนั้น ระบบจะข้ามการ cache โดยไม่แจ้ง error, request ถัดไปมาช้ากว่าอายุ cache หรือส่วนก่อนจุดตัดมีค่าที่เปลี่ยนทุกครั้ง เช่น timestamp หรือลำดับข้อความที่ได้จากการวน map ใน Go","vgqtxvjtprgjanl","ทำไมเปิด cache_control แล้ว cache_read_input_tokens ยังเป็น 0",{"answer":118,"id":119,"question":120},"ใช้ได้กับ Claude ทุกรุ่นที่ยังเปิดให้บริการ ทั้งแบบ automatic caching และแบบกำหนด breakpoint เอง แต่ขนาดขั้นต่ำที่ cache ได้ต่างกันตามรุ่น เช่น Opus 5.5 อยู่ที่ 512 tokens, Sonnet 5 อยู่ที่ 1,024 tokens และ Haiku 4.5 อยู่ที่ 4,096 tokens ถ้า prompt สั้นกว่านี้ระบบจะไม่ cache และไม่แจ้ง error","ismo0vgbu2u6baj","Prompt Caching ใช้กับ Claude รุ่นไหนได้บ้าง"]