feat(AI/MNN): 集成 MNN.xcframework + ObjC++ 桥(LLM+SME2,Phase 1-2)
挑战赛考核点要求 Qwen + MNN + SME2 + CPU 端侧推理,MLX(GPU)不满足。
本提交打通原生 MNN 集成的工程层:
- scripts/build-mnn-xcframework.sh:从 alibaba/MNN 源码构建 device+sim arm64
双切片 xcframework,MNN_BUILD_LLM=ON 导出 llm/llm.hpp,MNN_SME2=ON
(KleidiAI 运行时自动路由:A19/iPhone17 走 SME2,A17 回退 NEON)
- MNNLLMBridge.{h,mm}:ObjC++ 封装 MNN Llm 的加载/流式生成,streambuf 按
UTF-8 边界聚合回调,getContext() 取 prefill/decode 算 tok/s;模拟器编为桩
(走 MLX 兜底),SME2 经 sysctl hw.optional.arm.FEAT_SME2 探测
- pbxproj:链接 MNN.xcframework + bridging header
- 二进制 gitignore,由脚本本地生成防历史膨胀
模拟器 BUILD SUCCEEDED(0 error),xcframework 处理 + 桥编译 + 链接通过。
下一步 Phase 3:MNNBackend + AIRuntime 双后端路由。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
55
康康/AI/MNN/MNNLLMBridge.h
Normal file
55
康康/AI/MNN/MNNLLMBridge.h
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// MNNLLMBridge.h
|
||||
// 康康
|
||||
//
|
||||
// Objective-C 接口,封装 MNN-LLM(Qwen)的加载与流式推理。
|
||||
// 真实实现在 .mm 中以 ObjC++ 调用 <MNN/llm/llm.hpp>;模拟器下编为可用性返回 NO 的桩
|
||||
// (MNN.framework 仅 device arm64 切片有真实 CPU/SME2 内核,模拟器走 MLX 兜底)。
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// 末次生成的性能统计(取自 MNN LlmContext)。
|
||||
@interface MNNGenerateStats : NSObject
|
||||
@property (nonatomic, readonly) int promptTokens;
|
||||
@property (nonatomic, readonly) int genTokens;
|
||||
@property (nonatomic, readonly) double prefillMs;
|
||||
@property (nonatomic, readonly) double decodeMs;
|
||||
/// 解码速率 tok/s = genTokens / (decodeMs/1000)。demo 卖点 #6 / Live Activity 用。
|
||||
@property (nonatomic, readonly) double decodeTokensPerSecond;
|
||||
@end
|
||||
|
||||
@interface MNNLLMBridge : NSObject
|
||||
|
||||
/// 本构建是否含真实 MNN 运行时(device=YES,simulator 桩=NO)。
|
||||
+ (BOOL)isAvailable;
|
||||
/// CPU 是否支持 SME2(运行时探测);A19/iPhone17 YES,A17/iPhone15Pro NO。仅用于 UI 展示加速状态。
|
||||
+ (BOOL)cpuSupportsSME2;
|
||||
|
||||
/// 用 MNN llm 的 config.json 路径加载模型(目录含 llm.mnn / 权重 / tokenizer)。失败返回 nil。
|
||||
- (nullable instancetype)initWithConfigPath:(NSString *)configPath;
|
||||
|
||||
@property (nonatomic, readonly) BOOL isLoaded;
|
||||
|
||||
/// 纯文本流式生成。onToken 每解码出一段文本回调一次(在调用线程,同步阻塞直到生成结束)。
|
||||
/// 返回末次统计。
|
||||
- (MNNGenerateStats *)generateText:(NSString *)prompt
|
||||
maxTokens:(int)maxTokens
|
||||
onToken:(void (^)(NSString *piece))onToken;
|
||||
|
||||
/// 图→文(VL,需 MNN_BUILD_LLM_OMNI 构建)。imagePaths 为本地文件路径。
|
||||
/// 当前文本构建未含 OMNI 时返回 nil 并置 error。
|
||||
- (nullable MNNGenerateStats *)analyzeImages:(NSArray<NSString *> *)imagePaths
|
||||
prompt:(NSString *)prompt
|
||||
maxTokens:(int)maxTokens
|
||||
onToken:(void (^)(NSString *piece))onToken
|
||||
error:(NSError *_Nullable *_Nullable)error;
|
||||
|
||||
/// 请求取消当前生成(best-effort:置标志,后续 token 不再回调)。
|
||||
- (void)cancel;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Reference in New Issue
Block a user