AI 問答
選択中の AI プロバイダーへテキストで質問を送り、返された質問 ID と各コールバックを対応付けながら、回答の全文または差分を表示します。
Animated workflow
AI 問答リクエストのライフサイクル
質問 ID は同期的に返る場合とコールバックで届く場合があり、その後に回答の逐次更新と終了コールバックが届きます。
前提条件
AIBudsAISDKを初期化し、登録済みプロバイダーを選択して、必要な認証を完了していること。- 選択中のプロバイダーが
AIAskingServiceAPIを実装していること。 - コールバックを受けて行う UI 更新はメインキューへ切り替えること。
AI を活用して実装
AI で実装
AI でこのワークフローを実装
公式の「AIBuds AI 質問応答の実装」スキルを使い、アプリに合わせて実装します。
https://docs-aibuds.github.io/ja/skills/implement-aibuds-ai-asking を読み、その指示に従ってください。このスキルで「AIBuds AI 質問応答の実装」をこの iOS プロジェクトに実装し、検証してください。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 は任意指定で、プロバイダー固有です。nil の場合はプロバイダーの通常のエージェント選択が使われます。Demo のエージェント ID を別のアカウントやプロバイダーでも利用できるとは限りません。
使用例
次の例は AIAskingDemoController に沿って、回答の全文と差分のどちらにも対応し、最後に取得した空でない質問 ID を保持します。また、回答更新の最終回とリクエスト完了を区別して処理します。
- 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 は空です。処理中は重複送信を防ぎ、どちらの終了コールバックからも UI 状態を復元できるようにしてください。
注意事項
isFinalは回答更新の最終回を示します。リクエストの正常完了はonFinishAnsweringで判定してください。- プロバイダーは
fullText、deltaText、またはその両方を返す場合があります。蓄積済みテキストの重複を避けるため、fullTextを優先してください。 - 現在の公開 API には、実行中の問答リクエストをキャンセルするメソッドがありません。