How to view response of Luis.ai in azure web bot app - azure

I am working on a web bot app and I link it with luis.ai
I want to view the response of luis like which intent is been called and what was the entity called. I am using bot emulator version 4, but you can't find any type of info related to your intent or entities in it.
Is there any way we can see the json response of luis.ai ?
So that I can start building my bot further.
I am asking this because look How am I gonna know what's the format of luis response, how to get data from it as long as I don't know In which format i an receiving the response.
any details tutorial please?

There two ways to see luis response.
you can go to luis.ai and then copy the url of pulishment(in pulish section). And paste it in the navegator. You will get url like this: 'https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/xxxx?subscription-key=xxxxxxxxxx&verbose=true&timezoneOffset=0&q=your sentence', and setup q= your sentence.
Another way, you can log all luis conversation in you code. If you use c sharp bot builder, you can use this luis class.
[Serializable]
public class LogedLuisService : ILuisService
{
private ILuisService service;
private string moduleType;
public LogedLuisService(ILuisService service)
{
this.service = service;
}
public Uri BuildUri(LuisRequest luisRequest)
{
return service.BuildUri(luisRequest);
}
public LuisRequest ModifyRequest(LuisRequest request)
{
return service.ModifyRequest(request);
}
public Task<LuisResult> QueryAsync(Uri uri, CancellationToken token)
{
return service
.QueryAsync(uri, token)
.ContinueWith(
task => {
Trace.WriteLine("Luis: " + " : " + JsonConvert.SerializeObject(task.Result));
return task.Result;
});
}}

Related

Azure AppInsights end to end correlation

