antirez/ds4 - เอนจินรันอนุมานแบบโลคัลสำหรับ DeepSeek V4 Flash บน Metal
(github.com/antirez)- เอนจินรันอนุมานแบบโลคัล สำหรับ DeepSeek V4 Flash โดยเฉพาะ ที่ปรับแต่งมาสำหรับ Apple Metal GPU เป็นอิมพลีเมนเทชันเนทีฟ C ที่โฟกัสโมเดลเดียว ไม่ใช่ตัวรัน GGUF แบบอเนกประสงค์
- DeepSeek V4 Flash มีจำนวนพารามิเตอร์ที่ active น้อย จึงให้ ความเร็วสูง และในโหมด thinking จะสร้างช่วงการคิดที่สั้นกว่ารุ่นอื่นเพียงประมาณ 1/5
- รองรับ context window 1 ล้านโทเค็น และใช้ KV cache ที่บีบอัดอย่างมาก ทำให้รันอนุมาน long-context บนเครื่องโลคัลได้ พร้อมรองรับ การ persist ดิสก์ KV cache
- มี HTTP API server ในตัวที่เข้ากันได้กับ OpenAI และ Anthropic จึงเชื่อมต่อกับเอเจนต์เขียนโค้ดอย่าง Claude Code, opencode, Pi และอื่นๆ ได้ทันที
- สร้างอยู่บนพื้นฐานของ ecosystem ของ llama.cpp และ GGML และเป็นโปรเจ็กต์ที่พัฒนาโดยได้รับ การสนับสนุนด้านโค้ดดิ้งอย่างมากจาก GPT 5.5
ภาพรวมโปรเจ็กต์และปรัชญาการออกแบบ
ds4.cคือเอนจินรันอนุมานเนทีฟขนาดเล็ก สำหรับ DeepSeek V4 Flash เท่านั้น ไม่ใช่ตัวรัน GGUF แบบอเนกประสงค์หรือ wrapper ของรันไทม์อื่น- เส้นทางหลักคือ ตัวรันกราฟ Metal ที่ปรับแต่งสำหรับ DeepSeek V4 Flash พร้อมโค้ดสำหรับการโหลดแบบ DS4 โดยเฉพาะ การเรนเดอร์พรอมป์ต์ สถานะ KV และโค้ดเชื่อมต่อ API ของเซิร์ฟเวอร์
- แม้ในวงการ local inference จะมีโปรเจ็กต์ดีๆ มากมาย แต่เมื่อมีโมเดลใหม่ออกมาอย่างต่อเนื่อง ความสนใจก็มักกระจายออกไป
- โปรเจ็กต์นี้จึงตั้งใจโฟกัสที่ ทีละหนึ่งโมเดล และทำทั้งการตรวจสอบกับเวกเตอร์ทางการ (logits), การทดสอบ long-context และการเชื่อมต่อกับเอเจนต์
- วิสัยทัศน์ของ local inference คือ A) เอนจินอนุมานที่มี HTTP API ในตัว + B) GGUF ที่ปรับจูนให้เหมาะกับเอนจินนั้นโดยเฉพาะ + C) การทดสอบและตรวจสอบผ่านอิมพลีเมนเทชันของ coding agent โดยทั้งสามส่วนต้องทำงานร่วมกัน
- เป็น Metal-only และแม้ในอนาคตอาจรองรับ CUDA แต่ยังไม่ยืนยัน
- เส้นทาง CPU มีไว้เพื่อตรวจสอบความถูกต้องเท่านั้น และขณะนี้มี บั๊กในระบบ virtual memory ของ macOS ที่ทำให้รันโค้ด CPU แล้ว kernel crash
- โปรเจ็กต์นี้พัฒนาโดยได้รับ การสนับสนุนอย่างมากจาก GPT 5.5 โดยมนุษย์ยังเป็นผู้ขับเคลื่อนไอเดีย การทดสอบ และการดีบัก
เหตุผลที่สร้าง DeepSeek V4 Flash เป็นเอนจินแยกต่างหาก
- มีพารามิเตอร์ที่ active น้อย จึงให้ ความเร็วในการอนุมานที่สูงกว่า
- ในโหมด thinking จะสร้าง ช่วงการคิดที่สั้นกว่ารุ่นอื่นราว 1/5 และความยาวของช่วงคิด แปรผันตามความซับซ้อนของปัญหา
- แม้ในสถานการณ์ที่โมเดลอื่นใช้งานโหมด thinking ได้ไม่ค่อยจริงจังนัก DeepSeek V4 Flash ก็ยังใช้งานได้
- รองรับ context window 1 ล้านโทเค็น
- ที่ขนาด 284B พารามิเตอร์ โมเดลนี้รู้ข้อมูล ใกล้ขอบเขตความรู้ได้มากกว่า โมเดล 27B และ 35B
- เห็นความต่างได้จากคำถามเกี่ยวกับรายการทีวีภาษาอิตาลีหรือการเมือง
- คุณภาพการเขียนภาษาอังกฤษและอิตาลีอยู่ในระดับ ใกล้เคียงโมเดล frontier
- KV cache ถูกบีบอัดอย่างมาก ทำให้ทำ long-context inference บนคอมพิวเตอร์โลคัลได้ และรองรับ การ persist ดิสก์ KV cache
- หากใช้การ quantize แบบพิเศษ จะ ทำงานได้ดีแม้เป็น 2-bit quantization และรันได้บน MacBook RAM 128GB
- คาดว่าในอนาคต DeepSeek จะออก รุ่นอัปเดตของ V4 Flash
คำขอบคุณต่อ llama.cpp และ GGML
- แม้ ds4.c จะไม่ได้ลิงก์กับ GGML โดยตรง แต่ก็ยืนอยู่บน เส้นทางที่โปรเจ็กต์ llama.cpp บุกเบิกไว้
- เคอร์เนลของ llama.cpp, ฟอร์แมตการ quantize, ecosystem ของ GGUF และองค์ความรู้ด้านวิศวกรรมระดับฮาร์ดคอร์ ล้วนเป็นข้อมูลอ้างอิงสำคัญ
- มีโค้ดบางส่วนในระดับ source ที่คงไว้หรือประยุกต์ใช้ภายใต้ไลเซนส์ MIT เช่น layout และตารางของ GGUF quant, ตรรกะ CPU quant/dot และ Metal kernel บางตัว
- ไฟล์ LICENSE ยังคงการระบุลิขสิทธิ์ของผู้เขียน GGML ไว้
น้ำหนักโมเดล
- ใช้งานได้เฉพาะ DeepSeek V4 Flash GGUF ที่เผยแพร่สำหรับโปรเจ็กต์นี้เท่านั้น ไฟล์ DeepSeek/GGUF อื่นทั่วไปจะไม่เข้ากัน
- 2-bit quantization ใช้วิธี asymmetric quantization
- quantize เฉพาะ MoE expert: up/gate ใช้
IQ2_XXS, down ใช้Q2_K - คอมโพเนนต์ที่เหลือ เช่น shared expert, projection, routing จะ ไม่ถูก quantize เพื่อรักษาคุณภาพ
- quantize เฉพาะ MoE expert: up/gate ใช้
- ใช้
./download_model.sh q2เพื่อดาวน์โหลดโมเดลสำหรับเครื่อง RAM 128GB และ./download_model.sh q4สำหรับเครื่อง RAM 256GB ขึ้นไป- ดาวน์โหลดจาก Hugging Face (
antirez/deepseek-v4-gguf) และรองรับการ resume partial download ด้วยcurl -C -
- ดาวน์โหลดจาก Hugging Face (
- ใช้
./download_model.sh mtpเพื่อดาวน์โหลด GGUF ที่รองรับ speculative decoding แบบเลือกใช้ได้- เส้นทาง MTP/speculative decoding ยังอยู่ในขั้นทดลอง และตอนนี้ช่วยเพิ่มความเร็วได้เพียงเล็กน้อย
เบนช์มาร์กความเร็ว
- ตัวเลขจาก Metal CLI แบบรันเดี่ยว ภายใต้การตั้งค่า
--ctx 32768,--nothink, greedy decoding และ-n 256 - MacBook Pro M3 Max, 128GB (q2)
- พรอมป์ต์สั้น: prefill 58.52 t/s, generation 26.68 t/s
- พรอมป์ต์ 11709 โทเค็น: prefill 250.11 t/s, generation 21.47 t/s
- q4: N/A เพราะหน่วยความจำไม่พอ
- Mac Studio M3 Ultra, 512GB (q2)
- พรอมป์ต์สั้น: prefill 84.43 t/s, generation 36.86 t/s
- พรอมป์ต์ 11709 โทเค็น: prefill 468.03 t/s, generation 27.39 t/s
- Mac Studio M3 Ultra, 512GB (q4)
- พรอมป์ต์สั้น: prefill 78.95 t/s, generation 35.50 t/s
- พรอมป์ต์ 12018 โทเค็น: prefill 448.82 t/s, generation 26.62 t/s
วิธีใช้ CLI
- ใช้ตัวเลือก
-pเพื่อรัน one-shot prompt และหากรันโดยไม่ใส่-pจะเข้าสู่โหมด interactive multi-turn chat - CLI แบบ interactive จะเก็บ transcript ของแชตที่เรนเดอร์แล้วและ live Metal KV checkpoint ทำให้แต่ละเทิร์นต่อยอดจากบทสนทนาก่อนหน้า
- คำสั่งที่มีประโยชน์:
/help,/think,/think-max,/nothink,/ctx N,/read FILE,/quit- กด Ctrl+C เพื่อหยุดการสร้างข้อความปัจจุบันและกลับสู่พรอมป์ต์ได้
- ค่าเริ่มต้นคือ โหมด thinking และสามารถสลับเป็นโหมดตอบตรงได้ด้วย
/nothinkหรือ--nothink - ใช้
--mtp MTP.gguf --mtp-draft 2เพื่อเปิดเส้นทาง speculative แบบ MTP ได้- มีประโยชน์เฉพาะกับ greedy decoding และสามารถใช้ confidence gate (
--mtp-margin) เพื่อหลีกเลี่ยงการยอมรับส่วนที่ช้า
- มีประโยชน์เฉพาะกับ greedy decoding และสามารถใช้ confidence gate (
เซิร์ฟเวอร์
- สามารถรัน local HTTP server ที่เข้ากันได้กับ OpenAI/Anthropic
- เป็น Metal-only และเก็บกราฟ/KV checkpoint ที่แก้ไขได้หนึ่งชุดไว้ในหน่วยความจำ
- หากไคลเอนต์แบบ stateless ส่งพรอมป์ต์เดิมในเวอร์ชันที่ยาวกว่าเข้ามาใหม่ ก็สามารถ reuse shared prefix ได้
- การ parse request และ socket จะทำใน client thread แต่ตัว inference เองจะถูกทำแบบ serialize ผ่าน Metal worker เดี่ยว
- ปัจจุบันเซิร์ฟเวอร์ยังไม่ batch หลายคำขอที่เป็นอิสระต่อกัน และคำขอพร้อมกันจะรอตามลำดับ
-
endpoint ที่รองรับ
GET /v1/models,GET /v1/models/deepseek-v4-flashPOST /v1/chat/completions,POST /v1/completions,POST /v1/messages
-
/v1/chat/completions(เข้ากันได้กับ OpenAI)- รองรับ
messages,max_tokens/max_completion_tokens,temperature,top_p,top_k,min_p,seed,stream,stream_options.include_usage,tools,tool_choice - สคีมาของ tool จะถูกเรนเดอร์เป็น DSML tool format ของ DeepSeek และการเรียกใช้ DSML tool ที่สร้างขึ้นจะถูกแปลงกลับเป็น OpenAI tool call
- รองรับ
-
/v1/messages(เข้ากันได้กับ Anthropic)- เป็น endpoint สำหรับไคลเอนต์สไตล์ Claude Code
- รองรับ
system,messages,tools,tool_choice,max_tokens,temperature,top_p,top_k,stream,stop_sequencesและการควบคุม thinking - การใช้ tool จะถูกส่งกลับเป็น Anthropic
tool_useblock
- ทั้งสอง API รองรับ SSE streaming และในโหมด thinking จะสตรีมกระบวนการให้เหตุผลในรูปแบบ native API
การเชื่อมต่อกับ agent client
- ds4-server สามารถเชื่อมต่อกับ local coding agent ที่ใช้ chat completions แบบเข้ากันได้กับ OpenAI
- เมื่่อรัน 2-bit quant (81GB) บนเครื่อง RAM 128GB ค่า context window 100k~300k โทเค็น ถือว่าเหมาะสม
- context เต็ม 1M โทเค็นใช้หน่วยความจำราว 26GB (เฉพาะตัวบีบอัด indexer ใช้ประมาณ 22GB)
- ตั้งค่า output limit เป็น
384000เพื่อหลีกเลี่ยง token cap ได้ (โมเดลสามารถสร้างได้สูงสุด 384k โทเค็น) -
การเชื่อมต่อกับ opencode
- กำหนดค่าโดยเพิ่มรายการ provider และ agent ใน
~/.config/opencode/opencode.json - ตั้ง
baseURLเป็นhttp://127.0.0.1:8000/v1
- กำหนดค่าโดยเพิ่มรายการ provider และ agent ใน
-
การเชื่อมต่อกับ Pi
- เพิ่มการตั้งค่า provider ใน
~/.pi/agent/models.json - มีตัวเลือกความเข้ากันได้ เช่นฟอร์แมต thinking ของ DeepSeek, รองรับ reasoning effort และรองรับ usage แบบสตรีม
- สามารถตั้งเป็นโมเดลเริ่มต้นได้ใน
~/.pi/agent/settings.json
- เพิ่มการตั้งค่า provider ใน
-
การเชื่อมต่อกับ Claude Code
- ใช้ endpoint ที่เข้ากันได้กับ Anthropic และตั้งค่า environment variable ผ่าน wrapper script
~/bin/claude-ds4 - ตั้ง
ANTHROPIC_BASE_URLให้ชี้ไปยัง local server และตั้งค่าตัวแปรโมเดลทั้งหมดเป็นdeepseek-v4-flash - ในช่วงเริ่มต้น Claude Code จะส่ง พรอมป์ต์ขนาดใหญ่ราว 25k โทเค็น จึงจำเป็นต้องเปิด
--kv-disk-dir- หลัง prefill ครั้งแรกที่มีต้นทุนสูง ดิสก์ KV cache จะสามารถ reuse prefix ที่บันทึกไว้ ทำให้เซสชันถัดไปไม่ต้องประมวลผลพรอมป์ต์ทั้งหมดใหม่
- ใช้ endpoint ที่เข้ากันได้กับ Anthropic และตั้งค่า environment variable ผ่าน wrapper script
โหมด Thinking
- DeepSeek V4 Flash รองรับ 3 โหมดคือ non-thinking, thinking และ Think Max
- ค่าเริ่มต้นของเซิร์ฟเวอร์คือโหมด thinking
- สามารถขอ Think Max ได้ด้วย
reasoning_effort=maxแต่จะใช้ได้ก็ต่อเมื่อขนาด context ใหญ่พอตามคำแนะนำใน model card- หาก context เล็ก จะ fallback ไปใช้ thinking ปกติ
- OpenAI
reasoning_effort=xhighจะถูกแมปเป็น thinking ปกติ ไม่ใช่ Think Max - หากต้องการให้ตอบตรงๆ สามารถใช้
thinking: {"type":"disabled"},think:falseหรือใช้นามแฝงโมเดลแบบ non-thinking เช่นdeepseek-chat
ดิสก์ KV cache
- เนื่องจาก Chat/completion API เป็นแบบ stateless เอเจนต์ไคลเอนต์จึงต้องส่งบทสนทนาทั้งหมดซ้ำทุกครั้งที่ร้องขอ
- ds4-server จะประมวลผลโดยเทียบ token stream ที่เรนเดอร์แล้วกับ token prefix ที่ถูก cache ไว้
- live in-memory checkpoint จะรับผิดชอบเซสชันปัจจุบัน
- ดิสก์ KV cache คือกลไกสำหรับ เก็บ prefix ที่ยังมีประโยชน์ไว้ข้ามการสลับเซสชันและการรีสตาร์ตเซิร์ฟเวอร์
- ปัจจุบันในหน่วยความจำมี live KV cache เพียงชุดเดียว และหากเซสชันใหม่ที่ไม่เกี่ยวข้องเข้ามาแทนที่ ชุดก่อนหน้าจะกลับมาใช้ต่อได้แบบไม่ต้อง reprocess ก็ต่อเมื่อถูกเขียนลงดิสก์ KV cache ไว้แล้ว
- เปิดใช้งานได้ด้วย
--kv-disk-dirและ--kv-disk-space-mb -
คีย์แคชและโครงสร้างไฟล์
- คีย์แคชคือ SHA1 hash ของ token ID แบบตรงเป๊ะ ไม่ใช่ข้อความดิบ
- token ID แต่ละตัวจะถูก hash ในรูปแบบ little-endian 32-bit integer และชื่อไฟล์จะเป็น
<sha1>.kv - เขียนด้วย I/O แบบ
read/writeปกติ และไม่ใช้mmap(เพื่อหลีกเลี่ยงการเพิ่ม VM mapping ให้กับโปรเซสที่แมปโมเดลไว้อยู่แล้ว)
-
เลย์เอาต์ไฟล์ดิสก์แคช
- KVC fixed header 48 ไบต์: magic("KVC"), เวอร์ชัน, routed expert quant bit, เหตุผลที่บันทึก, จำนวนโทเค็นที่ cache, hit count, ขนาด context, เวลา Unix ของการสร้าง/ใช้งานครั้งล่าสุด และจำนวนไบต์ของ DS4 session payload
- ข้อความที่เรนเดอร์แล้ว: ข้อความที่ได้จาก tokenizer decode ของ token prefix ที่ cache ไว้ (มีไว้เพื่อการสังเกต ไม่ได้ใช้เป็นคีย์)
- DS4 session payload: เริ่มด้วยฟิลด์ little-endian u32 จำนวน 13 ค่า รวมถึง magic("DSV4"), เวอร์ชัน payload, ขนาด context, ขนาด prefill chunk, ความจุของ KV ring เป็นต้น
- เก็บ checkpoint token ID, float32 logits สำหรับโทเค็นถัดไป, จำนวน compressed attention row ต่อเลเยอร์, live raw sliding window KV row, KV row ของ compressed layer และ compressor frontier tensor เป็นต้น
-
จังหวะที่บันทึก checkpoint
cold: หลังพรอมป์ต์เริ่มต้นที่ยาวถึง stable prefix แล้ว ก่อนเริ่ม generationcontinued: เมื่อ prefill หรือ generation เดินหน้าไปตามช่วงที่กำหนดevict: ก่อนที่คำขอใหม่ที่ไม่เกี่ยวข้องจะมาแทนที่ live in-memory sessionshutdown: เมื่อเซิร์ฟเวอร์ปิดอย่างปกติ
- ระหว่างบันทึกแบบ cold จะมีการตัด token suffix เล็กๆ ออกและ จัดแนวให้ตรงกับขอบเขตของ prefill chunk เพื่อหลีกเลี่ยงความคลาดเคลื่อนจากการ re-tokenize ที่ขอบเขต BPE ในคำขออนาคต
- ค่าเริ่มต้น: prefix อย่างน้อย 512 โทเค็น, cold save สูงสุด 30000 โทเค็น, trim tail 32 โทเค็น และจัดแนว chunk ที่ 2048 โทเค็น
- ตามค่าเริ่มต้น สามารถ reuse checkpoint ระหว่างรุ่น routed-expert แบบ 2-bit และ 4-bit ได้ หาก token prefix ตรงกัน
- สามารถตั้งให้ reuse ได้เฉพาะ quantization เดียวกันด้วย
--kv-cache-reject-different-quant
- สามารถตั้งให้ reuse ได้เฉพาะ quantization เดียวกันด้วย
แบ็กเอนด์
- แบ็กเอนด์เริ่มต้นคือ Metal (
--metal) - มีเส้นทาง CPU สำหรับอ้างอิง/ดีบัก (
--cpu) เช่นกัน แต่ไม่ได้ออกแบบมาสำหรับ production- เซิร์ฟเวอร์รองรับเฉพาะ Metal และอิมพลีเมนเทชันที่ปรับแต่งแล้วจะอยู่ในเส้นทางกราฟ Metal
- ไลเซนส์ MIT, อิมพลีเมนเทชันด้วย C/Objective-C/Metal
1 ความคิดเห็น
ความเห็นจาก Hacker News
ลองใช้กับโค้ดเบสที่มีอยู่ร่วมกับ Claude Code แล้ว ดูเหมือนว่าจะยังพอทำงานของมันได้ แม้จะเป็นโมเดลควอนไทซ์ 2 บิต
การประมวลผลพรอมป์ต์ใช้เวลาหลายนาที แต่การแก้ไขจริงเร็วพอสมควรที่มากกว่า 20 โทเคน/วินาที
ในงานเล็ก ๆ มันสามารถสำรวจโค้ด, ปรับแก้, และเขียนเทสต์ได้สำเร็จ แต่กลับแก้ข้อสังเกตเล็กน้อยจุดหนึ่งไม่ได้
ที่แย่กว่านั้นคือ ระหว่างแก้ปัญหาอื่นอยู่ มันดันหลอนดึงบทสนทนาเกี่ยวกับ “The Duck” ที่คุยพร้อมกันขึ้นมา คงเป็นหนึ่งในตัวอย่างพรอมป์ต์เริ่มต้นของ Claude Code
ก่อนหน้านี้ผมเคยทำอะไรที่คล้ายกันมากสำหรับ โมเดล Qwen3 มันรันได้แค่ Qwen3, รองรับควอนไทซ์เพียงบางแบบ, โหลดจาก GGUF, และใช้ inference ที่ Claude ช่วย optimize แบบวนซ้ำ
ทั้งโปรเจกต์มีแค่ไม่กี่ไฟล์ เล็กและเข้าใจง่าย เลยทำไว้ให้นักศึกษาได้ลองเพิ่มกลยุทธ์การ decode หรือทดลองอย่าง abliteration เพื่อการเรียนรู้ เฟรมเวิร์กดัง ๆ มักใหญ่และซับซ้อนเกินไปจนแกะเล่นยาก ส่วนโปรเจกต์การศึกษาก็มักติดอยู่กับของเก่าอย่าง GPT-2
เริ่มจากเป็นโปรเจกต์เพื่อการศึกษา แต่ก็มีไอเดียหนึ่งที่ยังติดอยู่ในหัว: ถ้าลองทำ inference engine ที่ optimize แบบสุดทางสำหรับ คู่ GPU+โมเดล เฉพาะจะเป็นยังไง GPU แพงและยิ่งหาซื้อยากขึ้นเรื่อย ๆ ดังนั้นถ้าลอกชั้น abstraction ออกให้มากพอ แล้วจูนตรงกับฮาร์ดแวร์/โมเดลที่แน่นอน ก็น่าจะรีดประสิทธิภาพได้อีกมาก
แต่ปัญหาคือพอโมเดลล้าสมัย ก็ต้องเริ่มใหม่ทั้งหมดตั้งแต่ต้น
บนแพลตฟอร์มที่ไม่ค่อยนิยมยังพอมีช่องให้รีดประสิทธิภาพเพิ่มได้ง่าย แต่พื้นที่สำหรับการสร้างตัวรันโมเดลที่ optimize แบบสุดทางสำหรับตระกูล GPU ใดตระกูลหนึ่งแล้วได้ผลลัพธ์ดีกว่ามากนั้นมีไม่มาก แกนคำนวณหลักถูกจัดการโดย kernel ที่ optimize อย่างหนักสำหรับ GPU แต่ละตัวอยู่แล้ว
มีฟอร์กของ llama.cpp ที่ optimize ให้ทำงานดีกับสถาปัตยกรรม CPU บางแบบเหมือนกัน แต่ถ้าผู้ดูแลไม่ได้มีความเห็นต่างกัน การเอาปรับปรุงแบบนี้ไปรวม upstream น่าจะคุ้มเวลากว่าการแยกไปทำตัวรันเฉพาะโมเดล+GPU
https://codegolf.stackexchange.com/questions/215216/high-thr...
งานคำนวณหนักอย่าง การคูณเมทริกซ์ จะให้วงจรขยายสัญญาณเชิงคำนวณจัดการได้ไหม? แล้วแนวทางแบบแอนะล็อกนี้จะมีประสิทธิภาพกว่าข้อจำกัดของการแทนค่าด้วยบิตมากแค่ไหน?
ตอนนี้ AI รุ่นใหม่ไปถึงขั้นทำ kernel optimization ได้แล้ว ผมเลยคิดว่าน่าจะมีคนลองทำ inference ที่ดีกว่าสำหรับฮาร์ดแวร์ของตัวเองกันมากขึ้น
ผมมี W7900 (RDNA3) รุ่นเก่าอยู่ตัวหนึ่ง นอกจาก VRAM 48GB แล้ว สเปกอย่าง 123 FP16 TFLOPS/INT8 TOPS กับแบนด์วิดท์หน่วยความจำ 864GB/s ก็ถือว่าใช้ได้มาก แต่ทั้งการรองรับจาก AMD ROCm และจาก llama.cpp ต่างก็ขึ้นชื่อว่าแย่มาก
ช่วงหลังเลยเริ่มจูนโมเดล W8A8-INT8 เพื่อใช้การ์ดนี้เป็นเอ็นด์พอยต์สำหรับเอเจนต์/งานเขียนโค้ดโดยเฉพาะ ช่วงหลายวันที่ผ่านมา ผมปล่อยการวนซ้ำอัตโนมัติไปประมาณ 800 รอบ ลองใช้หลายโมเดลระดับ frontier/SOTA แล้วพบว่า Kimi K2.6 ทำได้ดีอย่างคาดไม่ถึง สุดท้ายแล้วบน Qwen3.6 MoE มันเร็วกว่าเลขที่ดีที่สุดของ llama.cpp อยู่ 20% ใน prefill และ 50% ใน decode
ตอนนี้กำลังขุดต่อในเรื่อง MTP กับการ optimize DFlash อยู่ ผลค่อนข้างน่าพอใจ และถัดไปว่าจะลอง Gemma 4
ถึงอย่างนั้น llama.cpp ก็ยังเป็นตัวที่รันโมเดลส่วนใหญ่ได้สม่ำเสมอ ถึงอาจไม่ใช่ตัวที่แรงสุด ดูเหมือนจะยังขาด MTP และมีปัญหา cache invalidation กับโมเดลแบบไฮบริด แต่ก็อย่างน้อยยังรู้ว่าอะไรพอจะรันได้
ส่วนตัวรัน inference ที่อิง Python นั้น ทั้ง uv/venv, venv ของผม, environment ระบบ, Python, และไลบรารีต่าง ๆ ปนกันมั่วไปหมด จนแทบต้องใช้อีกเอเจนต์มาช่วยดูว่าแท้จริงแล้วอะไรกำลังรันอยู่ ผมรู้ว่านี่อาจเป็นปัญหาทักษะหรือ user error แต่ตอนนี้ไม่มีเวลาเหลือไปลงกับมันแล้ว
ต่อให้ยังไม่สมบูรณ์ ถ้าเอาขึ้น GitHub หรือ Hugging Face เอเจนต์ตัวอื่นก็จะได้ต่อยอดจากตรงนั้นแทนที่จะเริ่มจากศูนย์ ผมก็ทำแบบนั้นกับ Ling-2.6-flash (107B-A7B4 MoE) และมันก็เป็น LLM ที่ใหญ่ที่สุดที่ผมพอจะรันใช้งานจริงได้บน M2 Max ซึ่งเป็นฮาร์ดแวร์อีกตัวที่มีไว้ใช้กับ local LLM
ต่อให้ MTP ยังทำงานไม่ดี มันก็ยังดีกว่าสถานะปัจจุบันที่ llama.cpp รัน Ling-2.6-flash ไม่ได้เลย การคุยเรื่องนี้อยู่ที่ https://huggingface.co/inclusionAI/Ling-2.6-flash/discussion... ส่วนควอนไทซ์ 4 บิตอยู่ที่ https://huggingface.co/ljupco/Ling-2.6-flash-GGUF และ branch อยู่ที่ https://github.com/ljubomirj/llama.cpp/tree/LJ-Ling-2.6-flas...
ผมคิดว่า llama.cpp น่าจะรองรับ PC ได้ดีกว่านี้มาก ส่วนหนึ่งอาจเพราะการสนับสนุนจากฝั่งเวนเดอร์ไม่ดี แต่ถึงจะมีผู้ใช้มากขนาดนี้ ก็ยังน่าแปลกที่เราไม่ค่อยเห็น inference ที่ optimize กว่านี้บน PC มาตรฐาน
เจ๋งมาก อยากรู้จริง ๆ ว่าถ้าเอา โมเดลโอเพนซอร์ส ตัวเดียวมาโฟกัส optimize อย่างจริงจังอยู่หลายเดือน ผลจะออกมาเป็นยังไง
ไม่ใช่แค่ inference serving แต่รวมถึงการ optimize harness และ workflow แบบปรับแต่งเฉพาะด้วย อยากเห็นว่ามันจะช่วยลดช่องว่างได้มากแค่ไหน ในเมื่อ frontier model ยังมีความสามารถในการอนุมานและสรุปสิ่งต่าง ๆ ที่โมเดลโอเพนซอร์สมักขาดไปโดยพื้นฐาน เพราะข้อจำกัดด้านขนาดหรือการฝึก
การรัน Kimi 2.6 ให้ได้ความเร็วโทเคน/วินาทีที่โอเคนั้นมีค่าใช้จ่ายเดือนละ 20,000 ดอลลาร์ แต่ถ้าจะขายโทเคนพวกนั้นให้มีกำไร ต้นทุนฮาร์ดแวร์ต่อเดือนต้องต่ำกว่า 1,000 ดอลลาร์
ถ้าคุณกำลังเดิมพันศักยภาพของตัวเองไว้กับอนาคตที่มหาเศรษฐียอมขายโทเคนต่ำกว่าทุน 10 ถึง 20 เท่าอย่างใจบุญ หรือกับภาพฝันว่าโมเดลโอเพนซอร์สที่เก่งพอจะลงบนฮาร์ดแวร์ผู้บริโภคได้ สภาพก็คือจบแล้ว
มีข้อมูลหนึ่งที่ทั้งสนุก น่าสนใจ และบอกอะไรได้เยอะ: MacBook M3 Max ของผมกินไฟขึ้นไปถึง 50W ตอนที่ DS4 สร้างโทเคนด้วยความเร็วสูงสุด
ถ้า DS4 Flash พีคที่ 50W และมี 280B พารามิเตอร์ งั้น DS4 Pro ที่ 1.6T พารามิเตอร์จะอยู่ราว ๆ 300W ไหม? ส่วน GPT 5 กับ Opus รุ่นล่าสุดก็ให้ความรู้สึกว่าน่าจะประมาณ 500W พอใช้ Claude Code แล้วโมเดลมันพร่ำอยู่คนเดียว เราควรนึกภาพว่าที่ไหนสักแห่งในดาต้าเซ็นเตอร์กำลังเผาไฟ 500W อยู่หรือเปล่า?
บน Mac Studio ตอนนี้สั่งออปชันเกิน RAM 96GB ไม่ได้เลย ทั้ง M3 Ultra และ M4 Max ก็เหมือนกัน ไม่แน่ใจว่าเป็นเฉพาะออสเตรเลียหรือเปล่า
แต่ MacBook Pro กลับเลือก 128GB ได้บน M5 Mac
https://www.apple.com/au/shop/buy-mac/mac-studio
Apple อาจเลือกที่จะไม่ตั้งราคาไปเลย ดีกว่าต้องเจอดราม่าขายแพงเกินจริงหรือเสียงบ่นเรื่องของขาด
Apple ถอด Mac Studio ทุกสเปกที่เกิน 96GB และ Mac mini รุ่นพื้นฐานออกไปแล้ว และยังมีข่าวลือว่ากำลังพิจารณาถอด Neo รุ่นพื้นฐานออกจากตลาดด้วย
ดูเหมือนว่าจะจัดการข้อจำกัดด้านกำลังการผลิตของ fab และอุปทาน RAM ด้วยวิธีนี้
ไม่แน่ใจว่าผมพลาด benchmark หรือเป้าหมายเชิงแรงจูงใจแบบง่าย ๆ อะไรไปรึเปล่า
เดาว่ามันน่าจะเร็วกว่า หรือทำให้รันโมเดลที่ใหญ่และฉลาดกว่าได้ เมื่อเทียบกับ toolchain ทั่วไป แต่เหมือนยังไม่ได้เขียนชัด ๆ ว่าจาก baseline นั้น ดีขึ้นมาเท่าไรแล้ว หรือคาดว่าจะดีขึ้นอีกแค่ไหน
ถ้ารู้ค่าที่ใช้เทียบก็คงคำนวณจากตัวเลขที่ให้มาได้อยู่หรอก
น่าประทับใจมาก แต่ก็ดูแปลกที่กับอินพุตใหญ่ ๆ มันเหมือนจะใช้เวลาประมาณ 4 นาที กว่าจะเริ่มตอบ
ผมไม่ได้ใช้ LLM บนฮาร์ดแวร์ Mac แต่ก็รู้สึกว่าน่าตกใจพอสมควร และน่าจะเป็นอุปสรรคใหญ่มากต่อการใช้งานจริง
แต่พออ่านคำอธิบายเรื่องแคชในการใช้งานทั่วไปแล้วก็สมเหตุสมผลขึ้นมาก เพราะ Claude Code มักส่งพรอมป์ต์ตั้งต้นก้อนใหญ่ราว 25k โทเคนก่อนเริ่มทำงานที่มีประโยชน์ และถ้าเปิด
--kv-disk-dirหลังจาก prefill รอบแรกที่แพงไปแล้ว ก็จะ reuse prefix ที่มี disk KV cache เก็บไว้ จึงไม่ต้องประมวลผลพรอมป์ต์ทั้งก้อนใหม่ทุกครั้งแต่บน M3 Ultra ความเร็ว prefill เกือบ 500 โทเคน/วินาที เลยยังอยู่ในระดับที่ใช้งานจริงได้สบาย ส่วน M3 Max ต้องมีความอดทนนิดหน่อยแต่ก็ใช้ได้ดี และถ้าใช้ pi agent มันจะแสดงกระบวนการคิดออกมา คุณเลยอ่าน chain of thought ที่ไม่ถูกเซ็นเซอร์ได้ระหว่างรอแทน
เมื่อวานผมโพสต์วิดีโอการใช้งานบน M3 Max ไว้ใน X มันพ่นโทเคนออกมาได้เร็วใช้ได้เลย
บน MacBook นั้น LLM ขนาดใหญ่มีความเร็วสร้างโทเคนที่พอยอมรับได้ แต่ปัญหาคือ การอ่านคอนเท็กซ์
ปัญหาไม่ได้อยู่ที่การอ่านแบบ incremental ซึ่งใช้ KV cache เหมือนในแชตเซสชัน แต่อยู่ที่การอ่านอินพุตก้อนใหญ่ เช่น เวลาวางไฟล์ใหญ่ ๆ เข้าไป ซึ่งอาจกินเวลาหลายนาที
ซึ่งมีโอกาสห่างไกลพอสมควรจากความฉลาดดั้งเดิมที่ผู้ให้บริการคลาวด์มอบให้
ถึงอย่างนั้นมันก็ยังแสดงศักยภาพของ local LLM ใน workflow แบบเอเจนต์ได้ดีขึ้น
มีสถาปัตยกรรมที่ไม่ต้องพึ่งการป้อนประวัติการสนทนาทั้งหมดกลับเข้าไปใหม่หรือไม่? เช่น LLM แบบ recurrent อะไรทำนองนั้น