
llama.cpp iOS 集成:Swift 开发指南
将 llama.cpp 集成到 iOS 应用的分步指南。项目设置、Metal GPU 加速、模型加载、token 流式输出和生产部署的内存管理。
llama.cpp 是在 Apple 硬件上运行 GGUF 语言模型的推理引擎。它使用 Metal 进行 GPU 加速,支持从 A14(iPhone 12)开始的所有 iPhone 机型,根据模型大小和设备不同,token 生成速度在每秒 20-50 个之间。
本指南涵盖从项目设置到生产部署的完整集成流程。
集成选项
选项 1:Swift Package(推荐)
llama.cpp 仓库包含一个 Swift Package,您可以直接添加到 Xcode 项目中:
- 在 Xcode 中,前往 File,Add Package Dependencies
- 输入 llama.cpp 仓库 URL
- 选择所需的版本或分支
- 在 Swift 文件中导入
llama模块
这是最简单的集成路径。该 package 将 llama.cpp 作为构建的一部分编译,并将 C API 暴露给 Swift。
选项 2:预编译 Framework
将 llama.cpp 编译为 XCFramework,作为二进制依赖项包含。这样可以避免在项目中编译 C++ 源代码:
# 构建 framework
mkdir build-ios && cd build-ios
cmake .. -G Xcode \
-DCMAKE_SYSTEM_NAME=iOS \
-DCMAKE_OSX_DEPLOYMENT_TARGET=15.0 \
-DLLAMA_METAL=ON \
-DBUILD_SHARED_LIBS=OFF
cmake --build . --config Release
选项 3:llama.swift 封装
社区维护的 Swift 封装在 C 绑定之上提供了更符合 Swift 风格的 API。这些封装处理了桥接样板代码并暴露了更简洁的接口。
项目设置
最低要求
- iOS 15.0+(Metal 计算着色器需要)
- Xcode 15+
- 测试需要物理设备(模拟器不支持 Metal 计算)
构建设置
将 Metal framework 添加到项目:
- 链接
Metal.framework和MetalKit.framework - 如需自定义着色器,设置
METAL_COMPILER_FLAGS
权限
无需特殊权限。llama.cpp 在应用的普通沙箱中运行。内存使用是主要关注点(见下文)。
加载模型
import llama
class LlamaEngine {
private var model: OpaquePointer?
private var context: OpaquePointer?
func loadModel(at path: String) throws {
// 模型参数
var modelParams = llama_model_default_params()
modelParams.n_gpu_layers = 99 // 将所有层卸载到 Metal
// 加载 GGUF 文件
model = llama_load_model_from_file(path, modelParams)
guard model != nil else {
throw LlamaError.modelLoadFailed
}
// 创建推理上下文
var ctxParams = llama_context_default_params()
ctxParams.n_ctx = 2048 // 上下文窗口大小
ctxParams.n_threads = 4 // CPU 线程数(用于非 Metal 操作)
ctxParams.n_batch = 512 // 提示处理的批次大小
context = llama_new_context_with_model(model, ctxParams)
guard context != nil else {
throw LlamaError.contextCreationFailed
}
}
func unload() {
if let ctx = context {
llama_free(ctx)
context = nil
}
if let mdl = model {
llama_free_model(mdl)
model = nil
}
}
deinit {
unload()
}
}
关键参数
n_gpu_layers: 设置为 99(或模型的实际层数)以将所有内容卸载到 Metal。这是最重要的性能设置。
n_ctx: 上下文窗口大小(以 token 为单位)。更大的窗口使用更多内存。2048 对大多数移动端用例来说是实用的。如需更长对话可设为 4096。
n_threads: 用于在 CPU 上运行操作的线程数。设置为设备的性能核心数量(iPhone 上通常为 2-4 个)。
n_batch: 提示评估期间每批处理的 token 数。更高的值加速提示处理但使用更多内存。512 是一个好的默认值。
生成文本
分词和提示处理
extension LlamaEngine {
func generate(
prompt: String,
maxTokens: Int = 256,
temperature: Float = 0.7,
onToken: @escaping (String) -> Void
) -> String {
guard let ctx = context, let mdl = model else { return "" }
// 对提示进行分词
let promptTokens = tokenize(prompt)
// 创建提示处理批次
var batch = llama_batch_init(Int32(promptTokens.count), 0, 1)
for (i, token) in promptTokens.enumerated() {
llama_batch_add(&batch, token, Int32(i), [0], i == promptTokens.count - 1)
}
// 处理提示
llama_decode(ctx, batch)
llama_batch_free(batch)
// 生成 token
var output = ""
for _ in 0..<maxTokens {
let logits = llama_get_logits(ctx)
// 采样下一个 token
let token = sampleToken(logits: logits!, temperature: temperature)
// 检查是否到达序列末尾
if llama_token_is_eog(mdl, token) { break }
// 将 token 解码为字符串
let piece = decodeToken(token)
output += piece
onToken(piece)
// 准备下一个批次
var nextBatch = llama_batch_init(1, 0, 1)
llama_batch_add(&nextBatch, token, Int32(promptTokens.count + output.count), [0], true)
llama_decode(ctx, nextBatch)
llama_batch_free(nextBatch)
}
return output
}
private func tokenize(_ text: String) -> [llama_token] {
let maxTokens = Int32(text.utf8.count + 16)
var tokens = [llama_token](repeating: 0, count: Int(maxTokens))
let count = llama_tokenize(model, text, Int32(text.utf8.count),
&tokens, maxTokens, true, false)
return Array(tokens.prefix(Int(count)))
}
private func decodeToken(_ token: llama_token) -> String {
var buf = [CChar](repeating: 0, count: 64)
let len = llama_token_to_piece(model, token, &buf, 64, 0, false)
return String(cString: Array(buf.prefix(Int(len))) + [0])
}
}
Metal GPU 加速
当设置了 n_gpu_layers 时,Metal 加速会自动启用。llama.cpp 在首次加载时编译 Metal 着色器(耗时 1-2 秒,之后会缓存)。
性能影响
| 配置 | iPhone 15 Pro, 3B Q4 | iPhone 14, 3B Q4 |
|---|---|---|
| 仅 CPU (n_gpu_layers = 0) | 8-12 tok/s | 6-10 tok/s |
| Metal (n_gpu_layers = 99) | 18-25 tok/s | 14-18 tok/s |
Metal 平均提供 2 倍加速。生产环境务必启用。
Metal 着色器缓存
llama.cpp 首次在设备上运行时会编译 Metal 着色器。这会在首次模型加载时增加 1-2 秒。后续加载是即时的(着色器由 iOS 缓存)。
内存管理
内存预算
iOS 大约给应用分配设备总 RAM 的 50-70%,超过后会触发 jetsam(强制终止):
| 设备 | 总 RAM | 应用预算 | 可用于模型 |
|---|---|---|---|
| iPhone 12 (4GB) | 4GB | 约 2.5GB | 约 1.5GB |
| iPhone 14 (6GB) | 6GB | 约 3.5GB | 约 2.5GB |
| iPhone 15 Pro (8GB) | 8GB | 约 5GB | 约 3.5GB |
3B Q4 模型在 RAM 中占用约 2.2GB。在 6GB 设备上,这为应用、iOS 和其他进程留下约 1.3GB。紧张但可行。
最佳实践
// 加载前检查可用内存
func canLoadModel(sizeBytes: Int) -> Bool {
let available = os_proc_available_memory()
// 为应用和系统预留 500MB
return available > sizeBytes + 500_000_000
}
// 处理内存警告
func didReceiveMemoryWarning() {
engine.unload()
// 显示"模 型已卸载"消息,提供重新加载选项
}
- 始终在加载前检查可用内存
- 当 AI 功能不活跃时卸载模型
- 通过卸载模型来处理
didReceiveMemoryWarning - 应用在后台时绝不保持模型加载状态
模型分发
内置打包
将 GGUF 文件作为资源添加到 Xcode 项目中。通过 Bundle.main 访问:
let modelPath = Bundle.main.path(forResource: "model", ofType: "gguf")!
对于超过 200MB 的模型,考虑使用 On Demand Resources 以避免增大初始下载大小。
下载安装
安装后下载模型并存储在应用的 Documents 目录中:
let documentsURL = FileManager.default
.urls(for: .documentDirectory, in: .userDomainMask)[0]
let modelURL = documentsURL.appendingPathComponent("model.gguf")
对大文件使用 URLSession 后台下载。支持中断后恢复下载。
生产清单
- 模型在目标设备上加载不崩溃(在最低 RAM 目标设备上测试)
- Metal 加速已启用(通过性能日志验证)
- 内存警告处理程序优雅地卸载模型
- 下载后验证 模型文件完整性(SHA256)
- 流式 token 在 UI 中平滑显示
- 用户可以取消生成(中断生成循环)
- 应用切换到后台时卸载模型
- 模型未加载时应用正常运行(优雅降级)
微调后的 GGUF 模型是关键要素。基础模型生成通用回复。在您的领域数据上微调的模型(通过 Ertas 等平台)生成与应用目的和风格相匹配的回复。llama.cpp 的集成方式无论使用哪个模型都是相同的。
Ship AI that runs on your users' devices.
Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.
Keep reading

AI in iOS Apps: CoreML, Cloud APIs, and On-Device LLMs Compared
Three paths to AI in your iOS app. CoreML for Apple's ecosystem, cloud APIs for capability, and on-device LLMs via llama.cpp for cost and privacy. A practical comparison for Swift developers.

Can LLMs Actually Run on iPhones? Benchmarks and Real-World Performance
Real benchmark data for running LLMs on iPhones via llama.cpp. Token generation speeds, memory usage, and thermal behavior across iPhone models from the iPhone 12 to iPhone 16 Pro.

llama.cpp on Android: A Kotlin Integration Guide
Step-by-step guide to integrating llama.cpp into an Android app with Kotlin. JNI bindings, Vulkan GPU acceleration, model loading, and memory management across the Android device spectrum.