I am looking into Azure AppInsights for my telemetry correlation requirement. I have created 3 simple APIs that call one another in succession as below:
First Api -----> Middle Api -----> Another Api
The Api calls are made using Typed HttpClient through a simple service class. All the Api projects have Microsoft.ApplicationInsights.AspNetCore and Microsoft.Extensions.Logging.ApplicationInsights NuGets references added. I have program and service classes for all the APIs as below:
Program.cs
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
...
//App Insights
builder.Services.AddSingleton(typeof(ITelemetryChannel),
new ServerTelemetryChannel() { StorageFolder = "/tmp/myfolder" });
builder.Services.AddApplicationInsightsTelemetry();
builder.Services.AddSingleton<IConfiguration>(builder.Configuration);
builder.Services.AddScoped<IWeatherService, DummyWeatherService>();
builder.Services.AddHttpClient<IWeatherService, DummyWeatherService>();
var app = builder.Build();
...
app.Run();
Service
using System.Net.Http.Headers;
using AppInsightsDemo.Api.Models;
namespace AppInsightsDemo.Api.Services;
public class DummyWeatherService : IWeatherService
{
private readonly IConfiguration _configuration;
private readonly HttpClient _httpClient;
public DummyWeatherService(
IConfiguration configuration,
HttpClient httpClient)
{
_configuration = configuration;
_httpClient = httpClient;
_httpClient.BaseAddress = GetMiddleApiBaseUri();
_httpClient.DefaultRequestHeaders.Accept.Clear();
_httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
private Uri GetAnotherApiBaseUri()
{
var configurationSection = _configuration.GetRequiredSection("Dependencies");
var baseUri = configurationSection.GetValue<string>("MiddleApiUri")
?? throw new ArgumentException("Another Api base uri is empty");
return new Uri(baseUri);
}
public async Task<Weather?> GetWeatherAsync()
{
Weather? weather = null;
var response = await _httpClient.GetAsync("middle");
if (response.IsSuccessStatusCode)
{
weather = await response.Content.ReadAsAsync<Weather>();
}
return weather;
}
}
This is what I end up with in AppInsights sample. The third API event has the same operation id as the first two Api events have but the third event has a different parent id. I expect the third event to have the id of my middle (second) api event (localhost://7290) as its parent id and the three events show up accordingly in a hierarchy.
Can anyone please advise if I am missing some configuration or not using this SDK right? Thank you
This is rather silly of me. I configured the ApplicationInsights connection string for my first api(:7176) and last api(:7206) but missed to configure it for my middle api (:7290) though I have added ApplicationInsights service to all Api projects. It took me a while to figure out the missing connection string. Now I get a nice dependency hierarchy as below:
I guess a connection string validation might come handy. Sorry for the trouble. Thanks.

I can't configure a webhook URI for "Whatsapp Cloud API"

I created an app and configure whatsapp but in configuring webhook I have issues
The error
URL can't be saved. The URL is ok, the endpoint was tested wih postman with no issues.
Server Code
I use Asp.Net Core - WebApi project and create a controller with the method and print in the console a log. I return Ok + challenge if token is equals, otherwise 403 http response.
using Microsoft.AspNetCore.Mvc;
namespace MyApiZ.WebApi.Controllers
{
[ApiController]
[Route("")]
public class MessageController : Controller
{
const string VerfifyToken = "1234";
[HttpGet("webhook")]
public ActionResult<string> SetupWebHook([FromQuery(Name = "hub_mode")] string hubMode,
[FromQuery(Name = "hub_challenge")] int hubChallenge,
[FromQuery(Name = "hub_verify_token")] string hubVerifyToken)
{
Console.WriteLine("█ WebHook with get executed. ");
Console.WriteLine($"█ Parameters: hub_mode={hubMode} hub_challenge={hubChallenge} hub_verify_token={hubVerifyToken}");
if (!hubVerifyToken.Equals(VerfifyToken))
{
return Forbid("VerifyToken doesn't match");
}
return Ok(hubChallenge);
}
[HttpPost("webhook")]
public ActionResult ReceiveNotification([FromBody] string data)
{
Console.WriteLine("█ WebHook with Post executed. ");
Console.WriteLine(data);
return Ok();
}
public IActionResult Index()
{
return View();
}
}
}
Test with Postman
No issues in request from Postman
My app is hosted in Azure App Service. I checked the app log in Azure Portal.
When the request is executed in Postman, the messages are printed. But when click on facebook in the "Verify and save button" the error is present, the message aren't print in the log, the endpoint is never called.
I have written a brief article on WhatsApp Cloud API like how to send and receive WhatsApp messages and also set up a never expiry access token. Please have a look enter link description here
You will get your answer from my article. BTW when you click the verify & save button then you will get the response from WhatsApp to your callback URL. You just need to respond back the hub_challenge key(sent from whatsapp) respond back to whatsapp with 200 status code then your webhook should automatically verify
Simple change
from
public ActionResult<string> SetupWebHook([FromQuery(Name = "hub_mode")] string hubMode,
[FromQuery(Name = "hub_challenge")] int hubChallenge,
[FromQuery(Name = "hub_verify_token")] string hubVerifyToken)
to
public ActionResult<string> SetupWebHook([FromQuery(Name = "hub.mode")] string hubMode,
[FromQuery(Name = "hub.challenge")] int hubChallenge,
[FromQuery(Name = "hub.verify_token")] string hubVerifyToken)
Once you click the Verify and Save button then you will get the API request from WhatsApp to your server webhook callback URL.
Now, your webhook needs to respond back > hub_challenge.

sending mails using sendgrid from azure app-service webjob

I have developed a C# console application sending emails to our customers when certain conditions occur. Mails are not sent when application is deployed as azure webjob.
When testing from visual studio in my development environment Mails are sent without any problems as intended, but when the application is deployed and run as an azure app-service webjob no mails are sent. The application is otherwise working as intended also when deployed as azure webjob.
public enum MailType : short { Plain, Html }
private static string MimeType(MailType type)
{ return (type == MailType.Html) ? "text/html" : "text/plain"; }
private static async Task sendMail(string to, string name, string subject, MailType mailType, string content)
{
SendGridMessage msg = new SendGridMessage();
msg.From = new EmailAddress("noreply#foo.org", "Foo Ltd.");
msg.AddTo(to, name);
msg.Subject = subject;
msg.AddContent(MimeType(mailType), content);
SendGridClient client = new SendGridClient(SendGridAPIKey);
await client.SendEmailAsync(msg);
}
public static void SendMail(string to, string name, string subject, MailType mailType, string content)
{
sendMail(to, name, subject, mailType, content).Wait();
}
Answers to all other questions regarding this issue (a lot of developers have met this problem) focus on the code; especially the async implementation, but it seems this is not the issue. Does azure have some restrictions to the communication between the application deployed as webjob and the sendgrid server? (I am using the sendgrid and sendgrid.helpers.mail)
I test with you code and it work well both on local and on Azure. I invoke the SendMail method in a queueTrigger.
public static void ProcessQueueMessage([QueueTrigger("queue1")] string message, TextWriter log)
{
log.WriteLine(message);
SendMail("xxxxx#gmail.com", "xxxxx", "hello world", MailType.Plain, "have a good day.");
}
So you could refer to the following ways to troubleshoot it.
1.Check your SendGridAPIKey. If you stored SendGridAPIKey as an environment variable in the project, you need to go to Configuration>Application Settings and add the key in it.
2.Check your SendGrid Activity.The problem could be getting your request to SendGrid, or it could be that SendGrid is getting your request but isn't fulfilling it. Check the Activity Feed and search for the particular email you are expecting

Messages not coming thru to Azure SignalR Service

I'm implementing Azure SignalR service in my ASP.NET Core 2.2 app with React front-end. When I send a message, I'm NOT getting any errors but my messages are not reaching the Azure SignalR service.
To be specific, this is a private chat application so when a message reaches the hub, I only need to send it to participants in that particular chat and NOT to all connections.
When I send a message, it hits my hub but I see no indication that the message is making it to the Azure Service.
For security, I use Auth0 JWT Token authentication. In my hub, I correctly see the authorized user claims so I don't think there's any issues with security. As I mentioned, the fact that I'm able to hit the hub tells me that the frontend and security are working fine.
In the Azure portal however, I see no indication of any messages but if I'm reading the data correctly, I do see 2 client connections which is correct in my tests i.e. two open browsers I'm using for testing. Here's a screen shot:
Here's my Startup.cs code:
public void ConfigureServices(IServiceCollection services)
{
// Omitted for brevity
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwtOptions => {
jwtOptions.Authority = authority;
jwtOptions.Audience = audience;
jwtOptions.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
// Check to see if the message is coming into chat
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/im")))
{
context.Token = accessToken;
}
return System.Threading.Tasks.Task.CompletedTask;
}
};
});
// Add SignalR
services.AddSignalR(hubOptions => {
hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(10);
}).AddAzureSignalR(Configuration["AzureSignalR:ConnectionString"]);
}
And here's the Configure() method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// Omitted for brevity
app.UseSignalRQueryStringAuth();
app.UseAzureSignalR(routes =>
{
routes.MapHub<Hubs.IngridMessaging>("/im");
});
}
Here's the method I use to map a user's connectionId to the userName:
public override async Task OnConnectedAsync()
{
// Get connectionId
var connectionId = Context.ConnectionId;
// Get current userId
var userId = Utils.GetUserId(Context.User);
// Add connection
var connections = await _myServices.AddHubConnection(userId, connectionId);
await Groups.AddToGroupAsync(connectionId, "Online Users");
await base.OnConnectedAsync();
}
Here's one of my hub methods. Please note that I'm aware a user may have multiple connections simultaneously. I just simplified the code here to make it easier to digest. My actual code accounts for users having multiple connections:
[Authorize]
public async Task CreateConversation(Conversation conversation)
{
// Get sender
var user = Context.User;
var connectionId = Context.ConnectionId;
// Send message to all participants of this chat
foreach(var person in conversation.Participants)
{
var userConnectionId = Utils.GetUserConnectionId(user.Id);
await Clients.User(userConnectionId.ToString()).SendAsync("new_conversation", conversation.Message);
}
}
Any idea what I'm doing wrong that prevents messages from reaching the Azure SignalR service?
It might be caused by misspelled method, incorrect method signature, incorrect hub name, duplicate method name on the client, or missing JSON parser on the client, as it might fail silently on the server.
Taken from Calling methods between the client and server silently fails
:
Misspelled method, incorrect method signature, or incorrect hub name
If the name or signature of a called method does not exactly match an appropriate method on the client, the call will fail. Verify that the method name called by the server matches the name of the method on the client. Also, SignalR creates the hub proxy using camel-cased methods, as is appropriate in JavaScript, so a method called SendMessage on the server would be called sendMessage in the client proxy. If you use the HubName attribute in your server-side code, verify that the name used matches the name used to create the hub on the client. If you do not use the HubName attribute, verify that the name of the hub in a JavaScript client is camel-cased, such as chatHub instead of ChatHub.
Duplicate method name on client
Verify that you do not have a duplicate method on the client that differs only by case. If your client application has a method called sendMessage, verify that there isn't also a method called SendMessage as well.
Missing JSON parser on the client
SignalR requires a JSON parser to be present to serialize calls between the server and the client. If your client doesn't have a built-in JSON parser (such as Internet Explorer 7), you'll need to include one in your application.
Update
In response to your comments, I would suggest you try one of the Azure SignalR samples, such as
Get Started with SignalR: a Chat Room Example to see if you get the same behavior.
Hope it helps!

