当前位置: 首页 > news >正文

移动端调用大模型详解

🌟 大家好,我是“没事学AI”!
🤖 在AI的星辰大海里,我是那个执着的航海者,带着对智能的好奇不断探索。
📚 每一篇技术解析都是我打磨的罗盘,每一次模型实操都是我扬起的风帆。
💻 每一行代码演示都是我的航线记录,每一个案例拆解都是我的藏宝图绘制。
🚀 在人工智能的浪潮中,我既是领航员也是同行者。让我们一起,在AI学习的航程里,解锁更多AI的奥秘与可能——别忘了点赞、关注、收藏,跟上我的脚步,让“没事学AI”陪你从入门到精通!

目录

      • 一、端侧调用大模型支持的格式(iOS与安卓对比)
      • 二、格式的应用场景与核心区别
        • 1. `.onnx`格式(开放神经网络交换格式)
        • 2. `.tflite`格式(TensorFlow Lite专用格式)
        • 3. `.mlmodel/.mlpackage`格式(Core ML专用格式)
        • 4. `.mnn`格式(阿里MNN框架格式)
      • 三、技术实现(端侧本地调用)
        • (一)安卓端实现
          • 1. `.onnx`格式(基于ONNX Runtime)
          • 2. `.mnn`格式(基于MNN框架)
        • (二)iOS端实现
          • 1. `.mlmodel`格式(基于Core ML)
          • 2. `.onnx`格式(基于ONNX Runtime for iOS)

一、端侧调用大模型支持的格式(iOS与安卓对比)

移动端端侧调用大模型需依赖模型格式与硬件架构的兼容性,iOS和安卓支持的核心格式及对应框架如下:

模型格式安卓支持框架iOS支持框架核心依赖硬件加速
.onnxONNX RuntimeONNX Runtime安卓:ARM CPU/GPU(Vulkan);iOS:Metal GPU
.tfliteTensorFlow LiteTensorFlow Lite安卓:NNAPI;iOS:Core ML Delegate(间接调用ANE)
.mlmodel/.mlpackageCore MLiOS:ANE(苹果神经网络引擎)
.mnnMNN(阿里)安卓:ARM NEON/Vulkan

二、格式的应用场景与核心区别

1. .onnx格式(开放神经网络交换格式)
  • 应用场景
    中大型模型(7B-13B参数,量化后),如本地文档问答、代码补全、多轮对话。适合需要跨平台(安卓/iOS)部署、模型精度要求较高的场景(如医疗辅助诊断的本地推理)。
  • 核心优势
    跨框架兼容(支持PyTorch/TensorFlow模型转换),支持INT4/INT8量化,推理速度均衡,适合对兼容性要求高的复杂任务。
  • 局限性
    模型体积较大(7B参数INT4量化后约4GB),对移动端内存要求高(需6GB以上运存)。
2. .tflite格式(TensorFlow Lite专用格式)
  • 应用场景
    轻量级模型(<1B参数),如输入法智能补全、实时语音转文本、简单问答机器人(如儿童教育APP的离线互动)。
  • 核心优势
    体积小(1B参数INT8量化后约250MB),推理速度快(<300ms),适合资源受限的移动端,支持安卓/iOS跨平台。
  • 局限性
    复杂任务精度较低,中大型模型转换后性能损耗明显。
3. .mlmodel/.mlpackage格式(Core ML专用格式)
  • 应用场景
    苹果生态专属场景,如iPhone/iPad本地语音助手、照片内容生成(如相册智能分类+文案生成)、离线翻译。适合依赖低功耗、高性能的场景(如续航敏感的移动设备)。
  • 核心优势
    深度优化苹果硬件(ANE加速),推理延迟低(<200ms),功耗比其他格式低30%-50%。
  • 局限性
    仅支持iOS,需专门转换,兼容性差。
4. .mnn格式(阿里MNN框架格式)
  • 应用场景
    安卓高性能场景,如实时图像生成(如电商APP的虚拟试衣间)、多模态推理(图文结合的商品推荐)。
  • 核心优势
    针对ARM架构深度优化,推理速度比ONNX Runtime快10%-20%,支持动态shape输入。
  • 局限性
    仅支持安卓,生态较封闭,模型转换工具链较少。

三、技术实现(端侧本地调用)

(一)安卓端实现
1. .onnx格式(基于ONNX Runtime)

