当下人工智能可谓是风头正劲,几乎所有的大厂都有相关的技术栈。微软在 AI 领域自然也是投入了重注,并且以 Azure 认知服务的方式投入了市场:

也就是说作为开发者我们不需要学习太多 AI 的理论知识,直接使用 Azure 提供的认知服务 API 就可以在程序中实现 AI 的功能了!

本文作为介绍 Azure AI 服务系列的第一篇,将通过 demo 介绍 Azure 认识服务中 Language 分类中的文本翻译服务(Translator Text API )。

Microsoft 文本翻译 API 是一种基于云的机器翻译服务, 支持多种语言。使用者可用于构建应用程序、网站、工具或任何需要多语言支持的解决方案。该服务是通过 REST API 提供的,所以我们可以以任何语言来调用它们。本文笔者使用 C# 通过构建一个 WPF 程序来演示如何通过简单的几步就能创建一个像模像样的翻译程序:

本文的完整 demo 请从这里下载

创建 Azure 服务

要使用 Azure 的翻译服务需要先在 Azure 上创建对应的实例,比如我们需要先创建一个 "Translator Text API" 服务实例:

在本文的 demo 程序中我们还会用到拼写检查的服务,所以还需要创建一个 "Bing Spell Check v7 API" 服务的实例:

说明:对于学习和练习来说,你可以创建免费的 Azure 账号并创建免费版的上述实例,详细信息请参考 Azure 官网。

创建 WPF 应用程序

先在 VS 中创建 WPF 程序并简单的布局。

既然是 REST API,那么我们肯定是以 url 的方式访问服务,下面分别是访问文本翻译服务和拼写检查服务的 url:

const string TEXT_TRANSLATION_API_ENDPOINT = "https://api.microsofttranslator.com/v2/Http.svc/";
const string BING_SPELL_CHECK_API_ENDPOINT = "https://api.cognitive.microsoft.com/bing/v7.0/spellcheck/";

在访问相应的服务时,我们用这两个常量再拼接上合适的参数就可以了。

需要注意的是,Azure 提供的认知服务 API 都是需要认证信息的。具体的方式就是把我们创建的服务的 key 随 API 发送的服务器端进行认证,比如把 key 添加到 http 请求的 header 中:

WebRequest.Headers.Add("Ocp-Apim-Subscription-Key", "your key");

你可以在创建的服务实例的详情界面获得对应的 key,我们在程序中通过定义的常量来保存它们:

const string TEXT_TRANSLATION_API_SUBSCRIPTION_KEY = "your translator key";
const string BING_SPELL_CHECK_API_SUBSCRIPTION_KEY = "your spell check key";

由于 demo 的代码比较长,为了能集中精力介绍 Azure AI 相关的内容,本文中只贴出相关的代码。完整的 demo 代码在这里

获取支持的语言列表

在进行任何的文本翻译之前,我们需要搞清楚 Azure 提供的翻译服务究竟支持哪些语言!下面的请求能够返回翻译服务支持的语言列表:

string uri = TEXT_TRANSLATION_API_ENDPOINT + "GetLanguagesForTranslate?scope=text";

我们把代码封装到下面的函数中:

private string[] languageCodes;
private void GetLanguagesForTranslate()
{
// 获得翻译服务支持的语言
string uri = TEXT_TRANSLATION_API_ENDPOINT + "GetLanguagesForTranslate?scope=text";
WebRequest WebRequest = WebRequest.Create(uri);
// 在 http 请求中添加认证信息
WebRequest.Headers.Add("Ocp-Apim-Subscription-Key", TEXT_TRANSLATION_API_SUBSCRIPTION_KEY);
WebResponse response = null; // 把返回的 xml 信息抽取到数组中
response = WebRequest.GetResponse();
using (Stream stream = response.GetResponseStream())
{
DataContractSerializer dcs = new DataContractSerializer(typeof(List<string>));
List<string> languagesForTranslate = (List<string>)dcs.ReadObject(stream);
languageCodes = languagesForTranslate.ToArray();
}
}

执行这个函数后,languageCodes 中的内容如下图所示:

虽然取到了可以翻译的语言列表,但是像图中的内容是无法显示给用户的,还需要把它们转换成对用户友好的名称,因此我们定义 GetLanguageNames 函数完成这个功能:

private SortedDictionary<string, string> languageCodesAndTitles =
new SortedDictionary<string, string>(Comparer<string>.Create((a, b) => string.Compare(a, b, true)));
private void GetLanguageNames()
{
// 获得简体中文的语言名称
string uri = TEXT_TRANSLATION_API_ENDPOINT + "GetLanguageNames?locale=zh-CHS";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Headers.Add("Ocp-Apim-Subscription-Key", TEXT_TRANSLATION_API_SUBSCRIPTION_KEY);
request.ContentType = "text/xml";
request.Method = "POST";
DataContractSerializer dcs = new DataContractSerializer(Type.GetType("System.String[]"));
using (Stream stream = request.GetRequestStream())
{
dcs.WriteObject(stream, languageCodes);
} // 把返回的 xml 信息抽取到数组中
var response = request.GetResponse();
string[] languageNames;
using (Stream stream = response.GetResponseStream())
{
languageNames = (string[])dcs.ReadObject(stream);
} // 把支持的语言列表及其友好名称保存到字典数据结构中,
// 随后会把它们绑定给 combo box 控件进行显示
for (int i = ; i < languageNames.Length; i++)
{
languageCodesAndTitles.Add(languageNames[i], languageCodes[i]);
}
}

这次我们拿到了用中文显示的语言名称:

初始化源和目标语言列表

当获得了支持翻译的语言列表后,就可以通过 UI 控件把它们显示出来:

private void PopulateLanguageMenus()
{
int count = languageCodesAndTitles.Count;
foreach (string menuItem in languageCodesAndTitles.Keys)
{
FromLanguageComboBox.Items.Add(menuItem);
ToLanguageComboBox.Items.Add(menuItem);
} // 设置默认的源语言和目标语言
FromLanguageComboBox.SelectedItem = "英语";
ToLanguageComboBox.SelectedItem = "简体中文";
}

在我们的使用场景中,把默认的翻译文本设置为 "英语",翻译的目标语言为 "简体中文":

翻译文本

接下来介绍文本翻译的 API,其核心是下面的 url 请求:

TEXT_TRANSLATION_API_ENDPOINT + "Translate?text=" + 待翻译文本 + "&from=" + 源语言 + "&to=" + 目标语言

同样,我们把它封装成一个具有完整功能的函数:

private void TranslateButton_Click(object sender, EventArgs e)
{
string textToTranslate = TextToTranslate.Text.Trim();
string fromLanguage = FromLanguageComboBox.SelectedValue.ToString();
string fromLanguageCode = languageCodesAndTitles[fromLanguage];
string toLanguageCode = languageCodesAndTitles[ToLanguageComboBox.SelectedValue.ToString()]; // 如果要翻译的文本是英语,还可以进行拼写检查
if (fromLanguageCode == "en")
{
textToTranslate = CorrectSpelling(textToTranslate);
// 把更新后的文本保存到 UI 控件上
TextToTranslate.Text = textToTranslate;
} // 处理文本为空和不需要翻译的情况
if (textToTranslate == "" || fromLanguageCode == toLanguageCode)
{
TranslatedText.Text = textToTranslate;
return;
} // 通过 http 请求执行翻译任务
string uri = string.Format(TEXT_TRANSLATION_API_ENDPOINT + "Translate?text=" +
System.Web.HttpUtility.UrlEncode(textToTranslate) + "&from={0}&to={1}", fromLanguageCode, toLanguageCode);
var translationWebRequest = HttpWebRequest.Create(uri);
translationWebRequest.Headers.Add("Ocp-Apim-Subscription-Key", TEXT_TRANSLATION_API_SUBSCRIPTION_KEY);
WebResponse response = null;
response = translationWebRequest.GetResponse(); // 把返回的翻译结果抽取到 UI 控件中
Stream stream = response.GetResponseStream();
StreamReader translatedStream = new StreamReader(stream, Encoding.GetEncoding("utf-8"));
System.Xml.XmlDocument xmlResponse = new System.Xml.XmlDocument();
xmlResponse.LoadXml(translatedStream.ReadToEnd());
TranslatedText.Text = xmlResponse.InnerText;
}

在调用翻译文本的 API 前,需要先从 UI 控件中取得用户设置的源语言和目标语言,并且还要对放在 url 中传输的文本内容进行编码:

string uri = string.Format(TEXT_TRANSLATION_API_ENDPOINT + "Translate?text=" +
System.Web.HttpUtility.UrlEncode(textToTranslate) + "&from={0}&to={1}", fromLanguageCode, toLanguageCode);

拼写检查

对于英语,我们可以通过 Bing Spell Check 服务进行翻译前的拼写检查。比如 TranslateButton_Click 函数中的:

// 如果要翻译的文本是英语,还可以进行拼写检查
if (fromLanguageCode == "en")
{
textToTranslate = CorrectSpelling(textToTranslate);
// 把更新后的文本保存到 UI 控件上
TextToTranslate.Text = textToTranslate;
}

主要的拼写检查逻辑被封装在了 CorrectSpelling 函数中:

private string CorrectSpelling(string text)
{
string uri = BING_SPELL_CHECK_API_ENDPOINT + "?mode=spell&mkt=en-US";
// 创建拼写检查的请求
HttpWebRequest spellCheckWebRequest = (HttpWebRequest)WebRequest.Create(uri);
spellCheckWebRequest.Headers.Add("Ocp-Apim-Subscription-Key", BING_SPELL_CHECK_API_SUBSCRIPTION_KEY);
spellCheckWebRequest.Method = "POST";
spellCheckWebRequest.ContentType = "application/x-www-form-urlencoded"; // 这个设置是必须的! // 把文本内容放在请求的 body 中
string body = "text=" + System.Web.HttpUtility.UrlEncode(text);
byte[] data = Encoding.UTF8.GetBytes(body);
spellCheckWebRequest.ContentLength = data.Length;
using (var requestStream = spellCheckWebRequest.GetRequestStream())
requestStream.Write(data, , data.Length);
HttpWebResponse response = (HttpWebResponse)spellCheckWebRequest.GetResponse(); // 从返回中取出 json 格式的拼写检查结果
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var responseStream = response.GetResponseStream();
var jsonString = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")).ReadToEnd();
dynamic jsonResponse = serializer.DeserializeObject(jsonString);
var flaggedTokens = jsonResponse["flaggedTokens"]; // 我们定义一个规则来应用拼写检查的结果,
// 比如:当拼写检查的权值大于 0.7 时就用建议的值替换掉文本中的值。
var corrections = new SortedDictionary<int, string[]>(Comparer<int>.Create((a, b) => b.CompareTo(a)));
for (int i = ; i < flaggedTokens.Length; i++)
{
var correction = flaggedTokens[i];
var suggestion = correction["suggestions"][];
if (suggestion["score"] > (decimal)0.7)
corrections[(int)correction["offset"]] = new string[]
{ correction["token"], suggestion["suggestion"] };
} foreach (int i in corrections.Keys)
{
var oldtext = corrections[i][];
var newtext = corrections[i][];
if (text.Substring(i, oldtext.Length).All(char.IsUpper)) newtext = newtext.ToUpper();
else if (char.IsUpper(text[i])) newtext = newtext[].ToString().ToUpper() + newtext.Substring();
text = text.Substring(, i) + newtext + text.Substring(i + oldtext.Length);
}
return text;
}

从上面的代码可以看出,拼写检查只是给出一些建议,具体怎么做还是由用户决定的。比如上面的代码中当拼写检查的权值大于 0.7 时就用建议的值替换掉文本中的值。下面我们来测试一下拼写检查的逻辑,运行程序,并输入 "helo world!" 进行翻译:

执行翻译操作,代码逻辑在检测到待翻译的语言为英语时,会先进行代码的拼写检查:

上图显示拼写检查函数 CorrectSpelling 纠正了我们的拼写错误,下面是翻译的结果:

有了代码的拼写检查,是不是感觉这个程序有点 "智能" 的味道啦!

总结

就像 azure 提供的其它服务一样,入门和上手非常的容易。我们简单的搞了几下就能够运行一个简单的文本翻译程序了。
当然这只是一个开始,希望大家和笔者一道通过本文开启 Azure AI 的一段旅程。

参考:
Microsoft Translator WPF application in C#

