炼数成金 门户 商业智能 Watson 查看内容

IBM Watson 服务在 Bluemix 中的应用

2016-1-26 14:40| 发布者: 炼数成金_小数| 查看: 21571| 评论: 0|原作者: 王传阳|来自: IBM

摘要: Bluemix 是 IBM 基于 Cloud Foundry(一个开源的平台即服务 PaaS)的一种开放云架构实现,它使得组织和开发人员能够快速而又轻松地在云上创建、部署和管理应用程序。同时,Bluemix 也提供了诸多企业级服务,这些服务 ...

工具 存储 Web 企业级 Watson 方法

Bluemix 是 IBM 基于 Cloud Foundry(一个开源的平台即服务 PaaS)的一种开放云架构实现,它使得组织和开发人员能够快速而又轻松地在云上创建、部署和管理应用程序。同时,Bluemix 也提供了诸多企业级服务,这些服务可轻松地与云应用程序相集成,用户无需知道如何安装或配置它们。在这些企业级服务中,包含已开放的 7 种 IBM Watson 服务。 IBM Watson 代表着一种新的计算方式——认知计算。本文将通过实例,向您介绍如何使用 Bluemix 中的 Watson 服务来构建具有认知计算能力的应用。通过本文的实践,您可以可初步感受到 IBM Watson 认知计算的魅力。

IBM Watson 作为认知计算的代表,近来受到诸多关注。以 Watson 为核心构建的企业级应用已逐步上线,例如 Watson Engagement Advisor 和 Chef Watson。然而一般开发人员接触到这些企业级应用的机会不多,因此 Watson 团队提供了多个具有代表性的功能模块,同时也部署在 Bluemix 中,作为“服务”为 Bluemix 中的应用提供与认知相关的计算能力。本文将会介绍 Bluemix 中的 Watson 服务,并通过一个简单的 Web 应用程序,描述如何调用这些 Watson 服务实现相关功能,以及相关的注意事项。

Bluemix 中的 IBM Watson 服务介绍
使用 IBM id 登录到 Bluemix 后,在 Catalog 中可以找到所有可用的 IBM Watson 服务,如图 1 所示:
Bluemix 中的 IBM Waston 服务
各个服务的功能描述和应用示例见表 1:
表 1.Bluemix 中 IBM Watson 服务的功能描述与应用举例

Bluemix 中的 IBM Watson 服务的使用方法
Watson 服务在使用之前,需要将其绑定到一个 Bluemix 应用中。绑定之后,可在 Bluemix 的 Web 控制台中看到该服务的 Credential 信息,即调用服务的资源地址、用户名和密码等信息。这些信息默认是存储在 Bluemix 应用中的系统环境变量中,我们也可将这些信息赋值给其他变量,从而使 Watson 服务也可以被 Bluemix 平台以外的其他应用进行调用,见清单 1:

清单 1.使用 Java 获取 Bluemix 中 Watson 服务的 Crendential 信息:
String VCAP_SERVICES = System.getenv("VCAP_SERVICES");

if(VCAP_SERVICES ==null){
//将 Watson 服务的 Credential 信息拷贝至此,
VCAP_SERVICES="{   \"Watson QAAPI-0.1\" : [ {     \"name\" : \"mt-svc\"......
//此处略去后面具体用户信息
}
if (VCAP_SERVICES != null) {
try {
JSONObject obj = (JSONObject)JSON.parse(VCAP_SERVICES);
JSONArray service = obj.getJSONArray("Watson QAAPI-0.1");

// 获取该服务的 Credential 信息
JSONObject catalog = service.getJSONObject(0);

// 解析 Credential 信息,并把相关字段赋值给本地成员属性
JSONObject credentials = catalog.getJSONObject("credentials");
endpoint = credentials.getString("uri");
username = credentials.getString("userid");
password = credentials.getString("password");

} catch (Exception e) {

e.printStackTrace();

}
}
清单 1 展示的是使用 Java 语言来获取并解析 Watson 服务中的“Question and Answer”服务的 Credential 信息。如果该应用是部署在 Bluemix 的 Liberty 容器中,则默认情况下,VCAP_SERVICES 是非空的。而当该应用是在 Bluemix 外部时,我们需要指定 VCAP_SERVICES 的值,如清单 1 的第三行所示。VCAP_SERVICES 中存储的是当前应用所绑定的所有 Service 的 Credential 信息,因此我们可以根据 Service 的标识 ID 取出相应的 Credential 信息。在清单 1 中,Question and Answer 服务的标识 ID 为 Watson QAAPI-0.1。之后,对于 Credential 信息的解析以及赋值,同样适应于其他 Bluemix 服务。在拿到了这些信息之后,便可根据 Bluemix 服务所提供的调用 API,进行各种请求操作。

