Liens
- Le bot rejoint la conversation en envoyant une Activity ConversationUpdate du Bot Framework Service au bot.
- Les utilisateurs rejoignent en envoyant une Activity ConversationUpdate du Bot Framework Service au bot.
- Les utilisateurs envoient des Activity Message du Bot Framework Service au bot.
- Le bot répond en envoyant des Activity Message du bot au Bot Framework Service.
Créer un bot dans Azure
- Azure → All resources → Add → AI + Machine Learning → Web App Bot
- Pricing tier
- F0 - gratuit - limité à 10.000 messages
- S1 - 0,49$ / 1.000 messages
- Bot Template
- Echo Bot
- Basic Bot (Language Understanding, Bot Analytics, Storage, Web app
Créé 4 services: Web App Bot, App Service, Storage account, Application Insights
- Enterprise Bot (Basic Bot + CosmosDB, Dispatch, QnA Maker, Authentication, Content Moderator, App Insights, PowerBI)
- Custom Assistant (Enterprise Bot + Linked Accounts ans Skills)
- Language Understanding Bot (LUIS app)
- QnA Bot
- Test: sélectionner le service Web App Bot → Test in Web Chat
- Récupérer le code source: sélectionner le service Web App Bot → Build → Download Bot source code
- Compléter le fichier appsettings.json avec les infos se trouvant dans Web App Bot → Application Settings
appsettings.json
|
{
"botFilePath": "MyBot.bot",
"botFileSecret": "..."
}
|
- Lancer l'application : F5
- Utiliser le botframework emulator : Url endpoint http://localhost:3978/api/messages
Publier les modifications sur Azure
- clique-droit sur le projet → Publish
- utiliser le mot de passe du fichier publish.cmd
Page de test
Azure → My Web App Bot → Channels
- Ajouter le channel DirectLine : Add a featured channel → Configure Direct Line chanel
- Copier les Secret Keys
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="https://cdn.botframework.com/botframework-webchat/latest/botchat.css" rel="stylesheet" />
</head>
<body>
<div id="bot"/>
<script src="https://cdn.botframework.com/botframework-webchat/latest/botchat.js"></script>
<script>
BotChat.App({
directLine: { secret: '' },
user: { id: '', name: ''},
bot: { id: 'MyBot' },
resize: 'detect'
}, document.getElementById("bot"));
</script>
</body>
</html>
|
Projet C#
MyBot.cs
|
public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken)
{
var activity = turnContext.Activity;
if (activity.Type == ActivityTypes.Message)
{
// Perform a call to LUIS to retrieve results for the current activity message.
var luisResults = await _services.LuisServices[LuisConfiguration].RecognizeAsync(turnContext, cancellationToken).ConfigureAwait(false);
var topScoringIntent = luisResults?.GetTopScoringIntent();
var topIntent = topScoringIntent.Value.intent;
switch (topIntent)
{
case GreetingIntent:
await turnContext.SendActivityAsync("Hello.");
break;
case HelpIntent:
await turnContext.SendActivityAsync("Let me try to provide some help.");
await turnContext.SendActivityAsync("I understand greetings, being asked for help, or being asked to cancel what I am doing.");
break;
case CancelIntent:
await turnContext.SendActivityAsync("I have nothing to cancel.");
break;
case NoneIntent:
default:
// Help or no intent identified, either way, let's provide some help.
// to the user
await turnContext.SendActivityAsync("I didn't understand what you just said to me.");
break;
}
}
else if (activity.Type == ActivityTypes.ConversationUpdate)
{
if (activity.MembersAdded.Any())
{
// Iterate over all new members added to the conversation.
foreach (var member in activity.MembersAdded)
{
// Greet anyone that was not the target (recipient) of this message.
// To learn more about Adaptive Cards, see https://aka.ms/msbot-adaptivecards for more details.
if (member.Id != activity.Recipient.Id)
{
var welcomeCard = CreateAdaptiveCardAttachment();
var response = CreateResponse(activity, welcomeCard);
await turnContext.SendActivityAsync(response).ConfigureAwait(false);
}
}
}
}
}
|
old
Controllers/MessageController.cs
|
[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)
{
await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
}
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;
}
|
Dialogs/RootDialog.cs
|
[Serializable]
public class RootDialog : IDialog<object>
{
public Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
return Task.CompletedTask;
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var activity = await result as Activity;
// calculate something for us to return
int length = (activity.Text ?? string.Empty).Length;
// return our reply to the user
await context.PostAsync($"You sent {activity.Text} which was {length} characters");
context.Wait(MessageReceivedAsync);
}
}
|
Permet de tester un projet ChatBot qui tourne en local.
Pour un projet déployé sur Azure, utiliser ngrok ou une page HTML de test avec la DirectLine.
endpoint |
http://localhost:3979/api/messages |
VS → Project → Properties → Web → Project Url + /api/messages
|
Microsoft App ID (inutile pour test local) |
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
Azure → Bot Channels Registration App → Settings → Microsoft App ID
|
Microsoft App Password (inutile pour test local) |
|
Azure → Bot Channels Registration App → Settings → Microsoft App ID → Manage Application Registration Portal → Bot Channels Registration App → Application Secrets → Password
|
%AppData%\botframework-emulator\botframework-emulator\server.json
|
"users": {
"currentUserId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"usersById": {
"default-user": {
"id": "default-user",
"name": "User"
},
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx": {
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"name": "MyUser"
}
}
|
ngrok
Permet de tester un bot hébergé sur Azure.
|
.\ngrok.exe http -host-header=rewrite 9000
|
- Azure → My Bot Channels Registration → modifier le endpoint du Bot avec l'adresse https fournie par ngrok + /api/messages ???
- Dans l'emulateur, utiliser l'adresse https fournie par ngrok + /api/messages ???
|
POST Response code 502 (Bad Gateway) |
OLD - Publier sur Azure
- Azure → créer une Web App Bot (Web App + Bot Channels Registration)
- Publier
- VS → Publish (création d'une Web App (App Service) au besoin)
- Azure → Create a resource → Web App → Get publish profile (à importer dans VS)
- Définir le Messaging endpoint: Azure → My Bot Channels Registration → Settings https://<url-app-service>/api/messages
- Récupérer l'AppId: Azure → My Bot Channels Registration → Settings → Microsoft App ID
- Récupérer le AppSecret: Azure → My Bot Channels Registration → Settings → Microsoft App ID → Manage → Create New Password
- The application was not found → utiliser Edge
- Ajouter le AppId et le AppSecret au web.config ou aux Application settings de la Web App
web.config
|
<configuration>
<appSettings>
<add key="BotId" value="YourBotId" />
<add key="MicrosoftAppId" value="" />
<add key="MicrosoftAppPassword" value="" />
|
Test: Azure → My Bot Channels Registration → Test in Web Chat
Dialogs/RootDialog.cs
|
var cocktailForm = new FormDialog<Cocktail>(
new Cocktail(),
() => Cocktail.BuildForm(),
FormOptions.PromptInStart);
context.Call<Cocktail>(cocktailForm, CocktailFormComplete);
private async Task CocktailFormComplete(IDialogContext context, IAwaitable<Cocktail> result)
{
Cocktail cocktail = null;
try
{
cocktail = await result;
}
catch (OperationCanceledException)
{
await context.PostAsync("You canceled the form!");
return;
}
if (cocktail != null)
{
await context.PostAsync(cocktail.Choice.ToString());
}
else
{
await context.PostAsync("Form returned empty response!");
}
context.Wait(MessageReceivedAsync);
}
|
Cocktail.cs
|
[Serializable]
public class Cocktail
{
[Prompt("Choisis ton cocktail: {||}")]
public CocktailChoice Choice { get; set; }
public static IForm<Cocktail> BuildForm()
{
return new FormBuilder<Cocktail>()
.Message("Bienvenu au bar!")
.Build();
}
}
public enum CocktailChoice
{
Rien, CubaLibre, Daïquiri, Mojito, Caïpirinha
};
|
Card
|
var card = new SigninCard("Please sign-in to use this functionality.",
new List<CardAction>()
{
new CardAction()
{
Title = "Sign in",
Type = ActionTypes.OpenUrl,
Value = "https://login.microsoftonline.com"
}
});
message.Attachments.Add(card.ToAttachment());
|
Format
|
Web
|
Teams
|
saut de ligne |
\n\n |
<br/>
|
gras |
**gras** |
gras
|
Channel
|
switch (context.Activity.ChannelId)
{
case ChannelIds.Msteams:
break;
default:
break;
}
|
PromptDialog
Permet de poser une question attendant une réponse et de boucler tant une réponse correcte n'a pas été fournie.
|
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var activity = await result as Activity;
if (activity.Text == "reboot")
{
PromptDialog.Confirm(
context,
AfterResetAsync,
"Voulez-vous vraiment lancer la commande reboot",
"Je n'ai pas compris votre réponse (yes/no)",
promptStyle: PromptStyle.None);
}
}
private async Task AfterRebootAsync(IDialogContext context, IAwaitable<bool> result)
{
var confirm = await result;
if (confirm)
{
await context.PostAsync("Lancement du Reboot");
}
else
{
await context.PostAsync("Annulation du Reboot");
}
context.Wait(MessageReceivedAsync);
}
|
Text analytics
Services
Language detection |
The API returns the detected language and a numeric score between 0 and 1. Scores close to 1 indicate 100% certainty that the identified language is true. A total of 120 languages are supported.
|
Key phrase extraction |
The API returns a list of strings denoting the key talking points in the input text.
|
Sentiment analysis |
The API returns a numeric score between 0 and 1. Scores close to 1 indicate positive sentiment, and scores close to 0 indicate negative sentiment.
|
Identify entities in your text |
Detect all named entities in the text, such as organizations, people, and locations.
|
Azure
- Web App Bot
- Functions Bot
- Bot Channels Registration
Channel
Skype Web Contol
|
<span class="skype-button bubble" data-bot-id="xxx"
data-color="#00AFF0">
</span>
<span class="skype-chat"
data-color-message="#80DDFF"
data-show-header="false"
data-can-upload-file="false"
data-theme="dark">
</span>
<script src="https://swc.cdn.skype.com/sdk/v1/sdk.min.js"></script>
|
Fenêtre blanche dans Chrome
Erreur: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.
chrome://settings/content/cookies
- Block third-party cookie = Off
- OU ajouter swc.cdn.skype.com dans les domaines autorisés Allow