Chatbot语言翻译:保存检测到的语言以进行响应翻译

时间:2020-10-30 22:01:02

标签: c# json chatbot azure-language-understanding language-translation

我有一个聊天机器人正在实现翻译中间件。中间件检测输入的语言并将查询翻译成英语。我一直在努力将检测到的语言另存为变量,以将响应转换为用户的语言,但是遇到了障碍。

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            var body = new object[] { new { Text = turnContext.Activity.Text } };
            var requestBody = JsonConvert.SerializeObject(body);

            //Console.WriteLine("------------------------------------------------------------------------");
            //Console.WriteLine(requestBody);
            //Console.WriteLine("------------------------------------------------------------------------");

            //var languageChoice = "de";
 
            using (var client = new HttpClient())
            using (var request = new HttpRequestMessage())
            {
                //var uri = "https://api.cognitive.microsofttranslator.com" + "/translate?api-version=3.0" + "&from=" + languageChoice + "&to=" + "en";
                var uri = "https://api.cognitive.microsofttranslator.com" + "/translate?api-version=3.0" + "&to=" + "en";

                request.Method = HttpMethod.Post;
                request.RequestUri = new Uri(uri);
                request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");

                request.Headers.Add("Ocp-Apim-Subscription-Key", _configuration["TranslatorKey"]);
                request.Headers.Add("Ocp-Apim-Subscription-Region", "westus2");
 
                var translatedResponse = await client.SendAsync(request);
                var responseBody = await translatedResponse.Content.ReadAsStringAsync();
 
                Console.WriteLine("------------------------------------------------------------------------");
                Console.WriteLine(responseBody);
                Console.WriteLine("------------------------------------------------------------------------");

                var translation = JsonConvert.DeserializeObject<TranslatorResponse[]>(responseBody);
                var detectedLanguage = JsonConvert.DeserializeObject<DetectLanguage[]>(responseBody);

                var ourResponse = detectedLanguage?.FirstOrDefault()?.DetectedLanguage?.FirstOrDefault()?.Language.ToString();

                Console.WriteLine("------------------------------------------------------------------------");
                Console.WriteLine(ourResponse);
                Console.WriteLine("------------------------------------------------------------------------");
                
                //Console.WriteLine("------------------------------------------------------------------------");
                //Console.WriteLine(turnContext.Activity.Text);
                //Console.WriteLine(translation?.FirstOrDefault()?.Translations?.FirstOrDefault()?.Text.ToString());
                //Console.WriteLine("------------------------------------------------------------------------");
                
                // Update the translation field
                turnContext.Activity.Text = translation?.FirstOrDefault()?.Translations?.FirstOrDefault()?.Text.ToString();
            }

            // First, we use the dispatch model to determine which cognitive service (LUIS or QnA) to use.
            var recognizerResult = await _botServices.Dispatch.RecognizeAsync(turnContext, cancellationToken);
            
            // Top intent tell us which cognitive service to use.
            var topIntent = recognizerResult.GetTopScoringIntent();
            
            // Next, we call the dispatcher with the top intent.
            // ***** ERROR *****
            await DispatchToTopIntentAsync(turnContext, topIntent.intent, recognizerResult, cancellationToken);
        }

使用responseBody中的控制台日志:

[{"detectedLanguage":{"language":"es","score":1.0},"translations":[{"text":"Hello","to":"en"}]}]

我们已确定responseBody是一个Object数组,其中包含属性“ detectedLanguage”,一个对象以及属性“ language”和“ score”。 为了从对象“ detectedLanguage”中检索变量“ language”,我们以“ turnContext.Activity.Text”作为翻译后的文本作为示例,进行了以下尝试。

我们还添加了两个内部类来模仿“ turnContext.Activity.Text”的实现:

1)

namespace Microsoft.BotBuilderSamples.Translation.Model
{
    /// <summary>
    /// Array of translated results from Translator API v3.
    /// </summary>
    internal class TranslatorResponse
    {
        [JsonProperty("translations")]
        public IEnumerable<TranslatorResult> Translations { get; set; }
    }
    internal class DetectLanguage
    {
        [JsonProperty("detectedLanguage")]
        public IEnumerable<LanguageResult> DetectedLanguage { get; set; }
    }
}
using Newtonsoft.Json;

namespace Microsoft.BotBuilderSamples.Translation.Model
{
    /// <summary>
    /// Translation result from Translator API v3.
    /// </summary>
    internal class TranslatorResult
    {
        [JsonProperty("text")]
        public string Text { get; set; }

        [JsonProperty("to")]
        public string To { get; set; }
    }
    internal class LanguageResult
    {
        [JsonProperty("language")]
        public string Language { get; set; }
    }
}

但是,当我们尝试在控制台中测试并显示“ ourResponse”时,会遇到以下错误消息:

fail: Microsoft.Bot.Builder.Integration.AspNet.Core.BotFrameworkHttpAdapter[0]
      [OnTurnError] unhandled error : Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[Microsoft.BotBuilderSamples.Translation.Model.LanguageResult]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
      To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. 
      Path '[0].detectedLanguage.language', line 1, position 33.

我们确定我们正在遇到此错误,因为“ detectedLanguage”不是像“ translations”那样的数组。 (显示在下面的控制台输出中):

[{"detectedLanguage":{"language":"es","score":1.0},"translations":[{"text":"Hello","to":"en"}]}]

我的问题是我们如何调整该实现以使其与数组外部的detectedLanguage对象一起使用,或者如何调整将其包含在字符串中以与该实现一起使用?

1 个答案:

答案 0 :(得分:0)

您的类结构与您的json不匹配。您想要的是以下内容:

internal class DetectedLanguage    
{
    [JsonProperty("language")]
    public string Language { get; set; }
    [JsonProperty("score")]
    public double Score { get; set; } 
}

internal class TranslatorResult
{
    [JsonProperty("text")]
    public string Text { get; set; }

    [JsonProperty("to")]
    public string To { get; set; }
}

internal class TranslatorResponse
{
    [JsonProperty("detectedLanguage")]
    public DetectedLanguage DetectedLanguage { get; set; } 
    [JsonProperty("translations")]
    public IEnumerable<TranslatorResult> Translations { get; set; } 
}

请注意,DetectedLanguage应该如何表示为TranslatorResponse对象上的单个对象,而您目前还没有这样做。另外,Language的{​​{1}}属性也是单个属性,而不是集合。