用Flutter实现小Q聊天机器人(一)用Flutter实现小Q聊天机器人(二)用Flutter实现小Q聊天机器人(三)用Flutter实现小Q聊天机器人(四)用Flutter实现小Q聊天机器人(五)

GitHub:https://github.com/baiyuliang/Qrobot_Flutter

前几篇我们基本实现了一个简单的聊天界面,也基本掌握了如何通过Flutter去完成这样一个布局及功能的实现,但离我们标题所需要实现的还差那么一步,既然是聊天机器人,那就不能只做本地的聊天了,网络请求+机器人API是必须的啦!

首先说一下本项目用到的机器人API是腾讯AI平台:大家可以到这里申请,然后会得到APP_ID和APP_KEY,就可以调用它的API并带入参数请求机器人回复了。

Dart网络请求需要引入一个库:http: ^0.12.0

具体写法:

import 'package:http/http.dart' as http;

http.get(Uri.parse(url), headers:{})
     .then((res){ })
     .catchError((error){ });
http.post(Uri.parse(url), headers:{},body:)
     .then((res){ })
     .catchError((error){ });

http常用的get、post、put、delete方法全部都有提供,根据接口类型使用不同方法,headers根据需要传入,格式如headers: {'Content-Type': 'application/x-www-form-urlencoded'},then就是请求结果回调,res就是请求结果,catchError是请求异常捕获,另外post请求时参数需要用body传入,如:body:params,params是key1=value1&key2=value2&…的String类型,这样一个网络请求就完成了,是不是好简单!

那我们 就来先试着请求一下机器人API,文档中已经给出API的url为:我们先忽略参数,直接去请求一下,来实验一下上述http请求方法是否可用:

import 'package:http/http.dart' as http;

main() {
  http.post("https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat").then((res) {
    print(res.body);
  });
}

运行结果:

{
  "ret": 4096,
  "msg": "paramter invalid",
  "data": {
      "session": "",
      "answer": ""
  }
}

网络请求没毛病,只是接口返回了错误信息:参数错误!那么接下来我们就要看文档,看这个接口到底需要怎样的参数:

Flutter快速开发多端聊天机器人 flutter语音聊天_Flutter快速开发多端聊天机器人


其中最主要的就是“sign”这个参数,点击接口鉴权,看看如何生成sign:

Flutter快速开发多端聊天机器人 flutter语音聊天_json_02


第一步:参数升序:

这个很简单,参数已知的,我们按顺序排列一下就行了:app_id,nonce_str,question,session,time_stamp;

第二步:拼接并编码:

按上述顺序进行键值对拼接,并且value部分需要URL编码,其实除了question参数是我们输入的,大部分为中文,需要去编码外,其它的都不需要编码,因此只对question编码即可;我们知道,在java中,直接调用系统方法URLEncoder.encode()方法编码即可,那在dart中用什么呢?这个需要dart提供的Uri这个类的Uri.encodeFull方法就可以了;

第三步:拼接appkey:

将&app_key=xxx继续拼接在第二步拼接的参数后面;

第四步:MD5后大写:

dart中md5方法需要导入两个库:

crypto: ^2.0.6
utf: ^0.9.0+5

然后就可以调用md5.convert方法,但convert需要传入的参数为字节数组,那么就需要先对参数进行编码utf8.encode(params)得到字节数组后再传入:

var sign = md5.convert(utf8.encode(params));

最后一步转换为大写,就很简单了,直接调用String的方法:sign.toString().toUpperCase()就行了!

另外,Flutter中获取当前时间可以用DateTime:

DateTime.now().millisecondsSinceEpoch

得到的是毫秒,类似于安卓的:

System.currentTimeMillis()

由于参数中需要传入秒,那么就需要/1000:

DateTime.now().millisecondsSinceEpoch/1000

但其并不会像java一样结果为整数,而是一个double类型,因此我们需要强制转换,dart中强制转化也不像java中直接在代码前面加转换类型,而是用到as

DateTime.now().millisecondsSinceEpoch/1000 as int

其可以简化为:

DateTime.now().millisecondsSinceEpoch ~/ 1000

“~”这个符号是不是很神奇?

好了,参数算完,我们就来试验一下效果:

import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:http/http.dart' as http;

var url = "https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat";
var app_id = "";//填入自己申请的appid
var app_key = "";//填入自己申请的appkey

main() {
  getText("你好");
}

getText(question) {
  var params =
      "app_id=$app_id&nonce_str=fa577ce340859f9fe&question=${Uri.encodeFull(question)}&session=10000&time_stamp=${DateTime.now().millisecondsSinceEpoch ~/ 1000}";
  http
      .post(Uri.parse(url),
          headers: {'Content-Type': 'application/x-www-form-urlencoded'},
          body: params + "&sign=" + getSign(params))
      .then((res) {
    print(res.body);
  }).catchError((error) {
    print(error);
  });
}

//获取签名
getSign(params) {
  params += "&app_key=$app_key";
  var sign = md5.convert(utf8.encode(params));
  return sign.toString().toUpperCase();
}

运行结果:

Flutter快速开发多端聊天机器人 flutter语音聊天_Flutter快速开发多端聊天机器人_03


注意:appid和appkey需要填入你自己申请的!

既然有接口请求,那么就要有json解析转换了,安卓中我们常用的是谷歌的GSON,很方便,而Dart中需要用到上面的一个库:dart:convert

jsonDecode(json)

需要注意的是,这个方法解析后得到的是一个map,比如我要取字段ret,就要这么写:

jsonDecode(json)['ret']

最终,我们将其封装为一个类:

import 'dart:convert';

class RobotMessage {
  int ret;
  var msg;
  RobotData data;

  RobotMessage(json) {
    var map = jsonDecode(json);
    ret = map['ret'];
    msg = map['msg'];
    var _data = map['data'];
    data = RobotData(_data);
  }
}

class RobotData {
  var session;
  String answer;

  RobotData(data) {
    session = data['session'];
    answer = data['answer'];
  }
}

那么在接口请求完成后,我们就可以直接用:

RobotMessage robotMessage = RobotMessage(res.body);

来解析并转换为RobotMessage 对象了!

UI和接口都完成了,那么结合起来后就基本上实现了一个简单的聊天机器人的应用了!

Flutter快速开发多端聊天机器人 flutter语音聊天_Flutter快速开发多端聊天机器人_04

Flutter快速开发多端聊天机器人 flutter语音聊天_Flutter快速开发多端聊天机器人_05

另外,在安卓中我们常用EventBus来进行通信,在Dart中也可以使用的,引入库:event_bus: ^1.0.3,使用方法:

1.初始化:
初始化需要在你生命的Event类中初始化,如:

EventBus eventBus=EventBus();

class EventTest{

}

一定要注意,初始化代码要写在class之外;

2.发送Event:

eventBus.fire(EventTest());

3.接收Event:

eventBus.on<EventTest>().listen((event) {
  
   });