微信小程序——智能小祕「遙知之」源碼分享(語義理解基於olami)

微信小程序智能生活小祕書開發詳解

>>>>>>>>>>>>>>>>>>>>>>>> 歡迎轉載 <<<<<<<<<<<<<<<<<<<<<<<<css

本文原地址:http://blog.csdn.net/happycxz/article/details/75432928java

「遙知之」微信小程序完整源碼下載:git

碼雲:http://git.oschina.net/happycxz/nlp_olami_yaozhizhi_wechat_littleapp_demogithub

CSDN: http://download.csdn.net/download/happycxz/9919690web

github: https://github.com/happycxz/nlp_olami_yaozhizhi_wechat_littleapp_demo算法

實現功能

實現一個智能生活信息查詢的小祕書功能,支持查天氣、新聞、日曆、匯率、笑話、故事、百科、詩詞、郵編、區號、菜譜、股票、節目預告,還支持閒聊、算24點、數學計算、單位換算、購物、搜索等功能。
使用方式上支持搖一搖、點界面按鈕、手動輸入、下拉刷新這四種方式。json

掃碼試用(左右皆可)

小程序碼小 二維碼小

界面展現

遙知之首頁

開發資源

  1. 免費開放語義接口平臺 olami.ai
  2. 微信小程序平臺
  3. js, css

源碼分析

源碼各文件說明

基本延用官方案例的目錄結構和命名,index.xx是首頁面相關代碼,logs.xx是日誌頁相關代碼。小程序

比官方目錄結構多了兩個文件:微信小程序

  1. config.jsapi

    由於用到一些配置,放在.js裏封裝起來比較好。

  2. pics/bg.jpg

    小程序背景圖片,開發環境上加載本地文件做爲背景圖片是生效的,預覽體驗時不生效,網上有人說不支持本地文件,所以這裏這個圖片其實沒有用到,只是暫時留着。

####小程序根目錄文件:app.js, app.json, app.wxss, config.js

app.js

提供獲取用戶微信帳號暱稱和所在地,獲取當前地理位置這兩個公共接口。

//app.js

const corpusList = require('./config').corpus
var UTIL = require('./utils/util.js');

App({
  onShow: function () {
    UTIL.log('App Show')
  },
  onHide: function () {
    UTIL.log('App Hide')
  },
  onLaunch: function () {
    UTIL.log('App Launch')
    this.updateUserLocation()
  },

  updateUserLocation: function() {
    var that = this
    wx.getLocation({
      //type: 'wgs84',  // gps原始座標
      type: 'gcj02', //國家標準加密座標
      success: function (res) {
        that.globalData.latitude = res.latitude
        that.globalData.longitude = res.longitude
        that.globalData.speed = res.speed
        //var accuracy = res.accuracy
        UTIL.log('REFRESH LOCATION: ' + that.globalData.latitude + ' | ' + that.globalData.longitude + ' , speed: ' + that.globalData.speed)
      },
      fail: function(res) {
        UTIL.log('REFRESH LOCATION FAILED...')
      }
    })
  },

  getUserInfo:function(cb){
    var that = this
    if(this.globalData.userInfo){
      typeof cb == "function" && cb(this.globalData.userInfo)
    }else{
      //調用登陸接口
      wx.login({
        success: function () {
          wx.getUserInfo({
            success: function (res) {
              that.globalData.userInfo = res.userInfo
              that.globalData.custId = UTIL.getUserUnique(that.globalData.userInfo);
              typeof cb == "function" && cb(that.globalData.userInfo)
            }
          })
        },
        fail: function () {
          UTIL.log('登陸WX失敗了!')
        }
      })
    }
  },

  clearUserInfo: function() {
    var that = this
    that.globalData.userInfo = null;
    that.globalData.hasLogin = false;
  },

  globalData:{
    userInfo:null,
    corpus: corpusList,
    custId: '',
    latitude: 0.0,
    longitude: 0.0,
    speed: 0,
  }
})

app.json

配置小程序窗體相關屬性:標題名稱,背景色,網絡超時等。
配置首頁面爲pages/index/index。

{
  "pages": [
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window": {
    "backgroundTextStyle": "black",
    "navigationBarBackgroundColor": "#F8F8F8",
    "navigationBarTitleText": "遙知之 -- olami語義支持",
    "navigationBarTextStyle": "black",
    "backgroundColor": "#F8F8F8"
  },
  "networkTimeout": {
    "request": 10000,
    "connectSocket": 10000,
    "uploadFile": 10000,
    "downloadFile": 10000
  }
}

app.wxss

配置了「遙知之」小程序container全局樣式

/**app.wxss**/
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}

配置文件:config.js

保存一些配置信息,包括NLI的key和secret,還有小程序中預置的語料集合。

module.exports = {

  //NLI appkey
  appkey: `b4118cd178064b45b7c8f1242bcde31f`,

  //NLI appsecret
  appsecret: `7908028332a64e47b8336d71ad3ce9ab`,
  
  corpus: [
    // '閒聊',
    // '天氣',
    // '詩詞',
    // '單位換算',
    // '新聞',
    // '算24點',
    // '菜譜',
    // '匯率',
    // '郵編',
    // '區號',
    // '股票',
    // '日曆',
    // '節目預告',
    // '笑話',
    // '故事',
    // '購物',
    // '數學運算',
    // '百科',
    // '搜索',

    '你今年多大啦',
    '上海今每天氣如何',
    '北京的呢',
    '李白寫過什麼詩',
    '我要聽李白的靜夜思',
    '背一首將進酒',
    '一千米等於多少英尺',
    '我要看體育新聞',
    '4567算24點',
    '紅燒肉的作法',
    '1美圓能換算多少人民幣',
    '查一下南昌的郵編',
    '鄭州的區號是多少',
    '中國石油的股價',
    '今年中秋節是哪一天',
    '明晚湖南衛視放什麼節目',
    '來個笑話',
    '講個故事聽聽',
    '我要買電腦',
    '1加到100等於多少',
    '黃山有多高',
    '百度搜一下薛之謙的照片',
  ]
};

