iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 16
0

前言

經過上一篇簡單說明與設定 Cognitive Service - 文字翻譯服務,在這一篇我們要開始實作英文翻譯機器人。這邊提供一個範例,您可以透過這個範例進行延伸,增加文字語言偵測或多語言翻譯功能,讓這個機器人功能更加完善與嚴謹。

註:若您尚未設定 Azure Translate Text API,請回到上一篇

如同上一篇說明的,我們的流程如下圖,會有兩個程式區塊:取得 Access Token 與使用翻譯服務。

https://d2mxuefqeaa7sj.cloudfront.net/s_E7B300E0091C5620F22EC144077D78492F85EFE44B3044FD0EEE604719A7F68C_1513612633125_image.png


程式

Step 1. 首先我們新增一個類別,命名為 AzureAuthToken.cs。
https://d2mxuefqeaa7sj.cloudfront.net/s_697E626105CF253282892C71BF725C033A124C7A7C4714D8E503BC2A567BF946_1513657207285_image.png

Step 2. 增加一個方法GetAccessTokenAsync用來進行驗證並且取得 Access Token,內容如下(參考範本):

public class AzureAuthToken
    {
        private static readonly Uri ServiceUrl = new Uri("https://api.cognitive.microsoft.com/sts/v1.0/issueToken");

        private const string OcpApimSubscriptionKeyHeader = "Ocp-Apim-Subscription-Key";

        private static readonly TimeSpan TokenCacheDuration = new TimeSpan(0, 5, 0);

        private string _storedTokenValue = string.Empty;

        private DateTime _storedTokenTime = DateTime.MinValue;

        public string SubscriptionKey { get; }

        public HttpStatusCode RequestStatusCode { get; private set; }

        public AzureAuthToken(string key)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentNullException(nameof(key), "A subscription key is required");
            }

            this.SubscriptionKey = key;
            this.RequestStatusCode = HttpStatusCode.InternalServerError;
        }
        public async Task<string> GetAccessTokenAsync()
        {
            if (string.IsNullOrWhiteSpace(this.SubscriptionKey))
            {
                return string.Empty;
            }

            // Re-use the cached token if there is one.
            if ((DateTime.Now - _storedTokenTime) < TokenCacheDuration)
            {
                return _storedTokenValue;
            }

            using (var client = new HttpClient())
            using (var request = new HttpRequestMessage())
            {
                request.Method = HttpMethod.Post;
                request.RequestUri = ServiceUrl;
                request.Content = new StringContent(string.Empty);
                request.Headers.TryAddWithoutValidation(OcpApimSubscriptionKeyHeader, this.SubscriptionKey);
                client.Timeout = TimeSpan.FromSeconds(2);
                var response = await client.SendAsync(request);
                this.RequestStatusCode = response.StatusCode;
                response.EnsureSuccessStatusCode();
                var token = await response.Content.ReadAsStringAsync();
                _storedTokenTime = DateTime.Now;
                _storedTokenValue = "Bearer " + token;
                return _storedTokenValue;
            }
        }

        public string GetAccessToken()
        {
            // Re-use the cached token if there is one.
            if ((DateTime.Now - _storedTokenTime) < TokenCacheDuration)
            {
                return _storedTokenValue;
            }

            string accessToken = null;
            var task = Task.Run(async () =>
            {
                accessToken = await this.GetAccessTokenAsync();
            });

            while (!task.IsCompleted)
            {
                System.Threading.Thread.Yield();
            }
            if (task.IsFaulted)
            {
                throw task.Exception;
            }
            if (task.IsCanceled)
            {
                throw new Exception("Timeout obtaining access token.");
            }
            return accessToken;
        }

    }

Step 3. 開啟 Bot Template 範本新專案,開啟 RootDialog.cs,先增加一個私有方法 AuthoizeService

private async Task<string> AuthoizeService(string key)
{
    var authTokenSource = new AzureAuthToken(key.Trim());
    string authToken;
    try
    {
        authToken = await authTokenSource.GetAccessTokenAsync();
    }
    catch (HttpRequestException)
    {
        if (authTokenSource.RequestStatusCode == HttpStatusCode.Unauthorized)
        {
            return "Request to token service is not authorized (401). Check that the Azure subscription key is valid.";
        }
        if (authTokenSource.RequestStatusCode == HttpStatusCode.Forbidden)
        {
            return "Request to token service is not authorized (403). For accounts in the free-tier, check that the account quota is not exceeded.";
        }
        throw;
    }

    return authToken;
}

Step 4. 新增一個私有方法 TranslateString,用於呼叫翻譯

註:因為是簡單講解如何介接服務,XML剖析部分,實作時請用更好的方法處理

private async Task<string> TranslateString(string authToken, string text)
{
    string from = "en";
    string to = "zh";
    string uri = "/v2/Http.svc/Translate?text=" + HttpUtility.UrlEncode(text) + "&from=" + from + "&to=" + to;

    string result = string.Empty;
    var client = new RestClient("https://api.microsofttranslator.com");
    var request = new RestRequest(uri, Method.GET);
    request.AddHeader("Authorization", authToken);
    var response = await client.ExecuteTaskAsync(request);

    return response.Content.Replace("<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">", "").Replace("</string>", "");
}

Step 5. 增加 Key

private string APIPassword = "83xxxxxxxxxxxxxxx";

Step 6. 修改程式如下:

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
    var activity = await result as Activity;

    string response = string.Empty;

    if (activity.Text.StartsWith("tran") || activity.Text.StartsWith("翻譯"))
    {
        string authToken = string.Empty;
        authToken = await AuthoizeService(APIPassword);
        response = await TranslateString(authToken, activity.Text.Replace("tran", "").Replace("翻譯",""));
    }

    // return our reply to the user
    await context.PostAsync($"{response}");

    context.Wait(MessageReceivedAsync);
}

Step 7.啟動專案
https://d2mxuefqeaa7sj.cloudfront.net/s_4BD31EC08DAC6681F125ECB2893F87311C2A9E8644E7E0D9FAA1622819FD5464_1512918057038_image.pn

Step 8.透過模擬器測試,成功!!
https://d2mxuefqeaa7sj.cloudfront.net/s_697E626105CF253282892C71BF725C033A124C7A7C4714D8E503BC2A567BF946_1513658707211_image.png


範例

https://github.com/matsurigoto/TranslatorBotExample.git


其實做多功能機器人好像沒有很難...? (被毆)/images/emoticon/emoticon05.gif


上一篇
15.Cognitive Service - 文字翻譯服務
下一篇
17.Cognitive Service - 圖片文字辨識
系列文
利用 MS Bot framework 與 Cognitive Service 建構自用智慧小秘書31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言