最近在本地模型圈子里,Perplexity 开源本地推理引擎 Lily 的消息讨论度很高。它针对 Apple silicon 做了专门优化,并且直接支持 Qwen3.6-35B-A3B 这种 MoE 架构模型。很多开发者在 M 系列芯片的 Mac 上尝试跑本地大模型时,会发现一个问题:模型参数一大,显存和内存直接告急,推理速度也不理想。Lily 的思路和传统 CPU/GPU 推理框架不太一样,它更贴近 Apple silicon 的统一内存架构,让本地跑 35B 级别 MoE 模型成为一件可以落地的事。
本文会围绕 Lily 的定位、环境准备、安装步骤、模型运行、性能优化和排错思路展开。如果你想在 MacBook 或 Mac Studio 上本地体验 MoE 大模型,或者对推理引擎底层优化感兴趣,这篇文章可以作为一份完整参考。下面进入正文。
1. 背景与核心概念
1.1 Perplexity Lily 是什么
Lily 是 Perplexity 开源的一个本地推理引擎,目标是在 Apple silicon 设备上高效运行大语言模型。简单理解,它是一层介于“模型权重”和“硬件算力”之间的软件层,负责把模型的计算图映射到苹果的统一内存与神经网络加速单元上。
传统推理引擎的思路通常围绕 NVIDIA GPU 生态设计,核心是显存管理、CUDA 内核调度、显存拷贝优化。但 Apple silicon 的架构不一样,CPU、GPU 和神经网络引擎共享同一块内存,不存在 PCIe 传输瓶颈,却也带来了新的挑战:如何让 GPU 高效访问统一内存、如何做算子融合、如何平衡 CPU 与 GPU 的负载。Lily 正是针对这套架构设计的推理引擎。
需要注意的是,Lily 不是一个“一键安装就能跑所有模型”的泛用工具。它更专注于 Apple silicon 平台,对 MoE(Mixture of Experts,混合专家)架构模型有针对性优化。这也解释了为什么它支持 Qwen3.6-35B-A3B 这类模型。
1.2 MoE 模型与 Qwen3.6-35B-A3B 的特别之处
Qwen3.6-35B-A3B 是一个典型的 MoE 模型,模型名称里的“35B”表示总参数量约 350 亿,“A3B”表示每个 token 实际激活的参数约 30 亿。这个“总参数”和“激活参数”的区分非常关键。
传统稠密模型(Dense Model)处理一个 token 时,所有参数都参与计算。MoE 模型则会把 Transformer 层中的 FFN(前馈网络)拆分成多个专家子网络,每次推理只激活其中一部分专家。举例来说,35B 总参数的模型,每次计算可能只激活 3B 参数,从而大幅降低单次推理的计算量。
对本地推理来说,MoE 模型的核心优势是:模型文件依然需要完整的 35B 参数权重,内存占用不会太夸张(相对稠密 70B 模型而言),但推理速度可以接近 3B 稠密模型。这正好匹配 Apple silicon 统一内存的硬件特点——内存容量大、带宽高,但 GPU 算力与高端独立显卡仍有差距。MoE 把“算力需求”降下来,把“内存需求”留下来,Lily 的优化刚好补上后面这块。
1.3 为什么要在 Apple silicon 上做本地推理
本地推理的价值不只是“离线可用”。对企业来说,代码、文档、内部数据不能随意上传到云端 API,本地推理是合规路径之一。对个人开发者来说,本地推理没有 API 费用,可以随意调试、微调实验,也不受服务商限流影响。
Apple silicon 设备在这条路上的优势有三点:
- 统一内存架构,CPU 与 GPU 共享大容量内存,可以加载大参数模型。
- 能效比高,M 系列芯片的功耗远低于同性能的传统 GPU。
- 设备普及率高,很多开发者手头的 MacBook Pro 或 Mac Studio 就能直接使用。
Lily 把这三个优势转化为实际可用的推理能力,这是它受到关注的根本原因。
2. 环境准备与版本说明
2.1 硬件与系统要求
本文的示例以 Apple silicon 设备为准,即 M1、M2、M3、M4 系列芯片。不同芯片在内存带宽、GPU 核心数上有差异,直接决定可跑模型的上限。
内存方面,Qwen3.6-35B-A3B 模型权重按半精度(Float16)存储,大约占用 70GB 空间;如果使用量化后的权重,则可能降到 20GB 到 35GB。因此建议至少 32GB 统一内存的机器,推荐 64GB 及以上。
系统方面,macOS 14 及以上版本比较稳妥,新版本系统对 Metal API 的支持更完善。
2.2 软件依赖准备
Lily 的安装和运行通常依赖以下组件:
- Homebrew 包管理器,用于安装底层依赖库。
- Python 3.10 及以上版本,Lily 的启动脚本和部分工具链基于 Python。
- Xcode Command Line Tools,提供编译器和 Metal 开发库。
- Git,用于拉取仓库。
版本需要根据你的项目实际情况调整,本文示例以常见环境为例,重点演示配置思路。在实际安装前,建议先执行下面的命令确认基础环境:
# 查看芯片架构,确认是 Apple silicon uname -m # Apple silicon 输出 arm64 # 查看 macOS 版本 sw_vers # 查看内存大小 sysctl hw.memsize # 查看 Python 版本 python3 --version如果你看到uname -m输出arm64,说明设备是 Apple silicon 架构,符合运行条件。
2.3 示例项目结构
本文后续会按照下面的目录结构组织内容:
~/lily-demo/ ├── lily/ # Lily 推理引擎源码 ├── models/ # 存放模型权重 │ └── qwen3.6-35b-a3b/ ├── scripts/ # 推理与测试脚本 │ └── run_inference.py └── logs/ # 日志输出目录3. 核心原理拆解:Lily 是怎么让 MoE 模型跑起来的
3.1 Apple silicon 统一内存与推理引擎的适配逻辑
传统深度学习推理中,数据需要从 CPU 内存拷贝到 GPU 显存,这是典型的“PCIe 传输瓶颈”。Apple silicon 采用统一内存,CPU、GPU 直接访问同一块物理内存。这意味着推理引擎不需要做数据搬运,但需要更精细的内存生命周期管理。
Lily 在适配这一架构时,重点做了三件事:
- 内存映射优化,减少模型权重在进程内的重复拷贝。
- 算子融合,把多个矩阵运算合并成更少的 Metal GPU 计算任务。
- 显存占用控制,让 MoE 模型只加载活跃专家到高速缓存。
这三点是理解 Lily 后续配置项的基础。
3.2 MoE 推理时专家调度的工作方式
MoE 模型的推理流程与稠密模型不同。每个 token 经过 Transformer 层时,路由器(Router)会计算所有专家的得分,选出 top-k 个专家参与 FFN 计算。这带来两个性能问题:
第一,路由计算本身有额外开销。第二,不同 token 可能激活不同专家,导致 GPU 计算不连续。
Lily 的优化思路是,把专家权重划分为“常驻”和“按需加载”两类。常用专家(比如路由器得分高的专家)常驻内存,冷门专家则在需要时从外存换入。这种策略在统一内存架构上比传统显存分页更高效,因为内存与“显存”本质相同,不存在跨设备拷贝。
3.3 量化在本地推理中的角色
Qwen3.6-35B-A3B 的全精度权重对内存压力较大,实践中通常会使用量化版本。量化就是把模型权重从 Float16 降低到 Int8 或 Int4 表示,换取更小的内存占用和更快的速度,代价是少量精度损失。
Lily 对量化的支持需要看具体版本。通用经验是:
- 首跑建议先使用 Float16 或 BF16,确认模型输出正确。
- 内存吃紧时切换 Int8 量化,通常质量损失很小。
- Int4 量化内存占用更低,但可能出现明显质量下降。
配置量化时,务必在“可用内存”和“输出质量”之间找平衡,不是越低越好。
4. 安装 Lily 与基础配置
4.1 下载 Lily 源码
第一步是把 Lily 仓库克隆到本地。具体仓库地址以 Perplexity 官方发布信息为准,下面是一个通用的拉取流程:
mkdir -p ~/lily-demo cd ~/lily-demo git clone https://github.com/PerplexityAI/Lily.git lily cd lily如果你使用的是稳定发布版本,建议切换到对应的 release 分支或标签,避免主分支的不稳定变更影响实验。
4.2 创建 Python 虚拟环境
Python 虚拟环境可以避免依赖包冲突,是本地开发推荐的做法:
cd ~/lily-demo/lily # 创建虚拟环境 python3 -m venv .venv # 激活虚拟环境 source .venv/bin/activate # 确认处于虚拟环境 which python3激活后,终端的命令提示符前会出现(.venv)标识,说明当前已在虚拟环境中。
4.3 安装依赖
Lily 的依赖项会随版本更新,建议通过项目提供的配置文件安装:
pip install --upgrade pip # 安装核心依赖 pip install -r requirements.txt # 如果是开发模式,可以执行可编辑安装 pip install -e .如果安装过程中遇到编译错误,通常是因为缺少 Xcode Command Line Tools。此时执行:
xcode-select --install安装完成后重启终端,再继续后续操作。
4.4 验证安装是否成功
可以运行 Lily 自带的版本命令或帮助命令,确认核心引擎可用:
lily --version lily --help如果命令无法识别,可能是可执行文件没有添加到 PATH,可以使用 Python 模块方式调用:
python -m lily --version看到版本号输出说明安装基本成功。
5. 实战运行 Qwen3.6-35B-A3B
5.1 获取模型权重
Qwen3.6-35B-A3B 的权重可以从 Hugging Face 等模型仓库获取。你可以使用huggingface-cli或git lfs下载模型文件。
推荐先创建一个模型目录:
mkdir -p ~/lily-demo/models/qwen3.6-35b-a3b cd ~/lily-demo/models/qwen3.6-35b-a3b随后执行下载命令。注意:模型文件较大,建议先确认磁盘空间充足。
# 查看磁盘空间 df -h ~/如果是通过 Hugging Face 下载,常见命令格式如下:
huggingface-cli download Qwen/Qwen3.6-35B-A3B --local-dir ./qwen3.6-35b-a3b如果你的网络访问 Hugging Face 不稳定,可以考虑使用国内镜像,例如在命令中增加镜像环境变量。此处只是示例思路,具体以你实际可用的下载源为准。
5.2 加载模型并执行文本生成
下面是一个使用 Lily 加载 Qwen3.6-35B-A3B 并执行文本生成的示例脚本。保存为~/lily-demo/scripts/run_inference.py:
# 文件路径:~/lily-demo/scripts/run_inference.py import time from lily import LilyModel, AutoTokenizer def main(): # 1. 指定模型路径 model_path = "~/lily-demo/models/qwen3.6-35b-a3b" # 2. 加载分词器 tokenizer = AutoTokenizer.from_pretrained(model_path) # 3. 加载 Lily 模型 # 参数说明: # model_path: 模型权重目录 # dtype: 权重精度,可选 "float16"、"int8"、"int4" # max_seq_len: 最大序列长度 model = LilyModel.from_pretrained( model_path, dtype="float16", max_seq_len=2048, ) # 4. 构造输入 prompt = "用一段话解释什么是混合专家模型 MoE。" inputs = tokenizer(prompt, return_tensors="pt") # 5. 执行推理 start = time.time() outputs = model.generate( inputs.input_ids, max_new_tokens=256, temperature=0.7, top_p=0.9, ) elapsed = time.time() - start # 6. 解码并输出结果 response = tokenizer.decode(outputs[0], skip_special_tokens=True) print("=== 输入 ===") print(prompt) print("=== 输出 ===") print(response) print(f"=== 耗时:{elapsed:.2f} 秒 ===") if __name__ == "__main__": main()这段代码的结构是:加载模型 → 编码输入 → 推理 → 解码输出。max_new_tokens=256控制生成长度,temperature和top_p控制随机性。
5.3 运行并观察输出
执行以下命令运行脚本:
cd ~/lily-demo source lily/.venv/bin/activate python scripts/run_inference.py预期输出包含输入的提示词、模型生成的回答,以及推理耗时。首次运行时模型需要完成权重加载和算子初始化,耗时较长属于正常现象。
如果程序提示显存或内存不足,可以改用dtype="int8"重新加载模型:
model = LilyModel.from_pretrained( model_path, dtype="int8", max_seq_len=2048, )这个示例重点演示配置思路与代码结构。实际版本中,类名、参数名称可能因版本迭代而变化,请以官方文档为准。
5.4 交互式聊天模式
命令行生成脚本适合快速验证。如果你想要一个可以连续对话的交互式环境,可以启动 Lily 自带的 CLI 聊天模式。参考命令如下:
lily chat \ --model ~/lily-demo/models/qwen3.6-35b-a3b \ --dtype float16 \ --max_seq_len 4096进入聊天界面后,输入文本即可得到模型回复。输入exit或quit退出。
6. Apple silicon 性能优化要点
6.1 批次大小(Batch Size)与吞吐量的平衡
本地推理时,批次大小直接影响吞吐量。批次增大,GPU 利用率提高,但内存占用也随之增加。Apple silicon 统一内存的优势在高批次下更明显,因为不需要额外的显存拷贝。
不过,MoE 模型有一个特性:不同 token 激活的专家不同。当批次增大时,被激活的专家集合更分散,可能导致部分专家成为瓶颈。实践建议是,先从 batch size = 1 开始验证正确性,再逐步增加批次大小,观察吞吐量和内存变化。
6.2 内存带宽是核心瓶颈
Apple silicon 的 GPU 算力与顶级台式机显卡有差距,但内存带宽表现很好。比如 M 系列 Pro/Max/Ultra 芯片的带宽远高于普通笔记本内存。在运行 MoE 模型时,真正限制速度的往往是“把权重从内存搬运到计算单元”的带宽,而不是 GPU 算力。
所以优化重点应该放在减少内存访问次数上,包括:
- 使用量化权重,减少每次读取的数据量。
- 尽量多地复用已加载的专家权重。
- 避免频繁地在 CPU 与 GPU 之间切换任务。
6.3 温度控制与功耗管理
长时间运行推理会让 Mac 的风扇全速运转。Apple silicon 虽然能效比高,但连续高负载下仍会发热降频。具体做法是:
- 在系统设置中开启“低电量模式”,限制 CPU/GPU 功耗。
- 使用
powermetrics命令监控功耗和温度:
sudo powermetrics --samplers smc -i 1- 控制推理进程的 CPU 亲和性,如果 Lily 支持,可以限制使用核心数。
6.4 模型权重格式的合理选择
对 Qwen3.6-35B-A3B 来说,不同精度的内存占用差异很大:
| 精度 | 近似内存占用 | 推理速度 | 质量 |
|---|---|---|---|
| Float16 / BF16 | 约 70GB | 较慢 | 完整精度 |
| Int8 量化 | 约 35GB | 中 | 损失小 |
| Int4 量化 | 约 18GB | 快 | 损失中等 |
如果内存只有 32GB,建议优先尝试 Int8 量化;如果内存 64GB 以上,可以尝试 Float16。如果你发现某次运行内存不足,不要直接上 Int4,先检查是否还有其他进程占用大量内存。
7. 常见问题与排查思路
7.1 模型加载时提示内存不足
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 加载模型时报内存不足 | 设备物理内存过小 | 换用 Int8 或 Int4 量化权重 |
| 加载后系统卡死 | 统一内存被模型占满 | 退出其他大型应用,减少内存占用 |
| 运行一段时间后被系统杀进程 | 长期高负载触发内存压力 | 降低 batch size,缩短 max_seq_len |
排查时可以先用系统自带的“活动监视器”查看内存压力曲线。如果内存压力持续为红色,说明设备容量不足以支撑当前配置。
7.2 推理速度远低于预期
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 生成速度很慢 | 使用了非量化权重 | 切换 int8 或 int4 |
| GPU 利用率低 | 任务调度在 CPU 上执行 | 检查 Lily 是否自动启用 GPU,手动指定设备 |
| 速度不稳定 | 系统散热降频 | 检查温度,控制负载,避免多个重任务同时运行 |
在 Apple silicon 上,如果推理引擎只是把模型加载进内存,但实际计算仍跑在 CPU 上,性能会大打折扣。你需要确认日志中出现了类似 “Using Metal GPU” 的信息。
7.3 输出质量明显偏差
模型输出质量差,不一定是推理引擎的问题。先检查:
- 是否使用了过低精度的量化(如 Int4)。
- 提示词是否完整。
- 采样参数是否设置过小或过大。
- 模型文件是否完整下载,没有中断。
建议用相同的提示词,分别运行 Float16 和 Int8,对比输出结果,判断偏差来源。
7.4 环境安装时的编译报错
编译错误最常见的原因是缺少开发依赖。你可以依次尝试:
# 1. 安装 Xcode 命令行工具 xcode-select --install # 2. 安装必要系统库 brew install cmake brew install libomp # 3. 清理并重装 Python 依赖 pip uninstall -y lily pip install -e .如果错误信息中包含clang: error: unsupported option,通常是编译器版本与 macOS SDK 不匹配,升级 Xcode 后重试。
8. 最佳实践与工程建议
8.1 把推理封装成服务
命令行调用适合验证功能,但在实际项目中,建议把 Lily 封装为本地推理服务,通过 HTTP API 对外提供接口,好处是解耦调用方与推理引擎,方便切换模型、升级引擎。
你可以使用 Flask 或 FastAPI 构建一个简易服务:
# 文件路径:~/lily-demo/scripts/serve.py from fastapi import FastAPI, Request from lily import LilyModel, AutoTokenizer app = FastAPI() model = LilyModel.from_pretrained( "~/lily-demo/models/qwen3.6-35b-a3b", dtype="int8", max_seq_len=2048, ) tokenizer = AutoTokenizer.from_pretrained("~/lily-demo/models/qwen3.6-35b-a3b") @app.post("/generate") async def generate(request: Request): data = await request.json() prompt = data.get("prompt", "") max_new_tokens = data.get("max_new_tokens", 128) inputs = tokenizer(prompt, return_tensors="pt") outputs = model.generate( inputs.input_ids, max_new_tokens=max_new_tokens, ) response = tokenizer.decode(outputs[0], skip_special_tokens=True) return {"response": response}启动服务:
cd ~/lily-demo source lily/.venv/bin/activate uvicorn scripts.serve:app --host 127.0.0.1 --port 8000请求示例:
curl -X POST http://127.0.0.1:8000/generate \ -H "Content-Type: application/json" \ -d '{"prompt": "你好,请介绍一下自己", "max_new_tokens": 64}'8.2 配置隔离与多环境管理
推理引擎的配置项(模型精度、max_seq_len、GPU 开关)应该与代码分离。推荐使用 YAML 配置文件:
# 文件路径:~/lily-demo/configs/default.yaml model: path: ~/lily-demo/models/qwen3.6-35b-a3b dtype: int8 max_seq_len: 2048 generate: max_new_tokens: 256 temperature: 0.7 top_p: 0.9 server: host: 127.0.0.1 port: 8000然后编写一个加载配置的模块,避免把参数散落在各个脚本中。
8.3 异常处理与日志记录
本地推理服务在生产环境中要特别关注异常情况:OOM(内存不足)、超时、请求并发等。建议做到三点:
- 捕获
MemoryError并返回友好提示,避免进程崩溃。 - 为每个请求记录开始时间、结束时间、token 数,方便分析吞吐量。
- 配置请求超时,避免推理卡住时连接长时间挂起。
一个示例日志格式:
2025-06-01 10:00:01 INFO request_id=abc123 prompt_tokens=12 generated_tokens=128 elapsed=3.42s8.4 安全与合规注意事项
本地部署大模型时,有几个边界要守住:
- 模型服务只监听
127.0.0.1,不要默认暴露到公网。 - 如果需要局域网访问,务必增加 API Token 鉴权。
- 不要将内部敏感数据未经脱敏地直接输入模型。
- 模型输出需要过滤,避免生成有害内容。
- 生产环境变更前,在测试环境验证内存占用、响应时间与稳定性。
Apple silicon 本地推理的引入不应成为安全简化的理由,权限模型和审计日志仍需保持完整。
8.5 保持依赖与模型的可复现性
大模型迭代速度快,Lily 引擎和 Qwen 模型都在持续更新。建议:
- 使用
requirements.txt锁定依赖版本。 - 记录模型权重的下载时间、来源和完整 SHA 哈希。
- 定期更新引擎时,先跑一个标准测试集,对比输出变化。
这样可以避免“昨天还能跑,今天升级依赖后结果完全变了”的问题。
9. 总结与下一步学习建议
这篇文章围绕 Perplexity 开源的本地推理引擎 Lily,拆解了它在 Apple silicon 上运行 Qwen3.6-35B-A3B 的完整链路。核心收获可以归纳为几点:
- MoE 模型的总参数量与激活参数量是两回事,理解这一点才能理解 Lily 的优化重点。
- Apple silicon 统一内存架构让本地加载大模型成为可能,但推理引擎必须针对 Metal 和内存管理做定制适配。
- 量化精度、内存容量和输出质量之间存在三角平衡,需要根据实际硬件选择配置。
- 本地推理服务化时,配置隔离、日志、鉴权和异常处理缺一不可。
如果你使用的是 32GB 内存的 MacBook Pro,建议从 Int8 量化开始;如果你有 64GB 内存的 Mac Studio,可以直接挑战 Float16。从速度角度,MoE 模型在 Apple silicon 上的表现会比同参数稠密模型好很多,这就是它的实际价值。
下一步你可以继续关注几个方向:Lily 官方的更新日志,看它对更多模型的支持情况;Qwen3.6 系列的其他规格,比如更小或更大尺寸的模型在本地机器的表现;以及量化技术的演进,AWQ、GPTQ 等方案与本地推理引擎的适配效果。
本地推理是一个值得长期投入的方向,它能让你在完全掌控数据的前提下,灵活体验前沿模型能力。如果这篇文章对你有帮助,可以收藏备用,也欢迎在实践中多跑几种配置组合,找到最适合自己设备的那一套参数。