####utils目錄文件:GUID.js, MD5.js, NLI.js, util.js

獲取隨機GUID:GUID.js

//表示全局惟一標識符 (GUID)。
function Guid(g) {
  var arr = new Array(); //存放32位數值的數組

  if (typeof (g) == "string") { //若是構造函數的參數爲字符串
    InitByString(arr, g);
  } else {
    InitByOther(arr);
  }

  //返回一個值,該值指示 Guid 的兩個實例是否表示同一個值。
  this.Equals = function (o) {
    if (o && o.IsGuid) {
      return this.ToString() == o.ToString();
    } else {
      return false;
    }
  }

  //Guid對象的標記
  this.IsGuid = function () { }
  //返回 Guid 類的此實例值的 String 表示形式。
  this.ToString = function (format) {
    if (typeof (format) == "string") {
      if (format == "N" || format == "D" || format == "B" || format == "P") {
        return ToStringWithFormat(arr, format);
      } else {
        return ToStringWithFormat(arr, "D");
      }
    } else {
      return ToStringWithFormat(arr, "D");
    }
  }

  //由字符串加載
  function InitByString(arr, g) {
    g = g.replace(/\{|\(|\)|\}|-/g, "");
    g = g.toLowerCase();
    if (g.length != 32 || g.search(/[^0-9,a-f]/i) != -1) {
      InitByOther(arr);
    } else {
      for (var i = 0; i < g.length; i++) {
        arr.push(g[i]);
      }
    }
  }

  //由其餘類型加載
  function InitByOther(arr) {
    var i = 32;
    while (i--) {
      arr.push("0");
    }
  }

  /*
  根據所提供的格式說明符,返回此 Guid 實例值的 String 表示形式。
  N  32 位: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  D  由連字符分隔的 32 位數字 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  B  括在大括號中、由連字符分隔的 32 位數字:{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
  P  括在圓括號中、由連字符分隔的 32 位數字:(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
  */

  function ToStringWithFormat(arr, format) {
    switch (format) {
      case "N":
        return arr.toString().replace(/,/g, "");
      case "D":
        var str = arr.slice(0, 8) + "-" + arr.slice(8, 12) + "-" + arr.slice(12, 16) + "-" + arr.slice(16, 20) + "-" + arr.slice(20, 32);
        str = str.replace(/,/g, "");
        return str;
      case "B":
        var str = ToStringWithFormat(arr, "D");
        str = "{" + str + "}";
        return str;
      case "P":
        var str = ToStringWithFormat(arr, "D");
        str = "(" + str + ")";
        return str;
      default:
        return new Guid();
    }
  }
}

//Guid 類的默認實例,其值保證均爲零。
Guid.Empty = new Guid();

//初始化 Guid 類的一個新實例。
Guid.NewGuid = function () {
  var g = "";
  var i = 32;

  while (i--) {
    g += Math.floor(Math.random() * 16.0).toString(16);
  }
  return new Guid(g).ToString();
}

module.exports = {
  NewGuid: Guid.NewGuid
}

計算MD5值:MD5.js

//md5加密算法
function md5(string) {
  var x = Array();
  var k, AA, BB, CC, DD, a, b, c, d;
  var S11 = 7, S12 = 12, S13 = 17, S14 = 22;
  var S21 = 5, S22 = 9, S23 = 14, S24 = 20;
  var S31 = 4, S32 = 11, S33 = 16, S34 = 23;
  var S41 = 6, S42 = 10, S43 = 15, S44 = 21;
  string = Utf8Encode(string);
  x = ConvertToWordArray(string);
  a = 0x67452301;
  b = 0xEFCDAB89;
  c = 0x98BADCFE;
  d = 0x10325476;
  for (k = 0; k < x.length; k += 16) {
    AA = a;
    BB = b;
    CC = c;
    DD = d;
    a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
    d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
    c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
    b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
    a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
    d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
    c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
    b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
    a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
    d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
    c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
    b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
    a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
    d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
    c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
    b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
    a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
    d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
    c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
    b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
    a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
    d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
    c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
    b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
    a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
    d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
    c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
    b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
    a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
    d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
    c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
    b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
    a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
    d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
    c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
    b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
    a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
    d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
    c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
    b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
    a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
    d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
    c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
    b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
    a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
    d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
    c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
    b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
    a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
    d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
    c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
    b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
    a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
    d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
    c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
    b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
    a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
    d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
    c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
    b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
    a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
    d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
    c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
    b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
    a = AddUnsigned(a, AA);
    b = AddUnsigned(b, BB);
    c = AddUnsigned(c, CC);
    d = AddUnsigned(d, DD);
  }
  var temp = WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d);
  return temp.toLowerCase();
}
function RotateLeft(lValue, iShiftBits) {
  return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}
