Thẻ tiêu đề hero cho Laya trên Apple Silicon với nội dung 'Bản chuyển MLX: 13,42 ms, không có token đầu ra', cùng dòng chân trang 'Số đo của tác giả bản chuyển trên M3 Max đã nêu rõ; không tính thời gian tải model.' và logo OrcaRouter ở góc dưới bên phải.
Guides & Insights

Laya trên Apple Silicon: Bản chuyển MLX mang lại cho bạn những gì, và những gì nó không mang lại

Tác giả

Alistair Wren

Ngày đăng

Mô hình mới nhất · 20Xem tất cả mô hình
Benchmark: Artificial Analysis · cập nhật hằng ngày
Quay lại tất cả bài viết

Laya là một mô hình ra quyết định, thứ không bao giờ viết ra một câu nào. Convai Innovations đã đưa trọng số của nó lên Hugging Face vào ngày 18 tháng 9 năm 2026, và ngay hôm sau, một lập trình viên tên là mizorewww đã công bố Laya-MLX — một bản chuyển độc lập chạy cả ba checkpoint của Laya một cách native trên Apple Silicon thông qua MLX, không cần PyTorch, không cần runtime Transformers và không cần gọi lên đám mây. Bản chuyển này báo cáo trung vị 13,42 ms cho một câu hỏi tiếng Anh ngắn trên checkpoint 421M, 7,39 ms trên bản đa ngôn ngữ 322M, và không có token đầu ra nào, trên một chiếc M3 Max. Trong khi đó Kev, gia đình mở còn lại đang theo đuổi cùng ý tưởng về quyết định có kiểu, được xây dựng trên Qwen3.5-4B-Base và cần hẳn một backend thứ hai trước khi có thể dùng được trên máy Mac, bởi vì PyTorch không có kernel nào cho các tầng DeltaNet của nó trên GPU của Apple. Hai dự án, cùng một tuần, cùng một mục tiêu, và chỉ một trong số chúng được chuyển sang một cách gọn gàng. Sự khác biệt đó chính là câu chuyện, và đó là câu chuyện về runtime chứ không phải câu chuyện về mô hình.

Lý do điều này đáng để viết thành một bài hôm nay không phải vì Laya mới. Mà là vì cho đến ngày 2026-09-19, không có cách nào chạy một mô hình quyết định có kiểu trên Mac mà không phải kéo theo cả một ngăn xếp PyTorch, và câu hỏi mà người đọc thực sự có — liệu tôi có thể chạy thứ này trên laptop của mình không, và tôi phải đánh đổi điều gì — cuối cùng đã có một câu trả lời đo lường được. Vậy nên bài viết này nói về đường phục vụ, những con số đằng sau nó, và những chỗ mà các con số không còn mang ý nghĩa như vẻ ngoài của chúng.

Đầu tiên, Laya không phải là gì

Laya không phải là một LLM. Nó không tự hồi quy: chỉ một lượt truyền xuôi hai chiều qua trạng thái cộng với các câu hỏi của bạn, và đầu ra là những câu trả lời có kiểu. Không có giải mã từng token, không có chuỗi suy luận, không có JSON được sinh ra để phân tích cú pháp, và không có token đầu ra để tính phí. Ba dạng trả lời nguyên thủy là choice (chọn một trong N tùy chọn được đặt tên), score (một mức thang đánh giá thứ bậc) và noul (một xác suất đã hiệu chỉnh rằng điều gì đó là đúng).

Điều đó quan trọng với cách bạn đọc mọi con số trong bài viết này. Khi bản port báo cáo 13.42 ms, nó không báo cáo 13.42 ms để tạo ra vài trăm token theo kiểu một benchmark sinh văn bản sẽ làm. Nó đang báo cáo toàn bộ thao tác. So sánh độ trễ của một mô hình ra quyết định với số token mỗi giây của một LLM là so sánh hai công việc khác nhau, và bất kỳ bài viết nào làm điều đó — kể cả bài đăng lan truyền "nhanh hơn Jev 50 lần" đã lưu hành sau khi ra mắt — đều đang đưa ra một tuyên bố mà công việc nền tảng không hề hỗ trợ.

