别再把大模型供在云端了,WWDC26 CoreAI 大模型下凡实战

引子

以前在苹果生态里搞 AI,有点像去五星级酒店点外卖:

你想吃火锅,前台微笑着说:「先生,我们这里只提供酒店特供套餐。」

Foundation Models 很香,隐私也漂亮,但菜单是苹果定的。第三方大模型?抱歉,请去云端排队,或者自己用 Metal 手搓推理引擎------后者相当于自带锅、自带火、自带厨师,还得保证不被 jetsam 一脚踹出房间。

WWDC26 之后,情况变了。

CoreAI 登场。苹果不再只给你「自家菜」,而是递过来一套厨房:你可以把 PyTorch 模型端上来,切好、炖好、装进 .aimodel,然后在 iPhone / Mac 上本地端着碗吃。

今天这篇,就从「这到底是什么」讲到「第三方 Qwen 怎么真在本机流式吐字」------有背景、有逻辑、有能跑通的代码味道。读完你未必马上能上架,但至少不会再把 CoreAI 当成「又一个神秘 Framework」。

无需等待,让我们马上开始 CoreAI 大冒险吧!;-)


一、WWDC26 的背景:苹果为什么要推 CoreAI?

先把时间线捋直,不然后面代码会像无根之木。

过去几年,苹果的端侧 AI 路线大致是:

  1. Core ML:偏传统机器学习 / 视觉音频,擅长「看图说话」,不太擅长「边想边聊」。
  2. Apple Intelligence + Foundation Models:系统级大模型能力,隐私优先,但模型选择权在苹果手里。
  3. 开发者的真实痛点:我想跑 Qwen、Llama、自家微调模型------既要 GPU/ANE 性能,又要 Swift 友好 API,还想少写一点 KV Cache 手活。

WWDC26 给出的答案叫 CoreAI

  • 面向 Apple silicon 的新一代本地推理框架;
  • 配套工具链:coreai-torch(导出)→ coreai-build(编译)→ CoreAI runtime(运行)
  • 官方参考仓 apple/coreai-models:既有导出配方,也有 Swift 侧 LLM 引擎、采样、KV Cache 等运行时工具;
  • 系统门槛很硬核:macOS / iOS 27.0+,Xcode 27.0+------不是「旧系统装个 SDK 就能用」那种温柔。

一句话概括:

CoreAI 不是「又一个聊天 SDK」,而是「把任意合适结构的模型,变成苹果芯片上的一等公民」的整条产线。

Foundation Models 像「苹果官方外卖」;CoreAI 像「你自带食材,厨房和灶台归苹果管」。


二、先建立心智模型:CoreAI 在干什么?

别一上来就背 API。先记住这条流水线:

text 复制代码
AUTHOR(可选)     按平台重写模型结构(静态 shape、ANE/GPU 友好)
    ↓
COMPRESS(可选)   量化 / 调色盘压缩,换体积与精度
    ↓
EXPORT             PyTorch → AIProgram(coreai-torch / TorchConverter)
    ↓
COMPILE(可选)    AOT 编译到目标平台(coreai-build)
    ↓
RUN                设备上加载 .aimodel,Swift / Python 推理

对应用开发者来说,日常最常碰到的是最后一步 RUN

而对「第三方大模型适配」来说,你会拿到的是别人已经导好的 LanguageBundle------目录里通常长这样:

text 复制代码
some_model_bundle/
  xxx.aimodel/          ← 真正的模型资产(含 main.mlirb 等)
  metadata.json
  tokenizer/

.aimodel 不是「把权重 zip 一下改个后缀」。它是经过导出、优化、面向 Apple 运行时的模型资产;LLM 场景下,外面还会包一层 LanguageBundle,把 tokenizer、上下文长度、function map 这些聊天相关的元数据绑在一起。

浅层理解:

CoreAI = 本地跑模型的「操作系统级厨房」。

深层理解:

你写的不是「HTTP 请求 OpenAI」,而是「加载 bundle → 创建推理引擎 → token 级 generate 流」。


三、最简 Runtime:先看「一张图」怎么跑

在聊 LLM 之前,先看官方风格的最小推理------这能帮你分清两层 API:

  • 底层AIModel + InferenceFunction + NDArray(通用张量推理)
  • 上层LanguageBundle + EngineFactory + InferenceEngine(给 LLM 准备好的引擎)

底层大概长这样:

swift 复制代码
import CoreAI

let model = try await AIModel(contentsOf: modelURL)
guard let fn = try model.loadFunction(named: "main") else { return }

var input = NDArray(shape: [1, 3, 224, 224], scalarType: .float32)
var view = input.mutableView(as: Float32.self)
// 填入图像数据...

var outputs = try await fn.run(inputs: ["image": input])
let result = outputs.remove("logits")?.ndArray

导出侧对应的是 Python:

python 复制代码
from coreai_torch import TorchConverter, get_decomp_table
import torch

