Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call google.apis.dialogflow.v2 in C#

I am new to Google APIs. I want to know how to call Google Dialogflow API in C# to get intent form the input text. But I can't find any example to call Dialogflow using C#.

Please provide some example to call Dialogflow from C#.

like image 784
Gowdham Avatar asked Jun 01 '18 04:06

Gowdham


People also ask

How do I access Dialogflow API?

Enter here service account name and service description and click on Create button. On the next page, you'll see Service account permissions settings. Select Dialogflow API Client role and click on the Continue button. The next page is to grant users access to the service account you just created.

What is Dialogflow v2?

1. Dialogflow is an end-to-end, build-once deploy-everywhere development suite for creating conversational interfaces for websites, mobile applications, popular messaging platforms, and IoT devices.

Should I use Dialogflow ES or CX?

Dialogflow ES supports only one agent per project, while the Dialogflow CX supports 100 agents/project. CX is an advanced agent type suitable for large or very complex agents with flows, pages, and state handlers to control the conversation paths.


2 Answers

If I understand your question correctly you want to call the DialogFlow API from within a C# application (rather than writing fulfillment endpoint(s) that are called from DialogFlow. If that's the case here's a sample for making that call:

using Google.Cloud.Dialogflow.V2;

...
...

var query = new QueryInput
{
    Text = new TextInput
    {
        Text = "Something you want to ask a DF agent",
        LanguageCode = "en-us"
    }
};

var sessionId = "SomeUniqueId";
var agent = "MyAgentName";
var creds = GoogleCredential.FromJson("{ json google credentials file)");
var channel = new Grpc.Core.Channel(SessionsClient.DefaultEndpoint.Host, 
              creds.ToChannelCredentials());

var client = SessionsClient.Create(channel);

var dialogFlow = client.DetectIntent(
    new SessionName(agent, sessionId),
    query
);
channel.ShutdownAsync();

In an earlier version of the DialogFlowAPI I was running into file locking issues when trying to re-deploy a web api project which the channel.ShutDownAsync() seemed to solve. I think this has been fixed in a recent release.

This is the simplest version of a DF request I've used. There is a more complicated version that passes in an input context in this post: Making DialogFlow v2 DetectIntent Calls w/ C# (including input context)

like image 100
Chris Christopher Avatar answered Oct 08 '22 20:10

Chris Christopher


(Nitpicking: I assume you know DialogFlow will call your code as specified/registered in the action at DialogFlow? So your code can only respond to DialogFlow, and not call it.)

Short answer/redirect:
Don't use Google.Apis.Dialogflow.v2 (with GoogleCloudDialogflowV2WebhookRequest and GoogleCloudDialogflowV2WebhookResponse) but use Google.Cloud.Dialogflow.v2 (with WebhookRequest and WebhookResponse) - see this eTag-error. I will also mention some other alternatives underneath.

Google.Cloud.Dialogflow.v2

Using Google.Cloud.Dialogflow.v2 NuGet (Edit: FWIW: this code was written for the beta-preview):

    [HttpPost]
    public dynamic PostWithCloudResponse([FromBody] WebhookRequest dialogflowRequest)
    {
        var intentName = dialogflowRequest.QueryResult.Intent.DisplayName;
        var actualQuestion = dialogflowRequest.QueryResult.QueryText;
        var testAnswer = $"Dialogflow Request for intent '{intentName}' and question '{actualQuestion}'";
        var dialogflowResponse = new WebhookResponse
        {
            FulfillmentText = testAnswer,
            FulfillmentMessages =
                { new Intent.Types.Message
                    { SimpleResponses = new Intent.Types.Message.Types.SimpleResponses
                        { SimpleResponses_ =
                            { new Intent.Types.Message.Types.SimpleResponse
                                {
                                   DisplayText = testAnswer,
                                   TextToSpeech = testAnswer,
                                   //Ssml = $"<speak>{testAnswer}</speak>"
                                }
                            }
                        }
                    }
            }
        };
        var jsonResponse = dialogflowResponse.ToString();
        return new ContentResult { Content = jsonResponse, ContentType = "application/json" }; ;
    }

Edit: It turns out that the model binding may not bind all properties from the 'ProtoBuf-json' correctly (e.g. WebhookRequest.outputContexts[N].parameters), so one should probably use the Google.Protobuf.JsonParser (e.g. see this documentation).

This parser may trip over unknown fields, so one probably also wants to ignore that. So now I use this code (I may one day make the generic method more generic and thus useful, by making HttpContext.Request.InputStream a parameter):

    public ActionResult PostWithCloudResponse()
    {
       var dialogflowRequest = ParseProtobufRequest<WebhookRequest>();
       ...
        var jsonResponse = dialogflowResponse.ToString();
        return new ContentResult { Content = jsonResponse, ContentType = "application/json" }; ;
    }

    private T ParseProtobufRequest<T>() where T : Google.Protobuf.IMessage, new()
    {
        // parse ProtoBuf (not 'normal' json) with unknown fields, else it may not bind ProtoBuf correctly
        // https://github.com/googleapis/google-cloud-dotnet/issues/2425 "ask the Protobuf code to parse the result"
        string requestBody;
        using (var reader = new StreamReader(HttpContext.Request.InputStream))
        {
            requestBody = reader.ReadToEnd();
        }
        var parser = new Google.Protobuf.JsonParser(JsonParser.Settings.Default.WithIgnoreUnknownFields(true));
        var typedRequest = parser.Parse<T>(requestBody);
        return typedRequest;
    }

BTW: This 'ProtoBuf-json' is also the reason to use WebhookResponse.ToString() which in turn uses Google.Protobuf.JsonFormatter.ToDiagnosticString.

Microsoft's BotBuilder

Microsoft's BotBuilder packages and Visual Studio template. I havent't used it yet, but expect approximately the same code?

Hand written proprietary code

A simple example of incoming request code (called an NLU-Response by Google) is provided by Madoka Chiyoda (Chomado) at Github. The incoming call is simply parsed to her DialogFlowResponseModel:

    public static async Task<HttpResponseMessage> Run([...]HttpRequestMessage req, [...]CloudBlockBlob mp3Out, TraceWriter log)
        ...
        var data = await req.Content.ReadAsAsync<Models.DialogFlowResponseModel>();

Gactions

If you plan to work without DialogFlow later on, please note that the interface for Gactions differs significantly from the interface with DialogFlow. The json-parameters and return-values have some overlap, but nothing gaining you any programming time (probably loosing some time by starting 'over').

However, starting with DialogFlow may gain you some quick dialog-experience (e.g. question & answer design/prototyping). And the DialogFlow-API does have a NuGet package, where the Gactions-interface does not have a NuGet-package just yet.

like image 38
Yahoo Serious Avatar answered Oct 08 '22 20:10

Yahoo Serious