Call LUIS outside of MessageController and after Authentication

Working on a Bot that authenticates using ADAL (AuthBot) and then post-Auth takes the user input and sends to LUIS to gather intents/entities. I use what's returned to build a URI that I send to Sharepoint Online REST API. If user input is valid, Sharepoint returns JSON that I parse and return to user.
The trouble is getting the user input to my LUIS class after authentication. I call AuthBot ActionDialog from my MessageController.
if (message.Type == "Message")
{
return await Conversation.SendAsync(message, () => new ActionDialog());
}
Within ActionDialog, I'm not sure how to move move the Message to the LUIS Class
public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<Message> item)
{
var message = await item;
if (message.Text == "logon")
{
if (string.IsNullOrEmpty(await context.GetAccessToken(ConfigurationManager.AppSettings["ActiveDirectory.ResourceId"])))
{
await context.Forward(new AzureAuthDialog(ConfigurationManager.AppSettings["ActiveDirectory.ResourceId"]), this.ResumeAfterAuth, message, CancellationToken.None);
}
else
{
context.Wait(MessageReceivedAsync);
}
}
else if (string.IsNullOrEmpty(await context.GetAccessToken(ConfigurationManager.AppSettings["ActiveDirectory.ResourceId"])))
{
await context.Forward(new AzureAuthDialog(ConfigurationManager.AppSettings["ActiveDirectory.ResourceId"]), this.ResumeAfterAuth, message, CancellationToken.None);
}
else
{
//this is where I want to send the next user input from bot to LUIS class.
}
}
The LUIS Class is standard and looks like this:
//Define the LuisModel that will be used. The LuisModel JSON file can be found at ~/json/letseat.json
[LuisModel("ModelID", "ModelSecret")]
[Serializable]
public class LuisDialog : LuisDialog<object>
Any Ideas? Thanks.
I assume that you are using AuthBot (by looking at the code).
What you need to add is the following:
await base.MessageReceived(context, item);
That will just pass the message to LUISDialog's MessageReceived implementation; which will issue a query to LUIS to understand which intent should be executed.

Resources