Screenshot of the Hugging Face model page for convaiinnovations/laya, showing the Apache 2.0 licence, the tags Text Classification, Transformers, Safetensors, system-one and calibrated-decisions, a model size of 0.4B params, the description of Laya as a multilingual, non-autoregressive System 1 decision model that never generates text, and the start of the checkpoint table listing convaiinnovations/laya on a ModernBERT-large backbone at 421M parameters with 512-token context.

Những gì cảng thực sự đo được

Những số liệu này là của chính tác giả bản port, được lấy trên một cỗ máy đã được nêu rõ, và chúng nên được đọc cùng với cỗ máy và phương pháp đi kèm. Laya-MLX đã đo chúng trên một chiếc M3 Max với 40 lõi GPU và 128 GiB bộ nhớ hợp nhất, ở FP16, không tính việc nạp mô hình.

• Một câu hỏi ngắn, P50 — 13.42 ms trên checkpoint tiếng Anh 421M, 7.39 ms trên checkpoint đa ngôn ngữ 322M.

• Một câu hỏi ngắn, P95 — lần lượt là 13.92 ms và 7.79 ms.

• Thông lượng 50 câu hỏi — 146,8 câu hỏi mỗi giây và 395,0 câu hỏi mỗi giây.

• Phân bổ MLX đỉnh — 943,6 MiB và 687,6 MiB.

Ranh giới đo thời gian là phần đáng đọc lại hai lần. Nó bao gồm chuẩn bị prompt, token hóa, xây dựng tensor, suy luận đồng bộ, hiệu chỉnh và định dạng kết quả. Nó không bao gồm việc tải mô hình. Lần chạy thông lượng 50 câu hỏi đã dùng batch_size=64, trong khi API mặc định là 16, vì vậy cặp số đó mô tả một khối lượng công việc được gom lô có chủ đích chứ không phải chi phí của một lệnh gọi tương tác đơn lẻ. Các độ dài đầu vào khác nhau, số lượng câu hỏi khác nhau và các điều kiện thời gian chạy khác nhau đều làm thay đổi kết quả. Những lưu ý đó là sự khác biệt giữa một con số và một phép đo chuẩn, và bản port tự nêu rõ chúng.

Mức sàn bộ nhớ là con số mà hầu hết độc giả sẽ dựa vào để hành động, và nó là con số ít mơ hồ nhất trong nhóm: dưới một gigabyte mức cấp phát MLX đỉnh cho một câu hỏi ngắn duy nhất, trên cả hai checkpoint. Đó không phải là khẳng định về tổng mức chiếm dụng trên máy Mac của bạn — hệ điều hành, terminal của bạn và tiến trình Python đều nằm bên cạnh nó — nhưng đây là một mức sàn thực sự, và nó thấp hơn khoảng ba bậc độ lớn so với mức mà việc chạy một mô hình sinh tạo cỡ trung bình tại máy đòi hỏi.

Kiểm tra độ trung thực là kết quả thú vị hơn.

Một bản port nhanh mà trả lời khác với mô hình mà nó port thì vô giá trị, và đây chính là chỗ dự án đã làm phần việc quan trọng. Cả ba checkpoint đều khớp với câu trả lời được chọn từ thượng nguồn trên 63/63 câu hỏi kiểm định ở cả FP32 lẫn FP16 — 378/378 phép so sánh. Mỗi cấu hình cũng chạy 100 lệnh gọi lặp lại, mang tính xác định mà không đo thấy mức tăng bộ nhớ hoạt động nào, và cả 36 tệp trọng số đã công bố đều vượt qua xác minh checksum từ xa nghiêm ngặt.

Hãy đọc phạm vi một cách trung thực: điều đó đo độ trung thành trên các fixture đó, chứ không phải độ chính xác đối với mọi câu hỏi có thể có. Nó cho bạn biết bản port trung thành với Laya. Nó không cho bạn biết liệu Laya có đúng hay không.

Độc lập, do cộng đồng duy trì, và vẫn chưa có trong danh sách

Bản port này tự nói về chính nó như vậy, hai lần: đây là một bản port MLX độc lập, không phải bản phát hành chính thức của Convai Innovations. Việc huấn luyện và tinh chỉnh RLCD vẫn ở upstream. Trọng số được ghi công cho Convai Innovations. Apache-2.0 ở cả hai phía.

