- Cấu hình coding agent cục bộ này cho phép chạy mô hình qua API tương thích OpenAI trên macOS ngay cả khi mất Internet, đồng thời để Pi xử lý đầu vào văn bản và hình ảnh
- Thử nghiệm dùng Apple M1 Max 64GB, macOS 15.7.7, với llama.cpp Metal và mô hình Gemma 4 26B-A4B GGUF; tốc độ sinh mặc định đạt 58.2 tok/s
- Sau khi thêm MTP draft model và chỉnh
--spec-draft-n-max 3, tốc độ sinh tăng lên 72.2 tok/s, cải thiện khoảng 24% - Cần nạp
mmproj-BF16.ggufbằng--mmprojvà đặt đầu vào mô hình của Pi thành["text", "image"]thì đầu vào hình ảnh như ảnh chụp màn hình mới được truyền đi - Cấu hình cuối cùng chạy máy chủ llama.cpp tại
127.0.0.1:8080/v1và để Pi dùng nó làm nhà cung cấp cục bộ; Qwen3.6 35B-A3B cho benchmark coding agent tốt hơn nhưng trong thử nghiệm này chậm hơn ở mức 55 tok/s
Mục tiêu của cấu hình coding agent cục bộ
- Một vài lần mất Internet khiến không thể dùng coding agent là động lực để thử cấu hình chạy cục bộ
- Cấu hình mong muốn phải đủ nhanh để dùng thực tế trên Mac và phải dùng được từ các công cụ khác thông qua API tương thích OpenAI
- Mục tiêu còn là có thể xử lý ảnh chụp màn hình hoặc hình ảnh khi cần để đưa lại kết quả do agent tạo ra làm đầu vào
- Cấu hình cuối cùng gồm
llama.cpp, Gemma 4 26B-A4B GGUF, Q8 MTP draft model, Gemma 4 multimodal projector và coding agent terminal Pi - Môi trường thử nghiệm là Apple M1 Max, 64GB bộ nhớ hợp nhất, macOS 15.7.7
Mô hình
- Mô hình chính là
gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf, nằm trong khounsloth-gemma-4-26B-A4B-it-GGUFtrên Hugging Face - Tệp này có dung lượng khoảng 16GB; khi để cùng MTP draft head và multimodal projector thì thư mục mô hình vào khoảng 17GB
- Prompt benchmark là
Write a compact Python function that parses a unified diff and returns the changed file paths. Then explain two edge cases. - Mỗi benchmark sinh khoảng 128 token
Chạy cơ bản: llama.cpp + Metal
- Mô hình chính được chạy trực tiếp bằng
llama.cppvới tăng tốc Metal - Lệnh chạy dùng
llama-clivới đường dẫn mô hình,-ngl 999,-fa on,-c 4096,-n 128 - Ở cấu hình cơ bản, tốc độ xử lý prompt là 298.0 tok/s và tốc độ sinh là 58.2 tok/s
- 58 tok/s không phải quá nhanh nhưng vẫn dùng được; với tác vụ coding agent thì càng cần tốc độ cao vì có nhiều lần gọi công cụ
Thêm MTP draft model
- Gemma 4 cung cấp MTP draft model ở dạng
MTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf - Trong
llama.cpp, mô hình này được nạp cho speculative decoding bằng--model-draft,--spec-type draft-mtp,--spec-draft-n-max - Lần chạy MTP đầu tiên ghi nhận 69.2 tok/s với 4 draft token
- Tài liệu Unsloth khuyến nghị bắt đầu với
--spec-draft-n-max 2, nhưng nên thử từ 1 đến 6 tùy phần cứng để chọn giá trị nhanh nhất - Sau khi tinh chỉnh
--spec-draft-n-max, mức nhanh nhất là 72.2 tok/s với 3 draft token - Mô hình chính chạy đơn lẻ đạt 58.2 tok/s, còn cấu hình thêm Q8 MTP draft model đạt 72.2 tok/s
- Tốc độ xử lý prompt gần như giữ nguyên, còn tốc độ sinh cải thiện khoảng 24%
Kết quả tinh chỉnh MTP
- Đã thử các giá trị
--spec-draft-n-maxtừ 1 đến 6 - Giá trị 1 cho 295.5 tok/s ở prompt và 68.4 tok/s ở sinh
- Giá trị 2 cho 299.1 tok/s ở prompt và 72.0 tok/s ở sinh
- Giá trị 3 cho 295.6 tok/s ở prompt và 72.2 tok/s ở sinh, là nhanh nhất
- Giá trị 4 cho 70.7 tok/s ở sinh, giá trị 5 là 63.7 tok/s, giá trị 6 là 61.2 tok/s nên chậm hơn
- Trên M1 Max,
3là nhanh nhất, còn2cũng cho kết quả rất gần
So sánh với MLX
- Để kiểm tra cách chạy mô hình nhanh hơn trên Mac, tác giả cũng thử các mô hình MLX dựa trên
mlx-lm llama.cpp Metal + MTPđạt 72.2 tok/s với tổ hợp Unsloth GGUF Q4 và Q8 MTPllama.cpp Metalđơn lẻ đạt 58.2 tok/s với Unsloth GGUF Q4MLX-LMđạt 45.8 tok/s với Unsloth UD MLX 4-bitMLX-LMđạt 43.9 tok/s vớimlx-community 4-bit, và 38.1 tok/s vớimlx-community OptiQ 4-bit- Trong cấu hình cụ thể này, llama.cpp nhanh hơn MLX, và llama.cpp có MTP là lựa chọn tốt nhất
- Tác giả cũng thử Gemma 4 MTP với
gemma-4-swift-mlx, nhưng checkpoint MLX 26B 4-bit đã thử không khớp với weight key mà loader mong đợi, nên dừng lại thay vì tải lại và tinh chỉnh mô hình mới
Thêm hỗ trợ hình ảnh
- Nếu muốn đính kèm ảnh chụp màn hình trong Pi thì đầu vào mô hình không thể chỉ là văn bản
- Ban đầu mục mô hình cục bộ được đặt là
"input": ["text"], và trong trường hợp đó Pi không thể gửi đúng đầu ra từ công cụ hình ảnh vào mô hình - Máy chủ
llama.cppcũng cần Gemma 4 multimodal projector làmmproj-BF16.ggufđể có khả năng đa phương thức - Khi nạp projector bằng
--mmproj,llama.cppsẽ công bố hỗ trợ đa phương thức và Pi có thể gửi hình ảnh - Bài test chạy
llama.cpp Metal + MTPmà không có projector cho 120.3 tok/s ở prompt và 71.4 tok/s ở sinh - Lần chạy cuối cùng có nạp
mmproj-BF16.ggufcho 297.4 tok/s ở prompt và 72.2 tok/s ở sinh - Ở lần chạy cuối có projector, không thấy suy giảm tốc độ sinh văn bản
Cài đặt llama.cpp
- Các phụ thuộc được cài bằng Homebrew gồm
cmake,git,tmux,python@3.11 - Tạo đường dẫn
~/Developer/ML-Models/Gemma4/reposrồi clone khoggml-org/llama.cppvàorepos/llama.cpp - Bản build được cấu hình bằng
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_METAL=ON -DGGML_ACCELERATE=ON - Sau đó chạy
cmake --build build --config Release -jđể build bản phát hành - Bản build được thử có các thiết lập
GGML_METAL=ON,GGML_ACCELERATE=ON,GGML_BLAS=ON,GGML_BLAS_VENDOR=Apple
Tải tệp mô hình
- Tạo môi trường ảo Python 3.11 và cài
huggingface_hubcùnghf_xet - Dùng
huggingface-cli downloadđể tải mô hình chính Gemma 4,mmproj-BF16.ggufvà MTP draft model - Các tệp cần tải là
gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf,mmproj-BF16.gguf,MTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf - Thư mục mô hình cuối cùng chứa ba tệp này dưới
models/unsloth-gemma-4-26B-A4B-it-GGUF/
Khởi động máy chủ cục bộ
- Máy chủ cuối cùng chạy bằng
llama-server, với mô hình chính, MTP draft model và multimodal projector đều được chỉ định - Các tùy chọn chính là
--spec-type draft-mtp,--spec-draft-n-max 3,-ngl 999,-fa on,-c 65536,--parallel 1 - Máy chủ chạy với
--host 127.0.0.1 --port 8080 - Endpoint tương thích OpenAI là
http://127.0.0.1:8080/v1 - Wrapper
start_server.shchạy máy chủ trong phiêntmuxvà ghi log vàologs/llama-server-mtp.log - Sau
chmod +x start_server.sh, khởi động máy chủ bằng./start_server.sh - Có thể kiểm tra máy chủ hoạt động bằng
curl http://127.0.0.1:8080/v1/models
Cấu hình Pi
- Pi đọc cấu hình nhà cung cấp mô hình từ
~/.pi/agent/models.json baseUrlcủa nhà cung cấp cục bộgemma4-localtrỏ tớihttp://127.0.0.1:8080/v1apilàopenai-completions, và vì là máy chủ cục bộ nênauthHeaderđược để làfalse- ID mô hình là
gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf, còn tên được đặt làGemma 4 26B-A4B Q4 + MTP inputphải là["text", "image"], nếu không Pi sẽ coi mô hình là chỉ hỗ trợ văn bản- Cửa sổ ngữ cảnh được đặt là 65536, số token tối đa là 8192
- Nếu cần, trong
~/.pi/agent/settings.jsoncó thể đặtdefaultProviderlàgemma4-localvàdefaultModellà tên tệp GGUF tương ứng - Khi chạy
pi --offline --list-models gemma, kết quả mong đợi là hỗ trợ hình ảnh hiển thịyes - Chạy mô hình cục bộ bằng
pi --provider gemma4-local --model gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf - Chạy không tương tác dùng dạng
pi -p --provider gemma4-local --model gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf "Explain what this repository does" - Đầu vào ảnh chụp màn hình dùng dạng
pi -p @"/path/to/screenshot.png" "Describe this image and point out anything relevant to the UI"
Cấu hình cuối cùng
- Runtime suy luận cuối cùng là
llama.cpp - Tăng tốc trên macOS là tổ hợp Metal + Accelerate
- Mô hình chính là
gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf - Draft model là
gemma-4-26B-A4B-it-Q8_0-MTP.gguf - Thiết lập MTP là
--spec-draft-n-max 3 - Multimodal projector là
mmproj-BF16.gguf - Máy chủ là
llama-servertại127.0.0.1:8080 - API là
/v1tương thích OpenAI - Coding agent là Pi, và đầu vào mô hình của Pi là
["text", "image"] - Trong môi trường này, MTP draft model đã nâng tốc độ sinh của Gemma 4 từ 58.2 tok/s lên 72.2 tok/s, đồng thời cấu hình vẫn đủ đơn giản để chạy như một máy chủ cục bộ tương thích OpenAI
Phương án thay thế Qwen3.6 35B-A3B
- Một số người đề xuất dùng
Qwen3.6 35B-A3Bthay choGemma 4 26B-A4B - Theo các benchmark có thể kiểm chứng, Qwen được đánh giá là coding agent tốt hơn đáng kể so với Gemma 4
- Tuy nhiên cấu hình Qwen chậm hơn; với tổ hợp
Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf,unsloth-Qwen3.6-35B-A3B-MTP-GGUF,mmproj-BF16.ggufthì đạt 55 tok/s - 55 tok/s thay vì 72 tok/s tạo ra khác biệt đáng kể khi người dùng phải chờ
- Cách tải mô hình Qwen là lấy
Qwen3.6-35B-A3B-UD-Q4_K_XL.ggufvàmmproj-BF16.gguftừunsloth/Qwen3.6-35B-A3B-MTP-GGUF - Máy chủ Qwen dùng cùng
llama-servernhưng chạy với--port 8081 - Tên nhà cung cấp Qwen trong cấu hình Pi là
qwen36-local,baseUrllàhttp://127.0.0.1:8081/v1 - Cấu hình mô hình Qwen dùng
reasoning: true,input: ["text", "image"],contextWindow: 65536,maxTokens: 8192
1 bình luận
Ý kiến trên Hacker News
Prompt benchmark là “viết một hàm Python ngắn gọn để phân tích unified diff và trả về đường dẫn tệp đã thay đổi, đồng thời giải thích hai edge case”, và nếu mỗi benchmark chỉ sinh khoảng 128 token thì có vẻ 128 token là quá ít để cho ra kết quả tốt
Tăng tốc MTP phụ thuộc vào việc các token dự đoán được chấp nhận thường xuyên đến đâu; theo kinh nghiệm thì ở phần đầu của đầu ra tỷ lệ chấp nhận cao hơn, nên các bài test ngắn có thể tạo ra tăng tốc dương tính giả
llama.cpp có một công cụ benchmark chuyên dụng quét qua các đối số mà không cần khởi động lại server và gửi prompt: https://github.com/ggml-org/llama.cpp/blob/master/tools/llam...
Phần tải mô hình cũng lẽ ra nên nhắc rằng tham số
-hfcủa llama.cpp có thể tự tải mô hình thay. Cảm ơn tác giả đã chia sẻ trải nghiệm, nhưng với người mới thì đây có thể không phải hướng dẫn tốt nhấtSau khi thấy công bố “nhanh gấp 2 lần” của Unclothe, tôi tự hỏi “liệu mức này đã đủ nhanh để dùng thực tế chưa?” nên đã tự thiết lập thử
Năm ngoái tôi cũng từng test với kiểu như Devstral, nhưng nó quá chậm và ngớ ngẩn nên tôi không muốn tiếp tục dùng; còn lần này thì cuối cùng tôi đã cảm thấy nó đủ dùng cả về tốc độ lẫn độ thông minh
llama.cpp có công cụ cho việc này, và để đo đúng thì cần thêm prefill trước khi sinh token. Việc đo tốc độ sinh token ở ngữ cảnh dài như 32k hay 64k cũng đang ngày càng quan trọng hơn
Trước đây tôi cũng từng viết một bài tương tự dùng ollama và opencode: https://blog.kulman.sk/running-local-llm-coding-server/
opencode có phải đang ngốn quá nhiều ngữ cảnh cho system prompt không? Mô hình cục bộ vốn bị giới hạn ngữ cảnh, và nếu nhớ không nhầm thì opencode dùng khoảng 10k hoặc gần mức đó
Nếu chỉ dùng llama.cpp thì có vẻ không nhất thiết phải cần
huggingface-cliđể tải thứ gì đó. Chỉ cần truyền-hf ...là nó sẽ tải mô hìnhNếu muốn đổi vị trí tải xuống thì đặt
LLAMA_CACHE:LLAMA_CACHE="models" ./llama-server \-hf unsloth/gemma-4-31B-it-GGUF:UD-Q4_K_XL \...-hfdNếu RAM bộ nhớ hợp nhất lớn nhưng teraflops và băng thông GB/s chỉ ở mức trung bình trở xuống, thì thường MoE là lựa chọn có hy vọng nhất. Trên môi trường của tôi là M2 Max 96GB, hạng nhất hiện tại theo tiêu chí
(trí tuệ, tok/s, độ sâu ngữ cảnh)là DeepSeek-V4-Flash REAP25<65gb gguf+ ds4-server + pi agentDĩ nhiên nó không tốt hơn API đám mây, nhưng nếu cần thì vẫn đủ để chấp nhận dùng. Ngay cả trên chuyến bay 4 tiếng không có Internet, LLM cục bộ ngốn 60W mà pin vẫn trụ đủ
Nhánh ds4 hỗ trợ REAP ở đây: https://github.com/ljubomirj/ds4/tree/reap-compact-support
Việc DS4F chỉ rơi xuống mức không dùng được dưới 10 tok/s ở ngữ cảnh 784K tạo ra khác biệt rất lớn
Tôi tự hỏi liệu những mô hình cục bộ kiểu này có thật sự giải quyết được vấn đề cho cả những người không phải chuyên gia ở một ngôn ngữ lập trình cụ thể hay không
Ngoài tự động hoàn thành nội dòng hay triển khai từng đơn vị, tôi chưa chắc nó có thể thiết kế và ghép nối các đặc tả kỹ thuật thực sự hoạt động được
Dùng llama.cpp/server để chạy LLM cục bộ rồi kết hợp với Claude Code hay Codex-CLI là tương đối đơn giản
Cài đặt llama server cần thiết thường bị rải rác khắp nơi, nên tôi đang duy trì hướng dẫn cho một vài open LLM phổ biến ở đây: https://pchalasani.github.io/claude-code-tools/integrations/...
Tôi đã khá thành công khi dùng omlx.ai để tải nhiều mô hình MLX phù hợp với phần cứng của mình, rồi tự động chạy open-source và harness đóng (Claude Code, Codex) bằng các mô hình đó
Làm được cả trên UI web lẫn desktop, nên cá nhân tôi thấy dùng omlx thì không cần phải làm theo bài blog đó
Các bản dựng Gemma 4 MLX mà tôi tìm được cho đến nay chậm hơn ở cùng mức lượng tử hóa, và với MTP thì chậm hơn rất nhiều
Sau khi chọn mô hình xong, web UI tích hợp của llama.cpp khá ổn, còn nếu muốn nghịch thử nhiều thứ thì LM Studio cũng tốt
Gemma-4 và Qwen 3.6 hoàn toàn không cần cả một khối lớn system prompt kiểu opencode thông thường, và bỏ đi còn tốt hơn
DeepSeek v4 Flash chạy bằng ds4 của antirez khá ấn tượng
Xét về “kiến thức được lưu sẵn” thì nó cho cảm giác như mô hình cỡ GPT-4, nhưng ở các luồng gọi công cụ dài thì còn làm tốt hơn các mô hình cỡ GPT-4
Trên MBP M4 Max 128GB, tốc độ sinh khoảng 24 t/s và prefill khoảng 200 t/s. Tôi tưởng nó sẽ chậm, và với các việc như sinh mã thì đúng là chậm, nhưng như một bộ điều phối máy móc cho các tác vụ đơn giản thì lại hữu ích đến ngạc nhiên
Với các mục đích không mang tính agent, đây là mô hình đủ ổn để trò chuyện, và còn có lợi thế là hoàn toàn tự chạy và riêng tư
[0]https://github.com/antirez/ds4
Nếu muốn làm theo kiểu cực lười thì chỉ cần mở Claude Code trong terminal, trỏ nó vào bài này rồi bảo “làm đi”
Còn Claude thì xử lý xong trong một lần hoặc chỉ cần chỉnh rất ít là được
Cánh cổng dẫn đến tri thức và thực thi giờ là LLM, còn Google Search thì có cảm giác như khủng long
Nó thậm chí còn ấn tượng hơn cả smartphone, như thể đang sống trước thời đại cả một thế kỷ vậy