Laya-MLX 实战指南:在 Apple Silicon 上以毫秒级延迟原生运行 Laya 类型化决策模型
2026/9/23 1:11:52 网站建设 项目流程

Laya-MLX 实战指南:在 Apple Silicon 上以毫秒级延迟原生运行 Laya 类型化决策模型

【免费下载链接】laya-mlxNative MLX runtime for Laya typed decision models — 7–14 ms short decisions on M3 Max. No text generation, PyTorch, or cloud API.项目地址: https://gitcode.com/gh_mirrors/la/laya-mlx

Laya-MLX 是 Laya 类型化决策模型(typed decision models)在 Apple Silicon 上的原生 MLX 推理运行时,它把“给出一段文本状态,回答一组结构化问题”的推理压缩到单次双向前向传播,零输出 token、无 PyTorch/Transformers 推理依赖、不调用任何云端 API。本文基于仓库 README.zh-CN.md 与源码,完整讲解它的安装、Python/CLI 用法、三种问题类型(choice/score/noul)、支持的检查点、M3 Max 实测性能、权重转换、多语言路由,以及可复现的测试与 benchmark 流程,读完即可在本机跑通一条端到端的本地决策推理链路。

类型化决策:为什么不需要“生成”答案

常规大模型回答任何问题都需要逐 token 解码;而软件系统真正需要的往往只是一个分类结论:这个工单该转给哪个部门?这个请求有多紧急?用户是不是要求退款?Laya 用“类型化决策”直接回答这类约束问题,推理过程是一句可概括的流水线:

state + typed question → 双向编码器 → 决策头 → 概率

三种问题类型由 laya_mlx/common.py 中的QTYPES定义,各对应一种确定性的结果格式:

  • choice:对若干命名选项输出分类概率(如billing / technical / sales三选一);
  • score:对有序评分等级输出概率,并给出期望得分(如not urgent / soon / critical);
  • noul:对某个命题输出P(true)(如“客户是否要求退款”)。

每个问题作为独立的一行输入双向编码器,编码器表示同时依赖 state 与问题本身——因此该运行时不宣称把 state 编码一次后跨任意问题复用 hidden states。结果保留上游的四位小数概率格式与action.act_probability字段;usage中的output_tokens恒为 0,这正是“0 输出 token”的由来(见 agent.py)。

编码器、决策 Transformer、评分头与动作头全部在 MLX 中运行,tokenization 使用 Hugging Face 的 Rust tokenizer(tokenizers库),原始预训练权重、问题格式、温度校准与输出 schema 均保留。需要说明的是,这是独立的 MLX 移植,并非 Convai Innovations 的官方发布;RLCD 训练与微调仍在上游项目进行,本仓库只负责推理与权重转换。

快速开始:三条命令跑通第一个决策

安装并加载 multilingual 检查点,对一个中文工单做一次部门分类:

pip install laya-mlx
import laya_mlx as laya agent = laya.load("aac6fef/laya-multilingual-mlx") result = agent.predict( "发票被重复扣款,请退款。", { "department": { "type": "choice", "instructions": "Who should handle this?", "criteria": ["billing", "technical", "sales"], } }, ) print(result["answers"]["department"])

首次load会从 Hugging Face 下载检查点,之后完全本地推理。predictsystem_one的别名;state 可以是纯文本、JSON 字典或对话列表。返回结果形如:

{ "answers": { "department": { "type": "choice", "confidence": 0.9987, "action": {"act_probability": 0.9982}, "choice": "billing", "probabilities": {"billing": 0.9987, "technical": 0.0009, "sales": 0.0004} } }, "usage": {"input_tokens": 46, "output_tokens": 0} }

choicecriteria可以是唯一标签列表,也可以扩展为{"标签": "描述"}的字典(描述会进入上下文,帮助模型区分相近选项);scorecriteria必须是等级列表,score返回从 0 开始的期望等级;noul返回P(true)。仓库自带的 examples/questions.json 就是一个同时包含三种类型的最小示例。

一次提问多个问题

决策模型的价值在于一次前向传播并行回答多个问题。把questions扩展为一个以问题 ID 为键的字典即可:

result = agent.predict( "发票被重复扣款,请今天退款。", { "department": { "type": "choice", "instructions": "Which department should handle this request?", "criteria": ["billing", "technical", "sales"], }, "refund": { "type": "noul", "instructions": "Does the customer ask for money back?", }, }, ) print(result["answers"])

