iOS ADK 集成指南
第一章:环境要求
项目 | 要求 |
最低部署目标 | iOS 13.0+( |
开发语言 | Objective-C(Swift 工程可直接集成) |
Xcode | 15.0+(Xcode 26.x 下 iOS 13.0 部署目标无弃用告警) |
第三方依赖 | SDK 自身零第三方依赖(仅 Foundation) |
强依赖 | 友盟 UMCommon / UMDevice(统计与设备标识基建,见第二章);UMCommon 最低版本 7.6.7 |
权限 key 清单(1.1.0 起,asr 场景,宿主 Info.plist 声明):
NSSpeechRecognitionUsageDescription——asr 语音识别所需(语音识别权限,SDK 端侧 asr 识别依赖,启用 asr 场景的宿主须声明);NSMicrophoneUsageDescription——SDK 自身不发起录音。asr 场景的输入为调用方传入的音频文件路径(audioFilePath)。麦克风权限仅宿主 App 自行实现录音功能时需要声明。
仅当宿主启用 asr 识别链路时需声明语音识别权限;麦克风权限与 SDK 无关(见上)。其余六场景无新增权限要求。
第二章:友盟 Common SDK 集成(强依赖)
UMADK 强依赖友盟 Common SDK 提供的设备标识基建,集成 UMCommon 为
必选项(缺失时设备标识相关数据不可用,直接影响风控与统计)。
最低版本要求:UMCommon ≥ 7.6.7(低于该版本不满足
UMADK 1.1.0 要求,请升级后再集成)。
2.1 CocoaPods 引入(推荐)
在 Podfile 中添加:
platform :ios, '13.0'
use_frameworks!
target 'YOUR_APP' do
pod 'UMCommon', '>= 7.6.7' # 最低版本要求 7.6.7
pod 'UMDevice'
end说明:UMCommon 为静态库(vendored 静态 xcframework)。CocoaPods 在
use_frameworks!下会自动完成静态库链接适配(注入-ObjC并链接其
所需系统库:sqlite3/z/CoreTelephony/SystemConfiguration),
无需手工配置。执行pod install后以.xcworkspace打开工程。
2.2 didFinishLaunching 中初始化
#import <UMCommon/UMCommon.h>
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 可选:开发期开启友盟日志
[UMConfigure setLogEnabled:YES];
// 友盟正式初始化(UMADK 与 UMConfigure 使用同一 appKey 注册,见 3.3)
[UMConfigure initWithAppkey:@"YOUR_APPKEY" channel:@"App Store"];
return YES;
}2.3 顺序约束
[UMConfigure initWithAppkey:channel:] 必须先于 UMADK 初始化
(+initializeWithCompletion:)执行,否则设备标识相关数据缺失,影响
统计与风控。推荐在 didFinishLaunching 中按「UMConfigure → UMADK
初始化」顺序调用。
2.4 手动集成补充
不使用 CocoaPods 时,手动引入 UMCommon.xcframework(友盟官方渠道下载,
版本 ≥ 7.6.7),并在宿主 target Build Settings 中补齐:
配置项 | 值 |
Embed | UMCommon 同为静态库,Do Not Embed |
OTHER_LDFLAGS | 追加 |
Link Binary With Libraries | 追加 |
第三章:ADK SDK 集成
3.1 依赖引入
方式一:CocoaPods 在线依赖(推荐)
在 Podfile 中添加(与第二章的 UMCommon 同一 target):
pod 'UMADK', '1.1.0'执行 pod install 后以 .xcworkspace 打开工程。
方式二:手动引入 UMADK.xcframework
将 UMADK.xcframework 拖入宿主工程(或 General > Frameworks, Libraries,
and Embedded Content 点击 + 添加),Embed 选项选择 Do Not Embed(SDK
为静态库,无需嵌入)。
两种方式等效,产物说明如下:
指标 | 说明 |
架构 |
|
公开头 |
|
Modules | 支持 |
隐私清单 | 内置 |
代码中统一引入唯一公开头:
#import <UMADK/UMADK.h>3.2 签名登记(iOS 特有)
UMADK 初始化需登记宿主 App 的 bundleId + teamId,登记要求如下:
服务端登记:接入前须将宿主 App 的 bundleId 与 teamId 登记至
U-ADK 服务端(随 appKey 一起);
未登记后果:初始化失败(
sCode=200050010,可经UMADKError.sCode定位);TeamID 获取方式(三选一):
登录 developer.apple.com/account,
Membership details 页查看 Team ID;
打开工程
project.pbxproj搜索DEVELOPMENT_TEAM;命令行:
xcodebuild -showBuildSettings | grep DEVELOPMENT_TEAM。
模拟器限制:UMADK 初始化在模拟器上无法走通(预期行为),
初始化与能力接口的验证须使用真机;如确有模拟器联调需求,见第九章
FAQ-1(手动注入签名描述文件即可,无需改动 SDK)。
3.3 初始化
ADK SDK 初始化通过 [UMADK initializeWithCompletion:] 完成,在
UMConfigure 初始化之后调用(appKey 与 UMConfigure 使用同一注册值,
UMCommon ≥ 7.6.7 初始化完成时 SDK 配置自动就绪,无需其他调用):
方法 | 说明 |
| 异步执行初始化,回调在后台线程;可重复调用(仅首次生效),失败后可重试 |
完整示例(AppDelegate):
#import "AppDelegate.h"
#import <UMADK/UMADK.h>
#import <UMCommon/UMCommon.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ① 友盟初始化(必须先于 UMADK 初始化,见 2.3)
[UMConfigure initWithAppkey:@"YOUR_APPKEY" channel:@"App Store"];
// ② 可选:开发期开启 SDK 调试日志(release 建议关闭)
[UMADK setDebugMode:YES];
// ③ UMADK 初始化:由业务侧按需显式调用(此处示例随启动触发)
[UMADK initializeWithCompletion:^(UMADKError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error == nil) {
// SDK 就绪,可调用业务接口([UMADK isReady] == YES)
} else {
// 初始化失败:error.code / error.sCode / error.source / error.message
}
});
}];
return YES;
}
@end完整可运行参照:仓库内 Example/UMADKDemo 演示工程(初始化由界面按钮显式触发)。3.4 调试模式
开发阶段可开启调试日志(release 包建议关闭):
[UMADK setDebugMode:YES]; // 开启:全部日志(d/w)输出
[UMADK setDebugMode:NO]; // 关闭:零日志(release 默认)敏感凭证在任何日志级别下均恒定脱敏,不会明文输出;开关仅控制日志
可见性。
3.5 版本号查询(1.1.0 新增)
获取当前 SDK 版本:[UMADK sdkVersion] 返回当前 SDK 版本号字符串(如 @"1.1.0");
与初始化状态无关,任意时刻可调,不发起网络请求。
第四章:能力接口使用
前提:所有业务接口须在 initializeWithCompletion: 成功回调之后调用,可通过 [UMADK isReady] 判断就绪状态。回调线程:所有回调均在后台线程触发(SDK 不切主线程),
UI 更新须自行 dispatch_async(dispatch_get_main_queue(), ...)。4.1 非流式聊天
接口:+ (void)chatWithRequest:(UMADKChatRequest *)request completion:(void (^)(UMADKChatResult *result, UMADKError *error))completion
请求参数(UMADKChatRequest):
参数 | 类型 | 必填 | 说明 |
| NSString | 否 | 模型名称(缺省 |
| NSArray<UMADKMessage *> | 是 | 对话消息列表;元素含 |
| NSString | 否 | 会话 ID( |
| BOOL | 否 | 是否开启深度思考(缺省 NO;需模型 |
| BOOL | 否 | 是否由服务端拼接同会话历史(缺省 YES;客户端自管上下文时传 NO) |
| UMADKImageParams | 否 | 文生图参数(仅 |
返回(UMADKChatResult,字段详见第五章):content(完整回答)/ reasoning(思考过程,可空)/ meta / usage / traceId / rawJson。
#import <UMADK/UMADK.h>
UMADKMessage *message = [UMADKMessage messageWithRole:@"user"
content:@"你好,请介绍一下自己"];
UMADKChatRequest *request = [UMADKChatRequest requestWithMessages:@[message]];
[UMADK chatWithRequest:request completion:^(UMADKChatResult * _Nullable result,
UMADKError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error != nil) {
// 错误处理见第六章
return;
}
NSString *answer = result.content;
NSString *reasoning = result.reasoning; // 思考过程,可为 nil
UMADKUsageInfo *usage = result.usage; // 用量与计费
// 更新 UI ...
});
}];4.2 流式聊天(SSE,四回调)
接口:+ (void)chatStreamWithRequest:(UMADKChatRequest *)request onMeta:(...) onDelta:(...) onDone:(...) onError:(...)
请求参数:与 4.1 完全一致(同一个 UMADKChatRequest,见 4.1 参数表)。
回调参数说明:
回调 | 参数类型 | 触发时机与说明 |
|
| 首事件,至多一次;含 |
|
| 零到多次,后台串行队列按序触发; |
|
| 至多一次,与 |
|
| 至多一次,与 |
#import <UMADK/UMADK.h>
UMADKMessage *message = [UMADKMessage messageWithRole:@"user"
content:@"写一首关于春天的诗"];
UMADKChatRequest *request =
[[UMADKChatRequest alloc] initWithModel:@"auto"
messages:@[message]
sessionId:nil
enableThinking:YES // 开启深度思考
loadHistory:YES
imageParams:nil];
__block NSMutableString *contentBuffer = [NSMutableString string];
[UMADK chatStreamWithRequest:request
onMeta:^(UMADKMetaInfo *meta) {
// 首事件,至多一次:保存 sessionId 用于多轮会话
NSString *sessionId = meta.sessionId;
}
onDelta:^(UMADKDeltaEvent *delta) {
// 零到多次,后台串行队列按序触发
if ([delta.type isEqualToString:UMADKDeltaTypeContent]) {
[contentBuffer appendString:delta.delta];
NSString *snapshot = [contentBuffer copy];
dispatch_async(dispatch_get_main_queue(), ^{
// textView.text = snapshot; 逐字刷新 UI
});
} else if ([delta.type isEqualToString:UMADKDeltaTypeReasoning]) {
// 思考过程增量
}
}
onDone:^(UMADKUsageInfo *usage) {
// 至多一次,与 onError 互斥;流式完成,获取用量
int64_t totalTokens = usage.totalTokens;
}
onError:^(UMADKError *error) {
// 至多一次,与 onDone 互斥;终态后不再触发任何回调
dispatch_async(dispatch_get_main_queue(), ^{
// 展示 error.message
});
}];回调时序:onMeta 先于一切 onDelta;onDone 与 onError 互斥、各至多
一次;终态后不再触发任何回调。
4.3 文生图
文生图与文本生成同一入口,须通过流式接口 chatStreamWithRequest:
调用,模型须为 modelType = image_generation 的模型(经 listModels
动态获取,勿硬编码模型名)。
请求参数:同 4.1 UMADKChatRequest(model 传 image_generation 模型的 displayName),其中 imageParams 子参数如下:
参数 | 类型 | 必填 | 说明 |
| NSString | 否 | 图片尺寸(缺省 |
| NSString | 否 | 图片质量: |
| NSInteger | 否 | 生成数量 1~4(缺省 1;越界回退 1;上限常量 |
返回:图链经 onDelta 以 type=content 整段 Markdown 一次性下发(形如 )。
#import <UMADK/UMADK.h>
UMADKMessage *message = [UMADKMessage messageWithRole:@"user"
content:@"一只在滑雪的柴犬"];
// 文生图参数:size/quality/n,nil 与越界值按缺省处理
UMADKImageParams *imageParams =
[[UMADKImageParams alloc] initWithSize:@"1024x1024"
quality:@"medium"
n:1];
UMADKChatRequest *request =
[[UMADKChatRequest alloc] initWithModel:@"<image_generation 模型 displayName>"
messages:@[message]
sessionId:nil
enableThinking:NO
loadHistory:YES
imageParams:imageParams];
[UMADK chatStreamWithRequest:request
onMeta:^(UMADKMetaInfo *meta) {}
onDelta:^(UMADKDeltaEvent *delta) {
if ([delta.type isEqualToString:UMADKDeltaTypeContent]) {
// 图链以 type=content 整段 Markdown 一次性下发,
// 形如 ;解析 URL 后经
// NSURLSession 下载或图片库加载
NSString *markdownImage = delta.delta;
}
}
onDone:^(UMADKUsageInfo *usage) {}
onError:^(UMADKError *error) {}];缺省常量:UMADKImageParamsDefaultSize("1024x1024")/UMADKImageParamsDefaultQuality("low")/UMADKImageParamsDefaultN(1)/
UMADKImageParamsMaxN(4)。全缺省可直接[UMADKImageParams defaultParams]。
图链判断请使用UMADKDeltaTypeContent(图链以type=content下发)。
4.4 模型列表
接口:+ (void)listModelsWithCompletion:(void (^)(NSArray<UMADKModelInfo *> *models, UMADKError *error))completion
请求参数:无。
返回(NSArray<UMADKModelInfo *>):
字段 | 类型 | 说明 |
| NSString | 对外展示名(即请求时 |
| NSString | 实际上游模型名 |
| NSString | 模型档位( |
| BOOL | 是否支持深度思考 |
| BOOL | 是否支持图片输入 |
| NSString | 模型类型( |
| NSString | 模型描述 |
列表顺序由服务端返回(auto 通常排首位)。
#import <UMADK/UMADK.h>
[UMADK listModelsWithCompletion:^(NSArray<UMADKModelInfo *> * _Nullable models,
UMADKError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error != nil) {
return;
}
for (UMADKModelInfo *model in models) {
NSLog(@"%@ | type=%@ | tier=%@ | thinking=%@",
model.displayName, model.modelType, model.tier,
model.supportsThinking ? @"YES" : @"NO");
}
});
}];4.5 多轮会话
会话 ID 由接入方自行保存与传递:
首轮不传 sessionId,从 meta.sessionId 获取后,后续轮次随请求传入;
loadHistory=YES(缺省)时服务端自动拼接同一 session 历史。
#import <UMADK/UMADK.h>
__block NSString *savedSessionId = nil;
// 第一轮:不传 sessionId
UMADKChatRequest *first = [UMADKChatRequest requestWithMessages:
@[[UMADKMessage messageWithRole:@"user" content:@"我叫小明"]]];
[UMADK chatStreamWithRequest:first
onMeta:^(UMADKMetaInfo *meta) {
savedSessionId = meta.sessionId; // 保存(sess- 前缀,服务端生成)
}
onDelta:^(UMADKDeltaEvent *delta) {}
onDone:^(UMADKUsageInfo *usage) {
// 第二轮:携带 sessionId,服务端拼接历史
UMADKChatRequest *second =
[[UMADKChatRequest alloc] initWithModel:@"auto"
messages:@[[UMADKMessage messageWithRole:@"user"
content:@"我叫什么?"]]
sessionId:savedSessionId
enableThinking:NO
loadHistory:YES
imageParams:nil];
[UMADK chatStreamWithRequest:second
onMeta:^(UMADKMetaInfo *meta) {}
onDelta:^(UMADKDeltaEvent *delta) {
// 模型将回答「小明」
}
onDone:^(UMADKUsageInfo *usage) {}
onError:^(UMADKError *error) {}];
}
onError:^(UMADKError *error) {}];4.6 场景化能力(七场景,1.1.0 新增)
SDK 提供 text/nlp/translate/ocr/vision/asr/tts 七个场景化类方法(类方法 + 场景专属 Request/Result + completion block):
场景 | 方法 | 媒体输入 |
text(摘要/改写/生成) |
| — |
nlp(分词/NER/关键词) |
| — |
translate(翻译) |
| — |
ocr(文字识别) |
| imageFilePath 或 imageUrl |
vision(视觉理解) |
| imageFilePath 或 imageUrl |
asr(语音识别,非实时) |
| audioFilePath 或 audioUrl |
tts(语音合成,非实时) |
| — |
使用说明:
无需指定模型:场景请求不传 model,非法场景/参数由服务端返回错误码 200001000;
媒体输入二选一:本地文件路径(
imageFilePath/audioFilePath,须先落盘;走云端执行时 SDK 自动完成素材上传)或已持有的素材 URL(imageUrl/audioUrl),二者必须且只能传一个(同传或均缺回调 1001);不支持 base64 内联;参数错误经回调返回:必填缺失、互斥冲突等参数错误通过 completion 回调
UMADKError(source=LOCAL, code=1001)返回,不会抛出异常;执行层读取:成功回调结果的
executedBy标注本次执行层(UMADKExecutedByVendor/UMADKExecutedByCloud);云端执行时另有meta/traceId,端侧执行时两者为 nil;回调后台线程:与既有能力一致,UI 操作须切主线程;
completion传 nil 为 no-op。
端侧执行相关说明:
tts 两种音频形态:端侧执行时通过
audioData交付本地合成音频(16-bit LE mono 裸 PCM,采样率见structured.audio_sample_rate,可构造 WAV 头播放,audioUrl为 nil);云端执行时返回audioUrl(audioData为 nil)。两字段互斥,按非空判断消费即可。长文本合成超时上限 30s,超时自动转云端执行。asr 端侧执行说明:asr 命中端侧执行时,音频经 Apple 服务器识别(音频会离开设备,但不经过友盟云端),依赖系统授权与网络,需宿主声明语音识别权限(见第一章权限 key 清单);SDK 自身不发起录音,麦克风权限仅宿主自行实现录音时需要。
text 场景端侧可用性:text 场景端侧执行依赖 FoundationModels(iOS 26 + Apple Intelligence,A17 Pro+),仅限海外已激活 Apple Intelligence 的设备,国内设备恒走云端执行。
本地错误码:1001 参数错误;1002 未初始化;1004 网络/执行异常;1006 设备能力不可用(常规策略下 SDK 会自动转云端执行,通常不会遇到)。
便捷入口——常用参数组合的简化构造:
入口 | 用途 |
| 构造用户消息(场景化调用推荐使用) |
| text 纯文本入口(需设置 prompt/maxLength/style/language 时使用全参初始化器) |
| nlp 纯文本入口(需设置 language 时使用全参初始化器) |
| translate 纯文本入口(需设置 sourceLang/domain 时使用全参初始化器) |
| tts 纯文本入口(需设置 voice/format/sampleRate/speed 时使用全参初始化器) |
ocr / vision / asr 无 | 无补充指令时直接使用该初始化器,无需传 |
结构化返回说明:各场景 structured 字段的存在条件与元素结构在 4.7「七场景参数与返回明细」逐字段说明,要点如下:
vision:端侧执行时
structured.result.{faces/objects/labels/items}可直接解析(见 4.7.5);云端执行时勿解析内部子键;nlp:
structured.tokens键名两条执行路径一致;partOfSpeech端侧执行时可能缺失、两条路径取值体系不同,仅用于展示(见 4.7.2);tts:音频时长统一为
structured.duration_ms(毫秒,两条执行路径均有);ocr / asr:识别全文经
content消费(两条执行路径均有),其余结构化字段按条件存在(见 4.7.4 / 4.7.6)。⚠️ 当前版本限制:vision 云端执行按实测参考形态解析(见 4.7.5);ocr 云端执行的
structured.result内部结构未定型,只消费content(见 4.7.4)。
示例(text 摘要,便捷入口):
#import <UMADK/UMADK.h>
// 最简形态(无可选参数):
// UMADKTextRequest *request = [UMADKTextRequest requestWithText:@"(待摘要的长文本)"
// task:UMADKTextTaskSummarize];
// 含可选参数(全参形态 + messageWithContent 便捷消息工厂):
UMADKTextRequest *request = [[UMADKTextRequest alloc]
initWithMessages:@[[UMADKMessage messageWithContent:@"(待摘要的长文本)"]]
task:UMADKTextTaskSummarize // @"SUMMARIZE"
prompt:nil
maxLength:@100
style:UMADKTextStyleConcise // @"CONCISE"
language:@"zh"];
[UMADK textWithRequest:request
completion:^(UMADKTextResult * _Nullable result,
UMADKError * _Nullable error) {
if (error != nil) {
NSLog(@"text 失败:%@(code=%ld, traceId=%@)",
error.message, (long)error.code, error.traceId);
return;
}
NSLog(@"摘要:%@(executedBy=%ld)", result.content,
(long)result.executedBy);
}];4.7 七场景参数与返回明细
4.7.0 公共返回结构(阅读各场景前必读)
各场景成功回调均返回场景专属结果对象(如 UMADKTextResult),全部继承同一基类,携带以下公共字段:
字段 | 类型 | 保证级 | 说明 |
|
| 恒有 | 本次结果的执行层,两种取值: |
| 对象 | 仅 | 消耗信息 / 模型信息 / 链路追踪 ID / 原始响应 JSON;端侧执行时四者为空 |
字段保证级图例(下文各表使用):
保证级 | 含义 | 接入方处理 |
恒有 | 成功回调中必定存在、可直接使用 | 直接消费 |
条件存在 | 仅在指定条件下存在(特定执行层 / 特定任务),表中已写明条件 | 按条件判断后消费 |
勿解析 | 字段存在但内部结构当前版本未定型 | 不读取内部子键 |
structured为结构化输出容器(NSDictionary),内部字段在各场景返回表中逐一说明;text / translate 场景的structured可能为空,只消费content即可。
按执行层分支的示例代码:
[UMADK ocrWithRequest:request completion:^(UMADKOcrResult *result, UMADKError *error) {
if (error != nil) { /* 失败处理,见第六章 */ return; }
NSString *text = result.content; // 恒有字段,直接消费
if (result.executedBy == UMADKExecutedByVendor) {
NSArray *blocks = result.structured[@"blocks"]; // 端侧执行形态
} else {
// 云端执行形态
}
}];4.7.1 text —— 文本生成 / 摘要 / 改写
接口:+ (void)textWithRequest:(UMADKTextRequest *)request completion:(void (^)(UMADKTextResult *, UMADKError *))completion
请求参数(UMADKTextRequest):
参数 | 类型 | 必填 | 说明 |
| NSArray<UMADKMessage *> | 是 | 待处理文本;便捷构造见 |
| NSString | 是 |
|
| NSString | 否 | 生成指令(task=GENERATE 时用) |
| NSNumber(整数) | 否 | 结果长度上限 |
| NSString | 否 | 摘要: |
| NSString | 否 | 语言(开放集,如 |
返回(UMADKTextResult):
字段 | 类型 | 保证级 | 说明 |
| NSString | 恒有 | 生成/摘要/改写结果文本(本场景唯一消费字段) |
| NSDictionary | 勿解析 | 可能为空,不消费 |
4.7.2 nlp —— 分词 / NER / 关键词抽取
接口:+ (void)nlpWithRequest:(UMADKNlpRequest *)request completion:(void (^)(UMADKNlpResult *, UMADKError *))completion
请求参数(UMADKNlpRequest):
参数 | 类型 | 必填 | 说明 |
| NSArray<UMADKMessage *> | 是 | 待分析文本;便捷构造见 |
| NSArray<NSString *> | 是(可多选) |
|
| NSString | 否 | 语言(开放集) |
返回(UMADKNlpResult):本场景无 content,结果全部经 structured 承载;端侧执行与云端执行的字段集不同,按 executedBy 分支。
structured 字段表:
字段 | 类型 | 存在条件 | 说明 |
| NSArray | 请求含 TOKENIZATION 时恒有 | 分词结果,元素结构见下表 |
| NSArray | 仅云端执行 + 请求含 NER | 命名实体,元素结构见下表 |
| NSArray | 仅云端执行 + 请求含 KEYWORD_EXTRACTION | 关键词,元素结构见下表 |
| NSString | 仅端侧执行 | 任务回显,值 |
| NSString | 仅端侧执行 | 检测到的主要语言(如 |
tokens[ ] 元素结构(两条执行路径键名一致):
键 | 类型 | 保证级 | 说明 |
| NSString | 恒有 | 词语原文 |
| NSNumber(整数) | 恒有 | 词语在原文中的起始字符偏移(含) |
| NSNumber(整数) | 恒有 | 词语在原文中的结束字符偏移(不含) |
| NSString | 条件存在 | 词性标签。两条注意:① 端侧执行时可能缺失(须先判断键存在);② 两条路径取值体系不同——端侧为英文词(如 |
entities[ ] 元素结构(仅云端):text(实体原文,恒有)、type(实体类型代码,如 ORG=机构 / PER=人名,恒有)、startOffset / endOffset(恒有)、confidence(0~1 浮点,恒有)。
keywords[ ] 元素结构(仅云端):text(关键词,恒有)、score(相关度 0~1 浮点,恒有)。
返回示例(端侧执行,TOKENIZATION):
{
"structured": {
"task": "TOKENIZATION",
"tokens": [
{"text": "友盟", "partOfSpeech": "Noun", "startOffset": 0, "endOffset": 2}
],
"dominant_language": "zh"
}
}返回示例(云端执行,TOKENIZATION + NER + KEYWORD_EXTRACTION):
{
"structured": {
"tokens": [
{"text": "友盟", "startOffset": 0, "endOffset": 2, "partOfSpeech": "NR"}
],
"entities": [
{"text": "友盟", "type": "ORG", "startOffset": 0, "endOffset": 2, "confidence": 0.98}
],
"keywords": [
{"text": "开发者数据服务", "score": 0.92}
]
}
}4.7.3 translate —— 翻译
接口:+ (void)translateWithRequest:(UMADKTranslateRequest *)request completion:(void (^)(UMADKTranslateResult *, UMADKError *))completion
请求参数(UMADKTranslateRequest):
参数 | 类型 | 必填 | 说明 |
| NSArray<UMADKMessage *> | 是 | 待翻译文本;便捷构造见 |
| NSString | 是(缺失回调 1001) | 目标语言(开放集,如 |
| NSString | 否 | 源语言;不填或 |
| NSString | 否 |
|
返回(UMADKTranslateResult,本场景恒云端执行):
字段 | 类型 | 保证级 | 说明 |
| NSString | 恒有 | 译文(本场景主消费字段) |
| NSString | 条件存在 | 自动检测出的源语言代码(如 |
4.7.4 ocr —— 文字识别
接口:+ (void)ocrWithRequest:(UMADKOcrRequest *)request completion:(void (^)(UMADKOcrResult *, UMADKError *))completion
请求参数(UMADKOcrRequest):
参数 | 类型 | 必填 | 说明 |
| NSString | 与 | 本地图片路径(须先落盘;白名单 png / jpg / jpeg;移交云端时 SDK 自动上传) |
| NSString | 与 | 已持有的素材 URL |
| NSString | 否 |
|
| NSArray<NSString *> | 否 | 语言提示(如 |
| NSArray<UMADKMessage *> | 否 | 补充指令(仅云端消费);无诉求时用无 |
返回(UMADKOcrResult):
字段 | 类型 | 保证级 | 说明 |
| NSString | 恒有 | 识别全文(本场景主消费字段,两条执行路径均有) |
| NSDictionary | 按执行层区分 | 端侧执行:文本块数组(见下);云端执行:内部结构未定型(见下) |
structured 详解:
端侧执行(
executedBy == UMADKExecutedByVendor):structured.blocks为数组,恒有;每个元素:键
类型
保证级
说明
textNSString
恒有
该文本块的识别文字
boundingBoxNSDictionary
恒有
文本块位置
{x, y, width, height},像素整数坐标(相对原图),无需换算云端执行(
executedBy == UMADKExecutedByCloud):structured为{task, result}结构,但result内部子结构当前版本未定型(服务端统一中),请勿解析其内部子键。
消费总结:读取 content(识别全文,恒有)即完成本场景消费;需要"文字块 + 位置坐标"时,在端侧执行下读取 structured.blocks。TABLE / CARD 任务的表格 / 卡证结构化将在服务端定型后随版本发布提供。
示例(本地文件形态,无 messages 便捷初始化器):
UMADKOcrRequest *request = [[UMADKOcrRequest alloc]
initWithImageFilePath:localImagePath // 与 imageUrl 互斥二选一
imageUrl:nil
task:UMADKOcrTaskGeneral // @"GENERAL"
languageHints:@[@"zh"]];
// 需要补充指令时改用全参初始化器(末位 messages 形参)
[UMADK ocrWithRequest:request
completion:^(UMADKOcrResult * _Nullable result,
UMADKError * _Nullable error) {
NSString *text = result.content; // 恒有,两条执行路径均可用
if (result.executedBy == UMADKExecutedByVendor) {
NSArray *blocks = result.structured[@"blocks"]; // 端侧:按块取 text/boundingBox
}
}];4.7.5 vision —— 视觉理解
接口:+ (void)visionWithRequest:(UMADKVisionRequest *)request completion:(void (^)(UMADKVisionResult *, UMADKError *))completion
请求参数(UMADKVisionRequest):
参数 | 类型 | 必填 | 说明 |
| NSString | 与 | 本地图片路径(须先落盘;白名单 png / jpg / jpeg;移交云端时 SDK 自动上传) |
| NSString | 与 | 已持有的素材 URL |
| NSString | 否 |
|
| NSDictionary | 否 | 附加选项: |
| NSArray<UMADKMessage *> | 否 | 补充指令(仅云端消费);无诉求时用无 |
返回(UMADKVisionResult):本场景无 content,结果经 structured 承载;structured.task 恒有(任务回显)。structured.result 按执行层区分:
端侧执行(executedBy == UMADKExecutedByVendor)——结构确定,可直接解析:
structured.result 按任务映射子键:
任务 |
| 元素中的 |
|
| 有 |
|
| 有 |
|
| 无(分类无坐标) |
|
| 有 |
各元素结构:
键 | 类型 | 保证级 | 说明 |
| NSString | 恒有 | 结果描述文本。注意:端侧物体检测不区分类别,该值为固定描述文字;端侧人脸检测为关键点描述 |
| NSNumber(浮点) | 恒有 | 置信度,0~1 |
| NSArray(4 个整数) | 条件存在 | 位置 |
云端执行(executedBy == UMADKExecutedByCloud)——当前版本实际返回形态(基于真机实测):
任务 |
|
|
|
|
|
| IMAGE_CLASSIFICATION | {category, subcategories[ ], confidence} |
返回示例(真机实测):
// FACE_DETECTION
{"task":"FACE_DETECTION","result":{"faces":[
{"boundingBox":{"x":95,"y":0,"width":905,"height":999},"confidence":0.998}
]}}
// OBJECT_DETECTION
{"task":"OBJECT_DETECTION","result":{"objects":[
{"bbox_2d":[28,254,723,894],"category":"laptop"},
{"bbox_2d":[554,454,701,654],"category":"mug"}
]}}
// IMAGE_CLASSIFICATION
{"task":"IMAGE_CLASSIFICATION","result":{
"category":"技术文档",
"subcategories":["人工智能","边缘计算","云原生"],
"confidence":0.95
}}云端形态使用须知:
以上形态为当前版本实测参考;服务端正在统一结构化输出,定型后将随版本发布调整,届时以更新后的集成指南为准;
坐标体系:实测坐标取值范围为 0~1000(疑似归一化刻度,非像素坐标),如需叠加绘制请自行标定换算;
字段差异:云端形态与端侧形态(上表)键名、坐标格式不同,双路径消费须按
executedBy分支解析。
消费总结:
端侧执行:解析
structured.result.{faces/objects/labels/items}(结构稳定,像素坐标)。vision 基础任务(FACE_DETECTION / OBJECT_DETECTION / IMAGE_CLASSIFICATION)端侧优先执行,端侧能力可用的设备通常命中端侧;云端执行:按上方实测形态表解析(当前版本参考)。
返回示例(端侧执行,OBJECT_DETECTION):
{
"structured": {
"task": "OBJECT_DETECTION",
"result": {
"objects": [
{"label": "矩形区域", "confidence": 0.95, "box": [180, 88, 500, 576]}
]
}
}
}4.7.6 asr —— 语音识别(非实时)
接口:+ (void)asrWithRequest:(UMADKAsrRequest *)request completion:(void (^)(UMADKAsrResult *, UMADKError *))completion
请求参数(UMADKAsrRequest):
参数 | 类型 | 必填 | 说明 |
| NSString | 与 | 本地音频路径(须先落盘;白名单 mp3 / wav / m4a / flac / aac / ogg / amr;移交云端时 SDK 自动上传) |
| NSString | 与 | 已持有的素材 URL(该形态恒走云端) |
| NSString | 否 | 音频格式申报: |
| NSNumber(整数) | 否 | 音频实际采样率(Hz,如 16000;仅云端消费) |
| NSArray<NSString *> | 否 | 语种提示(如 |
| NSArray<NSString *> | 否 | 热词(专有名词/术语;仅云端消费,端侧不支持) |
| NSArray<UMADKMessage *> | 否 | 当前无实际语义,推荐用无 |
返回(UMADKAsrResult):
字段 | 类型 | 保证级 | 说明 |
| NSString | 恒有 | 识别全文(本场景主消费字段,两条执行路径均有) |
| NSArray | 仅云端执行 | 分句结果,元素结构见下 |
| NSString | 仅云端执行 | 识别语种代码(如 |
sentences[ ] 元素结构(仅云端):text(句子文本,恒有)、begin_time(起始毫秒,恒有)、end_time(结束毫秒,恒有)。端侧执行时无 structured。
4.7.7 tts —— 语音合成(非实时)
接口:+ (void)ttsWithRequest:(UMADKTtsRequest *)request completion:(void (^)(UMADKTtsResult *, UMADKError *))completion
请求参数(UMADKTtsRequest):
参数 | 类型 | 必填 | 说明 |
| NSArray<UMADKMessage *> | 是 | 待合成文本(总长 ≤2000 字符,超限回调 1001);便捷构造见 |
| NSString | 否 | 音色标识(开放集);云端与端侧标识体系不通用,无效值云端报错、端侧静默回落默认音色 |
| NSString | 否 |
|
| NSNumber(整数) | 否 | 期望采样率(缺省 22050;端侧执行时忽略) |
| NSNumber(浮点) | 否 | 语速 0.5~2.0(缺省 1.0;两条执行路径均生效) |
返回(UMADKTtsResult):音频按执行层以两种形态互斥交付(哪个非空消费哪个):
字段 | 类型 | 保证级 | 说明 |
| NSString | 云端执行时恒有 | OSS 签名音频链接(有效期约 3 天,原样使用即可,无需二次鉴权) |
| NSData | 端侧执行时恒有 | 本地合成音频,固定为 16-bit LE mono 裸 PCM;采样率取 |
| NSNumber(整数) | 恒有 | 音频时长(毫秒),两条执行路径含义一致 |
| NSNumber(整数) | 仅端侧执行 | 端侧合成实际采样率(Hz);构造 WAV 头等场景使用 |
各场景的参数常量与结果字段完整声明见 UMADK.h 头文件注释。
随交付包提供的 UMADKDemo 演示工程包含七场景完整示范(七场景按钮、结果展示与媒体调用示例),可直接运行参考。第五章:数据模型参考
UMADKChatRequest
字段 | 类型 | 默认值 | 说明 |
model | NSString |
| 模型名称(非法值由服务端返回 sCode=200001004) |
messages | NSArray<UMADKMessage *> | — | 消息列表(必填) |
sessionId | NSString | nil | 会话 ID( |
enableThinking | BOOL | NO | 是否开启深度思考模式 |
loadHistory | BOOL | YES | 是否由服务端拼接历史消息 |
imageParams | UMADKImageParams | nil | 文生图参数(仅 image_generation 模型生效) |
构造方式:便捷工厂 +requestWithMessages:(全缺省);全参 designated
initializer -initWithModel:messages:sessionId:enableThinking:loadHistory:imageParams:
(nil model 回退 "auto")。对象不可变。
UMADKMessage
字段 | 类型 | 说明 |
role | NSString | 消息角色( |
content | NSString | 纯文本内容 |
构造:+messageWithRole:content: / +messageWithContent:(后者构造用户消息,场景化调用推荐)。
UMADKImageParams
字段 | 类型 | 默认值 | 说明 |
size | NSString |
| 图片尺寸(nil 入参用默认值) |
quality | NSString |
| 图片质量( |
n | NSInteger | 1 | 生成数量(1~4;越界回退 1;上限常量 |
UMADKChatResult(非流式完整响应)
字段 | 类型 | 说明 |
meta | UMADKMetaInfo | 会话元信息 |
content | NSString | 完整回答文本(文生图时为 |
reasoning | NSString | 思考过程全文(可为 nil) |
usage | UMADKUsageInfo | 用量与计费信息 |
traceId | NSString | 链路追踪 ID(缺失时为 nil;可提供给友盟技术支持用于问题排查;1.1.0 新增) |
rawJson | NSString | 对应节点原始 JSON 字符串 |
UMADKMetaInfo
字段 | 类型 | 说明 |
event | NSString | 事件类型(固定 |
requestId | NSString | 请求 ID |
sessionId | NSString | 会话 ID( |
requestedModel | NSString | 请求使用的模型名 |
actualModel | NSString | 实际调用的模型名 |
actualUpstreamModel | NSString | 实际上游调用的模型名 |
isRouted | NSInteger | 是否经过路由(1=是,0=否) |
routeLevel | NSString | 路由级别(仅 auto 路由时有值,如 "simple") |
routeScore | NSNumber | 路由评分(仅 auto 路由时有值) |
routeReason | NSString | 路由原因(仅 auto 路由时有值) |
routerVersion | NSString | 路由器版本(仅 auto 路由时有值) |
traceId | NSString | 单次请求链路追踪 ID(缺失时为空串;1.1.0 新增) |
rawJson | NSString | 对应节点原始 JSON 字符串 |
UMADKDeltaEvent
字段 | 类型 | 说明 |
type | NSString | 增量类型(取值见下方常量表) |
delta | NSString | 增量文本(文生图时为整段 Markdown 图链) |
rawJson | NSString | 对应节点原始 JSON 字符串 |
类型常量:
常量 | 值 | 说明 |
|
| 正文增量(文生图图链也以此类型整段下发) |
|
| 思考增量 |
UMADKUsageInfo
字段 | 类型 | 说明 |
event | NSString | 事件类型(固定 |
requestId | NSString | 请求 ID |
finishReason | NSString | 结束原因(如 |
inputTokens | int64_t | 输入 token 数 |
outputTokens | int64_t | 输出 token 数 |
totalTokens | int64_t | 总 token 数 |
thinkingTokens | int64_t | 思考 token 数(可为 0) |
cachedTokens | int64_t | 缓存 token 数(可为 0) |
costCredits | int64_t | 消耗算力点 |
credits | double | 消耗金额(精确小数) |
pricingTier | NSString | 定价档位(如 "0<Token≤1M") |
durationMs | int64_t | 请求耗时(毫秒) |
rawJson | NSString | 对应节点原始 JSON 字符串 |
UMADKModelInfo
字段 | 类型 | 说明 |
displayName | NSString | 对外展示名(即请求时 model 取值域) |
actualName | NSString | 实际上游调用名 |
tier | NSString | 模型档位(AUTO / FLAGSHIP / BALANCED / LITE) |
supportsThinking | BOOL | 是否支持深度思考 |
supportsImage | BOOL | 是否支持图片输入 |
modelType | NSString | 模型类型( |
modelDescription | NSString | 中文描述 |
UMADKModelInfo 不含 rawJson 字段。
UMADKError
字段 | 类型 | 说明 |
sCode | int64_t | 服务端九位错误码;本地/网络错误时为 0 |
code | NSInteger | 分类码(服务端 -1~-6;本地 1001-1006) |
message | NSString | 可展示错误消息 |
source | UMADKErrorSource | 错误来源枚举 |
cause | NSError | 原始 NSError(可为 nil) |
traceId | NSString | 链路追踪 ID(缺失时为 nil;1.1.0 新增) |
三 ID 语义分工(sessionId / requestId / traceId)
ID | 语义 | 生命周期 |
sessionId | 会话维度(多轮对话聚合) | 整个会话恒定,续轮随请求传入 |
requestId | 单次请求维度(服务端生成) | 单次请求 |
traceId | 单次请求链路追踪号 | 单次请求,每次请求不同 |
排查单请求链路问题时优先使用 traceId(可提供给友盟技术支持用于服务端链路检索)。多轮会话中 sessionId 恒定而 traceId 每次不同。
第六章:错误处理
6.1 UMADKError 结构说明
所有错误路径统一收敛为 UMADKError 对象(不可变),字段见第五章末表。
6.2 Source 枚举含义
枚举值 | 值 | 含义 | 典型场景 |
| 0 | 本地校验错误 | 参数非法、未初始化、SDK 已禁用 |
| 1 | 网络传输层错误 | DNS 失败、连接超时、IO 异常、非法 JSON |
| 2 | 网关业务错误 | 服务端返回业务失败(success=false) |
| 3 | SSE error 事件 | 流式传输中服务端推送 error 事件 |
| 4 | 凭证刷新失败 | 凭证获取/刷新链路异常 |
6.3 本地错误码
错误码 | 常量 | 说明 | 处理建议 |
1001 |
| 参数错误 | 检查 appKey / messages / 媒体路径等参数是否正确传入,请求的任务是否在上述支持的任务列表中 |
1002 |
| SDK 未初始化 | 确保 |
1003 |
| SDK 已禁用 | SDK 被服务端配置禁用,联系管理员 |
1004 |
| 网络错误 | 检查网络连接,适当重试 |
1005 |
| 凭证刷新失败 | 检查 appKey 有效性或网络状态,重试初始化 |
1006 |
| 设备能力不可用(1.1.0 新增) | 端侧执行不可用且无法转云端执行时返回(常规情况下 SDK 会自动转云端执行,通常不会遇到);如遇到请联系友盟技术支持 |
6.4 错误处理示例
void HandleUMADKError(UMADKError *error) {
switch (error.source) {
case UMADKErrorSourceLocal:
// 本地校验不通过:检查调用时机与参数(code 1001~1003)
break;
case UMADKErrorSourceNetwork:
// 网络异常:提示用户检查网络,适当重试(code 1004)
break;
case UMADKErrorSourceGateway:
// 服务端业务错误:经 error.sCode 获取九位错误码
//(如 bundleId/teamId 未登记,sCode=200050010)
break;
case UMADKErrorSourceSSE:
// 流式传输中服务端推送 error 事件
break;
case UMADKErrorSourceCredential:
// 凭证问题(code 1005):可重试 initializeWithCompletion:
break;
}
NSLog(@"[UMADK] error code=%ld sCode=%lld message=%@",
(long)error.code, (long long)error.sCode, error.message);
}第七章:工程配置(iOS 特有)
7.1 链接配置
CocoaPods 方式(3.1 方式一)无需以下配置,pod install 已自动处理;下表仅适用于手动引入 xcframework。配置项 | 值 | 说明 |
Embed(Embedded Content) | Do Not Embed | SDK 为静态库,无需嵌入 |
OTHER_LDFLAGS | 建议追加 | 静态库集成惯例 |
系统库依赖 | 无需手动链接 | SDK 仅依赖 Foundation |
Bitcode | 无需配置 | Apple 已废弃 Bitcode |
7.2 隐私清单(PrivacyInfo.xcprivacy)
SDK 产物双 slice 已内置 PrivacyInfo.xcprivacy(Apple 自 2024-05 起对
第三方 SDK 强制要求),无需接入方额外配置。申报内容摘要:
设备标识不关联用户身份(Linked=NO);
用户标识信息按 Apple 规范关联申报(Linked=YES);
收集用途仅为 App Functionality(风控);
无跨 App 跟踪(不使用 IDFA)。
出口合规提示:SDK 仅使用系统标准 HTTPS 加密,宿主 App 请自行在
Info.plist 声明 ITSAppUsesNonExemptEncryption(App 级义务)。7.3 混淆
iOS 平台无需额外混淆配置。
第八章:注意事项
回调线程:所有回调(初始化 / 场景调用 / 流式四回调 / listModels)均在后台线程触发(流式按序触发),UI 操作必须
dispatch_async(dispatch_get_main_queue(), ...)切主线程。线程安全:
UMADK全部公开类方法线程安全,可在任意线程调用。初始化可重复调用:
initializeWithCompletion:多次调用安全(仅首次生效;进行中忽略;失败后可重试),无副作用。sessionId 管理:会话 ID 由接入方自行保存与传递。首轮不传,从
meta.sessionId获取后随后续请求传入。model 取值:非法模型名由服务端返回错误(sCode=200001004)。推荐经
listModels获取可用模型的displayName作为取值。状态查询:调用业务接口前可经
[UMADK isReady]判断就绪状态,避免不必要的 1002 错误回调。loadHistory 默认行为:缺省 YES,服务端自动拼接同一 session 历史;若客户端自行管理上下文,构造请求时显式传 NO。
enableThinking 兼容性:深度思考需模型支持(
supportsThinking),对不支持的模型设置无效。文生图约束:仅对
modelType=image_generation的模型生效,且必须经流式接口chatStreamWithRequest:调用;模型名经listModels动态获取,禁止硬编码模型名。rawJson 用途:各响应对象的
rawJson保留对应节点原始 JSON,便于读取本文档未列出的扩展字段(ModelInfo 不带 rawJson)。模拟器限制:UMADK 初始化在模拟器上无法完成(预期行为),初始化与能力验证须使用真机(bundleId+teamId 须已在服务端登记)。如确有模拟器联调需求,见第九章 FAQ-1(手动注入签名描述文件,无需改动 SDK)。
素材上传:七场景传本地文件路径(
imageFilePath/audioFilePath)时,需要走云端执行的情况下由 SDK 自动完成素材上传,接入方无需处理。
第九章:常见问题(FAQ)
FAQ-1:能否在模拟器上跑通 UMADK 初始化与全链路?
默认不能(预期行为),但可通过手动注入签名描述文件实现,无需改动 SDK。
原因:初始化需要校验宿主 App 的签名信息(团队标识),模拟器构建
不具备有效的签名信息,因此初始化回调 1001(签名信息不可用)。真机
构建不受影响。
模拟器联调步骤(开发者在自己的开发环境注入自己的签名身份):
取得一份有效的
embedded.mobileprovision(二选一):从最近一次真机构建的产物中拷出(<DerivedData>/.../Products/Debug-iphoneos/<App>.app/embedded.mobileprovision);或从本机描述文件目录复制对应 profile(~/Library/MobileDevice/Provisioning Profiles/<uuid>.mobileprovision,可用security cms -D -i <文件>查看内容确认 bundleId 匹配)。将该文件重命名为
embedded.mobileprovision,拖入 Xcode 工程,勾选 app target 的 Target Membership(文件名必须完全一致,SDK 按mainBundle中该固定文件名读取)。以模拟器 destination 构建运行:初始化与全部能力即可在模拟器走通
(前提:bundleId+teamId 已在服务端登记)。
注意事项:
该 profile 的 bundleId 必须与工程一致(通配符 profile 同样可用);建议保持更新以免混淆。
真机构建不受影响:真机签名流程会使用系统嵌入的真实描述文件;为避免同名文件告警,可将该资源仅加入模拟器调试用的 target/configuration。
请勿将该文件随发布包上架:它属于开发调试产物,发布前建议从发布配置的资源中移除。
FAQ-2:初始化回调 1001(InvalidParameter,签名信息不可用)如何排查?
签名信息获取失败时初始化回调 1001(UMADKErrorCodeInvalidParameter);
1002(NotInitialized)仅当初始化未完成时调用业务接口才会出现。
遇到 1001 按以下顺序自查:
是否在模拟器上运行 → 见 FAQ-1(或改用真机);
真机上出现 1001(签名信息不可用)→ 检查构建签名配置(须为真实 provisioning
签名,
CODE_SIGNING_ALLOWED不可为 NO);1001(appKey 未注册)→ 检查
UMConfigure是否正常初始化(UMCommon ≥ 7.6.7初始化完成时 SDK 配置自动就绪),并确认 appKey 非空(参见第六章本地错误码表)。
FAQ-3:分发包(TestFlight / App Store)还需要为 teamId 做额外配置吗?
不需要。 SDK 自动从 App 自身签名数据获取团队标识,接入方无需任何
额外配置。即使分发处理环节剥离了签名描述文件,SDK 仍可从签名信息中
正常获取,初始化不受影响。
模拟器联调例外:模拟器构建无有效签名信息,仍需按 FAQ-1 手动注入描述文件。
注:文中「初始化」均指 [UMADK initializeWithCompletion:] 调用。