Microsoft has recently released two important AI services:
- Microsoft Cognitive Services are APIs which lets you tap into an ever-growing collection of powerful AI algorithms developed by experts in the fields of computer vision, speech, natural language processing, knowledge extraction and web search;
- Bot framework is a very useful framework to build and connect intelligent bots to interact with your users naturally wherever they are, from Telegram to Skype, Slack, Facebook and other popular services;
This article discovers this services and shows how developing artificial intelligence using .NET.
Demo
The demo shows how to build a Bot that can automatically caption photos sent by users.
Requirements
- Visual studio 2015 community edition , download here;
- Bot conversation emulator, click here to download;
- Microsoft cognitive services subscription, sign in here;
- Visual studio Bot Framework .NET template, which can be downloaded here. To install, save the zip file to your Visual Studio 2015 templates directory which is traditionally in
"%USERPROFILE%\Documents\Visual Studio 2015\Templates\ProjectTemplates\Visual C#\";
Setup the bot project
Create a new C# project using the new Bot Application template:
Visual studio generates a new controller, by default, called MessageController, which is the main entry point of your bot:
| using System; |
| using System.Linq; |
| using System.Net; |
| using System.Net.Http; |
| using System.Threading.Tasks; |
| using System.Web.Http; |
| using System.Web.Http.Description; |
| using Microsoft.Bot.Connector; |
| using Newtonsoft.Json; |
|
|
| namespace Bot_Application1 |
| { |
| [BotAuthentication] |
| public class MessagesController : ApiController |
| { |
| /// <summary> |
| /// POST: api/Messages |
| /// Receive a message from a user and reply to it |
| /// </summary> |
| public async Task<HttpResponseMessage> Post([FromBody]Activity activity) |
| { |
| if (activity.Type == ActivityTypes.Message) |
| { |
| ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl)); |
| // calculate something for us to return |
| int length = (activity.Text ?? string.Empty).Length; |
|
|
| // return our reply to the user |
| Activity reply = activity.CreateReply($"You sent {activity.Text} which was {length} characters"); |
| await connector.Conversations.ReplyToActivityAsync(reply); |
| } |
| else |
| { |
| HandleSystemMessage(activity); |
| } |
| 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; |
| } |
| } |
| } |
Setup the bot emulator
The emulator gives the possibility to test your bots locally. You can download the emulator
here.
The emulator requires 3 params:
- The Url for your bot set the localhost:<port> pulled from the last step. You will need to add the path “/api/messages” to your URL when using the Bot Application template;
- MicrosoftAppId field is NOT required to test bots locally;
- MicrosoftAppPassword field is NOT required to test bots locally;
Important: you need to run your bot project in Visual Studio, to use the bot emulator.
Setup images recognition (Microsoft cognitive services: Vision)
Microsoft Cognitive Services APIs offer the possibility to implement AI inside our applications. There are different services: Speech, Language, Knowledge, Vision and Search. This demo uses the Vision service to caption photos sent by users.
Class schema
Code
Firstly, add the IVisionConnector.cs interface and VisionConnector.csclass to your project:
| using Microsoft.Bot.Connector; |
| using Microsoft.ProjectOxford.Vision; |
| using Microsoft.ProjectOxford.Vision.Contract; |
| using System.Threading.Tasks; |
|
|
| namespace Blog.BotApplicationSample.Vision |
| { |
| public interface IVisionConnector |
| { |
|
|
| Task<AnalysisResult> AnalizeImage(Activity activity); |
|
|
| VisualFeature[] getVisualFeatures(); |
|
|
| VisionServiceClient getVisionClient(); |
| } |
| } |
The
IVisionConnector interface is referenced by
MessagesControllerand describes main methods which are used by
VisionConnector. API Token is required by
VisionServiceClient to consume APIs. You can get the APIs token
here.
| using Microsoft.Bot.Connector; |
| using Microsoft.ProjectOxford.Vision; |
| using Microsoft.ProjectOxford.Vision.Contract; |
| using System; |
| using System.Collections.Generic; |
| using System.IO; |
| using System.Linq; |
| using System.Threading.Tasks; |
| using System.Web; |
|
|
| namespace Blog.BotApplicationSample.Vision |
| { |
| public class VisionConnector : IVisionConnector |
| { |
|
|
| |
| private VisualFeature[] visualFeatures = new VisualFeature[] { |
| VisualFeature.Adult, //recognize adult content |
| VisualFeature.Categories, //recognize image features |
| VisualFeature.Description //generate image caption |
| }; |
|
|
| private VisionServiceClient visionClient = new VisionServiceClient("<YOUR API KEY HERE> https://www.microsoft.com/cognitive-services/en-us/sign-up"); |
|
|
|
|
|
|
| public async Task<AnalysisResult> AnalizeImage(Activity activity) { |
| //If the user uploaded an image, read it, and send it to the Vision API |
| if (activity.Attachments.Any() && activity.Attachments.First().ContentType.Contains("image")) |
| { |
| //stores image url (parsed from attachment or message) |
| string uploadedImageUrl = activity.Attachments.First().ContentUrl; ; |
| uploadedImageUrl = HttpUtility.UrlDecode(uploadedImageUrl.Substring(uploadedImageUrl.IndexOf("file=") + 5)); |
|
|
| using (Stream imageFileStream = File.OpenRead(uploadedImageUrl)) |
| { |
| try |
| { |
| return await this.visionClient.AnalyzeImageAsync(imageFileStream, visualFeatures); |
| } |
| catch (Exception e) |
| { |
| return null; //on error, reset analysis result to null |
| } |
| } |
| } |
| //Else, if the user did not upload an image, determine if the message contains a url, and send it to the Vision API |
| else |
| { |
| try |
| { |
| return await visionClient.AnalyzeImageAsync(activity.Text, visualFeatures); |
| } |
| catch (Exception e) |
| { |
| return null; //on error, reset analysis result to null |
| } |
| } |
| } |
|
|
|
|
|
|
| public VisualFeature[] getVisualFeatures() { |
| return visualFeatures; |
| } |
|
|
| public VisionServiceClient getVisionClient() |
| { |
| return visionClient; |
| } |
| } |
| } |
VisionConnector implements methods to communicate with Microsoft Cognitive API.
Next, go to MessagesController.cs class file and replace the following code:
| using System; |
| using System.Linq; |
| using System.Net; |
| using System.Net.Http; |
| using System.Threading.Tasks; |
| using System.Web.Http; |
| using System.Web.Http.Description; |
| using Microsoft.Bot.Connector; |
| using Newtonsoft.Json; |
| using Blog.BotApplicationSample.Vision; |
|
|
| namespace Blog.BotApplicationSample |
| { |
| [BotAuthentication] |
| public class MessagesController : ApiController |
| { |
|
|
| public IVisionConnector visionConnector; |
|
|
|
|
| public MessagesController() { |
| visionConnector = new VisionConnector(); |
| } |
|
|
| /// <summary> |
| /// POST: api/Messages |
| /// Receive a message from a user and reply to it |
| /// </summary> |
| public async Task<HttpResponseMessage> Post([FromBody]Activity activity) |
| { |
|
|
| ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl)); |
|
|
| if (activity.Type == ActivityTypes.Message) |
| { |
|
|
| var analysisResult =await visionConnector.AnalizeImage(activity); |
| Activity reply = activity.CreateReply("Did you upload an image? I'm more of a visual person. " + |
| "Try sending me an image or an image url"); //default reply |
|
|
| if (analysisResult != null) |
| { |
| string imageCaption = analysisResult.Description.Captions[0].Text; |
| reply = activity.CreateReply("I think it's " + imageCaption); |
| } |
| await connector.Conversations.ReplyToActivityAsync(reply); |
| return new HttpResponseMessage(HttpStatusCode.Accepted); |
| } |
| else |
| { |
| HandleSystemMessage(activity); |
| } |
| 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; |
| } |
| } |
| } |
MessageController class watches all incoming images and returns the detected caption.
All together now!
Finally, run your Visual studio project and set the bot URL on Bot emulator:
Final thoughts
They let you build cross-platform apps with powerful algorithms using just a few lines of code.
Bot framework is compatibile with the most famous chats: Facebook, Telegram, Skype and Whatsapp.
Cheers

0 comments:
Post a Comment
Note: only a member of this blog may post a comment.