IBM Watson 练习工程实践
为使您能够更方便直观地使用 Watson 服务,本小节会通过一个具体的 Web 应用开发来展示如何使用 Watson 服务实现相应的功能需求。
Web 应用所要实现的功能,是使用 Watson 的 Question and Answer 服务,对用户输入的问题进行回答,然后使用 Watson 的 Machine Translation 服务,将返回的答案由英文翻译成中文。
Web 工程构建
由于我们要实现的功能较简单,我们可以使用 JSP + Servlet 来实现 Web 前端和后端服务。因此我们可以使用 Eclipse 构建一个 Dynamic Web Project,如图 2:
图 2.Eclipse 中构建 Dynamic Web Project
eclipse 中构建 Dynamic Web Project
页面功能设计
由于本练习工程主要侧重后端 Watson 服务的使用,所以在前端方面设计较为简单即可。只需要构建两个页面,一个用于输入用户信息(即具体问题),一个用于显示 Watson 的返回信息(即问题的答案)。这两个页面如下图所示:
图 3.Watson 练习工程中的信息输入页面
图 3:Watson 练习工程中的信息输入页面
图 4.Watson 练习工程中的返回信息显示页面
图 4:Watson 练习工程中的返回信息显示页面
页面 1 的文本输入域可放在一个 Form 中,通过 ask Watson 按钮提交到后端的一个 servlet 进行处理。页面 2 的返回信息可通过在 servlet 中使用 request.setAttribute()方法将 Watson 返回的信息放入其中,然后在页面 2 中调用 request.getAttribute()将其取出并在页面显示。由于页面逻辑较为简单,因此这里不再给出有关页面方面的代码。

后端业务处理
在后端,我们需要有一个 servlet 来处理通过前端页面提交过来的请求,还需要有一个服务类来专门处理同 Watson 服务之间的交互,因此,后端的类图如下:
图 5.Watson 练习工程后端类图
图 5: Watson 练习工程后端类图
QAServlet 比较简单,它所调用的大部分方法都在 WatsonService 类中。WatsonService 负责获取与 Watson 服务相关的各种认证信息,以及与远程 Watson 服务之间的交互。关于认证信息的获取,这里会在 WatsonService 类被创建时来初始化 username 和 password 等,具体方法请参照前面的清单一。

与 Watson 服务之间的交互方面,按照设想我们会使用两个服务,所以每个服务各对应一个方法。askWatson 方法的具体代码如清单二所示:
清单 2.Watson 练习工程后端 askWatson 方法代码
public static String askWatson(String question) throws Exception {
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
provider.setCredentials(AuthScope.ANY, credentials);
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
builder.build(),SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
CloseableHttpClient client = HttpClients.custom().
setSSLSocketFactory(sslsf).
setDefaultCredentialsProvider(provider).
build();

HttpPost httpPost = new HttpPost(requestURI);
StringEntity ent = new StringEntity("{\"question\" : {\"questionText\" : \"" + question + "\"}}");
ent.setContentType("application/json");
httpPost.setEntity(ent);
httpPost.setHeader("X-SyncTimeOut", "60");

HttpResponse response = client.execute(httpPost);
HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity, "UTF-8");

return responseString;
}
askWatson 方法接受一个字符串类型的参数作为方法的输入,然后使用 Apache 的 httpclient 包中的相关类构建了一个 client 对象,包含相关 credential 信息。接下来构造一个 HttpPost 对象,它的 Entity 需要使用 StringEntity,String 的格式需要参考 Watson 服务的 API(关于 Watson 服务的 API,它的文档链接都会放在该服务在 Bluemix 中的图标下面)。然后使用 client 对象来执行 HttpPost 请求,并将返回结果保存到 HttpResponse 对象中,再进行进一步处理,就可得到返回的答案字符串。

WatsonService 类中的另一方法 translateText 会对返回的答案字符串进行翻译。由于 Question and Answer 服务返回的都是英文结果,因此我们可以使用 Watson 的翻译服务将其由英文翻译为中文。

translateText 方法同样接受一个字符串类型的参数作为方法的输入,方法的返回值即是对输入参数的翻译结果。具体代码如清单三所示:
清单 3.Watson 练习工程后端 translateText 方法代码
public String translateText(String text){
//指定字符串的语言类型及所需翻译的目标语言类型
String sid = "mt-enus-zhcn";
String result = "";
try {
String post = "rt=text&sid=" + URLEncoder.encode(sid, "UTF-8") +
"&txt=" + URLEncoder.encode(text, "UTF-8");
// 准备 Http 连接
HttpURLConnection conn = (HttpURLConnection)new URL(endpoint).openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "*/*");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String auth = username + ":" + password;
String encoded = new String(Base64.encodeBase64(auth.getBytes()));
conn.setRequestProperty("Authorization", String.format("Basic %s", encoded));
DataOutputStream output = new DataOutputStream(conn.getOutputStream());
//建立连接
conn.connect();
//发送 post 请求
output.writeBytes(post);
output.flush();
output.close();
// 读取返回结果
BufferedReader rdr = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
if (conn.getResponseCode()==HttpURLConnection.HTTP_OK)
System.out.println("Response OK  from: "+conn.getURL().toString());
else
System.err.println("Unsuccesful response: "+conn.getResponseCode()+ " from: "+conn.getURL().toString());
String line = "";
StringBuffer buf = new StringBuffer();
while ((line = rdr.readLine()) != null) {
buf.append(line);
buf.append("\n");
}
rdr.close();
return buf.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}

