SwiftUI-MLX本地大模型开发(二)
介绍
在 SwiftUI-MLX本地大模型开发一文中,我们已经详细讲了如何利用 MLX 进行本地大模型的开发。但是通过案例可以发现 2 个问题:
- MLX 内置的大模型数量有限。
- 每次大模型都需要从 HuggingFace 下载。
如何解决这 2 个问题,方案是:定制大模型与使用离线大模型。
定制大模型
- 通过扩展
MLXLLM.ModelRegistry
实现模型的定制。 - 可以在 Hugging Face 模型搜索地址 中搜索需要的 MLX 大模型。
// MARK: - 注册自定义模型,模型必须为MLX格式
extension MLXLLM.ModelRegistry {public static let llama3_2_3B_4bit = ModelConfiguration(id: "mlx-community/Llama-3.2-3B-Instruct-4bit", // Hugging Face上模型的仓库路径overrideTokenizer: "PreTrainedTokenizer" // 分词器)
}
使用离线大模型
- 每次都从 HuggingFace 在线下载模型非常麻烦,如果已经离线下载了模型到本地,可以通过指定路径的方式加载模型。
- 可以在 Model Scope 模型搜索地址 中搜索并下载需要的 MLX 大模型。
extension MLXLLM.ModelRegistry {public static let localModel = ModelConfiguration(directory: URL(fileURLWithPath: "/Users/yangfan/Documents/modelscope/Llama-3.2-3B-Instruct"), // 本地模型的路径overrideTokenizer: "PreTrainedTokenizer")
}
使用
struct ContentView: View {// 提示词@State private var prompt: String = "什么是SwiftUI?"// 输出结果@State private var response: String = ""@State private var isLoading: Bool = falsevar body: some View {VStack(spacing: 16) {// 顶部输入区域HStack {TextField("输入提示词...", text: $prompt).textFieldStyle(.roundedBorder).font(.system(size: 16))Button {response = ""Task {do {try await generate()} catch {debugPrint(error)}}} label: {Text("生成").foregroundStyle(.white).padding(.horizontal, 16).padding(.vertical, 8).background(prompt.isEmpty ? Color.gray : Color.blue).cornerRadius(8)}.buttonStyle(.borderless).disabled(prompt.isEmpty || isLoading)}.padding(.horizontal).padding(.top)// 分隔线Rectangle().fill(Color.gray.opacity(0.2)).frame(height: 1)// 响应展示区域if response != "" {ResponseBubble(text: response)}Spacer()}if isLoading {ProgressView().progressViewStyle(.circular).padding()}}
}extension ContentView {// MARK: 文本生成func generate() async throws {isLoading = true// 加载模型// let modelConfiguration = ModelRegistry.llama3_2_3B_4bitlet modelConfiguration = ModelRegistry.localModellet modelContainer = try await LLMModelFactory.shared.loadContainer(configuration: modelConfiguration) { progress inprint("正在下载 \(modelConfiguration.name),当前进度 \(Int(progress.fractionCompleted * 100))%")}// 生成结果let _ = try await modelContainer.perform { [prompt] context inlet input = try await context.processor.prepare(input: .init(prompt: prompt))let result = try MLXLMCommon.generate(input: input, parameters: .init(), context: context) { tokens inlet text = context.tokenizer.decode(tokens: tokens)Task { @MainActor inself.response = textself.isLoading = false}return .more}return result}}
}struct ResponseBubble: View {let text: Stringvar body: some View {ScrollView {VStack(alignment: .leading, spacing: 8) {Text("AI").font(.system(size: 16)).foregroundColor(.gray)Text(text).font(.system(size: 16)).lineSpacing(4).padding().background(Color.blue.opacity(0.1)).cornerRadius(12)}}.padding(.horizontal)}
}
效果
- 定制大模型。

定制大模型.gif
- 使用离线大模型。

使用离线大模型.gif
© 著作权归作者所有,转载或内容合作请联系作者

喜欢的朋友记得点赞、收藏、关注哦!!!