Création d'un CRM avec Xamarin.Forms et Azure, partie 3
Dans la troisième partie de cette série de blogs, nous expliquerons comment entraîner un modèle LUIS AI personnalisé pour avoir des conversations de chat naturelles à l'aide de l'interface utilisateur Telerik pour le contrôle de l'interface utilisateur conversationnelle de Xamarin.
Vous pouvez trouver Première partie de notre series ici où nous avons construit le backend. Dans La deuxième partie de la série nous avons créé l'interface utilisateur avec Telerik UI pour Xamarin.
Dans ce dernier épisode de cette série de blogs, nous verrons comment créer une interface utilisateur conversationnelle à l'aide de RadChat et d'une modèle de compréhension du langage naturel Azure formé (aka LUIS). Ces articles peuvent être lus indépendamment, mais si vous voulez rattraper le retard, lisez la première et la deuxième partie.
Alimenter la conversation
L'interface utilisateur Telerik pour Xamarin Le contrôle RadChat est intentionnellement conçu pour être indépendant de la plate-forme. Bien que j'utilise Azure pour ce projet, vous pouvez utiliser tout ce que vous voulez ou avez actuellement.
Je voulais être sûr que l'application disposait d'un service dynamique et intelligent communiquant avec l'utilisateur, c'est là qu'Azure entre en scène encore. Nous pouvons former un modèle LUIS pour identifier certains contextes pour comprendre ce que l'utilisateur demande. Par exemple, demandent-ils les détails du produit ou les informations de livraison?
Pour commencer, suivez le Démarrage rapide: créez une nouvelle application dans le didacticiel du portail LUIS . Il est rapide et facile de lancer un projet et de commencer à entraîner le modèle avec vos intentions personnalisées.
À ce stade, vous voudrez peut-être réfléchir si vous souhaitez utiliser Intents Entities ou les deux. La page d'assistance ArtGallery CRM est mieux servie avec l'utilisation d'intentions. Pour vous aider à choisir la bonne approche pour votre application, Microsoft propose un joli tableau de comparaison – Entity par rapport à Intent .
Intentions
Dans la page de discussion de l'application CRM, l'utilisateur interagit avec un bot d'assistance. Ainsi, nous devons principalement déterminer si l'utilisateur demande des informations sur un produit, un employé, une commande ou un client. Pour ce faire, j'ai décidé d'utiliser les intentions suivantes:
énoncé . Jetons un coup d'œil aux énoncés pour l'intention Product .
le didacticiel de démarrage rapide d'Azure Bot pour savoir comment créer un nouveau service de bot dans votre portail Azure. Lorsque vous suivez les étapes de configuration, veillez à choisir le modèle de bot C # afin que le back-end du bot soit une application ASP.NET:
Dans le cas de notre bot d'écho, il s'agit de ActivityType.Message auquel cas la logique détermine que nous répondons avec une instance de EchoDialog . Maintenant, regardons la classe EchoDialog . Ceci se trouve dans le dossier Dialogs : C'est la logique que le bot utilisait lorsque vous discutiez simplement dans le chat Web! Ici, vous pouvez voir comment tous les messages que vous avez envoyés ont été répercutés et pourquoi il a été précédé d'un nombre de messages. Maintenant qu'un simple bot d'écho est en cours d'exécution, il est temps de configurer le côté client. Pour ce faire, nous aurons besoin de quelques éléments: Faisons d'abord la classe de service, puis passons ensuite au XAML. En plus du contrôle WebChat qui est intégrable, le Bot Service vous permet d'interagir directement avec lui en utilisant des requêtes réseau via DirectLine API . Bien que vous puissiez créer et envoyer manuellement des requêtes HTTP, Microsoft a fourni un SDK client .NET qui rend très simple et indolore la connexion et l'interaction avec le service Bot via le Microsoft.Bot.Connector.DirectLine NuGet package . Avec cela, nous pourrions techniquement simplement l'utiliser directement dans le modèle de vue (ou code derrière) de la page Xamarin.Forms, mais je voulais avoir une certaine séparation des préoccupations. Nous allons donc créer une classe de service qui n'est pas étroitement liée à cette page spécifique. [194550] [1945908] [194550] [1945519050] [1945519050] [1945519050] Il n'y a vraiment que deux responsabilités, envoyer des messages au bot et afficher les messages du bot entrants à l'utilisateur. Dans le constructeur de classe, nous instancions un objet DirectLineClient. Notez qu'il a besoin d'un paramètre App ID vous pouvez le trouver dans la page Paramètres du portail Azure pour l'application bot Voici une capture d'écran pour vous guider. L'ID est le champ "Microsoft App ID": documentation RadChat MVVM Support . L'instance de service peut être définie comme un champ privé qui est créé lorsque le modèle de vue est initialisé: Quand un message vient de th e bot, le service appellera la méthode OnMessageReceived du modèle de vue et transmettra un paramètre d'activité. avec ces informations, vous pouvez ajouter un message à la collection ConversationItems: Pour le message sortant de l'utilisateur, nous utiliserons les éléments de conversation Événement CollectionChanged . Si le message qui a été ajouté provient de l'utilisateur, nous pouvons le donner à la classe de service pour qu'il soit poussé vers le bot. [19455090] Dans la vue, tout ce que vous avez à faire est de lier la propriété ConversationItems à la propriété ItemsSource de RadChat. Lorsque l'utilisateur entre un message dans la zone de discussion, un nouveau TextMessage est créé par le contrôle et inséré automatiquement dans le ItemsSource (déclenchant CollectionChanged). Vous pouvez montrer qui est en train de taper avec une ObservableCollection Consultez le didacticiel Typing Indiciators pour plus d'informations. Vous pouvez également consulter cet article de la base de connaissances dans lequel j'explique comment avoir une expérience de salle de chat en temps réel avec les indicateurs. RadChat lui-même vous offre des fonctionnalités prêtes à l'emploi et est livré avec des styles à utiliser tels quels. Cependant, vous pouvez également personnaliser les éléments pour répondre à vos directives de marque ou créer de superbes effets tels que des messages consécutifs groupés. Pour plus d'informations, consultez le didacticiel ItemTemplateSelector . Vous pouvez exécuter l'application à ce stade et confirmer que le bot fait écho à vos messages. Cependant, il est maintenant temps de connecter la logique du serveur de bot à LUIS afin que vous puissiez renvoyer des messages significatifs à l'utilisateur! Pour ce faire, nous devons retourner au projet de bot et ouvrir la classe EchoDialog. Vous pouvez renommer cette classe pour mieux correspondre à ce qu'elle fait, par exemple, la boîte de dialogue de la démo CRM s'appelle "SupportDialog". [19659050] The Primary Key, Endpoint and LUIS App ID values are found in the luis.ai portal. (different than the Microsoft App ID for the bot project). Learn more here Quickstart: SDK Query Prediction Endpoint. The code above uses a very simple check for a "Product" intent and just replies with a statement. If there was no match, there's no reply. The takeaway here is though you are in control over what gets sent back to the user, with LUIS helping you make intelligent decisions, you can provide for the user's needs better than ever. I hope, though the course of this series, I was able to help show you that with the power of Telerik UI for Xamarin doing the heavy lifting in the UI category, and Azure powering intelligent backend services, you can build a enterprise ready, scalable, application with Xamarin Forms. The Art Gallery CRM demo has a much more robust solution in place that has many intents and detects user sentiment. For example, if the user is mad or happy, the bot will comment on it in addition to answering their question! Missed part of the series? You can find Part One herewhere we built the backend. In Part Twowe built the UI with Telerik UI for Xamarin. Now that you're familiar with the structure of the application, I highly recommend taking a look through the ArtGallery CRM source code on GitHub as you will recognize all the parts we discussed in this series. You can also install app for yourself, available in the: If you have any trouble with the Telerik UI for Xamarin controls, you can open a Support Ticket and get help from the Xamarin team directly (you get complete support with your trial). You can also search and post the UI for Xamarin Forums to discuss with the rest of the community. If you have any questions about this series, leave a comment below or reach out to me on Twitter @lancewmccarthy. [ResponseType(
typeof
(
void
))]
public
virtual
] Async Task
{
// Si le type d'activité est un Message, appelez la boîte de dialogue Assistance
if
(activity! =
null
&& activity.GetActivityType () = = ActivityTypes.Message )
{
Conversation en attente .SendAsync (activity, () =>
new
Dialogs. EchoDialog () );
} [19659443]
...
}
public
async Task MessageReceivedAsync (contexte IDialogContext, argument IAwaitable
{
var message = wait argument;
if
(message.Text ==
"reset"
)
{
// Si l'utilisateur a envoyé "reset", répondez avec une boîte de dialogue d'invite
PromptDialog.Confirm (
] [19659050]
contexte,
AfterResetAsync,
[19659103] "Voulez-vous vraiment réinitialiser le décompte?"
"Je n'ai pas compris!"
promptStyle: PromptStyle.Auto);
}
else
{
// If l'utilisateur a envoyé autre chose, répondez avec le même message précédé du nombre de messages
wait context.PostAsync ($
"{this.count ++ }: Vous avez dit {message.Text} "
); [1 9659443]
context.Wait (MessageReceivedAsync);
}
[19659050] }
Service de discussion Xamarin.Forms
Bot Service Class et l'API DirectLine
Voici la classe de service: utilisant
System;
using
System.Linq;
using
System.Threading.Tasks;
using
ArtGalleryCRM.Forms.Common;
using
Microsoft.Bot.Connector. DirectLine;
using
Xamarin.Forms;
namespace
ArtGalleryCRM.Forms .Services
{
public
class
ArtGallerySupportBotService
{
private
readonly
string
_user;
privé
Action
private
readonly
DirectLineClient _client;
[1945908] ] private
Conversation _conversation;
private
string
_watermark;
public
ArtGallerySupportBotService (
string
userDisplayName) [1965944390]
{
// Créer un DirectLineClient avec votre App Secret
[19659187] this
._ client =
new
DirectLineClient (ServiceConstants.DirectLineSecret);
this
._ user = userDisplayName;
}
[19659177]
internal
void
AttachOnReceiveMessage (Action
{
this
._ onReceiveMessage = onMessageReceived;
}
public
async Task StartConversationAsync ()
{
this
._ conversation = wait _client.Conversations.StartConversationAsync ();
}
// Envoie le message au bot
public
async
void
SendMessage (
string
text)
{
var userMessage =
new
Activity
{
From =
new
ChannelAccount (
this
._user),
Text = text,
Type = ActivityTypes.Message [19659443]
};
wait
this
._ client.Conversations.PostActivityAsync (
this
._ conversation.ConversationId, userMessage);
attend
this
.ReadBotMessagesAsync ();
}
// Affiche le message entrant à l'utilisateur
private
async Task ReadBotMessagesAsync ()
{
var activitySet = wait
this [19659053] ._ client.Conversations.GetActivitiesAsync (
this
._ conversation.ConversationId, _watermark);
[19659187] if
(activitySet! =
null
)
{
this
._ watermark = activitySet.Watermark;
var activities = activitySet.Activities.Where (x => x.From.Id == ServiceConstants.BotId);
Device.BeginInvokeOnMainThread (() = >
{
foreach
(Activité d'activité
dans
activités)
{
this
._onReceiveMessage? .Invoke (activité);
}
}); [19659443]
}
}
}
}
public
ObservableCollection
get
;
réglé
; } =
new
ObservableCollection
classe publique
SupportViewModel: PageViewModelBase
{
private
ArtGallerySupportBotService
ArtGallerySupportServiceBotService 19659443]
public
async Task InitializeAsync ()
{
this
.botService =
new
ArtGallerySupportBotService (
"Lance"
); [19659443]
this
.botService.AttachOnReceiveMessage (
this
.OnMessageReceived);
[1965509050]
}
...
}
private
void
OnMessageReceived (Activité d'activité)
{
ConversationItems.Add (
] nouveau
TextMessage
{
Author =
this [19659053] .SupportBot,
// l'auteur du message
Text = activity.Text
// the message
});
}
private
void
ConversationItems_CollectionChanged (
object
expéditeur, NotifyCollectionChangedEventArgs e)
{
{
if
(e.Action == NotifyCollectionChangedAction.Add)
{
// Récupère le message qui vient d'être ajouté à la collection
var chatMessage = (TextMessage) e.NewItems [0];
// Vérifier l'auteur du message
if
(chatMessage.Author ==
this
.Me)
{
// Minuterie anti-rebond
Device.StartTimer (TimeSpan.FromMilliseconds (500), () =>
[19659050]
{
Device.BeginInvokeOnMainThread (() =>
{
// Envoyez la question de l'utilisateur au bot!
this
.botService.SendMessage (chatMessage.Text);
});
return
false
;
});
}
}
}
Le XAML
<
conversationnelUi: RadChat
ItemsSource
=
"{Binding ConversationItems}"
Author
=
"{Binding Me}"
/>
Indicateurs de saisie
<
conversationalUi: RadChat
ItemsSource
=
"{Binding ConversationItems}"
Author
=
"{Binding Me}"
> [19659443]
<
conversationnelUi: RadChat.TypingIndicator
>
<
conversationUi: TypingIndicator
ItemsSource
=
"{Binding TypingAuthors}"
/>
</ [19659052] conversationnelUi: RadChat.TypingIndicator
>
</
conversationationalUi: RadChat
>
Style de message
Connexion du bot à LUIS
public
async Task MessageReceivedAsync (Contexte IDialogContext, argument IAwaitable
{
var userMessage = attendre l'argument;
en utilisant
(var luisClient =
new
LUISRuntimeClient (
new
] ApiKeyServiceClientCredentials (
«YOUR LUIS PRIMARY KEY»
)))
{
[19659050]
luisClient.Endpoint = "VOTRE LUIS ENDPOINT" ;
// Créer un client de prédiction
var prediction =
new
Prediction (luisClient); [19659443]
// Obtenir la prédiction de LUIS
var luisResult = attendre la prédiction. ResolveAsync (
appId: "YOUR LUIS APP ID"
requête: userMessage
timezoneOffset:
null [19659053]
verbose:
true
mise en scène :
false
,
spellCheck:
false
,
bingSpellCheckSubscriptionKey:
null
,
log:
false
,
cancellationToken: CancellationToken.None);
// You will get a full list of intents. For the purposes of this demo, we'll just use the highest scoring intent.
var topScoringIntent = luisResult?.TopScoringIntent.Intent;
// Respond to the user depending on the detected intent
if
(topScoringIntent ==
"Product"
)
{
// Have the Bot respond with the appropriate message
await context.PostAsync(
"I'm happy you asked about products!"
);
}
}
}
Conclusion
More Resources
Complete Source Code
Install the App
Further Support
Source link