Cách upstream đối xử với nó hé lộ nhiều hơn bất kỳ tuyên bố miễn trừ nào. README của Laya có một danh sách Công cụ Cộng đồng, và tính đến ngày 2026-09-23, danh sách này gồm bốn mục: omp-laya-judge, laya-adk-toolkit, laya-Ascend cho các NPU Huawei Ascend, và laya-apple — một runtime Apple Silicon sử dụng GPU MLX và Neural Engine. Mục thứ tư đó đến qua pull request #260, được hợp nhất vào ngày 2026-09-23. Bản port mà bài viết này nói tới không nằm trong số bốn mục. Danh sách của upstream giờ hướng độc giả Apple Silicon tới một dự án cộng đồng khác với dự án đã phát hành trước và có các benchmark.

Trình theo dõi vấn đề của chính Upstream nói phần còn lại. Issue #50, "Apple silicon ports," mở ngày 2026-09-21, vẫn còn mở; người bảo trì đã trả lời cùng ngày rằng hỗ trợ Apple Silicon đang được theo dõi và rằng các bản port cộng đồng như Laya-MLX đang khám phá suy luận Metal gốc, rồi trả lời lại vào 2026-09-23 bằng một dòng đáng trích dẫn nguyên văn: "Bản port MLX vẫn do cộng đồng duy trì." Bản sửa phía PyTorch — MPS autocast và một bản chỉnh sửa RoPE của transformers 4.x — đã được đưa vào dưới dạng pull request #273, được hợp nhất vào 2026-09-23, với một người phản biện trong luồng đó lưu ý rằng nó vẫn cần được kết hợp với bản tái cấu trúc autocast riêng trong #109, vốn vẫn còn mở. Và issue #52, mở ngày 2026-09-21, báo cáo một sidecar Laya-MLX đã tăng lên khoảng 21,7 GB bộ nhớ Metal sau vài giờ hoạt động, với vmmapquy khoảng 21,4 GB cho hệ thống con đồ họa thay vì heap Python; nó đề xuất giới hạn bộ nhớ đệm của allocator và xóa bộ đệm đó sau mỗi lần suy luận, và nó vẫn còn mở.

Ghép những điều đó lại, câu trả lời thực tế là: runtime này không được upstream chính thức công nhận, nó được cộng đồng duy trì theo chính mô tả của người bảo trì, và vấn đề bộ nhớ duy nhất đáng quan tâm đối với một sidecar chạy lâu dài đang được xử lý công khai thay vì được sửa trong một bản phát hành.

Screenshot of the GitHub repository page for mizorewww/laya-mlx, showing the description 'Native MLX runtime for Laya typed decision models — 7–14 ms short decisions on M3 Max. No text generation, PyTorch, or cloud API.', the Apache-2.0 licence label, 5.9k stars, 432 forks, 4 open issues and 6 open pull requests.

Tôi có thể chạy nó trên laptop của mình không, và tôi phải đánh đổi những gì?

Cài đặt chỉ cần một lệnh pip duy nhất, và bản port phát hành sẵn các trọng số FP16 đã được chuyển đổi trước để bạn không phải tự chuyển đổi bất cứ thứ gì:

pip install laya-mlx

Sau đó import laya_mlx as laya, agent = laya.load("aac6fef/laya-mlx"), và gọi agent.predict(state, questions). Yêu cầu là Apple Silicon, Python 3.11+ và macOS 14+. Môi trường được đo đạc là macOS 27.2, Python 3.12.13 và MLX 0.32.2 — và ghi chú về bản chuyển cổng nêu rằng bản phát hành MLX mà nó sử dụng đi kèm các wheel cho macOS 14, 15 và 26 trong khi trình cài đặt lại chọn bản 26, đồng thời rằng các phiên bản macOS cũ hơn được hỗ trợ đã không được kiểm thử trên máy đó.

Những gì bạn từ bỏ, theo từng chiều:

• FP16 so với FP32 — FP16 là mặc định và là nguồn của mọi con số chính ở trên. FP32 cho độ khớp số sát hơn với hệ thống nguồn, và xác suất có thể khác nhau đôi chút giữa các độ chính xác ngay cả khi nhãn được chọn vẫn khớp. Có thể yêu cầu BF16, nhưng nó không thuộc ma trận xác thực đã công bố, nên hãy coi nó là chưa được kiểm thử.