function AddUnsigned(lX, lY) {
  var lX4, lY4, lX8, lY8, lResult;
  lX8 = (lX & 0x80000000);
  lY8 = (lY & 0x80000000);
  lX4 = (lX & 0x40000000);
  lY4 = (lY & 0x40000000);
  lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
  if (lX4 & lY4) {
    return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
  }
  if (lX4 | lY4) {
    if (lResult & 0x40000000) {
      return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
    } else {
      return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
    }
  } else {
    return (lResult ^ lX8 ^ lY8);
  }
}
function F(x, y, z) {
  return (x & y) | ((~x) & z);
}
function G(x, y, z) {
  return (x & z) | (y & (~z));
}
function H(x, y, z) {
  return (x ^ y ^ z);
}
function I(x, y, z) {
  return (y ^ (x | (~z)));
}
function FF(a, b, c, d, x, s, ac) {
  a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
  return AddUnsigned(RotateLeft(a, s), b);
}
function GG(a, b, c, d, x, s, ac) {
  a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
  return AddUnsigned(RotateLeft(a, s), b);
}
function HH(a, b, c, d, x, s, ac) {
  a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
  return AddUnsigned(RotateLeft(a, s), b);
}
function II(a, b, c, d, x, s, ac) {
  a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
  return AddUnsigned(RotateLeft(a, s), b);
}
function ConvertToWordArray(string) {
  var lWordCount;
  var lMessageLength = string.length;
  var lNumberOfWords_temp1 = lMessageLength + 8;
  var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
  var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
  var lWordArray = Array(lNumberOfWords - 1);
  var lBytePosition = 0;
  var lByteCount = 0;
  while (lByteCount < lMessageLength) {
    lWordCount = (lByteCount - (lByteCount % 4)) / 4;
    lBytePosition = (lByteCount % 4) * 8;
    lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
    lByteCount++;
  }
  lWordCount = (lByteCount - (lByteCount % 4)) / 4;
  lBytePosition = (lByteCount % 4) * 8;
  lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
  lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
  lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
  return lWordArray;
}
function WordToHex(lValue) {
  var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount;
  for (lCount = 0; lCount <= 3; lCount++) {
    lByte = (lValue >>> (lCount * 8)) & 255;
    WordToHexValue_temp = "0" + lByte.toString(16);
    WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
  }
  return WordToHexValue;
}
function Utf8Encode(string) {
  var utftext = "";
  for (var n = 0; n < string.length; n++) {
    var c = string.charCodeAt(n);
    if (c < 128) {
      utftext += String.fromCharCode(c);
    } else if ((c > 127) && (c < 2048)) {
      utftext += String.fromCharCode((c >> 6) | 192);
      utftext += String.fromCharCode((c & 63) | 128);
    } else {
      utftext += String.fromCharCode((c >> 12) | 224);
      utftext += String.fromCharCode(((c >> 6) & 63) | 128);
      utftext += String.fromCharCode((c & 63) | 128);
    }
  }
 return utftext;
}
module.exports = {
  md5: md5
}

olami免費開放語義平臺NLI接口封裝:NLI.js

var app = getApp()

const appkey = require('../config').appkey
const appsecret = require('../config').appsecret

var MD5 = require('./MD5.js');
var UTIL = require('./util.js');

const requestUrl = "https://cn.olami.ai/cloudservice/api";
const api = "nli";


function getLocationJson() {
  var lat = app.globalData.latitude;
  var lng = app.globalData.longitude;
  if (lat < 180 && lng < 180) {
    lat *= 1000000;
    lng *= 1000000;
  }

  return { "position_type": 0, "longitude": lng, "latitude": lat };
}

//NLI接口訪問
//參數:corpus爲句子;cb爲回調函數(帶兩個參數,第一個參數表示調用NLI是否成功,第二個參數是NLI的返回數據)
function process(corpus, cb) {
  var timestamp = new Date().getTime();
  var originalSign = appsecret + "api=" + api + "appkey=" + appkey + "timestamp=" + timestamp + appsecret;
  var sign = MD5.md5(originalSign);

  var locationJson = getLocationJson();
  var rqdataJson = { "data": { "input_type": 1, "text": corpus, "location": locationJson }, "data_type": "stt" };
  var rqdata = JSON.stringify(rqdataJson);

  UTIL.log('input:' + rqdata + '\r\n, custId:' + app.globalData.custId + ', originalSign:' + originalSign);

  wx.request({
    url: requestUrl,
    data: {
      appkey: appkey,
      api: api,
      timestamp: timestamp,
      sign: sign,
      rq: rqdata,
      cusid: app.globalData.custId,
    },
    header: {
      'content-type': 'application/x-www-form-urlencoded'
    },
    method: 'POST',
    success: function (result) {
      var data = result.data.data;
      var jsonData = JSON.stringify(data);
      typeof cb == "function" && cb(true, jsonData)
    },
    fail: function ({errMsg}) {
      typeof cb == "function" && cb(false, jsonData)
    }
  })
}

module.exports = {
  process: process,
}

其它utils:util.js

//獲取應用實例
var app = getApp()

var Guid = require('./GUID.js');

var uuidSaved = '';

//將date格式的數據轉成  hh:mm:ss 字符串格式
function formatTime(date) {
  var year = date.getFullYear()
  var month = date.getMonth() + 1
  var day = date.getDate()

  var hour = date.getHours()
  var minute = date.getMinutes()
  var second = date.getSeconds()


  //return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
  return [hour, minute, second].map(formatNumber).join(':')
}

function formatNumber(n) {
  n = n.toString()
  return n[1] ? n : '0' + n
}