步骤

  1. 模型转换(PC端):用optimum将Hugging Face模型转为ONNX并量化(如Llama 3-8B→INT4)。
  2. 安卓集成:通过ONNX Runtime加载模型,实现推理。

代码实现

// 1. 依赖配置(app/build.gradle)
dependencies {implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.16.3'implementation 'androidx.appcompat:appcompat:1.6.1'
}// 2. 模型管理类
import ai.onnxruntime.OrtEnvironment;
import ai.onnxruntime.OrtException;
import ai.onnxruntime.OrtSession;
import android.content.Context;
import java.io.File;
import java.util.Collections;public class ONNXModelRunner {private OrtEnvironment env;private OrtSession session;private Tokenizer tokenizer;// 初始化模型(从手机本地加载)public void init(Context context) throws OrtException, IOException {// 模型路径(假设已复制到/files目录)File modelFile = new File(context.getFilesDir(), "llama3-8b-int4.onnx");env = OrtEnvironment.getEnvironment();OrtSession.SessionOptions options = new OrtSession.SessionOptions();options.setIntraOpNumThreads(4); // 启用4线程options.enableVulkanAcceleration(); // 启用GPU加速(需设备支持)session = env.createSession(modelFile.getAbsolutePath(), options);// 初始化分词器(加载vocab.txt)tokenizer = new Tokenizer(new File(context.getFilesDir(), "vocab.txt"));}// 文本生成推理public String generate(String input) throws OrtException {// 分词:文本→token IDlong[] inputTokens = tokenizer.encode(input);// 构建输入TensorOrtSession.Result result = session.run(Collections.singletonMap("input_ids", ai.onnxruntime.Tensor.createTensor(env, inputTokens, new long[]{1, inputTokens.length})));// 解码:token ID→文本long[] outputTokens = (long[]) result.get("output_ids").getValue();return tokenizer.decode(outputTokens);}// 释放资源public void close() throws OrtException {session.close();env.close();}
}// 3. 分词器实现(核心逻辑)
class Tokenizer {private Map<String, Long> vocab;private Map<Long, String> reverseVocab;public Tokenizer(File vocabFile) throws IOException {// 加载词表(格式:"词 编号")vocab = new HashMap<>();List<String> lines = Files.readAllLines(vocabFile.toPath(), StandardCharsets.UTF_8);for (String line : lines) {String[] parts = line.split(" ");vocab.put(parts[0], Long.parseLong(parts[1]));}// 构建反向映射reverseVocab = vocab.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));}public long[] encode(String text) {// 简化实现:按空格分割(实际需用Hugging Face分词逻辑)String[] words = text.split(" ");long[] tokens = new long[words.length + 2];tokens[0] = 1; // 起始符<s>for (int i = 0; i < words.length; i++) {tokens[i + 1] = vocab.getOrDefault(words[i], 0L); // 未知词用0}tokens[tokens.length - 1] = 2; // 结束符</s>return tokens;}public String decode(long[] tokens) {StringBuilder sb = new StringBuilder();for (long token : tokens) {if (token == 1 || token == 2) continue; // 跳过特殊符sb.append(reverseVocab.getOrDefault(token, "[UNK]")).append(" ");}return sb.toString().trim();}
}// 4. 调用示例(Activity)
public class ONNXActivity extends AppCompatActivity {private ONNXModelRunner runner;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_onnx);// 复制模型到本地(首次运行)copyAssetsToFiles("llama3-8b-int4.onnx", "vocab.txt");// 初始化并推理try {runner = new ONNXModelRunner();runner.init(this);String result = runner.generate("请介绍ONNX格式的优势");Log.d("ONNX Result", result);} catch (Exception e) {e.printStackTrace();}}// 复制assets文件到/files目录private void copyAssetsToFiles(String... filenames) {new Thread(() -> {try {for (String filename : filenames) {InputStream in = getAssets().open(filename);File outFile = new File(getFilesDir(), filename);OutputStream out = new FileOutputStream(outFile);byte[] buffer = new byte[1024];int len;while ((len = in.read(buffer)) > 0) out.write(buffer, 0, len);in.close();out.close();}} catch (IOException e) {e.printStackTrace();}}).start();}@Overrideprotected void onDestroy() {super.onDestroy();try {runner.close();} catch (OrtException e) {e.printStackTrace();}}
}
2. .mnn格式(基于MNN框架)