• Sàn bộ nhớ so với dư địa — mức phân bổ MLX đỉnh dưới 1 GiB cho một câu hỏi ngắn là thoải mái trên bất kỳ máy Mac dòng M nào. Đây không phải là một tuyên bố về tải máy chủ duy trì liên tục, và issue #52 là lý do cần thận trọng nếu bạn định chạy nó như một sidecar tồn tại lâu dài thay vì một lệnh gọi thư viện.

• Đa ngôn ngữ so với tiếng Anh — checkpoint đa ngôn ngữ 322M là bản nhanh hơn trong hai bản và là bản bao phủ hơn 100 ngôn ngữ, nhưng bản port này cố ý giữ nguyên cảnh báo của upstream: các checkpoint tiếng Anh không phải là bản thay thế cho bản đa ngôn ngữ. Việc định tuyến qua lại giữa chúng chính là mô hình sử dụng dự kiến, chứ không phải một thứ xa xỉ.

• Được upstream ủng hộ so với được cộng đồng duy trì — đây là phương án thứ hai. Không có gì trong ghi chú phát hành của upstream đảm bảo rằng bản port này vẫn tiếp tục hoạt động qua các thay đổi của upstream.

• Tốc độ so với hiệu chuẩn — một bản chuyển đổi nhanh không khắc phục được một bucket hiệu chuẩn vốn được phát hành với độ tự tin quá cao. Thượng nguồn kẹp các nhiệt độ đã khớp vào [0.5, 5.0], và choice:11+ bucket được phát hành là 0.1006, con số này sẽ làm logit sắc nét hơn khoảng mười lần và báo cáo một lần tung đồng xu thành gần như chắc chắn. Việc khớp nhiệt độ hiệu chuẩn tồn tại là có lý do; hãy khớp chúng trên dữ liệu giữ riêng của bạn trước khi bạn rẽ nhánh dựa trên một xác suất.

