AI-вопросы
Отправляйте текстовый вопрос выбранному поставщику AI-сервисов, связывайте callbacks с идентификатором вопроса и отображайте накопленный текст ответа либо его приращения.
Жизненный цикл AI-вопроса
Идентификатор запроса может быть получен синхронно или через callback; затем поступают потоковые обновления ответа и один завершающий callback.
Предварительные условия
- Инициализируйте
AIBudsAISDK, выберите зарегистрированного поставщика и при необходимости завершите авторизацию. - Убедитесь, что выбранный поставщик реализует
AIAskingServiceAPI. - Выполняйте обновления интерфейса из callbacks в главной очереди.
Реализация с помощью AI
Реализуйте этот сценарий с AI
Используйте официальный навык «Реализация вопросов к ИИ AIBuds» и адаптируйте сценарий к приложению.
Прочитайте и выполните инструкции https://docs-aibuds.github.io/ru/skills/implement-aibuds-ai-asking. Используйте этот навык, чтобы реализовать «Реализация вопросов к ИИ AIBuds» в данном iOS-проекте и проверить результат.API Reference
Framework
AIBudsAI.xcframework
Import
- Swift
- Objective-C
import AIBudsAI
import AIBudsAIFoundation#import <AIBudsAI/AIBudsAI-Swift.h>Declaration
- 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 необязателен и зависит от поставщика. Оставьте nil, чтобы использовать стандартный выбор агента. Идентификатор из Demo может быть недействителен для другой учётной записи или поставщика.
Примеры использования
Примеры соответствуют 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. Идентификатор вопроса в callback ошибки при этом пуст. Пока запрос активен, блокируйте повторную отправку и восстанавливайте интерфейс из обоих завершающих callbacks.
Примечания
isFinalотмечает последнее потоковое обновление ответа; успешное завершение запроса определяйте поonFinishAnswering.- Поставщик может передать
fullText,deltaTextили оба значения. ПредпочитайтеfullText, чтобы не дублировать накопленный текст. - Публичный API сейчас не предоставляет метод отмены активного запроса.