batch_size=16(默认)控制每次前向计算的问题数,更多问题会自动分块处理(见 agent.py);内存充足时可以调大。batch_size必须是正整数,否则构造Agent时直接抛ValueError

关键加载参数

laya.load对应 agent.py 中的Agent构造参数:

参数默认值说明
dtype"float16"计算精度:float32/float16/bfloat16。默认 FP16;需要更接近原版 FP32 的数值时用"float32"bfloat16可请求但不在已发布的验证矩阵内
batch_size16单次前向的最大问题数,超出分块处理
deviceNone"gpu"/"metal"/"cpu"None时用 MLX 默认设备
revisionNone固定 Hub revision 哈希,保证可复现
subfolderNone从捆绑仓库中选择某个子目录检查点(如multilingual
compileFalse启用mx.compile编译,适合重复负载;首次使用有编译开销与形状特化
pad_to_multipleNone把序列长度补齐到该值的整数倍(如 16),配合编译使用;某些负载可能变慢
cache_promptsFalse前缀缓存,上限 128 个问题,共享 CPU 侧 state tokenization,但每个问题仍单独计算编码器

加载时会对每个参数名与形状做严格校验(strict=True),不支持的编码器与非默认 RoPE 缩放会直接失败;ModernBERT 的全局/局部注意力模式、滑动窗口边界、双 RoPE base 与首层归一化行为都被保留。以上三个优化选项默认全部关闭,实测数据见 docs/SNAKE_OPTIMIZATION.md。

支持的检查点

检查点编码器参数量最大上下文用途
convaiinnovations/layaModernBERT-large421M512英文
convaiinnovations/laya-multilingualmmBERT-base322M1,024多语言输入(100+ 语言)
convaiinnovations/laya-typed-decisionsModernBERT-large421M1,024上游 typed-decisions 工作流

上下文预算包含问题、选项与输入状态。中文等非英语输入应使用 multilingual 检查点——英文检查点在非英语输入上会剧烈退化并伴随高置信度,这是路由器必须存在的原因(详见下文)。

三个已转换的 FP16 MLX 权重仓库可直接传给laya.load(...)

  • aac6fef/laya-mlx(英文)
  • aac6fef/laya-multilingual-mlx(多语言)
  • aac6fef/laya-typed-decisions-mlx(typed-decisions 工作流)

每个模型仓库都附带模型卡、验证结果、来源、许可证与文件校验清单;三个仓库共 36 个文件均通过严格远端校验,固定版本与权重哈希记录在 benchmarks/results/hub-publication.json。

也可以加载上游捆绑仓库中的子目录:

# 在上游捆绑仓库中选择 multilingual 子目录 multi = laya.load("convaiinnovations/laya", subfolder="multilingual") # 固定 revision 以保证可复现 agent = laya.load( "convaiinnovations/laya", revision="c5d78730f3493e4fe16d61507ef4b78eef7318cf", )

M3 Max 实测:13.4 ms 与 7.4 ms 的含义

FP16,端到端Laya 421MMultilingual 322M
单个短问题 P5013.42 ms7.39 ms
单个短问题 P9513.92 ms7.79 ms
50 问题吞吐量146.8 q/s395.0 q/s
单个短问题 MLX 峰值分配943.6 MiB687.6 MiB

硬件为 M3 Max(40 核 GPU、128 GiB 内存)。计时包含提示准备、tokenization、张量构建、GPU 同步推理、校准与结果格式化,排除模型加载;50 问题吞吐量使用batch_size=64(公开 API 默认 16)。不同长度、问题数量与运行条件都会改变延迟,完整方法与每个计时样本见 BENCHMARKS.md。

移植一致性:三个检查点在 FP32 与 FP16 下均通过 63/63 验证问题的上游 argmax 对齐,合计 378/378 次比较;每个配置各执行 100 次重复调用,结果有限、确定,实测活跃内存增长为零。这验证的是移植保真度,不代表所有实际问题都能答对——模型能力与限制来自上游。

需要特别区分两个数字:13.4 / 7.4 ms 来自单问题 API 基准;而贪吃蛇 demo 的每帧会批量回答三个问题,帧耗时另有独立的 docs/SNAKE_BENCHMARKS.md 报告。README 顶部那张 GIF 就是真实本地运行的原速回放:每一步都调用 Laya,界面同时显示循环路径安全层及其接管次数。

安装与运行

环境要求

  • Apple Silicon Mac(本机实测环境:M3 Max,40 核 GPU,128 GB 内存)
  • macOS 14+
  • Python 3.11+(实测 Python 3.12.13)
  • MLX 0.32.2(pyproject.toml中约束为mlx>=0.32.2,<0.33,仅 darwin/arm64)

实测 MLX 0.32.2 提供 macOS 14 / 15 / 26 的 wheel,本机选择了 26 构建;旧系统未在这台机器上实测。

方式一:PyPI 安装(推荐)

pip install laya-mlx

方式二:源码开发安装

gh repo clone mizorewww/laya-mlx cd laya-mlx uv sync uv run python examples/quickstart.py

uv sync会按 pyproject.toml 解析依赖;模型权重单独下载,不进入 Git 仓库。若需运行贪吃蛇 demo,则要安装demoextra:

pip install 'laya-mlx[demo]' hf download aac6fef/laya-multilingual-mlx laya-snake

hf download提前下载一次权重,游戏运行期间完全本地推理。终端至少需要104 列 × 35 行;空格暂停、↑/↓ 调速、R 重开、Q 退出。--max-speed持续满速运行,每一步都等待新的模型结果。

laya-snake --optimize --max-speed启用经过验证的编译与前缀复用路径:在同轮成对测试中,2,400 步达到75.40 步/秒,零死亡、安全接管 2 次,比 eager 基线快约6.5%。完整游戏表现、优化测量与一致性证据见 docs/SNAKE_OPTIMIZATION.md。

命令行预测

命令行支持文本或 JSON 状态输入,问题定义从 JSON 文件读取(格式见 examples/questions.json):

uv run laya-mlx predict \ --model aac6fef/laya-multilingual-mlx \ --state '发票被重复扣款,请退款。' \ --questions examples/questions.json

也可用--state-file examples/state.json传入 JSON 状态(examples/state.json 展示了from / subject / body的邮件结构,与email_questions预置配合)。CLI 入口定义在 laya_mlx/cli.py:--state--state-file互斥且必选其一,--questions必填,另有--dtype(默认float16)、--devicegpu/cpu)、--batch-size(默认 16)、--subfolder--revision。若权重已下载在本地,把--model改成相应本地目录(如models/下的路径)即可避免再次下载。