//log接口封裝
function log(obj) {
  console.log('<' + formatTime(new Date(Date.now())) + '>' + ' ' + obj)

  //往用戶緩存去寫
  // var logs = wx.getStorageSync('logs') || []
  // logs.unshift('[' + formatTime(new Date(Date.now())) + ']' + ' ' + obj)
  // wx.setStorageSync('logs', logs)
}

//獲取用戶惟一標識,NLI接口中要上傳用戶惟一標識,這裏獲取:第一次登陸時生成的uuid+微信號所在地+暱稱
function getUserUnique(userInfo) {
  //從緩存中讀取uuid
  if (typeof uuidSaved === 'undefined' || uuidSaved === '') {
    var tmpUuid = wx.getStorageSync('uuid');
    if (typeof tmpUuid === 'undefined' || tmpUuid === '') {
      uuidSaved = Guid.NewGuid();
      wx.setStorageSync('uuid', uuidSaved);
    } else {
      uuidSaved = tmpUuid;
    }
  }

  var unique = uuidSaved;
  if (userInfo != null) {
    unique += '_' + userInfo.province + '_' + userInfo.nickName;
  }
  log('getUserUnique() return:' + unique)
  return unique;
}

module.exports = {
  formatTime: formatTime,
  log: log,
  getUserUnique: getUserUnique
}

####page/logs頁面:logs.js, logs.json, logs.wxml, logs.wxss

logs.js

var util = require('../../utils/util.js')
Page({
  data: {
    logs: []
  },
  onLoad: function () {
    this.setData({
      logs: (wx.getStorageSync('logs') || []).map(function (log) {
        var DATE = new Date(log);
        if (typeof DATE === 'date') {
          //當log是一個毫秒數,延用官方的案例,轉成對應時間存LOG中(util.formatTime被我改爲只輸出時分秒)
          return util.formatTime(new Date(log))
        }
        
        //非毫秒數時,記錄LOG原始內容,不做轉換
        return log;
      })
    })
  }
})

logs.json

{
    "navigationBarTitleText": "調試LOG頁"
}

logs.wxml

<!--logs.wxml-->
<view class="container log-list">
  <block wx:for="{{logs}}" wx:for-item="log" wx:key="*this">
    <text class="log-item">{{index + 1}}. {{log}}</text>
  </block>
</view>

logs.wxss

.log-list {
  display: flex;
  flex-direction: column;
  padding: 40rpx;
}
.log-item {
  margin: 10rpx;
}

####page/index頁面:index.js, index.json, index.wxml, index.wxss

index.js

// index.js

//獲取應用實例
var app = getApp()

var UTIL = require('../../utils/util.js');
var GUID = require('../../utils/GUID.js');
var NLI = require('../../utils/NLI.js');

var cursor = 0;
var lastYYYTime = new Date().getTime();

var domainCorpus = '';
var lastCorpus = '';


function log(obj) {
  UTIL.log(obj)
}

Page({

  isShow: false,

  /**
   * 頁面的初始數據
   */
  data: {
    //調試後門
    isDbg: false,
    //輸入框文本
    inputTxt: '',
    //輸出框文本
    outputTxt: ''
  },

  /**
   * 生命週期函數--監聽頁面加載
   */
  onLoad: function (options) {
    log('index.onLoad')
    //調用應用實例的方法獲取全局數據
    app.getUserInfo(function (userInfo2) {
      log('user unique 1: ' + UTIL.getUserUnique(userInfo2))
    })
    log('user unique 2: ' + UTIL.getUserUnique(app.globalData.userInfo))
  },

  /**
   * 生命週期函數--監聽頁面初次渲染完成
   */
  onReady: function () {
    log('index.onReady')
  },

  /**
   * 生命週期函數--監聽頁面顯示
   */
  onShow: function () {
    log('index.onShow')

    var that = this;
    that.isShow = true;

    //調用重力加速度傳感API模擬搖一搖接口
    wx.onAccelerometerChange(function (e) {
      
      if (!that.isShow) {
        //當前界面不顯示時不該該調用
        return
      }

      if (isBong(e.x) && isBong(e.y)) {
        if (new Date().getTime() - lastYYYTime <= 2000) {
          //1秒限制搖一次,避免搖一下觸發屢次請求
          log('搖的太頻繁啦,請等2秒再搖!' + e.x + ', '+ e.y + ', ' + e.z);
          return;
        }

        //更新最後一次成功搖的時間戳
        lastYYYTime = new Date().getTime()

        //從語料庫中挑選語料運行語義理解,顯示結果
        var selectedCorpus = selectCorpusRunNli(that);

        //彈Toast窗提示當前刷到哪句語料
        wx.showToast({
          title: selectedCorpus,
          icon: 'success',
          duration: 1500
        });
      }
    })
  },

  /**
   * 生命週期函數--監聽頁面隱藏
   */
  onHide: function () {
    log('index.onHide')
    //頁面隱藏後,關掉搖一搖檢測
    wx.stopAccelerometer();
  },

  /**
   * 生命週期函數--監聽頁面卸載
   */
  onUnload: function () {
    log('index.onUnload')
  },

  /**
   * 頁面相關事件處理函數--監聽用戶下拉動做
   */
  onPullDownRefresh: function () {
    log('index.onPullDownRefresh')
    
    wx.stopPullDownRefresh();

    //頁面下拉,觸發輪換語料理解
    selectCorpusRunNli(this)
  },

  /**
   * 頁面上拉觸底事件的處理函數
   */
  onReachBottom: function () {
    log('index.onReachBottom')
  },

  /**
   * 用戶點擊右上角分享
   */
  onShareAppMessage: function () {
    log('index.onShareAppMessage')

    wx.showToast({
      title: '謝謝分享!',
      icon: 'success',
      duration: 1500
    });
  },

  switchChange: function (e) {
    log('index.switchChange by:' + e.detail.value)
  },

  //輸入文本框聚焦觸發清除輸入框中的內容
  bindFocusClear: function(e) {
    log('index.bindFocusClear')
    if (e.detail.value === '') {
      return;
    }

    log('clear: ' + e.detail.value)
    var self = this;
    self.setData({
      inputTxt: ''
    });
  },

  //點擊完成按鈕時觸發
  bindConfirmControl: function(e) {
    var inputTxt = e.detail.value;
    log('index.bindConfirmControl input string: ' + inputTxt);

    //手動打字輸入語料運行語義理解
    singleCorpusRunNli(inputTxt, this)
  },

  //測試按鈕觸發事件
  bindTest: function () {
    log('index.bindTest')

    //測試按鈕替代搖一搖,從語料庫中選語料測試
    selectCorpusRunNli(this)
  },

  //快捷按鈕觸發語料運行語義理解
  bindCorpusGenerator: function (e) {
    log('index.bindCorpusGenerator')
    //獲取"data-cp"中的語料
    var corpusList = e.target.dataset.cp.split('|');

    //默認頭一次(或新切換時)點擊,選用第一句語料
    var corpus = corpusList[0];
    if (domainCorpus !== corpusList[0]) {
      domainCorpus = corpusList[0];
    } else {
      //不然在語料表中隨機挑選一個
      corpus = getRandomItem(corpusList);

      //與上一句重複就換一句
      if (lastCorpus === corpus) {
        corpus = getRandomItem(corpusList);
        if (lastCorpus === corpus) {
          corpus = getRandomItem(corpusList);
          if (lastCorpus === corpus) {
            corpus = getRandomItem(corpusList);
          }
        }
      }
    }

    //記錄最近一次使用的語料
    lastCorpus = corpus;

    singleCorpusRunNli(corpus, this);
  }
})