return result;
}
不同于 askWatson 方法,这里对 Http 连接和请求的构建,使用的是 JDK 的 API 而并非 Apache HttpClient,对返回结果的处理也同样使用 JDK 的 API。当然,使用 Apahce HttpClient 也可实现这一功能。代码中需要特别说明的是对 sid 变量的指定。sid 变量声明的是输入字符串的语言类型及所要翻译的目标语言类型。该变量必须被包含在 HttpPost 请求中,否则 Watson 翻译服务会认为请求非法。目前 Bluemix 中的 Watson 翻译服务只开放了有限的几种语言之间的文字翻译,其实用性还有待提高。

WatsonService 类中还有一个私有方法 parseResult,作用是对 Watson 服务所返回的字符串信息进行处理。本练习工程中用到的这两个 Watson 服务所返回的字符串格式是不同的。Watson 翻译服务所返回的字符串格式较为简单,不需要做特殊处理即可直接使用。而 Question and Answer 服务返回的是 JSON 字符串,因此需要使用 parseResult 方法来处理这个 JSON 字符串,将其中有用的域值抽取出来,作为结果返回给调用层。由于对 JSON 字符串处理的代码较为常见,因此这里不再给出 parseResult 方法的具体内容。

对于另一个类 QAServlet 而言,其 doGet 或 doPost 方法可直接调用 WatsonService 中提供的各种方法来对从前端得到的字符串进行处理,其代码如下:
清单 4.Watson 练习工程后端 QAServlet 类的主要代码
 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//读取前端页面输入的问题
String question = req.getParameter("question");
WatsonService watsonSvc = new WatsonService();
String answer =null;
String translatedAnswer = null;
try {
//对问题进行回答
answer = watsonSvc.askWatson(question);
//对答案进行翻译
translatedAnswer = watsonSvc.translateText(answer);
req.setAttribute("answer", translatedAnswer);
req.getRequestDispatcher("result.jsp").forward(req,resp); 
} catch (Exception e) {
e.printStackTrace();
}
}
QAServlet 会将从前端得到的问题进行回答并翻译,然后放到 request 对象中,并使前端页面跳转到 result.jsp 来对结果进行显示。
以上是对 Watson 练习工程中主要的类及方法的详细说明。通过该练习工程,希望您在实际应用中能注意到,Bluemix 中的 Watson 服务有着不同的 API,在进行调用时,需要首先参考其 API 文档,使用合适的方式进行调用。同时,不同的 Watson 服务所返回的结果格式也不尽相同,有可能需要做进一步处理才能够使用。

Watson 练习工程可被导出成 WAR 包,部署在 Bluemix 外部的应用服务器上直接运行。Bluemix 提供了 Liberty server 来运行 Java Web 程序,因此我们也可以将该 WAR 包部署到 Bluemix 平台中,具体的部署方法及步骤请参考Bluemix 官方文档。

结语
Bluemix 为开发人员提供了一个可快速开发、部署和管理应用的平台,它的开放性使得开发者可以提供自己的服务并发布到平台上,供其他开发人员使用。IBM Watson 团队目前在 Bluemix 平台开发并提供的这 9 种服务,虽然成熟度不高,但这已彰显出一种趋势,即 Bluemix 所提供的平台,是今后认知计算服务发挥作用的舞台之一。开发都通过 Bluemix 使用认知计算服务,可以避免各种环境的重复搭建,更专注于认知计算本身的研究与使用。本文通过一个实际的练习工程的开发,希望起到抛砖引玉的作用,使更多开发人员对 Bluemix 和 Watson 服务产生兴趣,并运用它们开发出更加富有创新性的应用。

欢迎加入本站公开兴趣群
商业智能与数据分析群
兴趣范围包括各种让数据产生价值的办法,实际应用案例分享与讨论,分析工具,ETL工具,数据仓库,数据挖掘工具,报表系统等全方位知识
QQ群:81035754
1

鲜花

握手

雷人

路过

鸡蛋

刚表态过的朋友 (1 人)

最新评论

热门频道

  • 大数据
  • 商业智能
  • 量化投资
  • 科学探索
  • 创业

热门文章

     

    GMT+8, 2020-10-22 05:01 , Processed in 0.170938 second(s), 25 queries .