转换权重:从上游检查点导出 MLX 格式

uv run laya-mlx convert \ --model convaiinnovations/laya \ --dtype float16 \ --output models/laya-mlx-fp16

转换后可直接用laya.load("./models/laya-mlx-fp16")加载。输出目录包含model.safetensors、编码器与 agent 配置、tokenizer 文件以及mlx_config.json。注意两点:

  1. 已有目录不会被覆盖,模型权重不会提交到 GitHub;
  2. 原始检查点本身存储的就是 FP16 权重,这里的转换只是调整参数命名与计算精度,不是量化,也不涉及重新训练。选择 FP32 提高的是算术精度,而不是源权重的存储精度。

转换命令的具体参数解析与convert调用链见 laya_mlx/cli.py。

多语言路由与预置问题

上游路由的核心教训是:英文检查点在非英语输入上不是温和退化,而是近乎崩溃——例如在 20 选项的 MASSIVE intent 上,对印地语得分 0.100、韩语 0.103(随机猜测为 0.050),且报出高置信度(ECE 0.855)。因此脚本检测是第一路由信号。

from laya_mlx import Router, triage_questions router = Router(dtype="float16", max_loaded=2) result = router.predict({"message": "发票被重复扣款,请退款。"}, triage_questions()) print(result["routing"]) # multilingual

Router(laya_mlx/router.py)默认管理三个检查点:englishmultilingualtyped-decisions,三者合计约 1.16B 参数。路由优先级为:显式model> 显式task> 检测到的工作流(需auto_task_detection=True显式开启)> 显式lang> 脚本/语言检测 > 默认值。

  • max_loaded:限制常驻模型数量,超出时按 LRU 驱逐。冷加载耗时数秒而语言检测只需微秒级,因此交替使用多语言的服务建议Router(preload=True)一次性驻留全部三个模型,或router.preload(["english", "multilingual"])只驻留所需两个;
  • attach(name, agent):把进程里已构建的Agent登记给路由器,避免重复加载同一份 421M 参数;
  • unload()/loaded:释放一个或全部模型、查看当前常驻列表;
  • task="typed_decisions":显式选择 typed-decisions 检查点。该检查点针对四个合成工作流微调,永远不会被自动选中,除非你显式开启auto_task_detection=True,或传入task="typed_decisions",或问题 ID 集合与某个工作流签名完全匹配(精确集合匹配,见_TYPED_DECISION_WORKFLOWS)——这是刻意的设计,避免它成为静默默认值。

