1 điểm bởi GN⁺ 2025-05-18 | 1 bình luận | Chia sẻ qua WhatsApp
  • KVSplit là một dự án mã nguồn mở giúp chạy LLM cỡ lớn và cửa sổ ngữ cảnh dài trên Apple Silicon
  • Thông qua phân bổ độ chính xác tách biệt cho key và value, dự án đạt giảm bộ nhớ tối đa 72% với mức suy giảm chất lượng dưới 1%
  • Được tối ưu cho chip M1/M2/M3 và framework Metal
  • Cải thiện tốc độ chạy và tiết kiệm bộ nhớ đã được chứng minh bằng benchmark đo đạc thực tế và công cụ trực quan hóa
  • Cung cấp cài đặt dễ dàng, so sánh bằng một lệnh và nhiều công cụ benchmark và phân tích

Giới thiệu: Vì sao KVSplit quan trọng

KVSplit là một công cụ mã nguồn mở cho phép chạy LLM dung lượng lớn và cửa sổ ngữ cảnh dài hơn nhiều trên môi trường Apple Silicon (M1/M2/M3) bằng cách áp dụng lượng tử hóa với độ chính xác khác nhau cho key và value bên trong KV cache. Dự án vượt qua hạn chế của các dự án trước đây vốn lượng tử hóa key và value theo cùng một cách, đồng thời giảm mạnh mức sử dụng bộ nhớ nhưng vẫn giữ mức suy giảm chất lượng gần như khó nhận thấy. Benchmark thực tế, tốc độ và các chỉ số chất lượng đều được công khai, nên có độ tin cậy cao, đồng thời hỗ trợ Metal và các công cụ so sánh, trực quan hóa trực quan giúp nâng cao hiệu suất phát triển.

Những ưu điểm chính so với các dự án cùng loại gồm:

  • Tách độ chính xác key-value để quản lý bộ nhớ hiệu quả hơn
  • Chuyên biệt cho Apple Silicon và hỗ trợ tối ưu hóa đầy đủ cho framework Metal
  • Tích hợp benchmark, perplexity, đo lường/trực quan hóa bộ nhớ, tốc độ và chất lượng
  • Cài đặt bằng một lệnh, tương thích mô hình, tích hợp llama.cpp
  • Trực quan hóa tiết kiệm bộ nhớ theo thời gian thực và nhiều công cụ kiểm thử so sánh

Tính năng chính và nội dung cốt lõi

Tổng quan

  • Với KVSplit, có thể chạy LLM lớn hơn nhiềuđộ dài ngữ cảnh dài hơn trên Apple Silicon so với trước đây
  • Gán độ chính xác lượng tử hóa khác nhau cho từng key và value để vừa tiết kiệm bộ nhớ vừa cải thiện tốc độ
  • Xác nhận được tiết kiệm bộ nhớ tối đa 72%cải thiện tốc độ (5-15%↑), với mức suy giảm chất lượng dưới 1%
  • Hỗ trợ Metal đầy đủ, đạt hiệu quả tăng tốc tối ưu trên Apple Silicon

Kết quả benchmark chính

  • Với cấu hình K8V4 (key 8-bit, value 4-bit)
    • Tiết kiệm 59% bộ nhớsuy giảm chất lượng 0,86% (theo perplexity)
    • Nhanh hơn 5,7% so với FP16
  • Với cấu hình K4V4 (cả key/value đều 4-bit)
    • Tiết kiệm bộ nhớ tối đa 72%
    • Chất lượng giảm khoảng 6%. Phù hợp cho các trường hợp ít nhạy cảm với chất lượng

So sánh hiệu quả tiết kiệm bộ nhớ

  • Theo mốc FP16, 176MB (8K token)
    • K8V8 (key/value 8-bit) : 93.5MB (47%)
    • K8V4 (key 8-bit, value 4-bit) : 71.5MB (41%)
    • K4V4 (key/value 4-bit) : 49.5MB (28%)

Tính năng chính

  • Lượng tử hóa riêng cho key và value của KV cache
  • Tối ưu hóa hoàn toàn cho Apple Silicon và Metal
  • Script phân tích benchmark/chất lượng (perplexity)/mức dùng bộ nhớ
  • Công cụ trực quan hóa và tạo biểu đồ chất lượng xuất bản
  • Thiết lập bằng một lệnh và so sánh theo thời gian thực