ep = torch.export.export(model, args=(torch.randn(1, 3, 224, 224),))
ep = ep.run_decompositions(get_decomp_table())

program = (
    TorchConverter()
    .add_exported_program(ep, input_names=["image"], output_names=["logits"])
    .to_coreai()
)
program.optimize()
program.save_asset("model.aimodel")

看到没?苹果这次把「训练框架 → 设备资产 → App 调用」串成了闭环。

LLM 只是在这条环上,多叠了一层语言引擎。


四、进入正题:第三方 LLM 怎么接进 CoreAI?

下面以社区已转换好的 Qwen3.5-2B CoreAI LanguageBundle 为例(Hugging Face 上已有现成资产)。思路适用于同类 pipelined LLM。

1)加载:不是 open(file),是「建一座小发电厂」

swift 复制代码
import CoreAIShared
import CoreAILanguageModels
import Tokenizers

// 某些 pipelined decode 图是 static [1,1],需要在创建引擎前设置
if getenv("COREAI_CHUNK_THRESHOLD") == nil {
    setenv("COREAI_CHUNK_THRESHOLD", "1", 1)
}

let bundle = try LanguageBundle(at: bundleDirectory)

let config = ModelConfig(
    name: bundle.name,
    tokenizer: bundle.tokenizer,
    vocabSize: bundle.vocabSize,
    maxContextLength: bundle.maxContextLength,
    serializedModel: [bundle.modelAssetPath],
    function: bundle.language.functionMap?.name(for: "main") ?? "main"
)

let engine = try await EngineFactory.createEngine(
    config: try JSONEncoder().encode(config),
    modelURL: try bundle.requireModelURL(for: ModelBundle.ComponentKey.main),
    options: EngineOptions(variant: "coreai-pipelined")
)

let tokenizer = try await bundle.loadTokenizer()

这里有几个「看起来像咒语、其实很关键」的点:

为什么重要
LanguageBundle 一次读齐模型路径、词表、上下文长度、tokenizer
EngineFactory.createEngine 真正把 .aimodel 特化成可推理引擎
variant: "coreai-pipelined" 告诉运行时:这是流水线式 decode 图,不是普通前馈
COREAI_CHUNK_THRESHOLD=1 适配 static [1,1] decode;设错了可能加载成功、生成翻车

第一次加载往往会触发 specialization(特化):系统按当前设备把计算图「烤」成更合适的执行形态。冷启动可能几十秒,还可能吃掉数 GB 磁盘缓存------所以产品上千万别让用户盯着转圈圈傻等,得有「首次准备模型」的心智。

2)Prompt:别直接 encode(用户原话)

很多模型吃的是 chat template,不是裸字符串。正确姿势是先组 messages,再套模板:

swift 复制代码
let messages: [[String: String]] = [
    [
        "role": "system",
        "content": "你是一个直接回答问题的助手。优先使用中文,回答简洁清楚。"
    ],
    [
        "role": "user",
        "content": prompt
    ]
]

let inputIds = try tokenizer
    .applyChatTemplate(messages: messages)
    .map { Int32($0) }

guard inputIds.count < maxContextLength - 1 else {
    throw MyError.promptTooLong
}

对 Qwen 这类带 /think/no_think 的模型,还可以在应用层做三种模式:

  • 高效 :系统提示 + /no_think,尽量直接给答案
  • 推理 :追加 /think,允许展开思考
  • 跟随输入:尊重用户自己写的控制指令

这不是 CoreAI 的硬性要求,却是「第三方模型适配」里最容易被忽略的产品细节------引擎只会吐 token,不会替你懂产品语义。

3)生成:AsyncSequence 式地「一个字一个字挤牙膏」

swift 复制代码
try await engine.reset()

let stream = try engine.generate(
    with: inputIds,
    samplingConfiguration: SamplingConfiguration(
        temperature: 0.7,
        topK: 20,
        topP: 0.8,
        minP: nil
    ).normalized(),
    inferenceOptions: InferenceOptions(maxTokens: maxTokens)
)

var answer = ""
for try await step in stream {
    try Task.checkCancellation()
    let tokenId = Int(step.tokenId)
    // 解码、过滤 stop sequence、<think> 块等
    let chunk = decodeAndFilter(tokenId)
    if !chunk.isEmpty {
        answer += chunk
        // 推到 SwiftUI
    }
}

这就是本地 LLM 的「灵魂回路」:

text 复制代码
prompt → chat template → token ids
       → engine.generate 流
       → 逐 token 解码
       → 停词 / 过滤 / UI 追加

采样参数(Temperature / Top-K / Top-P / Min-P)和云 API 概念一致;差别在于:一切发生在进程内,隐私不错,内存账单很真实。


五、再深一层:适配第三方模型时,你会撞上的「人情世故」

代码能跑,不等于产品能用。真实适配里,常见坑如下------每条都来自「本机真跑过」的经验,不是 PPT。

1)模型别塞进 .app