Còn hai giới hạn nữa đáng để ghi nhớ, cả hai đều đến từ trình theo dõi của chính upstream. action.act_probability hiện không mang tín hiệu hữu dụng nào — nó đọc 1.0 với gần như mọi đầu vào, và các logit thô của nó chạy đối chiếu với tính đúng đắn ở AUROC 0.30 trên 396 quyết định đã gán nhãn (vấn đề #185). Hãy gate trên confidence thay vào đó, vốn đạt 0.77 trên cùng các mục. Và noul câu hỏi có thể đi theo nhãn lựa chọn của chúng thay vì trạng thái (vấn đề #156) — thẻ của chính upstream báo cáo "no" đầy tự tin trên đầu vào rõ ràng tích cực, mạnh nhất trên checkpoint tiếng Anh. Cách xử lý mà nó gợi ý không phải là dùng một mô hình khác mà là định dạng lại câu hỏi: hỏi nó dưới dạng hai lựa chọn choice với các khóa trung tính (A/B) và từ ngữ có/không của bạn làm mô tả lựa chọn.

Vì sao một mô hình quyết định có thể được port một cách sạch sẽ, còn mô hình kia thì không

Sự tương phản ở đây mang tính kiến trúc, và đây là điều hữu ích nhất trong bài viết này đối với bất kỳ ai đang lựa chọn giữa hai họ.

Xương sống của Laya là ModernBERT-large, một bộ mã hóa hai chiều được xây dựng hoàn toàn từ attention. Attention là thứ mà ngăn xếp GPU của Apple làm tốt nhất, và cũng là thứ mà MLX đã dồn công sức vào. Vì vậy, bản port là sự tái triển khai các lớp vốn đã có đường dẫn nhanh: bộ mã hóa, các lớp Transformer của head quyết định, head tính điểm và head hành động đều chạy trong MLX, còn token hóa vẫn đi qua Rust tokenizer của Hugging Face.

Các backbone của Kev là các base Qwen3.5, và Qwen3.5 kết hợp các lớp attention với các lớp Gated DeltaNet. DeltaNet có tính hồi quy và bỏ qua mặt nạ attention. Điều đó dẫn đến hai hệ quả. Thứ nhất, mỗi câu hỏi phải chạy thành một hàng riêng thay vì dùng chung một chuỗi được mặt nạ, và dự án Kev xử lý việc này bằng cách tính trạng thái một lần rồi tái sử dụng cache của nó cho từng hàng. Thứ hai — và đây chính là phần gây đau đầu trên máy Mac — không có kernel PyTorch nào cho các lớp đó trên GPU của Apple, nên PyTorch phải quay về dùng mã tham chiếu. jaredpalmer/kev-4bThẻ model vẫn ghi rõ giới hạn kết quả bằng ngôn ngữ bình dân: một yêu cầu gồm năm câu hỏi mất 0,17 giây trên bản dựng Qwen3 của Kev-4B nhưng mất 0,78 giây ở bf16 trên một chiếc M5.

Kiểm tra cách diễn đạt hiện tại trước khi trích dẫn điều đó, vì nó đã thay đổi. README của kho lưu trữ Kev nay cho biết máy chủ chạy các mô hình Qwen3.5 thông qua MLX trên Apple Silicon thay vào đó, và công bố các số liệu M5 của riêng mình cho một yêu cầu năm câu hỏi với ba lựa chọn mỗi câu trên một trạng thái khoảng 270 token: Kev-4B đạt 721 ms trên một trạng thái mới và 136 ms trên một trạng thái lặp lại thông qua bộ đệm tiền tố, so với 3.302 ms và 847 ms trên đường dẫn PyTorch bf16 MPS. Kev-0.8B đạt 149 ms và 28 ms. Các mô hình Qwen3 thế hệ trước vẫn chạy trên PyTorch MPS thuần và dự án gọi chúng là một lựa chọn tốt trên Mac.

Hãy cẩn thận đừng biến đó thành một kết quả cuộc đua. Đây không phải là những phép đo đối đầu trực diện. 13,42 ms của Laya-MLX là một câu hỏi ngắn trên một chiếc M3 Max; 721 ms của Kev là năm câu hỏi, mỗi câu có ba lựa chọn, trên một trạng thái ~270 token trên một chiếc M5. Số lượng câu hỏi khác nhau, số lựa chọn khác nhau, độ dài trạng thái khác nhau, máy khác nhau, thời gian chạy khác nhau. Điều có thể kiểm chứng và đáng để so sánh là hình dạng của bài toán, không phải một người thắng cuộc: một bộ mã hóa thuần attention chuyển sang Apple Silicon mà không gặp trở ngại gì, còn một mô hình attention tuyến tính lai cần hẳn một backend thứ hai trước khi nó có thể dùng được ở đó.

Mô hình quyết định thực sự dùng để làm gì

Bỏ qua các benchmark đi, trường hợp sử dụng thực tế thì hẹp, và chính dự án cũng thừa nhận điều đó: Laya là một mô hình nền nhanh để chuyên biệt hóa, chứ không phải một cỗ máy ra quyết định zero-shot. Trên chính benchmark typed-decisions của Convai, hai checkpoint cơ sở đạt 0.362 và 0.342 khi zero-shot, so với mức cơ sở 0.461 của lớp đa số và mức 0.318 ngẫu nhiên. Chúng nằm dưới mức mà bạn sẽ đạt được nếu luôn trả lời nhãn phổ biến nhất. Con số nổi bật 0.766 thuộc về laya-typed-decisions, checkpoint được tinh chỉnh trên chính tập huấn luyện của benchmark đó, và không bao giờ nên được trích dẫn như năng lực tổng quát.

Bản so sánh đã công bố của Convai với TypeSafe Jev 1.13.0 đáng đọc chính vì lý do này, và nó được ghi nhãn cẩn thận ở phía họ: mọi con số của Laya là những gì bộ định tuyến thực sự trả về, còn các con số của Jev là những số liệu đã công bố của bên thứ ba mà Convai chưa từng đo vì nó không có quyền truy cập API TypeSafe. Trong bản so sánh đó, Laya được định tuyến đạt 0.766 so với 0.727 của Jev trên typed-decisions, với ECE sau temperature là 0.081 so với 0.246, và độ trễ p50 là 32.8 ms so với 236–276 ms trên Tesla T4 — chênh lệch 7.8 lần ở một câu hỏi. Đó là con số cần trích dẫn. Con số "nhanh hơn Jev 50 lần" đã lan truyền trên mạng xã hội không xuất hiện trong tài liệu của dự án hay các benchmark của dự án, và bản so sánh do chính dự án công bố không ủng hộ nó. Jev cũng dẫn đầu ở những chỗ nó dẫn đầu: trên Banking77, Jev đạt 0.870 so với 0.425 của Laya, vì các lựa chọn của Laya chia sẻ một ngân sách token cố định và 77 nhãn chỉ còn lại khoảng ba đến bốn token mỗi nhãn.

Vậy nên hình dạng của một triển khai thực tế là một đầu quyết định rẻ, cục bộ và hẹp — định tuyến một ticket, chấm điểm mức độ khẩn cấp, trả lời một cổng yes/no — với một thứ mang tính sinh tạo đứng sau nó cho phần cần viết. Mô hình quyết định đưa ra lệnh gọi đã định kiểu trong vài mili giây rồi chuyển cấp. Nửa sinh tạo là một mô hình khác trên một runtime khác, và đó chính là chỗ một router khẳng định được giá trị của mình: hơn 200 mô hình sau một khóa duy nhất với giá niêm yết của nhà cung cấp, không phụ phí, nên khi nhà cung cấp đổi giá thì cập nhật ngay trong ngày, và tự động chuyển đổi dự phòng khi một nhà cung cấp suy giảm giữa chừng. OrcaRouter không phục vụ Laya, cũng không phục vụ Kev hay Jev — dòng Qwen3.5 có trong danh sách mô hình của chúng tôi, còn bản thân các mô hình quyết định thì không. Thứ chúng tôi đảm nhiệm là nửa sinh tạo của ngăn xếp đó, tức nửa mà bạn gọi trong mọi yêu cầu mà đầu quyết định chuyển cấp.

Còn một lý do nữa để giữ tách biệt hai nửa thay vì chọn một mô hình làm cả hai. Một đầu quyết định cục bộ không tốn token đầu ra và không bao giờ truy cập mạng là một kiểu phụ thuộc khác với một lệnh gọi API: nó vẫn hoạt động khi mạng không hoạt động, và chi phí của nó không tăng theo lượng văn bản mà nó đọc. Đó là đặc tính đáng để trả giá. Mọi thứ khác trong bài viết này nói về cái giá bạn phải trả cho nó về độ trung thực, bộ nhớ và bảo trì.

Ai nên chạy nó, và ai nên chờ

Chạy Laya-MLX nếu bạn đang dùng Mac dòng M, các quyết định của bạn bị giới hạn — một lựa chọn giữa các tùy chọn được đặt tên, một điểm theo rubric, một cổng có/không — và bạn hoặc có nhãn để tinh chỉnh, hoặc đã sẵn sàng tự khớp nhiệt độ hiệu chuẩn. Việc cài đặt chỉ là một lệnh, mức sàn bộ nhớ dưới một gigabyte, và phần việc đảm bảo độ trung thực đã được thực hiện và công bố.

Khoan đã, nếu bạn cần các bảo đảm hỗ trợ từ upstream, nếu bạn đang chạy một sidecar tồn tại lâu dài và muốn câu hỏi về tăng trưởng bộ nhớ được giải quyết trong một bản phát hành thay vì một issue còn mở, hoặc nếu các câu hỏi của bạn là mở. Một encoder không tự hồi quy trả lời "tôi nên làm gì tiếp theo" không phải là một phiên bản nhỏ hơn của một LLM làm cùng việc đó. Nó là một công cụ khác, và nó chỉ đọc tốt khi câu hỏi đã được định hình sẵn cho nó.

A generated two-column scoreboard for Laya-MLX on Apple Silicon. Left column 'Laya 421M English': One short question P50 13.42 ms, P95 13.92 ms, 50-question throughput 146.8 q/s, Peak MLX allocation 943.6 MiB, Output tokens zero, Precision FP16. Right column 'Laya 322M multilingual': P50 7.39 ms, P95 7.79 ms, 395.0 q/s, 687.6 MiB, zero output tokens, FP16. Footer 'Port author measurements on a stated M3 Max (40-core GPU, 128 GiB); model loading excluded.', with the OrcaRouter logo in the bottom-right corner.

So sánh trong bài viết này1

Phát hiện từ bài viết này · Benchmark: Artificial Analysis · cập nhật hằng ngày