Cấu trúc thư mục dự án

  • llama.cpp: bao gồm bản build tối ưu cho Metal
  • models: lưu file mô hình
  • scripts: gồm script benchmark/cài đặt/so sánh/trực quan hóa
  • results, plots: lưu kết quả benchmark và file trực quan hóa
  • README.md

Insight khoa học và kết quả thực nghiệm

Hiện tượng cốt lõi của KV cache

  • Vector keyđộ nhạy với lượng tử hóa cao hơn nhiều so với vector value → cần cấp độ chính xác cao hơn cho key để duy trì chất lượng
  • K8V4 là điểm ngọt: phân bổ key 8-bit/value 4-bit là điểm cân bằng tối ưu giữa chất lượng và bộ nhớ
    • Tiết kiệm 59% bộ nhớ, perplexity chỉ xấu đi 0,86%, và tốc độ còn nhanh hơn FP16
  • K4V8 dù có cùng tổng số bit với K8V4 nhưng gây ra mức suy giảm chất lượng lớn hơn hơn 7 lần → chứng minh tầm quan trọng của độ chính xác phía key

Hàm ý tổng hợp

  • Đạt được cả hiệu quả bộ nhớ lẫn bảo toàn chất lượng mô hình → cho phép vận hành mô hình lớn hơn và ngữ cảnh dài hơn nhiều trên phần cứng tiêu dùng

Ví dụ sử dụng và khuyến nghị cấu hình

Ví dụ chạy với nhiều mức độ chính xác lượng tử hóa khác nhau

  • Mặc định (FP16): ./llama.cpp/build/bin/llama-cli -m models/your-model.gguf -p "prompt" -t 8 --flash-attn
  • Khuyến nghị K8V4: --kvq 8
  • K4V8 (DEMO): --kvq-key 4 --kvq-val 8
  • K4V4 (tiết kiệm tối đa): --kvq 4

Ví dụ ngữ cảnh dài

  • Ngữ cảnh 32K: FP16 cần khoảng ~1.4GB, nhưng K8V4 có thể chạy với ~400MB

Giải thích cờ dòng lệnh

  • -t 8: số luồng, khuyến nghị 8 cho M1/M2/M3
  • --flash-attn: tối ưu cho Apple Silicon
  • --kvq N: đặt cả key/value ở N-bit
  • --kvq-key, --kvq-val: hỗ trợ thiết lập riêng
  • -c N: số token ngữ cảnh (càng dài thì hiệu quả của KVSplit càng lớn)
  • -n N: số token sinh ra
  • -f FILE: file tài liệu đầu vào
  • -m MODEL: đường dẫn mô hình

Benchmark nâng cao và trực quan hóa

  • Dùng benchmark_kvsplit.py để đo đặc tính theo từng cấu hình, độ dài chuỗi, bộ nhớ/tốc độ/perplexity/khả năng mở rộng
  • Dùng visualize_results.py để tạo biểu đồ chất lượng ở mức bài báo
  • Kết quả được tự động lưu dưới dạng CSV/JSON và có kèm phần tóm tắt

Tối ưu hóa cho Apple Silicon và trực quan hóa bộ nhớ

  • Tận dụng đầy đủ framework Metal
  • Đặc biệt hiệu quả với các máy M1/M2/M3 có áp lực bộ nhớ cao
  • Có thể trực quan hóa mức tiết kiệm bộ nhớ theo thời gian thực bằng capture_memory.sh
  • Do căn chỉnh trang tùy biến, dung lượng tiết kiệm thực tế có thể chênh nhẹ so với giá trị lý thuyết

Tóm tắt tính năng

  • Độ chính xác bit độc lập cho key/value và lượng tử hóa tùy biến
  • Tối ưu hóa hoàn toàn cho Apple Silicon và Metal
  • Cung cấp benchmark tổng hợp về bộ nhớ/tốc độ/chất lượng
  • Hỗ trợ trực quan hóa chất lượng mức bài báo và so sánh thời gian thực, cùng khả năng capture bộ nhớ
  • Giao diện cài đặt/sử dụng cực kỳ đơn giản

Trích dẫn và nghiên cứu tham khảo

  • "More for Keys, Less for Values: Adaptive KV Cache Quantization" (2024)
  • "Unifying KV Cache Compression for Large Language Models with LeanKV" (2025)
  • Triển khai nền tảng: [llama.cpp], mô hình thử nghiệm: [TinyLlama]

