AI 问答
向当前 AI 服务商发送文本问题,通过返回的问题 ID 关联后续回调,并展示完整或增量回答。
Animated workflow
AI 问答请求生命周期
问题 ID 可能由方法同步返回,也可能通过回调返回;随后会收到流式回答和最终回调。
前提条件
- 初始化
AIBudsAISDK、选择已注册的 AI 服务商,并在需要时完成鉴权。 - 确认所选 AI 服务商实现
AIAskingServiceAPI。 - 将回调触发的 UI 操作派发到主队列。
使用 AI 辅助实现
使用 AI 开发
让 AI 帮助实现此工作流
使用官方“实现 AIBuds AI 问答”技能,根据你的 App 完成实现。
请阅读并遵循 https://docs-aibuds.github.io/zh-Hans/skills/implement-aibuds-ai-asking,使用该技能在当前 iOS 项目中完成“实现 AIBuds AI 问答”,并验证结果。API 参考
框架
AIBudsAI.xcframework
导入
- Swift
- Objective-C
import AIBudsAI
import AIBudsAIFoundation#import <AIBudsAI/AIBudsAI-Swift.h>声明
- Swift
- Objective-C
/// Sends a text question to the currently selected AI service and receives
/// the answer as a stream of updates.
///
/// - Parameters:
/// - question: The question or prompt to send.
/// - config: Configuration for the request. Defaults to `.default`.
/// - onStartAnswering: Called when the service starts answering. The
/// question identifier may be `nil` if it has not yet been assigned.
/// - onAnswer: Called for each answer update.
/// - questionId: The identifier of the question being answered.
/// - deltaText: Newly generated text in this update, if available.
/// - fullText: The accumulated answer text, if available.
/// - isFinal: `true` when this is the final answer update.
/// - onFinishAnswering: Called when answering finishes successfully.
/// - onError: Called when validation fails or the provider reports an error.
/// - Returns: The question identifier when the request is created; otherwise `nil`.
public static func send(question: String,
config: AIAskingConfig = .default,
onStartAnswering: ((_ questionId: String?) -> Void)? = nil,
onAnswer: ((
_ questionId: String,
_ deltaText: String?,
_ fullText: String?,
_ isFinal: Bool
) -> Void)? = nil,
onFinishAnswering: ((_ questionId: String) -> Void)? = nil,
onError: ((_ questionId: String, _ error: Error) -> Void)? = nil) -> String?/// Sends a text question and streams answer updates.
///
/// - Parameters:
/// - question: The question or prompt to send.
/// - config: Configuration for this request.
/// - onStartAnswering: Called when the provider starts answering.
/// - onAnswer: Returns the question ID, delta text, accumulated text, and
/// whether this is the final answer update.
/// - onFinishAnswering: Called when answering finishes successfully.
/// - onError: Called for synchronous validation or provider errors.
/// - Returns: The question identifier when created; otherwise `nil`.
+ (NSString * _Nullable)sendQuestion:(NSString * _Nonnull)question
config:(AIBudsAIAskingConfig * _Nonnull)config
onStartAnswering:(void (^ _Nullable)(NSString * _Nullable))onStartAnswering
onAnswer:(void (^ _Nullable)(NSString * _Nonnull, NSString * _Nullable, NSString * _Nullable, BOOL))onAnswer
onFinishAnswering:(void (^ _Nullable)(NSString * _Nonnull))onFinishAnswering
onError:(void (^ _Nullable)(NSString * _Nonnull, NSError * _Nonnull))onError;请参阅 send 和 AIAskingConfig。
配置
AIAskingConfig.specifiedAgent 是 AI 服务商专用的可选值。设为 nil 时,由服务商自动选择 Agent。Demo 中的 Agent ID 不一定适用于其他账号或 AI 服务商,请勿直接复用。
使用示例
示例参考 AIAskingDemoController:既能处理完整累积回答,也能处理增量回答;保留最新的非空问题标识符,并区分最终回答更新与请求完成。
- Swift
- Objective-C
let question = input.trimmingCharacters(in: .whitespacesAndNewlines)
guard !question.isEmpty else { return }
let config = AIAskingConfig()
config.specifiedAgent = selectedAgentID
var activeQuestionID: String?
var answer = ""
let returnedID = AIBudsAISDK.send(
question: question,
config: config,
onStartAnswering: { questionID in
DispatchQueue.main.async {
activeQuestionID = questionID ?? activeQuestionID
}
},
onAnswer: { questionID, deltaText, fullText, isFinal in
DispatchQueue.main.async {
activeQuestionID = questionID
if let fullText {
answer = fullText
} else if let deltaText {
answer += deltaText
}
render(answer: answer, isFinalUpdate: isFinal)
}
},
onFinishAnswering: { questionID in
DispatchQueue.main.async {
activeQuestionID = questionID
setAsking(false)
}
},
onError: { questionID, error in
DispatchQueue.main.async {
if !questionID.isEmpty { activeQuestionID = questionID }
setAsking(false)
show(error)
}
}
)
activeQuestionID = returnedID ?? activeQuestionIDNSString *question =
[self.input stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
if (question.length == 0)
return;
AIBudsAIAskingConfig *config = [[AIBudsAIAskingConfig alloc] init];
config.specifiedAgent = self.selectedAgentID;
__block NSString *activeQuestionID = nil;
__block NSString *answer = @"";
NSString *returnedID = [AIBudsAISDK sendQuestion:question
config:config
onStartAnswering:^(NSString *questionID) {
dispatch_async(dispatch_get_main_queue(), ^{
activeQuestionID = questionID ?: activeQuestionID;
});
}
onAnswer:^(NSString *questionID, NSString *deltaText, NSString *fullText, BOOL isFinal) {
dispatch_async(dispatch_get_main_queue(), ^{
activeQuestionID = questionID;
answer = fullText ?: [answer stringByAppendingString:deltaText ?: @""];
[self renderAnswer:answer isFinalUpdate:isFinal];
});
}
onFinishAnswering:^(NSString *questionID) {
dispatch_async(dispatch_get_main_queue(), ^{
activeQuestionID = questionID;
[self setAsking:NO];
});
}
onError:^(NSString *questionID, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (questionID.length > 0)
activeQuestionID = questionID;
[self setAsking:NO];
[self showError:error];
});
}];
activeQuestionID = returnedID ?: activeQuestionID;错误处理
如果提交前的检查失败,send 可能返回 nil 并同步调用 onError,此时错误回调中的问题 ID 为空。请求进行期间应避免重复提交,并在 onFinishAnswering 或 onError 中恢复 UI。
注意事项
isFinal标记最后一次流式回答更新;使用onFinishAnswering表示请求成功完成。- AI 服务商可能返回
fullText、deltaText或同时返回两者。优先使用fullText,避免重复拼接文本。 - 公开 API 当前没有提供取消活动提问请求的方法。