//從語料數組中隨機挑選一條語料
function getRandomItem(corpusList) {
  var ret = corpusList[0];
  ret = corpusList[Math.floor(Math.random() * corpusList.length)];
  return ret;
}

//解析NLI接口返回的數據,從語義結果中篩選出適合顯示的文本內容
function getSentenceFromNliResult(nliResult) {
  var sentence;
  try {
    var resultJson = JSON.parse(nliResult);
    var nliArray = resultJson.nli;
    for (var i = 0; i < nliArray.length; i++) {
      var singleResult = nliArray[i];
      sentence = singleResult.desc_obj.result;

      var content = '';
      var appName = singleResult.type;
      //0: normal, 1: selection, 9 : openweb
      var tagType = 0;
      if (appName === 'selection') {
        appName = singleResult.desc_obj.type;
        tagType = 1;
      } else if (appName === 'openweb') {
        //appName = singleResult.desc_obj.type;
        tagType = 9;
      }
      switch (appName) {
        case 'joke' :
        case 'story' :
          sentence = singleResult.data_obj[0].content;
          break;
        case 'poem' :
          if (tagType === 1) {
            for (var k = 0; k < singleResult.data_obj.length; k++) {
              content += '第' + (k + 1) + '個: ' + singleResult.data_obj[k].author + '   ' + singleResult.data_obj[k].poem_name + '\n';
            }
          }
          break;
        case 'cooking':
          if (tagType === 1) {
            for (var k = 0; k < singleResult.data_obj.length; k++) {
              content += '第' + (k + 1) + '個: ' + singleResult.data_obj[k].name + '\n';
            }
          } else if (tagType === 0) {
            content = singleResult.data_obj[0].content;
          }
          break;
        case 'baike' :
          var filedNames = singleResult.data_obj[0].field_name;
          var filedValues = singleResult.data_obj[0].field_value;
          for (var k = 0; k < filedNames.length; k++) {
            content += filedNames[k] + ' : ' + filedValues[k] + '\n';
          }
          break;
        case 'news' :
          if (tagType === 1) {
            for (var k = 0; k < singleResult.data_obj.length; k++) {
              content += singleResult.data_obj[k].title + '\n';
              content += singleResult.data_obj[k].detail + '…………\n';
              content += '【欲看此條新聞詳情請說第' + (k+1) + '個,或拷此連接到瀏覽器中打開:' + singleResult.data_obj[k].ref_url + '】\n\n';
            }
          } else if (tagType === 0) {
            content = singleResult.data_obj[0].detail;
          }
          break;
        case 'stock' :
          var nowHour = new Date().getHours();
          var isKaiPan = (nowHour >= 9) && (nowHour <= 15);
          for (var k = 0; k < singleResult.data_obj.length; k++) {
            content += singleResult.data_obj[k].name + ' : ' + singleResult.data_obj[k].id + '\n';
            content += '開盤:' + singleResult.data_obj[k].price_start + '\n';
            if (isKaiPan) {
              content += '現價(' + getHHMMSS(singleResult.data_obj[k].time) + '):' + singleResult.data_obj[k].cur_price + '\n';
            } else {
              content += '收盤:' + singleResult.data_obj[k].price_end + '\n';
            }
            content += '成交量:' + singleResult.data_obj[k].volume + '\n';
            content += '成交額:' + singleResult.data_obj[k].amount + '\n';
            content += '最高價:' + singleResult.data_obj[k].price_high + '\n\n';
          }
          break;
        case 'tvprogram':
          for (var k = 0; k < singleResult.data_obj.length; k++) {
            content += singleResult.data_obj[k].time + '   ' + singleResult.data_obj[k].name + '\n';
          }
          break;
        case 'openweb':
          content += '【拷此連接到瀏覽器中打開:' + singleResult.data_obj[0].url + '】\n';
          break;
        defalt :
          break;
      }
      if (content !== '') {
        sentence += '\n\n' + content;
      }
      log('NLI返回sentence:' + sentence)
    }
  } catch (e) {
    log('錯誤' + e.message + '發生在' + e.lineNumber + '行');
    sentence = '沒明白你說的,換個話題?'
  }
  
  if (typeof sentence === 'undefined' || sentence === '') {
    sentence = '沒明白你說的什麼意思';
  }

  return sentence;
}

