Bot

画像を検索する Bot を作ってみた

Bot FrameWork ネタです。
今回は、画像を検索する Bot を作ってみました。

参考情報は、下記になります。
https://docs.botframework.com/en-us/bot-intelligence/search/#example-gif-search-bot

画像の検索の機能は、Azure Cognitive Service の Bing Search API を使っています。

 

エミュレーターで動かすと、こんな感じ。Bing の画像検索の最初に出てきたものが応答される感じです。

 

 

ソース

 

基本的には、以下のドキュメントを使っていく感じです。
https://docs.botframework.com/en-us/bot-intelligence/search/#example-gif-search-bot

BingImageSearchResponse.cs は、そのままコピペして作ったので、割愛しちゃいます。

 

MessagesController.cs は、以下のようにしました。
自分で変えたのは19行目の URI を変えたのと、あとはデータが見つからなかった時に「Not Found!」って返すようにしたくらいです。

 

    [BotAuthentication]
    public class MessagesController : ApiController
    {
        ///
<summary>
        /// POST: api/Messages
        /// Receive a message from a user and reply to it
        /// </summary>

        public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity)
        {
            ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));

            if (activity == null || activity.GetActivityType() != ActivityTypes.Message)
            {
                //add code to handle errors, or non-messaging activities
                HandleSystemMessage(activity);
            }

            const string apiKey = "<< Bing Search API の Key >>";
            string queryUri = "https://api.cognitive.microsoft.com/bing/v5.0/images/search"
                              + "?q=" + System.Web.HttpUtility.UrlEncode(activity.Text);
            //                  + "&imageType=AnimatedGif"; //parameter to filter by GIF image type

            // string queryUri = "https://bingapis.azure-api.net/api/v5/images/search"
            //                   + "?q=" + activity.Text
            //                   + "&imageType=AnimatedGif"; //parameter to filter by GIF image type

            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey); //authentication header to pass the API key
            client.DefaultRequestHeaders.Add("Accept", "application/json");
            string bingRawResponse = null;
            BingImageSearchResponse bingJsonResponse = null;

            try
            {
                bingRawResponse = await client.GetStringAsync(queryUri);
                bingJsonResponse = JsonConvert.DeserializeObject<BingImageSearchResponse>(bingRawResponse);
            }
            catch (Exception e)
            {
                //add code to handle exceptions while calling the REST endpoint and/or deserializing the object
                Console.Out.WriteLine(e.Message);
            }

            var replyMessage = activity.CreateReply();

            ImageResult[] imageResult = bingJsonResponse.value;
            if (imageResult == null || imageResult.Length == 0)
            {
                //add code to handle the case where results are null or zero
                replyMessage.Text = "Not Found!";
            }
            else
            {
                string firstResult = imageResult[0].contentUrl; //we only need the first result for this example

                replyMessage.Recipient = activity.From;
                replyMessage.Type = ActivityTypes.Message;
                replyMessage.Text = $"Here is what i found:";
                replyMessage.Attachments = new System.Collections.Generic.List<Attachment>();
                replyMessage.Attachments.Add(new Attachment()
                {
                    ContentUrl = firstResult,
                    ContentType = "image/png"
                });
            }

            //Reply to user message with image attachment
            await connector.Conversations.ReplyToActivityAsync(replyMessage);

            var response = Request.CreateResponse(HttpStatusCode.OK);
            return response;
        }

        private Activity HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                // Handle conversation state changes, like members being added and removed
                // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
                // Not available in all channels
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }

            return null;
        }
    }

 

Bing Search API

Bing Serch API を利用するには、Microsoft Azure のポータル画面よりサービスを作成して、キーを取得する必要があります。
取得したキーは先ほどのソースの18行目に設定する感じです。

ポータルからは、「Data + Analytics」 を選択し、 「API Type」 を 「Bing Search APIs」にする感じです。

 

ちなみに料金はこんな感じ。
一番安いプランでも、秒間10回のコール、月に1000回のコールまでできます。

 

Bing Search API のドキュメント
https://www.microsoft.com/cognitive-services/en-us/bing-image-search-api/documentation

Image Search API Reference
https://msdn.microsoft.com/en-us/library/dn760791.aspx

 

Bing 系の API は、Project Oxford の頃から Preview Service として利用できましたが、先月に GA されました。

General availability: Bing APIs in Microsoft Cognitive Services
https://azure.microsoft.com/en-us/updates/general-availability-microsoft-cognitive-services-bing-apis/

 

まとめ

Micorosft Azure の Cognitive Service の Bing Search API を使うことで、特定のキーワードで検索した結果を Bot の応答に利用するってことは簡単にできちゃいます。

今回は、画像検索でしたが、他にもWebの情報だったり動画だったり、ニュースの検索とかもできるみたいです。

 

ただ、いろいろ使ってみるとBing 側の検索が、いまいちフィットしてないんだよなぁーってところは、若干ありました。

「きたあずちゃん」でBingの画像検索結果

 

「きたあずちゃん」でGoogle画像検索の結果

一般的な言葉での検索は、大丈夫なんだと思うのですが。。。

-Bot
-, ,