把M5 Ultra Mac Studio作为AI服务器真正投入使用,光靠Quick Start上那一行看起来很漂亮很简单的命令是远远不够的:demo会告诉你某个机器可以跑某个模型,但这个模型真正要投入生产,你需要研究考虑的细节真的很多。
这些天折腾了很多MLX VLM的东西,和大家分享一下:
首先,无论你运行什么模型,都要修改默认的KV窗口、并发上限、缓存内存上限、缓存磁盘上限和内存驻留条数,这样你才能获得一个相对可用的上下文长度,并保证中缓率,我的设置是这样的:
--max-kv-size 1048576(最大1M)
MLX_VLM_MAX_NUM_SEQS=4(最多4并发)
APC_MEMORY_MAX_GB=24(24GB内存缓存)
APC_DISK_MAX_GB=1024(1T磁盘缓存)
APC_EXACT_CACHE_ENTRIES=8(内存驻留最多8条)
另外,一定要检查APC_ENABLED这个环境变量,不开这个环境变量就没有缓存,一切请求都不会中缓
但即使如此,带图的请求中缓率也异常低,这是因为:
1,媒体安全门要求命中长度必须超过新Prompt的最后一张图,这让追加新截图必然导致无法中缓;
2,计算媒体哈希时,MLX VLM会覆盖请求内的全部图片,追加新图必然导致新旧哈希不等。
因此我给MLX VLM做了三处修改:
1,放宽媒体安全门限制,允许带图请求命中"之后还带新图"的前缀;
2,让图片哈希只覆盖候选前缀内的图,防止追加新图影响旧条目;
3,让图片标记留在原属消息前缀,而不是剥离并搬到最后
(否则会导致Prefill阶段前缀发生变化,只能命中第一张图之前的部分,显著降低缓存命中率)
这三处修改是直接修改的项目内的py文件实现的,并没有原生的环境变量可以控制,属于是我自己打的补丁了
除此之外的注意点还有不少,比如Model ID和Reasoning Effort的路由规则,再比如不同Agent工具读的reasoning字段也不一样(有的读reasoning,有的读reasoning_content),这个也要注意……
当然,还有模型层面的,我最开始用的Qwen 3.8 Flash来自MLX Community,那玩意儿是纯4bit量化,精度不高,而且没有MTP,吞吐也相对更慢,后来用pipenetwork的混合4/8bit权重,但砍掉了视觉……
归根结底,很多优化都是为了让它能在128GB上跑起来,但放在256GB机器上就没必要这么做了,所以我最后是缝合了上游MTP草稿模型+MLX Community的分词器+pipenetwork的混合4/8bit权重,做到了同时支持VL+MTP+mixed 4/8bit
这一周下来真是太多的学习……