//由 毫秒數字符串 獲取  HH:mm:ss 格式時間
function getHHMMSS(dateStr) {
  var dateVal = new Date(parseInt(dateStr));
  var hh = dateVal.getHours()
  var mm = dateVal.getMinutes()
  var ss = dateVal.getSeconds()

  return ((hh >= 10) ? hh : '0' + hh) + ':' + ((mm >= 10) ? mm : '0' + mm) + ':' + ((ss >= 10) ? ss : '0' + ss)
}

//處理NLI語義結果
function NliProcess(corpus, self) {
  var nliResult;
  NLI.process(corpus, function (isSuccess, result) {
    if (isSuccess) {
    } else {
    }
    nliResult = result;
    log("NLI RESULT IS:" + nliResult);
    typeof self !== 'undefined' && self.setData ({
      outputTxt: getSentenceFromNliResult(nliResult)
    })
  })
}

//如輸入是dbg且確認,則切換到debug模式,多顯示兩個按鈕
function singleCorpusRunNli(inputTxt, self) {
  if (inputTxt === 'dbg' || inputTxt === 'DBG' || inputTxt === 'Dbg') {
    self.setData({
      //打開調試按鈕
      isDbg: true,
      inputTxt: ''
    });
    // 打開調試
    wx.setEnableDebug({
      enableDebug: true
    })
    return;
  } else if(inputTxt === 'gbd' || inputTxt === 'GBD' || inputTxt === 'Gbd') {
    self.setData({
      //關閉調試按鈕
      isDbg: false,
      inputTxt: ''
    });
    // 關閉調試
    wx.setEnableDebug({
      enableDebug: false,
    })
    return;
  }

  //正經常使用戶輸入文本
  if (inputTxt !== '') {
    self.setData({
      inputTxt: inputTxt
    });
    NliProcess(inputTxt, self);
  }
}

//選擇預置語料運行語義理解
function selectCorpusRunNli(self) {
  var corpus = app.globalData.corpus;

  //順序選擇一句語料
  var corpusSelected = corpus[cursor]

  self.setData({
    //更新頁面input框顯示
    inputTxt: corpusSelected
  })

  log('selected corpus:' + corpusSelected)
  //調用語料處理,刷新輸出框結果
  NliProcess(corpusSelected, self);

  //光標後移,備下次挑選下一條語料
  if (cursor++ >= corpus.length - 1) {
    cursor = 0;
  }

  return corpusSelected;
}

//檢測加速度傳感器靈敏度
function isBong(val) {
  //目前靈敏度設置爲0.8,且搖一搖只監測了x和y軸變更,具體見調用此函數的地方
  if (val >= 0.8 || val <= -0.8) {
    return true;
  }

  return false;
}

index.json

首頁延用app.json中的配置,不須要單獨的配置,這裏主要配置一個容許下拉。

{
  "window": {
    "enablePullDownRefresh": true
  }
}

index.wxml

這個是首頁的h5佈局。

