SwiftUI-MLX本地大模型开发(二)

介绍

SwiftUI-MLX本地大模型开发一文中,我们已经详细讲了如何利用 MLX 进行本地大模型的开发。但是通过案例可以发现 2 个问题:

  1. MLX 内置的大模型数量有限。
  2. 每次大模型都需要从 HuggingFace 下载。

如何解决这 2 个问题,方案是:定制大模型与使用离线大模型。

定制大模型

swift 复制代码
// 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 大模型。
swift 复制代码
extension MLXLLM.ModelRegistry {
    public static let localModel = ModelConfiguration(
        directory: URL(fileURLWithPath: "/Users/yangfan/Documents/modelscope/Llama-3.2-3B-Instruct"),  // 本地模型的路径
        overrideTokenizer: "PreTrainedTokenizer"
    )
}

使用

swift 复制代码
struct ContentView: View {
    // 提示词
    @State private var prompt: String = "什么是SwiftUI?"
    // 输出结果
    @State private var response: String = ""
    @State private var isLoading: Bool = false

    var 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_4bit
        let modelConfiguration = ModelRegistry.localModel
        let modelContainer = try await LLMModelFactory.shared.loadContainer(configuration: modelConfiguration) { progress in
            print("正在下载 \(modelConfiguration.name),当前进度 \(Int(progress.fractionCompleted * 100))%")
        }
        // 生成结果
        let _ = try await modelContainer.perform { [prompt] context in
            let input = try await context.processor.prepare(input: .init(prompt: prompt))
            let result = try MLXLMCommon.generate(input: input, parameters: .init(), context: context) { tokens in
                let text = context.tokenizer.decode(tokens: tokens)
                Task { @MainActor in
                    self.response = text
                    self.isLoading = false
                }
                return .more
            }
            return result
        }
    }
}

struct ResponseBubble: View {
    let text: String

    var 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)
    }
}

效果

  • 定制大模型。
  • 使用离线大模型。
相关推荐
leo03082 小时前
【LLM微调】拒绝“假装聪明”:SFTTrainer 中 completion_only_loss 新旧版本用法详解
llm·sft·huggingface·trl
ariesjzj2 小时前
DeepSeek时代的Large-scale LLM推理
大模型·llm·deepseek·推理优化·大规模ep
智泊AI4 小时前
长上下文、Agent记忆、Text2SQL中,谁会取代RAG?
llm
Mac技巧大咖10 小时前
Mac误删文件,废纸篓也清了?Mac时光机器仍可恢复找回
macos·mac误删文件
程序员果子12 小时前
零拷贝:程序性能加速的终极奥秘
linux·运维·nginx·macos·缓存·centos
天庭鸡腿哥12 小时前
macOS的功能,在Windows上也能实现
windows·microsoft·macos·visual studio·everything
weixin_4624462313 小时前
macOS 安装 git-lfs
git·macos
CoderJia程序员甲13 小时前
GitHub 热榜项目 - 日榜(2025-12-7)
git·ai·开源·llm·github
大模型教程14 小时前
小猫都能懂的大模型原理 3 - 自注意力机制
程序员·llm·agent
大模型教程14 小时前
小猫都能懂的大模型原理 2 - 初见大语言模型
程序员·llm·agent