C#开发微信门户及应用(31)--微信语义理解接口的实现和处理
微信语义理解接口提供从用户自然语言输入到结构化解析的技术实现,使用先进的自然语言处理技术给开发者提供一站式的语义解析方案。该平台覆盖多个垂直领域的语义场景,部分领域还可以支持取得最终的展示结果。开发者无需掌握语义理解及相关技术,只需根据自己的产品特点,选择相应的服务即可搭建一套智能语义服务。结合语音识别接口,通过微信语音识别得到用户的语音信息之后,经过语义分析理解,得到用户需求,及时回复用户。本文介绍如何实现对微信语义接口的封装处理,以及一些常用场景的调用。
1)微信语义理解接口
这个东西也就是把我们日常的话语(称之为自然语言)解析为对应的信息结构体,方便我们提取里面的相关信息进行搜索查询,并精确回应给对应的请求者的一个桥梁,其主要的功能就是解析我们所说的内容。
微信开放平台语义理解接口调用(http请求)简单方便,用户无需掌握语义理解及相关技术,只需根据自己的产品特点,选择相应的服务即可搭建一套智能语义服务。我们来看看微信语义理解接口的定义内容。
http请求方式: POST(请使用https协议)
https://api.weixin.qq.com/semantic/semproxy/search?access_token=YOUR_ACCESS_TOKEN
POST数据格式:JSON,POST数据例子:
{ "query":"查一下明天从北京到上海的南航机票", "city":"北京", "category": "flight,hotel", "appid":"wxaaaaaaaaaaaaaaaa", "uid":"123456" }
参数说明
参数 | 是否必须 | 参数类型 | 说明 |
access_token | 是 | String | 根据appid和appsecret获取到的token |
query | 是 | String | 输入文本串 |
category | 是 | String | 需要使用的服务类型,多个用“,”隔开,不能为空 |
latitude | 见接口协议文档 | Float | 纬度坐标,与经度同时传入;与城市二选一传入 |
longitude | 见接口协议文档 | Float | 经度坐标,与纬度同时传入;与城市二选一传入 |
city | 见接口协议文档 | String | 城市名称,与经纬度二选一传入 |
region | 见接口协议文档 | String | 区域名称,在城市存在的情况下可省;与经纬度二选一传入 |
appid | 是 | String | 公众号唯一标识,用于区分公众号开发者 |
uid | 否 | String | 用户唯一id(非开发者id),用户区分公众号下的不同用户(建议填入用户openid),如果为空,则无法使用上下文理解功能。appid和uid同时存在的情况下,才可以使用上下文理解功能。 |
注:单类别意图比较明确,识别的覆盖率比较大,所以如果只要使用特定某个类别,建议将category只设置为该类别。
返回说明 正常情况下,微信会返回下述JSON数据包:
{ “errcode”:0, “query”:”查一下明天从北京到上海的南航机票”, “type”:”flight”, “semantic”:{ “details”:{ “start_loc”:{ “type”:”LOC_CITY”, “city”:”北京市”, “city_simple”:”北京”, “loc_ori”:”北京” }, “end_loc”: { “type”:”LOC_CITY”, “city”:”上海市”, “city_simple”:”上海”, “loc_ori”:”上海” }, “start_date”: { “type”:”DT_ORI”, “date”:”2014-03-05”, “date_ori”:”明天” }, “airline”:”中国南方航空公司” }, “intent”:”SEARCH” }
返回参数说明
参数 | 是否必须 | 参数类型 | 说明 |
errcode | 是 | Int | 表示请求后的状态 |
query | 是 | String | 用户的输入字符串 |
type | 是 | String | 服务的全局类型id,详见协议文档中垂直服务协议定义 |
semantic | 是 | Object | 语义理解后的结构化标识,各服务不同 |
result | 否 | Array | 部分类别的结果 |
answer | 否 | String | 部分类别的结果html5展示,目前不支持 |
text | 否 | String | 特殊回复说明 |
上面就是微信官方给出的代码案例,以及一个《语义理解接口协议文档》,里面介绍了各个场景的语义结构信息,虽然这个文档好像好久都没怎么更新,不过总体内容还是稳定的,我们可以通过这个文档进行相关的类库设计工作。
2、语义理解接口的C#实现
根据《语义理解接口协议文档》文档,我们可以定义各种所需的语义结构类库,这些是我们开展语义接口的基础类。
例如我们定义基础的时间协议类,如下所示。
/// <summary>
/// 时间相关协议datetime
/// </summary>
public class Semantic_DateTime
{
/// <summary>
/// 单时间的描述协议类型:“DT_SINGLE”。DT_SINGLE又细分为两个类别:DT_ORI和DT_INFER。DT_ORI是字面时间,比如:“上午九点”;
/// DT_INFER是推理时间,比如:“提前5分钟”。 时间段的描述协议类型:“DT_INTERVAL”
/// 重复时间的描述协议类型:“DT_REPEAT” DT_ REPEAT又细分为两个类别:DT_RORI和DT_RINFER。DT_RORI是字面时间,比如:“每天上午九点”;DT_RINFER是推理时间,比如:“工作日除外”
/// </summary>
public string type { get; set; }
/// <summary>
/// 24小时制,格式:HH:MM:SS,默认为00:00:00
/// </summary>
public string time { get; set; }
/// <summary>
/// Time的原始字符串
/// </summary>
public string time_ori { get; set; }
} /// <summary>
/// 单时间的描述协议datetime
/// </summary>
public class Semantic_SingleDateTime : Semantic_DateTime
{
/// <summary>
/// 格式:YYYY-MM-DD,默认是当天时间
/// </summary>
public string date { get; set; } /// <summary>
/// 格式:YYYY-MM-DD 农历
/// </summary>
public string date_lunar { get; set; } /// <summary>
/// date的原始字符串
/// </summary>
public string date_ori { get; set; }
}
当然时间还有很多类型的定义,都基本上按照文档所列的字段进行处理,上面的代码只是定义了常用的单时间的描述协议类型:“DT_SINGLE”。
除了时间协议,还有数字,地点位置等相关协议,如数字协议如下所示。
public class Semantic_Number
{
/// <summary>
/// 大类型:“NUMBER” NUMBER又细分为如下类别:NUM_PRICE、NUM_PADIUS、NUM_DISCOUNT、NUM_SEASON、NUM_EPI、NUM_CHAPTER。
/// </summary>
public string type { get; set; }
/// <summary>
/// 开始
/// </summary>
public string begin { get; set; }
/// <summary>
/// 结束
/// </summary>
public string end { get; set; }
}
地点位置协议如下所示
/// <summary>
/// 地点相关协议
/// </summary>
public class Semantic_Location
{
/// <summary>
/// 大类型:“LOC” LOC又细分为如下类别:LOC_COUNTRY、LOC_PROVINCE、LOC_CITY、LOC_TOWN、LOC_POI、NORMAL_POI。
/// </summary>
public string type { get; set; }
/// <summary>
/// 国家
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string country { get; set; }
/// <summary>
/// 省全称,例如:广东省
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string province { get; set; }
/// <summary>
/// 省简称,例如:广东|粤
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string province_simple { get; set; }
/// <summary>
/// 市全称,例如:北京市
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string city { get; set; }
/// <summary>
/// 市简称,例如:北京
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string city_simple { get; set; } ..............
前面我们看到了,语音立即的POST数据格式是一个较为固定的格式内容,我们可以把它定义为一个类,方便数据处理。
POST数据格式:JSON,POST数据例子如下所示:
{ "query":"查一下明天从北京到上海的南航机票", "city":"北京", "category": "flight,hotel", "appid":"wxaaaaaaaaaaaaaaaa", "uid":"123456" }
那么我们可以定义它的类库如下所示。
/// <summary>
/// 语义查询条件
/// </summary>
public class SemanticQueryJson
{
/// <summary>
/// 输入文本串
/// 必填
/// </summary>
public string query { get; set; } /// <summary>
/// 需要使用的服务类别,多个用,隔开,不能为空
/// 必填
/// </summary>
public string category { get; set; } /// <summary>
/// 城市名称,与经纬度二选一传入
/// 见说明,选填
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string city { get; set; } /// <summary>
/// App id,开发者的唯一标识,用于区分开放者,如果为空,则没法使用上下文理解功能。
/// 非必填
/// </summary>
public string appid { get; set; } /// <summary>
/// 用户唯一id(并非开发者id),用于区分该开发者下不同用户,如果为空,则没法使用上下文理解功能。appid和uid同时存在的情况下,才可以使用上下文理解功能。
/// 非必填
/// </summary>
public string uid { get; set; } ................
}
接着我们分析语义理解的接口返回值,它们基本上都是很有规律的内容,如下所示。
这样我们也就可以定义一个通用的类库对象,用来存储不同的返回内容了,如下代码所示。
/// <summary>
/// 微信语义结果
/// </summary>
public class SemanticResultJson<T> : ErrorJsonResult
{
/// <summary>
/// 用户的输入字符串
/// </summary>
public string query { get; set; }
/// <summary>
/// 服务的全局类别id
/// </summary>
public string type { get; set; } /// <summary>
/// 语义理解后的结构化标识,各服务不同
/// </summary>
public T semantic { get; set; }
}
而其中的T semantic就是另外一个结构体里面的内容,这个结构体总体也是固定的内容,我们继续定义一个如下的类。
/// <summary>
/// 详细信息里面的对象
/// </summary>
/// <typeparam name="T"></typeparam>
public class SemanticDetail<T>
{
/// <summary>
/// 详细信息
/// </summary>
public T details { get; set; } /// <summary>
/// 查询类型
/// </summary>
public string intent { get; set; }
}
有了这些类库的支持,我们可以封装语义理解接口的返回值了,这样它的接口定义和封装处理代码如下所示。
/// <summary>
/// 语意理解接口
/// 微信开放平台语义理解接口调用(http请求)简单方便,用户无需掌握语义理解及相关技术,只需根据自己的产品特点,选择相应的服务即可搭建一套智能语义服务。
/// </summary>
public class SemanticApi : ISemanticApi
{
/// <summary>
/// 发送语义理解请求
/// </summary>
/// <param name="accessToken">调用接口凭证</param>
/// <param name="data">查询条件</param>
public SemanticResultJson<SemanticDetail<T>> SearchSemantic<T>(string accessToken, SemanticQueryJson data)
{
var url = string.Format("https://api.weixin.qq.com/semantic/semproxy/search?access_token={0}", accessToken);
string postData = data.ToJson(); return JsonHelper<SemanticResultJson<SemanticDetail<T>>>.ConvertJson(url, postData);
}
由于微信语义结果是针对不同的服务协议,我们需要根据这些不同的服务协议,来定义属于这些信息结构,如在文档里,我们可以看到有很多不同类型的服务协议。
根据文档的详细字段说明,我们可以定义不同服务的对应类库。
例如对于旅游服务的语义理解,它们的协议类如下所示。
/// <summary>
/// 旅游服务(travel)
/// </summary>
public class Semantic_Details_Travel
{
/// <summary>
/// 旅游目的地
/// </summary>
public Semantic_Location location { get; set; }
/// <summary>
/// 景点名称
/// </summary>
public string spot { get; set; }
/// <summary>
/// 旅游日期
/// </summary>
public Semantic_SingleDateTime datetime { get; set; }
/// <summary>
/// 旅游类型词
/// </summary>
public string tag { get; set; }
/// <summary>
/// 0默认,1自由行,2跟团游
/// </summary>
public int category { get; set; }
}
那么调用的旅游语义的案例代码如下所示
var api = new SemanticApi();
var json = new SemanticQueryJson
{
appid = appId,
uid = openId,
category = SemanticCategory.travel.ToString(),
query = "故宫门票多少钱",
city = "北京市"
}; var travel = api.SearchSemantic<Semantic_Details_Travel>(token, json);
Console.WriteLine(travel.ToJson());
如果我们测试,上面的代码跑起来会返回一个旅游的协议对象,包括了相关的数据信息。
{
"errcode" : ,
"query" : "故宫门票多少钱",
"semantic" : {
"details" : {
"answer" : "",
"context_info" : {},
"hit_str" : "故宫 门票 多少 钱 ",
"spot" : "故宫"
},
"intent" : "PRICE"
},
"type" : "travel"
}
我们再来看一个例子,例如对于航班服务,我们定义它的语义理解协议如下所示。
/// <summary>
/// 航班服务(flight)
/// </summary>
public class Semantic_Details_Flight
{
/// <summary>
/// 航班号
/// </summary>
public string flight_no { get; set; }
/// <summary>
/// 出发地
/// </summary>
public Semantic_Location start_loc { get; set; }
/// <summary>
/// 目的地
/// </summary>
public Semantic_Location end_loc { get; set; }
/// <summary>
/// 出发日期
/// </summary>
public Semantic_SingleDateTime start_date { get; set; }
/// <summary>
/// 返回日期
/// </summary>
public Semantic_SingleDateTime end_date { get; set; }
/// <summary>
/// 航空公司
/// </summary>
public string airline { get; set; }
/// <summary>
/// 座位级别(默认无限制):ECONOMY(经济舱)BIZ(商务舱)FIRST(头等舱)
/// </summary>
public string seat { get; set; }
/// <summary>
/// 排序类型:0排序无要求(默认),1价格升序,2价格降序,3时间升序,4时间降序
/// </summary>
public int sort { get; set; }
}
那么调用获取语义理解内容的代码如下所示。
json = new SemanticQueryJson
{
appid = appId,
uid = openId,
category = SemanticCategory.flight.ToString(),
query = "查一下明天从广州到上海的南航机票",
city = "广州"
};
var flight = api.SearchSemantic<Semantic_Details_Flight>(token, json);
Console.WriteLine(flight.ToJson());
我们可以获取到的JSON数据如下所示
{
"errcode" : ,
"query" : "查一下明天从广州到上海的南航机票",
"semantic" : {
"details" : {
"airline" : "中国南方航空公司",
"answer" : "已帮您预定2016-04-13,从广州市出发,前往上海市的航班。",
"context_info" : {
"isFinished" : "",
"null_times" : ""
},
"end_loc" : {
"city" : "上海市",
"city_simple" : "上海|沪|申",
"loc_ori" : "上海",
"modify_times" : "",
"slot_content_type" : "",
"type" : "LOC_CITY"
},
"hit_str" : "查 一下 明天 从 广州 到 上海 南航 机票 ",
"sort" : "",
"start_date" : {
"date" : "2016-04-13",
"date_lunar" : "2016-03-07",
"date_ori" : "明天",
"modify_times" : "",
"slot_content_type" : "",
"type" : "DT_ORI",
"week" : ""
},
"start_loc" : {
"city" : "广州市",
"city_simple" : "广州",
"loc_ori" : "广州",
"modify_times" : "",
"province" : "广东省",
"province_simple" : "广东|粤",
"slot_content_type" : "",
"type" : "LOC_CITY"
}
},
"intent" : "SEARCH"
},
"type" : "flight"
}
这样就是我们把我们常规的语义,分析成了机器可以识别的准确的数据结构了,我们可以根据不同的语义场合对它进行分析,然后给用户进行不同的响应就可以了,结合微信语音识别为文本内容,我们可以把它做得很强大,有的类似机器智能的味道了。
微信语义理解是一个好东西,不过在微信官网上没有看到进一步的案例,如果能够有一些与实际结合的例子,估计更能帮助我们理解和应用了。
C#开发微信门户及应用(31)--微信语义理解接口的实现和处理的更多相关文章
- C#开发微信门户及应用(38)--微信摇一摇红包功能
摇一摇周边红包接口是为线下商户提供的发红包功能.用户可以在商家门店等线下场所通过摇一摇周边领取商家发放的红包.我曾经在<C#开发微信门户及应用(28)--微信“摇一摇·周边”功能的使用和接口的实 ...
- C#开发微信门户及应用(37)--微信公众号标签管理功能
微信公众号,仿照企业号的思路,增加了标签管理的功能,对关注的粉丝可以设置标签管理,实现更加方便的分组管理功能.开发者可以使用用户标签管理的相关接口,实现对公众号的标签进行创建.查询.修改.删除等操作, ...
- C#开发微信门户及应用(36)--微信卡劵管理的封装操作
前面几篇介绍了微信支付方面的内容,本篇继续微信接口的一些其他方面的内容:卡劵管理.卡劵管理是微信接口里面非常复杂的一个部分,里面的接口非常多,我花了不少时间对它进行了封装处理,重构优化等等工作,卡劵在 ...
- C#开发微信门户及应用(35)--微信支付之企业付款封装操作
在前面几篇随笔,都是介绍微信支付及红包相关的内容,其实支付部分的内容还有很多,例如企业付款.公众号支付或刷卡支付.摇一摇红包.代金券等方面的内容,这些都是微信接口支持的内容,本篇继续微信支付这一主题, ...
- C#开发微信门户及应用(34)--微信裂变红包
在上篇随笔<C#开发微信门户及应用(33)--微信现金红包的封装及使用>介绍了普通现金红包的封装和使用,这种红包只能单独一次发给一个人,用户获取了红包就完成了,如果我们让用户收到红包后,可 ...
- C#开发微信门户及应用(33)--微信现金红包的封装及使用
我在上篇随笔<C#开发微信门户及应用(32)--微信支付接入和API封装使用>介绍为微信支付的API封装及使用,其中介绍了如何配置好支付环境,并对扫码支付的两种方式如何在C#开发中使用进行 ...
- C#开发微信门户及应用(32)--微信支付接入和API封装使用
在微信的应用上,微信支付是一个比较有用的部分,但也是比较复杂的技术要点,在微商大行其道的年代,自己的商店没有增加微信支付好像也说不过去,微信支付旨在为广大微信用户及商户提供更优质的支付服务,微信的支付 ...
- C#开发微信门户及应用(25)-微信企业号的客户端管理功能
我们知道,微信公众号和企业号都提供了一个官方的Web后台,方便我们对微信账号的配置,以及相关数据的管理功能,对于微信企业号来说,有通讯录中的组织架构管理.标签管理.人员管理.以及消息的发送等功能,其中 ...
- C#开发微信门户及应用(24)-微信小店货架信息管理
在前面微信小店系列篇<C#开发微信门户及应用(22)-微信小店的开发和使用>里面介绍了一些微信小店的基础知识,以及<C#开发微信门户及应用(23)-微信小店商品管理接口的封装和测试& ...
随机推荐
- ubuntu 下安装scrapy
1.把Scrapy签名的GPG密钥添加到APT的钥匙环中: sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 6272 ...
- 6_Win7下Chrome主页被流氓网站hao123.com劫持后的解决方法。
今天安装了一个PDF阅读器,免费的,你懂的,结果自己安装的时候没有将默认的选项取消,就被hao123流氓网站劫持啦. 说实话某免费PDF阅读器还算好的,有一个可以供你选择的项.不想某些软件直接就默认选 ...
- JavaScript学习笔记(二)——闭包、IIFE、apply、函数与对象
一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...
- iOS - 模态Model视图跳转和Push视图跳转的混合需求实现原理
在研发中总会遇到一些莫名的需求,本着存在即合理的态度跟大家分享一下"模态Model视图跳转和Push视图跳转的需求实现",本文仅仅传授研发技术不传授产品以及UE的思想,请大家合理对 ...
- Openfire的启动过程与session管理
说明 本文源码基于Openfire4.0.2. Openfire的启动 Openfire的启动过程非常的简单,通过一个入口初始化lib目录下的openfire.jar包,并启动一个 ...
- UML类图(上):类、继承和实现
面向对象设计 对于一个程序员来说,在工作的开始阶段通常都是别人把东西设计好,你来做.伴随着个人的成长,这个过程将慢慢变成自己设计一部分功能来实现,自己实现.如果要自己设计,无论是给自己看,还是给别人看 ...
- 《深入理解Java虚拟机》虚拟机性能监控与故障处理工具
上节学习回顾 从课本章节划分,<垃圾收集器>和<内存分配策略>这两篇随笔同属一章节,主要是从理论+实验的手段来讲解JVM的内存处理机制.好让我们对JVM运行机制有一个良好的概念 ...
- 实现ABP中Person类的权限功能
菜单项的显示功能已经完全OK了.那么我们就开始制作视图功能吧. 首先测试接口是否正常 我们通过代码生成器将权限和application中大部分功能已经实现了.那么我们来测试下这些接口ok不. 浏览/a ...
- ABP源码分析二十七:ABP.Entity Framework
IRepository:接口定义了Repository常见的方法 AbpRepositoryBase:实现了IRepository接口的常见方法 EfRepositoryBase:实现了AbpRepo ...
- Tomcat 8熵池阻塞变慢详解(putty)
原因 Tomcat 7/8都使用org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom类产生安全随机类SecureRand ...