<view class="container">
  <view class="page-section">
    <view class="text-box" scroll-y="true">      
      <text style="max-width:200px;overflow-y:auto;height:200px;" selectable="true">{{outputTxt}}</text>
    </view>
  </view>

  <view class="page-section page-gap page-center">
    <text selectable="true" class="text-head">語義理解基於「歐拉密」:cn.olami.ai</text>
    <text selectable="true" class="text-description little-gap-top">支持「搖一搖」、點按鈕、手動輸入、向下拉</text>
  </view>

  <view class="page-section">
    <view class="weui-cells weui-cells_after-title">
        <input class="weui-input" placeholder-style="color:#6aa84f"  maxlength="50" 
          placeholder="點此手動輸入" value="{{inputTxt}}" confirm-type ="send" bindconfirm="bindConfirmControl" bindfocus="bindFocusClear"/>
    </view>
  </view>

  <view class="button-selection page-gap">
    <view class="{{isDbg?'button-show':'common-disappear'}}">
      <button type="default" size="mini" bindtap="bindTest">調試</button>
    </view> 

    <view class="button-selection2">
      <button type="default" size="mini" data-cp="今每天氣|北京今天有雨嗎|西安今天冷不冷|今天適合洗車嗎|那後天上海怎麼樣|北京明天有霧霾嗎|南京今天空氣污染指數有多高" bindtap="bindCorpusGenerator">天氣</button>
      <button type="default" class="little-gap-left" size="mini" data-cp="今天的體育新聞|看國內新聞|今天有什麼重大新聞|今天有沒有什麼大事|有今天的財經新聞嗎|釣魚島事件的最新進展是什麼|來個軍事新聞|接下來還有嗎" bindtap="bindCorpusGenerator">新聞</button>
      <button type="default" class="little-gap-left" size="mini" data-cp="今年何時中秋節|目前時間|明天星期幾|農曆八月15是哪天|離國慶節還有幾天|還有多久到六點|今年是閏年嗎?" bindtap="bindCorpusGenerator">日曆</button>
      <button type="default" class="little-gap-left" size="mini" data-cp="100人民幣能換多少美金|美國用什麼貨幣|100美金能換多少日元|英鎊如今多少錢|美圓如今什麼價格|幫我查查美圓匯率" bindtap="bindCorpusGenerator">匯率</button>
      <button type="default" class="little-gap-left" size="mini" data-cp="來個段子|說個笑話聽聽|講個黑色幽默|講個笑話逗逗我|還要一個笑話|換一個|隨便來幾個笑話聽聽" bindtap="bindCorpusGenerator">笑話</button>
    </view>

    <view class="button-selection2">
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="我要看鬼故事|給我講個好聽的故事|下一個|換一個" bindtap="bindCorpusGenerator">故事</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="好無聊啊|你是機器人嗎|很高興見到你|你能嫁給我嗎|你的心上人是誰|你今天吃飯了嗎|你困了嗎|喂,你好嗎|你喜歡吃蔬菜嗎|你餓嗎|你今天過生日嗎|你何時出生的|你要喝水嗎|能和我聊會天嗎|你怎麼那麼笨啊|我在罵你|你聽不懂嗎|我要生氣啦 |你想要氣死我啊|怎麼什麼都不會|你真讓我失望|你寂寞嗎|你以爲本身聰明嗎|我好傷心啊|你有外號嗎|你須要休息嗎|你要不要休息會啊|你感受累嗎|你臉皮真薄" bindtap="bindCorpusGenerator">閒聊</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="介紹一下劉德華|李雙江的老婆是誰|張學友簡介|黃山有多高|湖南省有多大|太湖有多大|印度有多少人口" bindtap="bindCorpusGenerator">百科</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="背一首李白的望廬山瀑布|春眠不覺曉下一句是什麼|惟見長江天際流上一句是什麼|將進酒是誰寫的|李白有什麼詩|李白還寫過什麼詩|背首李白的詩" bindtap="bindCorpusGenerator">詩詞</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="6789算24點怎麼算|用三三八八算出24|1357怎麼等於24|1689怎麼獲得24|怎麼用3567獲得24|1357幫我刷24點|算24點數字爲2346" bindtap="bindCorpusGenerator">24點</button>
    </view>

    <view class="button-selection2">
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="江西婺源的郵編是多少|哪裏的郵政編碼是201203|什麼地方的郵政編碼是201203|我要你幫我查郵政編碼|我要查郵政編碼|告訴我北京的郵政編碼|給我查個郵政編碼|我要查郵編|幫我查郵政編碼|找一下上海的郵政編碼" bindtap="bindCorpusGenerator">郵編</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="幫忙查一下揚州的區號|哪裏的區號是021|區號021是哪裏|我要查區號|幫我查區號|找一下上海的區號" bindtap="bindCorpusGenerator">區號</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="鱸魚能夠怎麼作|排骨怎麼烹飪好吃|怎樣燉排骨|排骨能夠作成什麼菜|常見的魯菜有哪些|川菜有哪些菜式比較有名|有哪些川菜比較有名|哪些菜屬於魯菜|川菜怎麼作|你會作川菜嗎|推薦幾種清真菜|介紹幾個湘菜給我" bindtap="bindCorpusGenerator">菜譜</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="今天的大盤指數|中國石化的行情怎麼樣|今天的行情|中國石化的價格是多少|中國石化的成交量怎麼樣|上證指數如今多少點|查一下招商銀行今日的開盤價|今天上證指數幾點" bindtap="bindCorpusGenerator">股票</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="我想買個電風扇|我要買兩袋大米|我要網購一盒牛奶|我要在京東買一臺電腦|我要買一部HTC的手機|我想買個飛利浦的剃鬚刀" bindtap="bindCorpusGenerator">購物</button>
    </view>

    <view class="button-selection2">
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="今晚番茄臺放什麼節目|中央一臺今晚有什麼節目|非誠勿擾今晚何時播出|7點到9點哪一個臺有電影|晚上11點之後哪一個臺放蜘蛛俠|我要看湖南衛視" bindtap="bindCorpusGenerator">節目預告</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="3的平方加8再乘以6再除以2等於幾|5的平方根|6的七次方|99的三倍|19的三分之一是多少|77的一半加13等於多少|67個9加起來是多少|5個15乘在一塊兒等於幾|4乘以6加5乘以8加12乘以7|四分之三|7的9倍|三的一半|17個9|12的對數|23的天然對數|5加六加七再乘10|三隻蘋果加五隻蘋果等於幾隻蘋果|19加7" bindtap="bindCorpusGenerator">計算</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="搜索薛之謙|幫我找一些九寨溝的圖片|我想看看范冰冰的照片|我要查一下白羽雞|幫我搜下科魯茲的性能" bindtap="bindCorpusGenerator">搜索</button>
      <button type="default" class="little-gap-left little-gap-top" size="mini" data-cp="1光年等於多少千米|1標準大氣壓等於多少帕|1標準大氣壓等於多少毫米汞柱|1兆瓦等於多少毫瓦|1籤卡等於多少焦|1納米等於多少毫米|1埃等於多少納米|1釐米等於多少英寸|1公斤等於多少克|1擔等於多少斤|1兩等於多少錢|1毫克等於多少微克|1畝等於多少公頃" bindtap="bindCorpusGenerator">單位換算</button>
    </view>
  </view>
</view>