Khuyến nghị cấu hình và kế hoạch tương lai

  • K8V4 (key 8-bit/value 4-bit): mức cân bằng tối ưu với suy giảm chất lượng 0,86%, giảm 59% bộ nhớ, tốc độ +5,7%
  • K4V4: tiết kiệm bộ nhớ tối đa (72%), chất lượng giảm khoảng 6%. Phù hợp khi ưu tiên bộ nhớ lên hàng đầu
  • Đặc biệt mạnh trong chạy ngữ cảnh dài, có thể vận hành ngữ cảnh dài hơn 2-3 lần

Lộ trình sắp tới

  • Độ chính xác thích ứng dựa trên tầm quan trọng của token
  • Lượng tử hóa riêng theo từng layer
  • Tối ưu hóa tùy biến theo từng mô hình (Mistral, Phi-3, v.v.)
  • Dự kiến hỗ trợ web demo và di động (iOS/iPadOS)

Giấy phép và hướng dẫn đóng góp

  • Giấy phép MIT
  • Bất kỳ nhà phát triển/nhà nghiên cứu AI nào cũng có thể đóng góp qua Issue và PR

1 bình luận

 
GN⁺ 2025-05-18
Ý kiến trên Hacker News
  • Bày tỏ sự quan tâm vì thấy thú vị, hỏi trực giác vì sao hiện tượng này xuất hiện và quá trình đi đến phát hiện đó, đề xuất cải thiện tính thân thiện với người dùng như việc bước áp dụng patch trong script cài đặt còn dang dở và nên dùng git submodule, đồng thời gợi ý cần tách llama.cpp khỏi các phụ thuộc Python để phù hợp với nhiều môi trường Python khác nhau

    • Phản hồi rằng đây là câu hỏi hay, giải thích khác biệt chính liên quan đến vai trò cốt lõi của attention: key quyết định sẽ chú ý đến token nào để tạo ra mẫu attention, còn value chỉ truyền tải thông tin đã cho; nhấn mạnh rằng nếu lượng tử hóa vector key quá mạnh thì độ méo trong mọi tương tác token sẽ tăng lớn, trong khi lỗi ở vector value chỉ ảnh hưởng đến thông tin của chính token đó; ví von rằng nếu số kệ sách trong thư viện (key) bị sai thì sẽ tìm nhầm hẳn một cuốn sách khác; về mặt toán học, key đi vào softmax nên lỗi nhỏ cũng có thể bị khuếch đại mạnh, còn value là trung bình tuyến tính nên lỗi có thể được triệt tiêu; cũng chia sẻ rằng bản thân đã biết đến tính bất đối xứng này từ bài báo và muốn kiểm chứng định lượng tác động trên Apple Silicon; hứa sẽ cải thiện phản hồi về cài đặt và phụ thuộc Python
    • Chỉ ra rằng patch thực tế không được áp dụng vào llama.cpp, mã phân tích tham số đã chuyển sang arg.cpp nên patch đó vô nghĩa, đồng thời giải thích rằng tùy chọn lượng tử hóa K/V đã được thêm vào llama.cpp từ năm 2023; đặt câu hỏi về ý nghĩa tồn tại của patch, cho rằng có vẻ chỉ đơn giản là thay đổi đối số dòng lệnh, và khuyến cáo mạnh mẽ không nên chạy install.sh từ một kho lưu trữ mới chỉ để áp dụng một file patch đơn giản như vậy
  • Hỏi liệu patch này có thể áp dụng được trong MLX hay không, vì MLX cho tốc độ tốt hơn và kỳ vọng cách tiếp cận này sẽ giúp người dùng Mac hỗ trợ hội thoại dài với tốc độ thực tế hơn

    • Có lẽ là có thể, nhưng hiện đang tự mình đào sâu vào MLX; cảm nhận rằng framework được thiết kế tốt, nhưng code ví dụ và thông tin benchmark còn thiếu nên vẫn hơi non; ngược lại, ấn tượng cá nhân là mong chờ nhất ở binding Haskell, vì đặc tính lazy evaluation có thể phù hợp và cấu trúc đồ thị biên dịch thuần hàm cũng có thể ăn khớp tốt; hy vọng ML trong Haskell sẽ rất thú vị
  • Hỏi liệu có khác biệt thực chất nào so với các tùy chọn --cache-type-k, --cache-type-v hay không

    • Ý kiến gay gắt rằng đây có vẻ chỉ là nỗ lực kiếm GitHub star cho LLM, và thực tế không khác gì tính năng đã có sẵn
    • Nhớ rằng MLX/MPS không có hỗ trợ 4-bit, hoặc ngay cả 8-bit trước đây cũng còn thiếu, hỗ trợ bf16 cũng chỉ mới được thêm gần đây; trước kia trên GPU của Apple, với cách type_k/v thì thấp nhất cũng chỉ đến 16-bit (f16/bf16), nên dù không rõ nội bộ llama.cpp, có thể đây là một cách tiếp cận hơi khác
    • Đồng tình ngắn gọn rằng bản thân cũng tò mò về điểm khác biệt đó
  • Sau khi đọc code thì kết luận patch là không cần thiết, xác nhận qua liên kết PR rằng chức năng này đã được đưa vào llama.cpp từ năm 2023; cảnh báo cần dè chừng việc hướng dẫn chạy install.sh theo kiểu áp dụng patch thay vì chỉ dùng kho fork; chỉ ra cấu trúc kho lưu trữ rối rắm với nhiều file patch, mã trùng lặp và cả việc ghi đè file patch; thực tế chỉ thêm tùy chọn --kvq, trong khi các tùy chọn lượng tử hóa K/V riêng đã tồn tại; nghi ngờ rằng tác giả không thể nào không biết các chức năng sẵn có này; không khuyến nghị chạy script từ những kho lưu trữ cung cấp script phức tạp như vậy; chỉ trích rằng bài đăng HN và số GitHub star cao nhưng nội dung dễ gây hiểu lầm, và cũng lo ngại việc tác giả liên tục né tránh câu hỏi; bổ sung rằng kho lưu trữ và script đều bị trộn lẫn với codebase llama.cpp cũ, không khớp với cấu trúc hiện tại nên càng gây rối

    • Nói rằng bản thân cũng thấy nhiều điểm đáng nghi, nhưng vẫn chờ lời giải thích của tác giả phòng trường hợp mình đã bỏ sót điều gì; tuy nhiên có nhiều dấu hiệu cảnh báo, và nhìn vào lịch sử hoạt động GitHub thì nghi ngờ có ý đồ spam các dự án Popular bằng code do LLM tạo ra
    • Ý kiến rằng cuối cùng cũng có người nói điều hợp lý; chỉ riêng việc không fork dự án gốc mà lại làm theo kiểu áp dụng patch đã là một rủi ro về độ tin cậy; sự hiện diện GitHub của tác giả cũng đáng ngờ, có xu hướng gửi hàng loạt PR còn sót dấu vết LLM vào các dự án nổi tiếng để ngụy trang mình là người đóng góp; bày tỏ lo ngại về ô nhiễm thông tin, hay giai đoạn đầu của sự sụp đổ niềm tin do AI gây ra
  • Hỏi liệu có thể áp dụng lượng tử hóa KV phân biệt (K8V4 v.v.) cho cả các mô hình định dạng .gguf đã được chuyển đổi sẵn hay không, và có bị giới hạn bởi loại mô hình hoặc cấu hình tokenizer hay không

    • Ưu điểm chính của KVSplit là có thể dùng trực tiếp với các mô hình .gguf hiện có mà không cần chuyển đổi đặc biệt; lượng tử hóa chỉ được áp dụng cho KV cache tại thời điểm chạy nên không liên quan đến trọng số mô hình; chỉ cần dùng cờ --kvq-key--kvq-val để chỉ định định dạng lưu trữ trong bộ nhớ; tác giả đã thử thành công trên nhiều mô hình như LLama-3, Mistral, Phi-2/Phi-3, TinyLlama, Qwen; tuy nhiên hiện chỉ dành cho backend Metal của llama.cpp, và vì Flash Attention hiện bỏ qua định dạng KV cache tùy chỉnh nên cần tùy chọn -fa 0; ngoài ra, nếu là kiến trúc transformer dùng attention thì đều có thể áp dụng
  • Hỏi liệu patch này có nhanh hơn hoặc tốt hơn trên các máy Apple Silicon RAM lớn như 64GB, 128GB hay không; đề cập tin đồn rằng mở rộng context window trên Apple Silicon thực tế khá chậm, và băn khoăn liệu nó có ý nghĩa thực chất trên máy bộ nhớ lớn hay không

    • Hiệu quả tiết kiệm bộ nhớ của KVSplit tỷ lệ thuận với độ dài context, nên Mac có RAM lớn càng có lợi ích tuyệt đối lớn hơn; trên Mac Studio 128GB, có thể xử lý context hàng trăm nghìn token; tuy nhiên nó không làm tăng tốc độ tính toán về bản chất mà chỉ cải thiện hiệu quả bộ nhớ; benchmark cho thấy cấu hình K8V4 quan sát được mức tăng throughput 14.5%, nhưng đó là do hiệu quả truy cập bộ nhớ; vấn đề “tốc độ chậm” ở mô hình lớn chủ yếu do giới hạn năng lực tính toán nên không liên quan đến RAM hay việc có tối ưu KV cache hay không; nghĩa là KVSplit hữu ích khi đang chạm trần bộ nhớ, và trong thực tế sẽ lý tưởng hơn khi cấp context lớn hơn cho các mô hình nhỏ như 7B~13B; nếu vừa cần mô hình lớn vừa cần cửa sổ cực dài thì GPU cấp máy chủ vẫn phù hợp hơn, nhưng điểm có ý nghĩa là nó mở rộng giới hạn những gì phần cứng Apple có thể làm được
  • Bày tỏ sự quan tâm và muốn có lời giải thích ở góc nhìn cao hơn một chút: có thể dùng nó để mở rộng mô hình 2048 token lên 4~6k hay không, hoặc dùng mô hình context 128k thành cửa sổ 256k+ hay không, và hỏi các trường hợp sử dụng lý tưởng của mô hình cục bộ là gì

    • Với cấu hình K8V4 có thể tiết kiệm 59% bộ nhớ, nên độ dài context tối đa tăng đến 2.4 lần; tức là mô hình 2048 token có thể lên khoảng 5000 token, mô hình 8K có thể lên khoảng 19.5K; thực tế có thể dùng để xử lý cả một cuốn sách trên MacBook trong một lần, phân tích codebase lớn, hoặc duy trì lịch sử hội thoại dài trong ứng dụng tương tác; hiệu quả tiết kiệm bộ nhớ tăng tuyến tính theo độ dài context; theo kinh nghiệm cá nhân, ở context 8K thì KV cache giảm từ 176MB xuống 72MB, còn ở 128k thì phần tiết kiệm lên đến hàng GB; đây là giải pháp hiệu quả nhất khi bị OOM do giới hạn độ dài đầu vào
    • Vì nó giảm tài nguyên cho một mô hình cụ thể nên có thể ứng dụng linh hoạt tùy mục đích; tuy nhiên việc tự mở rộng context window không hề dễ với người không chuyên, nên tốt hơn là dùng mô hình đã được huấn luyện cho cửa sổ lớn hơn; mô hình cục bộ có thể được dùng đa dạng cho mục đích offline/bảo mật/thử nghiệm, còn phần lớn là phục vụ thí nghiệm tinh chỉnh mô hình
  • Khen đây là một ý tưởng và thử nghiệm rất hay, rồi hỏi thêm liệu có thể áp dụng cho GPU hay không và có thể kết hợp với các kỹ thuật lượng tử hóa khác hay không

    • Cách này có lẽ áp dụng y hệt được cho GPU NVIDIA/AMD, vì nguyên lý key cần độ chính xác cao hơn value là độc lập với phần cứng; backend CUDA của llama.cpp hiện cũng đã hỗ trợ cấu hình tách riêng bằng --cache-type-k, --cache-type-v; patch hiện tại được tối ưu riêng cho Metal nhưng nguyên lý có thể port nguyên vẹn; cũng có thể dùng song song với các kỹ thuật lượng tử hóa khác, và vì lượng tử hóa KV cache chỉ áp dụng lúc chạy nên không xung đột với lượng tử hóa trọng số; đó là một bước tách biệt trong pipeline chuyển đổi; tuy nhiên với các engine dùng cấu trúc cache khác như vLLM, TensorRT-LLM thì cần triển khai riêng; trên GPU, hiệu quả lớn nhất sẽ đến khi tích hợp trực tiếp vào kiến trúc FlashAttention, nơi tiết kiệm bộ nhớ có thể chuyển hóa thành tăng tốc độ
  • Nói rằng có những chỗ thực sự không hiểu và cảm thấy có gì đó lạ, khuyên tránh chạy script đó, đồng thời cho biết đã báo cáo

  • Hỏi hiệu năng thay đổi ra sao; dù đưa được context dài hơn vào bộ nhớ thì tốc độ tính toán cuối cùng có lẽ vẫn như nhau phải không

    • Cảm nhận thực tế là với cùng mô hình, cùng prompt, khi thay loại cache giữa fp16, q8, q4 thì tốc độ mỗi vòng lặp gần như tương đương; dù chưa kiểm tra hoạt động nội bộ, đã kỳ vọng vector sẽ được đóng gói để xử lý SIMD hàng loạt ở 4~8 bit, nhưng ấn tượng thực tế là dường như không có đóng gói như vậy