Понимание того, почему перевод выполняется три раза в образце Bot Builder Framework: MultiLingualBot - PullRequest
1 голос
/ 26 июня 2019

Официальный пример Microsoft, который обеспечивает языковой перевод в промежуточном программном обеспечении в боте, кажется, обеспечивает языковой перевод, который запускается в промежуточном программном обеспечении 3 различными способами.

Мой вопрос: почему 3 разных типа / способа не перекрываются? (Как триггеры являются взаимоисключающими?)

Код, о котором идет речь, живет здесь

Три раза, как кажется, срабатывает:

1)  if (turnContext.Activity.Type == ActivityTypes.Message) //trigger translation
2) turnContext.OnSendActivities(async (newContext, activities, nextSend) => //trigger translation
3) turnContext.OnUpdateActivity(async (newContext, activity, nextUpdate) => //trigger translation

Отдельный вопрос, который может помочь внести ясность -> Документация гласит ... "остерегайтесь короткого замыкания" вашего промежуточного ПО, но не ясно, как одно мое (преднамеренно или случайно) замкнуло его промежуточное ПО , Замкнут ли промежуточное ПО одно из следующих двух операторов возврата?

                return await nextSend(); //LINE 83 at time of writing
                return await nextUpdate(); //LINE 100 at time of writing

Для потомков ссылочный код:


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;

namespace Microsoft.BotBuilderSamples.Translation
{
    /// <summary>
    /// Middleware for translating text between the user and bot.
    /// Uses the Microsoft Translator Text API.
    /// </summary>
    public class TranslationMiddleware : IMiddleware
    {
        private readonly MicrosoftTranslator _translator;
        private readonly IStatePropertyAccessor<string> _languageStateProperty;

        /// <summary>
        /// Initializes a new instance of the <see cref="TranslationMiddleware"/> class.
        /// </summary>
        /// <param name="translator">Translator implementation to be used for text translation.</param>
        /// <param name="languageStateProperty">State property for current language.</param>
        public TranslationMiddleware(MicrosoftTranslator translator, UserState userState)
        {
            _translator = translator ?? throw new ArgumentNullException(nameof(translator));
            if(userState == null)
            {
                throw new ArgumentNullException(nameof(userState));
            }

            _languageStateProperty = userState.CreateProperty<string>("LanguagePreference");
        }

        /// <summary>
        /// Processes an incoming activity.
        /// </summary>
        /// <param name="turnContext">Context object containing information for a single turn of conversation with a user.</param>
        /// <param name="next">The delegate to call to continue the bot middleware pipeline.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public async Task OnTurnAsync(ITurnContext turnContext, NextDelegate next, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            var translate = await ShouldTranslateAsync(turnContext, cancellationToken);

            if (translate)
            {
                if (turnContext.Activity.Type == ActivityTypes.Message)
                {
                    turnContext.Activity.Text = await _translator.TranslateAsync(turnContext.Activity.Text, TranslationSettings.DefaultLanguage, cancellationToken);
                }
            }

            turnContext.OnSendActivities(async (newContext, activities, nextSend) =>
            {
                string userLanguage = await _languageStateProperty.GetAsync(turnContext, () => TranslationSettings.DefaultLanguage) ?? TranslationSettings.DefaultLanguage;
                bool shouldTranslate = userLanguage != TranslationSettings.DefaultLanguage;

                // Translate messages sent to the user to user language
                if (shouldTranslate)
                {
                    List<Task> tasks = new List<Task>();
                    foreach (Activity currentActivity in activities.Where(a => a.Type == ActivityTypes.Message))
                    {
                        tasks.Add(TranslateMessageActivityAsync(currentActivity.AsMessageActivity(), userLanguage));
                    }

                    if (tasks.Any())
                    {
                        await Task.WhenAll(tasks).ConfigureAwait(false);
                    }
                }

                return await nextSend();
            });

            turnContext.OnUpdateActivity(async (newContext, activity, nextUpdate) =>
            {
                string userLanguage = await _languageStateProperty.GetAsync(turnContext, () => TranslationSettings.DefaultLanguage) ?? TranslationSettings.DefaultLanguage;
                bool shouldTranslate = userLanguage != TranslationSettings.DefaultLanguage;

                // Translate messages sent to the user to user language
                if (activity.Type == ActivityTypes.Message)
                {
                    if (shouldTranslate)
                    {
                        await TranslateMessageActivityAsync(activity.AsMessageActivity(), userLanguage);
                    }
                }

                return await nextUpdate();
            });

            await next(cancellationToken).ConfigureAwait(false);
        }

        private async Task TranslateMessageActivityAsync(IMessageActivity activity, string targetLocale, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (activity.Type == ActivityTypes.Message)
            {
                activity.Text = await _translator.TranslateAsync(activity.Text, targetLocale);
            }
        }

        private async Task<bool> ShouldTranslateAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            string userLanguage = await _languageStateProperty.GetAsync(turnContext, () => TranslationSettings.DefaultLanguage, cancellationToken) ?? TranslationSettings.DefaultLanguage;
            return userLanguage != TranslationSettings.DefaultLanguage;
        }
    }
}

1 Ответ

1 голос
/ 04 июля 2019

Перевод сообщения должен происходить, когда бот получает определенные виды действий. Некоторые виды деятельности не требуют перевода. Типы активности протокола можно найти здесь

        "message",
        "contactRelationUpdate",
        "conversationUpdate",
        "typing",
        "endOfConversation",
        "event",
        "invoke",
        "deleteUserData",
        "messageUpdate",
        "messageDelete",
        "installationUpdate",
        "messageReaction",
        "suggestion",
        "trace",
        "handoff"

Пример MultiLingualBot демонстрирует перевод:

1) активность входящих сообщений в TranslationSettings.DefaultLanguage для обработки ботом

2) действия с исходящими сообщениями обратно на предпочитаемый язык пользователя

3) действия messageUpdate


1)  if (turnContext.Activity.Type == ActivityTypes.Message) //trigger translation
2) turnContext.OnSendActivities(async (newContext, activities, nextSend) => //trigger translation
3) turnContext.OnUpdateActivity(async (newContext, activity, nextUpdate) => //trigger translation

Короткое замыкание промежуточного программного обеспечения не будет вызывать

await next(cancellationToken).ConfigureAwait(false);
or 
return await nextSend();
or
return await nextUpdate();

Если они не вызываются, обработка сообщений прекращается. Другое промежуточное программное обеспечение из стека не будет обрабатывать входящее сообщение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...