Router.predict的返回在system_one结果基础上追加routing字段,包含modelreporeasondetection信息。

预置问题函数(laya_mlx/presets.py)覆盖常见生产场景,均可直接传入predict

函数场景含问题
triage_questions()客服工单分诊intent(choice)、is_urgent(noul)、frustration(score)、refund_requested(noul)、churn_risk(noul)
email_questions()入站邮件分诊与威胁过滤category(choice)、is_spamis_phishingurgency(score)、needs_reply
guard_questions()LLM 输入护栏jailbreakprompt_injectionsensitive_dataharm_severity(score)、topic(choice)
moderation_questions()内容安全与审核toxicharassmentthreatspamseverity(score)
router_questions()智能模型路由difficulty(score)、domain(choice)、needs_tools(noul)、is_sensitive(noul)

此外 laya_mlx/email.py 提供clean_email_bodyemail_state,laya_mlx/lang.py 提供detect_languagedetect_scriptis_english,全部在 laya_mlx/init.py 中统一导出(__version__为 0.1.0)。

测试与 benchmark:完整复现链路

单元测试使用小型随机模型,并包含与 Transformers 及固定版本上游决策头的直接对比(fixture 见 tests/conftest.py);真实检查点验证则覆盖 tokenization、logits、校准概率、重复输出与活跃内存增长。完整复现流程:

uv sync --extra dev --extra reference --extra benchmark --extra demo source .venv/bin/activate gh repo clone NandhaKishorM/laya .upstream git -C .upstream checkout 6a5819129eb220570792e417e49723d697efd76f pytest -q python -m benchmarks.download python -m benchmarks.validate --repeats 100 python -m benchmarks.run --iterations 50 --warmup 5 python -m benchmarks.accuracy --per-class 64 python -m benchmarks.report

GPU 测试应串行运行。benchmark 在每个新进程中运行各后端/检查点,并把全部计时样本写入 benchmarks/results(原始数据都在这里,含 FP16/FP32 的 P50/P95、吞吐量、内存、数值一致性、重复运行与固定抽样分类测试)。pytest中的 integration 标记需要已下载的真实检查点(对应 pyproject.toml 中的integrationmarker)。GitHub Actions 只在 macOS arm64 runner 上跑小模型 CPU 测试,完整检查点的 GPU benchmark 是本地测量,不属于托管 CI。

关于“再快 10 倍”的性能研究结论

仓库还附有两份面向“能否再快一个数量级”的深入报告,均基于本地实测而非推测:

  • docs/PERFORMANCE_RESEARCH.md:初步性能研究,分析实现瓶颈、MLX kernel 派发与受控实验计划;
  • docs/MATH_10X_RESEARCH.md:数学分析——计算预算、带宽条件下界、真实权重谱、精确复用,以及蒸馏学生模型的设计空间;
  • docs/ENGINEERING_10X_RESEARCH.md:工程实测——编译、量化、最后一层输出裁剪、自定义 Metal 核与代表性矩阵乘法实验。

experiments/ 目录保存研究脚本与原始数据,各实验变体的耗时与数值一致性单独记录。目前证据不支持在相同检查点下普遍再快 10 倍:部分场景的逐轮配对中位加速约为 1.03–1.08 倍;误差区间、量化保真结果与自定义 Metal 核的实测详见工程报告——这本身就是一份克制且严谨的结论。

小结

Laya-MLX 用“单次前向传播 + 三类结构化问题”把本地决策推理的延迟压到毫秒级:M3 Max 上单问题端到端中位耗时 13.42 ms(英文 421M)与 7.39 ms(多语言 322M),吞吐量分别达 146.8 q/s 与 395.0 q/s,且 378/378 次 argmax 对齐验证了移植保真度。它适合工单分诊、邮件分类、LLM 输入护栏、内容审核等需要低延迟、低依赖、完全本地的结构化决策场景。项目采用 Apache-2.0 协议,原作者与移植说明见 NOTICE。需要留意的是:英文检查点不能替代 multilingual 检查点,模型输出概率也不等于答案必然正确——这些限制与上游保持一致。

【免费下载链接】laya-mlxNative MLX runtime for Laya typed decision models — 7–14 ms short decisions on M3 Max. No text generation, PyTorch, or cloud API.项目地址: https://gitcode.com/gh_mirrors/la/laya-mlx

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询