代码实现

// 1. 依赖配置
dependencies {implementation 'com.aliyun.mnn:mnn:1.3.0'
}// 2. 模型管理类
import com.aliyun.mnn.MNNNetInstance;
import com.aliyun.mnn.Tensor;
import com.aliyun.mnn.MNNForwardType;public class MNNModelRunner {private MNNNetInstance instance;private MNNNetInstance.Session session;private Tokenizer tokenizer;public void init(Context context) {// 加载模型(启用GPU加速)String modelPath = new File(context.getFilesDir(), "multimodal-model.mnn").getAbsolutePath();MNNNetInstance.Config config = new MNNNetInstance.Config();config.forwardType = MNNForwardType.FORWARD_VULKAN; // Vulkan GPU加速instance = MNNNetInstance.createFromFile(modelPath, config);MNNNetInstance.SessionConfig sessionConfig = new MNNNetInstance.SessionConfig();sessionConfig.numThread = 4;session = instance.createSession(sessionConfig);// 初始化分词器tokenizer = new Tokenizer(new File(context.getFilesDir(), "vocab.txt"));}// 多模态推理(输入文本,输出文本)public String generate(String input) {int[] inputTokens = tokenizer.encodeInt(input); // 转为int型token// 输入Tensor配置Tensor inputTensor = Tensor.create(new int[]{1, inputTokens.length}, Tensor.DataType.INT32, session);inputTensor.copyFrom(inputTokens);session.input("input_ids", inputTensor);// 推理session.run();// 输出TensorTensor outputTensor = session.getOutput("output_ids");int[] outputTokens = outputTensor.getIntData();// 释放资源inputTensor.release();outputTensor.release();return tokenizer.decodeInt(outputTokens);}
}
(二)iOS端实现
1. .mlmodel格式(基于Core ML)

步骤

  1. 模型转换(PC端):用coremltools将Hugging Face模型转为.mlmodel(如Llama 3-8B→INT8)。
  2. iOS集成:Xcode导入模型,通过Core ML API调用。

代码实现(Swift)

// 1. 导入模型(拖入Xcode,自动生成Llama3_8b类)
import CoreML// 2. 模型管理类
class CoreMLModelRunner {private let model: Llama3_8bprivate let tokenizer: Tokenizerinit() throws {// 初始化模型guard let model = try? Llama3_8b(configuration: .init()) else {throw NSError(domain: "ModelError", code: 0)}self.model = model// 初始化分词器(加载vocab.txt)guard let vocabURL = Bundle.main.url(forResource: "vocab", withExtension: "txt") else {throw NSError(domain: "TokenizerError", code: 0)}tokenizer = try Tokenizer(vocabURL: vocabURL)}// 异步推理func generate(text: String) async throws -> String {// 1. 分词let inputTokens = try tokenizer.encode(text: text)// 2. 构建输入(Core ML要求MLMultiArray)let inputShape = [1, inputTokens.count] as [NSNumber]guard let inputArray = try? MLMultiArray(shape: inputShape, dataType: .int32) else {throw NSError(domain: "InputError", code: 0)}// 填充输入数据for (index, token) in inputTokens.enumerated() {inputArray[index] = token as NSNumber}let modelInput = Llama3_8bInput(input_ids: inputArray)// 3. 推理(利用ANE加速)let output = try await model.prediction(input: modelInput)// 4. 解码let outputTokens = output.output_ids as! [Int32]return try tokenizer.decode(tokens: outputTokens)}
}// 3. 分词器实现(Swift)
class Tokenizer {private var vocab: [String: Int32] = [:]private var reverseVocab: [Int32: String] = [:]init(vocabURL: URL) throws {let content = try String(contentsOf: vocabURL, encoding: .utf8)let lines = content.components(separatedBy: .newlines)for line in lines {let parts = line.components(separatedBy: .whitespaces)if parts.count == 2, let id = Int32(parts[1]) {vocab[parts[0]] = idreverseVocab[id] = parts[0]}}}func encode(text: String) throws -> [Int32] {let words = text.components(separatedBy: .whitespaces)var tokens: [Int32] = [1] // 起始符for word in words {tokens.append(vocab[word] ?? 0)}tokens.append(2) // 结束符return tokens}func decode(tokens: [Int32]) throws -> String {var text = ""for token in tokens {guard token != 1, token != 2 else { continue }text += reverseVocab[token] ?? "[UNK]"text += " "}return text.trimmingCharacters(in: .whitespaces)}
}// 4. 调用示例(ViewController)
class CoreMLViewController: UIViewController {private var runner: CoreMLModelRunner!override func viewDidLoad() {super.viewDidLoad()do {runner = try CoreMLModelRunner()Task {let result = try await runner.generate(text: "介绍Core ML的优势")print("Core ML Result: \(result)")}} catch {print("Error: \(error)")}}
}
2. .onnx格式(基于ONNX Runtime for iOS)

代码实现(Swift)

// 1. 依赖配置(Podfile)
// pod 'ONNXRuntime'import ONNXRuntimeclass ONNXiOSRunner {private let env: ORTEnvironmentprivate let session: ORTSessionprivate let tokenizer: Tokenizerinit(modelName: String) throws {env = try ORTEnvironment(loggingLevel: .error)// 加载模型(从bundle)guard let modelURL = Bundle.main.url(forResource: modelName, withExtension: "onnx") else {throw NSError(domain: "ModelError", code: 0)}let options = ORTSessionOptions()try options.setIntraOpNumThreads(4)try options.enableMetalAcceleration() // GPU加速session = try ORTSession(environment: env, modelPath: modelURL.path, options: options)// 初始化分词器guard let vocabURL = Bundle.main.url(forResource: "vocab", withExtension: "txt") else {throw NSError(domain: "TokenizerError", code: 0)}tokenizer = try Tokenizer(vocabURL: vocabURL)}func generate(text: String) throws -> String {let inputTokens = try tokenizer.encode(text: text)let inputShape: [NSNumber] = [1, NSNumber(value: inputTokens.count)]let inputTensor = try ORTTensor(data: inputTokens,shape: inputShape,elementType: .int64,environment: env)> 🌈 我是“没事学AI”!要是这篇文章让你学 AI 的路上有了点收获:
👁️ 【关注】跟我一起挖 AI 的各种门道,看看它还有多少新奇玩法等着咱们发现
👍 【点赞】为这些有用的 AI 知识鼓鼓掌,让更多人知道学 AI 也能这么轻松
🔖 【收藏】把这些 AI 小技巧存起来,啥时候想练手了,翻出来就能用
💬 【评论】说说你学 AI 时的想法和疑问,让大家的思路碰出更多火花
学 AI 的路还长,咱们结伴同行,在 AI 的世界里找到属于自己的乐趣和成就!
http://www.xdnf.cn/news/1285363.html

相关文章:

  • Web学习笔记5
  • [git] 重配ssh key | 解决冲突
  • 一键生成 Android 适配不同分辨率尺寸的图片
  • Wireshark专家模式定位网络故障:14种TCP异常深度解剖
  • Ceph存储池参数中pg_num和pgp_num的关系
  • 终端安全检测和防御技术
  • 华为发布AI推理新技术,降低对HBM内存依赖
  • 负载均衡详解
  • 纯CSS+JS制作抽奖大转盘
  • C#教程之NPOI读写excel文件XLS,XLSX格式
  • 【vue(二)Vuex】
  • damn the jvm again(2)
  • 《Qwen2.5-VL 》论文精读笔记
  • 【测试】Bug+设计测试用例
  • 【Bug经验分享】由jsonObject-TypeReference引发的序列化问题
  • 无人机在环保监测中的应用:低空经济发展的智能监测与高效治理
  • 从0开始的中后台管理系统-5(菜单的路径绑定以及角色页面的实现)
  • Javase 之 字符串String类
  • 《飞算Java AI:从安装到需求转实战项目详细教学》
  • 机器学习算法篇(十):TF-IDF算法详解与应用实战
  • 线性代数 · 矩阵 | 最小多项式
  • IoTDB与传统数据库的核心区别
  • Spring Boot项目使用WebClient调用第三方接口详细教程
  • Elasticsearch Node.js 客户端连接指南(Connecting)
  • 一起来聊聊GPT-5
  • 面试经典150题[001]:合并两个有序数组(LeetCode 88)
  • 从零开始手搓一个GPT大语言模型:从理论到实践的完整指南(一)
  • 安全合规5--终端安全检测和防御技术
  • MySQL基础面试
  • MySQL 索引优化实战:从执行计划分析到优化策略落地