こんにちは、高崎@アノテーション です。
はじめに
先日 LINE ヤフー社より下記のニュースがリリースされました。
Messaging APIでユーザーとのトーク画面にローディングのアニメーションを表示できるようになりました
どういった動きをするのか、手持ちの LINE 環境に組み込んでみました。
アニメーション表示について
例えばボットの応答に時間を要する場合、今まではユーザー側が要求してしばらく待って応答が来る、という間に実行中である旨を知らせるため LINE 側で用意したアニメーションで視覚的に伝えるやり方です。
詳細な画面については ローディングのアニメーションを表示する をご参照ください。
API リファレンスの説明は下記でした。
内容を確認しますと、
curl -v -X POST https://api.line.me/v2/bot/chat/loading/start \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {channel access token}' \
-d '{
"chatId": "U4af4980629...",
"loadingSeconds": 5
}'
と、shell で設定するやり方しか載っておらず、手持ちの LINE 環境(TypeScript ベース)にどのような関数を用意すれば良いかリファレンスだけでは伺いしれずでした。
で、探してみた
line-bot ライブラリ を上記の URL char/loading/start
で検索してみますと下記の関数を発見。
showLoadingAnimation
抜粋しますと、
lib/messaging-api/api/messagingApiClient.ts
/**
* Display a loading animation in one-on-one chats between users and LINE Official Accounts.
* @param showLoadingAnimationRequest
*
* @see <a href="https://developers.line.biz/en/reference/messaging-api/#display-a-loading-indicator"> Documentation</a>
*/
public async showLoadingAnimation(
showLoadingAnimationRequest: ShowLoadingAnimationRequest,
): Promise<object> {
return (
await this.showLoadingAnimationWithHttpInfo(showLoadingAnimationRequest)
).body;
}
/**
* Display a loading animation in one-on-one chats between users and LINE Official Accounts..
* This method includes HttpInfo object to return additional information.
* @param showLoadingAnimationRequest
*
* @see <a href="https://developers.line.biz/en/reference/messaging-api/#display-a-loading-indicator"> Documentation</a>
*/
public async showLoadingAnimationWithHttpInfo(
showLoadingAnimationRequest: ShowLoadingAnimationRequest,
): Promise<Types.ApiResponseType<object>> {
const params = showLoadingAnimationRequest;
const res = await this.httpClient.post(
"/v2/bot/chat/loading/start",
params,
);
return { httpResponse: res, body: await res.json() };
}
このshowLoadingAnimation
をコールすると出来そうですね。
2024/04/30 現在の話ですので今後 I/F 等が変わる可能性があります。
組み込んでみた
ベース環境
下記の記事に整理したものをベースにします。
方針
ask
コマンドで Amazon Bedrock に画を要求する箇所にローディングアニメーションを追加したいと思います。
下記に変更前ソースを抜粋で記載します。
backend/src/use-case/line-bot-use-case/dispatchCommand.ts
/**
* ask コマンド実行
* @param imageCraftRepository : ImageCraft データリポジトリ
* @param orderedText : 生成要求テキスト
* @param quoteToken : LINE のユニークトークン
* @returns replyMessage 形式
*/
export const execAskCommand = async({
imageCraftRepository,
orderedText,
quoteToken,
}: {
imageCraftRepository: ImageCraftRepository,
orderedText: string,
quoteToken: string,
}): Promise<ReplyMessages> => {
const reply: ReplyMessages = [];
try {
// 画像生成要求
await imageCraftRepository.createImage({ orderedText, quoteToken });
// 画像 URL 取得(戻り値に使用するため)
const imageUrl = await imageCraftRepository.getImageUrl(quoteToken);
// 応答メッセージを作成
reply.push({
type: "image",
originalContentUrl: imageUrl,
previewImageUrl: imageUrl,
});
} catch (e) {
// コンソールにエラーを出す
console.error(e);
// 応答メッセージを作成
reply.push({
type: "text",
text: (e instanceof Error) ? e.message : "画像生成時にエラーが発生しました",
quoteToken: quoteToken,
});
}
return reply;
}
画像生成要求と URL 取得を纏めたローカル関数を設定し、今回用意するshowLoadingAnimation
を呼び出す line-bot ドメイン関数と並行して実行するようにします。
また、当該関数の引数に line-bot ドメインクラスと宛先に使う LINE ユーザー ID を追加し、下記のように実装しました。1
リファレンス推奨されている実装ではないのでご注意ください。
backend/src/use-case/line-bot-use-case/dispatchCommand.ts
/**
* ask コマンド実行実関数
* @param imageCraftRepository : ImageCraft データリポジトリ
* @param orderedText : 生成要求テキスト
* @param quoteToken : LINE のユニークトークン
* @returns S3 に保存した画像の URL
*/
const _execAskCommand = async ({
imageCraftRepository,
orderedText,
quoteToken,
}: {
imageCraftRepository: ImageCraftRepository,
orderedText: string,
quoteToken: string,
}): Promise<string> => {
try {
// 画像生成要求
await imageCraftRepository.createImage({ orderedText, quoteToken });
// 画像 URL 取得(戻り値に使用するため)
return await imageCraftRepository.getImageUrl(quoteToken);
} catch (e) {
// コンソールにエラーを出す
console.error(e);
// 応答メッセージを作成
return (e instanceof Error) ? e.message : "画像生成時にエラーが発生しました";
}
}
/**
* ask コマンド実行
* @param imageCraftRepository : ImageCraft データリポジトリ
* @param orderedText : 生成要求テキスト
* @param quoteToken : LINE のユニークトークン
* @param lineUserId : LINE ユーザ ID
* @param lineBotClient : LINE ボットドメインクラス
* @returns ReplyMessages 形式での応答
*/
export const execAskCommand = async({
imageCraftRepository,
orderedText,
quoteToken,
lineUserId,
lineBotClient,
}: {
imageCraftRepository: ImageCraftRepository,
orderedText: string,
quoteToken: string,
lineUserId: string,
lineBotClient: LineBot,
}): Promise<ReplyMessages> => {
const reply: ReplyMessages = [];
// 2処理を並行で動作させ ask コマンドの実行結果を取得する
const [, resultCreateImage] = await Promise.all([
// 1. ローディングアニメーションを表示させてみる
// replyMessage するとアニメーションは消えるので 30 秒ほど多めに設定しておく
lineBotClient.showLoadingAnimation({
chatId: lineUserId,
loadingSeconds: 30,
}),
// 2. ask コマンド実行
_execAskCommand({ imageCraftRepository, orderedText, quoteToken, })
]);
// 応答メッセージを作成
reply.push({
type: "image",
originalContentUrl: resultCreateImage,
previewImageUrl: resultCreateImage,
})
return reply;
}
結果
動作確認
動画を撮ってみました。
この動作確認は 2024/04/28 に行っており、描画結果が現在では変わっている可能性があります。
動かない時
当初、筆者の端末に対して API を実行すると結果が 202 リターンして正常終了したにもかかわらず、端末にアニメーション画面が出てこないことがありました。
その場合、端末側のキャッシュをクリア すると表示しましたので、ご参考になれば幸いです。
ソース環境
ソース環境は下記の GitHub です。
おわりに
今回はユーザーに時間のかかる応答を視覚的に見せられる仕組みとして追加されたローディングアニメーションについて実装して確認してみました。
実装する際にライブラリのソースから探したのでリファレンス推奨じゃないかもしれませんが、LINE ボットの Node.js ライブラリに更新があれば新たに実装を合わせたいと思います。
アノテーション株式会社について
アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。
サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイトをぜひご覧ください。
- この他にも定義クラスや呼び出しの line-bot ユースケース、Bedrock の生成 AI エンジン呼び出しも変更していますが省略します。ソース環境の GitHub にて変更を確認ください。 ↩