2B 级量化包常常 ~3GB。打进 App 包,审核会皱眉,用户下载会骂娘。正确姿势是:

  • 首次启动后下载 / 本地导入
  • 先落到 staging,校验齐全再原子替换到正式目录
  • 至少确认 .aimodelmain.mlirbmetadata.jsontokenizer/ 齐全,且大文件不是 Git LFS 指针冒充

2)Think 块会「偷吃」你的可见输出

模型可能先吐 <think>...。如果你在「高效模式」还直接把原文糊到 UI,用户会以为 App 坏了。

应用层需要:

  • 过滤完整 <think>...</think>
  • 未闭合时先别展示后面内容
  • 必要时用更强硬的 system prompt 重试一次

CoreAI 负责「算」,你负责「做人话」。

3)Stop sequence 与「假结束」

命中 EOS 不一定等于「答完了」。高效模式下偶发短句提前结束、没有句末标点------这时可以识别为 incomplete EOS,再补一句「只从截断处继续」。

长回答撞到 token 上限,则做续写:把已有答案塞回 prompt,要求「不要重复,从中断处自然接着写」。

4)内存与 entitlement 是物理定律

  • Mac 上建议给系统和别的进程留足余量(官方指导常见说法是留出数 GB headroom)
  • iPhone 上大模型可能需要更高内存限额相关 entitlement,否则冷 specialization 直接 bad_alloc
  • 用进程 footprint 观察「加载前后涨了多少」,比凭感觉喊「好卡」有用得多

5)平台策略不同

苹果自己的指导也很直白:

  • iOS:偏能效,静态 shape、更激进压缩,模型尽量别太大
  • macOS:可更吃规模,动态 shape / 控制流更宽松

同一套「第三方模型适配」,在 iPhone 和 Mac 上可能要选不同压缩配方------这不是口味问题,是物理与系统策略问题。


六、把整条链路压成一张图

text 复制代码
┌──────────────────────────────┐
│  已转换的 LanguageBundle     │
│  (.aimodel + tokenizer + md) │
└───────────────┬──────────────┘
                │ LanguageBundle(at:)
                ▼
┌──────────────────────────────┐
│  ModelConfig + EngineFactory │
│  variant: coreai-pipelined   │
└───────────────┬──────────────┘
                │ loadTokenizer()
                ▼
┌──────────────────────────────┐
│  chat template → input ids   │
└───────────────┬──────────────┘
                │ engine.generate(...)
                ▼
┌──────────────────────────────┐
│  Async token stream          │
│  → 过滤 / 停词 / UI 流式刷新 │
└──────────────────────────────┘

如果你只会画 HTTP 时序图,现在可以在旁边再贴一张这个------云端是请求-响应;CoreAI 是加载-特化-流式解码。


七、一句中式总结

CoreAI 的出现,意味着苹果终于承认一件事:

「端侧智能」不能只靠皇家厨师,也得允许民间大厨进厨房------但刀具、灶台、排烟系统,还得按苹果标准来。

对开发者而言:

  • :本地加载 .aimodel,Swift 里流式生成
  • :LanguageBundle + EngineFactory + chat template + 采样
  • :导出、量化、静态 shape、specialization、内存与平台策略

Foundation Models 解决「大多数 App 的官方智能」;

CoreAI 解决「我就要跑自己的 / 社区的模型,而且要跑在苹果芯上」。

两条腿,才算站稳。


尾声

今天我们顺着「第三方大模型怎么在 CoreAI 里被叫起来」走完了调用侧:bundle、引擎、模板、流式、坑点。

你手里已经有一张能照着做的地图------从「听说 WWDC26 出了 CoreAI」,走到了「真的能在本机看 Qwen 一个 token 一个 token 往外蹦」。

故事到这里就告一段落了,感谢宝子们的观赏。

我是大熊猫侯佩,再会啦!8-)

相关推荐
lifallen3 小时前
Avernet:Agent 的组织网络
人工智能·学习·ai·开源软件·ai编程
必须会一定会4 小时前
用纯 HTML/JS 做一个 AI 需求澄清器:把模糊想法转换成可执行任务书
开发语言·前端·javascript·人工智能·html·ai编程
00后程序员张4 小时前
有没有更轻量的 iOS 开发环境?快蝎kxapp轻量化路径与构成
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
小帅不太帅4 小时前
1.5M 参数的 OCR 模型,我把它跑进了浏览器
前端·javascript·ai编程
chaors10 小时前
DeepResearchSystem 0x08:KB 知识记忆
langchain·agent·ai编程
程序员黑豆11 小时前
Java 注释详解:单行、多行与文档注释的完整指南
java·前端·ai编程
飞哥数智坊13 小时前
实测7套 Code Agent组合:最终效果,真不只取决于模型
ai编程
东小西14 小时前
番外篇二:《不到十行代码,我用ReactAgen搭了个会自己调工具的 Agent》
openai·ai编程
kyriewen17 小时前
我用Claude Code两天干完了团队两周的排期——周报发出去那一刻我就后悔了
前端·javascript·ai编程