<view class="little-gap-top button-selection2 button-show bottom-button">
  <button type="primary" size="mini" open-type="contact">聯繫做者</button>
  <button type="primary" size="mini" open-type="share">幫忙分享</button>
</view>

index.wxss

首頁用到的一些樣式,以及配置首頁背景圖片。

page{
  background-color:beige;
  background-image: url(http://img.blog.csdn.net/20170720105808995?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFwcHljeHo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast);
  background-size: cover;
}

.page-section{
  display: flex;
  flex-direction: column;
  margin-bottom: 10rpx;
}

.page-center {
  align-items: center;
}

.page-gap{
  margin-top: 5rpx;
}

.button-selection {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.button-selection2 {
  justify-content: space-between;
  align-content: space-between;
  flex-shrink:1;
}

.little-gap-top {
  margin-top: 15rpx; 
}

.little-gap-left {
  margin-left: 5rpx; 
}

.text-description{
  color: #ff0000;
  font-size: 28rpx;
}

.text-head{
  color: #00BFFF;
  font-size: 36rpx;
}

.common-disappear {
  display: none
}

.button-show {
  display: flex;
  align-self: center;
  justify-content: center;
}

.text-box{
  margin-bottom: 0rpx;
  margin-left: 50rpx;
  margin-right: 50rpx;
  padding: 40rpx 0;
  display: flex;
  min-height: 300rpx;
  max-width: 600rpx;
  width:600rpx;
  background-color: #ffffff;
  justify-content: center;
  align-items: center;
  text-align: left;
  font-size: 30rpx;
  color: #353535;
  line-height: 2em;
  word-wrap: break-word;
  border: 1px solid cornflowerblue;
}

.weui-cells {
  position: relative;
  margin-top: 1.17647059em;
  background-color: #DCDCDC;
  line-height: 1.41176471;
  font-size: 14px;
}

.weui-cells_after-title {
  margin-top: 0;
}

.weui-input {
  height: 2.58823529em;
  width: 17em;
  min-height: 2.58823529em;
  line-height: 2.58823529em;
}

.bottom-button {
  justify-content: space-around;
  flex-shrink:0;
}

olami平臺資源配置

,在配置上稍微有些不一樣,下面我會重點說明一下。

  1. 用上次註冊的帳號,在olami.ai上登陸。
  2. 選擇「API&解決方案」中的「NLI 天然語言語義互動管理系統」,而後點「開始免費試用」進入應用配置界面。
  3. 生成一個新的應用,好比取名「遙知之NLI能力」
  4. 「配置模塊」進去,會有兩個標籤頁:

    a. 「NLI模塊」:我以前作過一個匯率換算的小DEMO 用olami開放語義平臺作匯率換算應用 用的是使用「NLI模塊」的功能,其實就是語義接口。

    b. 「對話系統模塊」:此次作「遙知之」微信小程序,用的是他們平臺的「處理結果」的能力,就是對應「對話系統模塊」這裏。

    注:有些朋友估計會有點弄不清楚,這裏我舉個例子,好比「今天上海的天氣如何」這一句話:應用配置在「NLI模塊」裏勾天氣相對應的模塊,接口會返回這一句話的意思「今天,上海,查天氣」; 應用配置在「對話系統模塊」裏勾「weather」,接口返回的就是今天上海天氣的查詢結果。

    好了,弄明白上述兩塊,接下來就知道,此次我作的「遙知之」全是要結果輸出的,因此把「對話系統模塊」中全部的功能模塊全勾選上了,後面有配置優先級的,優先級是用來處理語義衝突時仲裁哪一個模塊優先的,我都沒有動,直接用默認值,根據提示:數值越小優先級越高,1000是優先級最高。

  5. 「遙知之NLI能力」應用中,點擊「查看Key」能夠獲取調用OLAMI開放語義平臺的受權密鑰,包括「App Key」「App Secret」。 這兩個碼,對應小程序源碼中的「config.js」中的「appkey」和「appsecret」。
  6. 「遙知之NLI能力」應用中有個「測試」,須要的話,可點進去輸入一些句子測輸出結果(注:這裏是NLI接口輸出的一部分)。

>>>>>>>>>>>>>>>>>>>>>>>> 歡迎轉載 <<<<<<<<<<<<<<<<<<<<<<<<

本文原地址:http://blog.csdn.net/happycxz/article/details/75432928

「遙知之」微信小程序完整源碼下載:

碼雲:http://git.oschina.net/happycxz/nlp_olami_yaozhizhi_wechat_littleapp_demo

CSDN: http://download.csdn.net/download/happycxz/9919690

github: https://github.com/happycxz/nlp_olami_yaozhizhi_wechat_littleapp_demo

寫在最後

此次作微信小程序,是邊摸索邊作,JS和CSS基本是邊改邊學,好在微信小程序框架清晰,接口文檔全,另外olami平臺以前作 用olami開放語義平臺作匯率換算應用 時接觸過,因此整體來說還算順利。


另外這裏特地推薦一下跟天然語言理解相關的比較不錯的文章:

根據OLAMI平臺開發的日曆Demo

用olami開放語義平臺作匯率換算應用

天然語言處理-實際開發:用語義開放平臺olami寫一個翻譯的應用

自定義java.awt.Canvas—趣味聊天

微信小程序+OLAMI天然語言API接口製做智能查詢工具--快遞、聊天、日曆等

熱門天然語言理解和語音API開發平臺對比

使用OLAMI SDK和訊飛語音合成製做一個語音回覆的短信小助手

微信小程序——智能小祕「遙知之」源碼分享(語義理解基於olami)

相關文章
相關標籤/搜索