Azure AI 服务之文本翻译的更多相关文章

  1. Azure AI 服务之语音识别

    笔者在前文<Azure AI 服务之文本翻译>中简单介绍了 Azure 认知服务中的文本翻译 API,通过这些简单的 REST API 调用就可以轻松地进行机器翻译.如果能在程序中简单的集 ...

  2. HMS Core 机器学习服务6.4.0版本更新啦,文本翻译功能增加10种小语种语言类型!

    近日,HMS Core机器学习服务(ML Kit)文本翻译功能在6.4.0版本更新中增加了10种小语种语言类型,分别是马其他语.马其顿.冰岛.乌尔都语.波斯尼亚语.乌克兰语.加泰罗尼亚语.斯洛文尼亚语 ...

  3. Azure 认知服务概述

    背景知识 近些年随着机器学习.深度学习等技术的不断发展,人工智能在越来越多的场景得到了应用,如人脸识别.图像识别.语音识别.语音生成.自然语言处理.决策分析等等,让机器拥有了听.说.看和思考的能力,很 ...

  4. 技术博客:Azure 认知服务

    Azure 认知服务 1.概述 ​ 微软认知服务(Microsoft Cognitive Services)集合了多种智能API以及知识API,使每个开发人员无需具备机器学习的专业知识就能接触到 AI ...

  5. Azure 媒体服务的 RTMP 支持和实时编码器

    Cenk Dingiloglu Azure 媒体服务高级项目经理 直播流媒体目前已在公共预览版中提供,其中一项受支持的输入协议便是 RTMP.RTMP 是用于输入和分发包括直播流媒体在内的丰富媒体的一 ...

  6. Azure认知服务的实际应用-资讯采集推送

    Azure认知服务的实际应用-资讯采集推送 演示 实现的是通过使用各种azure服务,每天自动获取资讯.博客,定时推送到公众号的功能! 微信公众号搜索TechViews,或直接扫描二维码关注,每天推送 ...

  7. Azure认知服务之表格识别器

    认知服务 Azure 认知服务的目标是帮助开发人员创建可以看.听.说.理解甚至开始推理的应用程序. Azure 认知服务中的服务目录可分为五大主要支柱类别:视觉.语音.语言.Web 搜索和决策.开发人 ...

  8. 解读 Windows Azure 存储服务的账单 – 带宽、事务数量,以及容量

    经常有人询问我们,如何估算 Windows Azure 存储服务的成本,以便了解如何更好地构建一个经济有效的应用程序.本文我们将从带宽.事务数量,以及容量这三种存储成本的角度探讨这一问题. 在使用 W ...

  9. Microsoft Azure File 服务简介

    我们非常高兴地宣布在微软Azure中国区推出 Microsoft Azure File 服务预览版.Azure File 服务使用标准 SMB 2.1 协议提供文件共享.Azure 中运行的应用程序现 ...

随机推荐

  1. Redis 中的数据类型及基本操作

    Redis 内置的数据类型有 5种:字符串String.哈希Hash.列表List.集合Set.有序集合ZSet 字符串类型 String 是 Redis 中最基本的类型,一个 key 对应着一个 v ...

  2. 【BootStrap】 概述 & CSS

    BootStrap BootStrap由Twitter开发,基于HTML,CSS,JS,是一套前端框架.它的特点是对浏览器良好的支持(目前市面上所有流行浏览器都可以),兼容移动设备,以及响应式设计(响 ...

  3. 【JS】 Javascript与HTML DOM的互动 寻路

    JS HTML DOM DOM的全程是Document Object Module,即文档对象模型.一般来说,当一个页面被加载时,浏览器会在内部创建一个当前文档的DOM.就像用python的Etree ...

  4. 【Python】 list & dict & str

    list & dict & str 这三种类型是python中最常用的几种数据类型.他们都是序列的一种 ■ 序列通用操作 1. 分片   s[a:b] 返回序列s中从s[a]到s[b- ...

  5. Java集合:TreeMap源码剖析

    一.概念 TreeMap是基于红黑树结构实现的一种Map,要分析TreeMap的实现首先就要对红黑树有所了解. 要了解什么是红黑树,就要了解它的存在主要是为了解决什么问题,对比其他数据结构比如数组,链 ...

  6. Struts2 之 Action 类访问 WEB 资源

    接着上次博客的内容我继续分享我所学到的知识,和自己在学习过程中所遇到问题以及解决方案.当然,如果读者发现任何问题均可以在下方评论告知我,先谢! 在 Action 中访问 WEB 资源 web 资源 所 ...

  7. 凡事预则立(Beta)

    听说--凡事预则立 吸取之前alpha冲刺的经验教训,也为了这次的beta冲刺可以更好更顺利地进行,更是为了迎接我们的新成员玮诗.我们开了一次组内会议,进行beta冲刺的规划. 上一张我们的合照: 具 ...

  8. C语言第一周作业

    题目一:7-3 温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验代码 2.设计 ...

  9. 201621123050 《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行一个总结. 1.2 可选:使用常规方法总结其他上课内容. L ...

  10. JAVA接口基础知识总结

    1:是用关键字interface定义的. 2:接口中包含的成员,最常见的有全局常量.抽象方法. 注意:接口中的成员都有固定的修饰符. 成员变量:public static final     成员方法 ...