聊天机器人的实现(基于C#和图灵API)

今日闲来无事,脑洞大开,决定写一个聊天机器人。

当然,我们去自己实现人工智能的聊天对话功能是不现实了,即使去做,也要花费大量的时间精力,最后可能也搞不出来。于是,从网上搜索相关的API接口,于是,找到了这个:http://www.tuling123.com/openapi/

感觉虽然和微软的小冰和韩国的小黄鸡还有些差距,不过也还好,就这样吧。

先上效果图(比较丑。。。)

聊天机器人的实现(基于C#和图灵API)_第1张图片


图灵机器人API的使用非常简单,用一个http的get形式获取,就会返回一个json数据,再解析json数据即可

举例说来就是:

如果发送过去这个:

请求示例: http://www.tuling123.com/openapi/api?key=KEY&info=你漂亮么

其中的KEY是在注册图灵API的时候提供给你的

那么返回的就是这样的一个json数据:

{

"code":100000,

"text":"恩恩,害羞ing……"

}

很简单的样子...


下面开始着手去做了

首先,把要解决的问题罗列出来:

1,使用什么工具编写

2,如何使用http get

3,如何解析json数据


下面逐一解决:

问题一:使用什么工具编写

最初打算使用python来着,简单易用,还可以跨平台。

但是吧。。。由于图灵API返回的数据是utf-8编码的,Python对于utf-8编码的转换很复杂,总是报错,上网查询好久无果,只好退而求其次,使用C#编写吧。

(没使用C和C++主要是界面描画很麻烦,C本身描画界面就需要借助第三方的东西,C++用MFC感觉太复杂了。Java学的不好。。。)


问题二:怎么使用Http get

参考如下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;

namespace HttpGetter
{
    class Program
    {
        static void Main(string[] args)
        {
            String url = "http://www.csdn.net"; //设定要get的地址
            Encoding encoding = Encoding.GetEncoding("utf-8");  //设定编码格式

            String data = HttpGet(url, encoding);

            if (data != "")
            {
                Console.WriteLine(data);
            }
            Console.ReadLine();
        }

        public static string HttpGet(string url, Encoding encoding)
        {
            string data = "";
            try
            {
                WebRequest request; //使用url发出请求的类
                request = WebRequest.Create(url);
                request.Credentials = CredentialCache.DefaultCredentials;   //使用默认的身份验证
                request.Timeout = 10000;    //设定超时
                WebResponse response;   //提供响应的类
                response = request.GetResponse();
                data = new StreamReader(response.GetResponseStream(), encoding).ReadToEnd();    //获取数据
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }

            return data;
        }
    }
}

上面的代码是在C#命令行中运行的,之后会制造一个界面,做成一个窗口形式的程序


问题三:如何解析json数据

这个问题搞得很头大,C#自带的json解析感觉比较复杂,玩不转。只好下载了一个第三方的json解析工具:Newtonsoft.Json

安装这个很简单,但是如果网络不好,会出现下载失败的问题

以我使用的VS2013为例,

工具 -> NuGet程序包管理器 -> 程序包管理器控制台

之后再出现的控制台上输入这个:

install-package newtonsoft.json

之后,如果之前没下载过得话,会联网进行下载,下载完成之后,就可以使用Newtonsoft.Json的工具类了


下面开始编码吧


应用界面的实现


界面的实现,就是两个Textbox,一个按钮,和一个图片框。

一个TextBox作为输入框,一个作为聊天记录的现实,按钮作为提交按钮,图片框里放一张你喜欢的机器人头像就好(哆啦A梦,阿童木,阿拉蕾随意。。。)

可能需要调整的细节有:

聊天记录的TextBox不允许用户输入,所以ReadOnly属性要置为True

软件希望按下回车能够自动提交输入内容,所以,窗体的AcceptButton要设定为窗体上的那个按钮。


制造url


想要正常的与机器人交流,必须要遵循机器人的规则,这里要按照如下格式进行对话的提交:

http://www.tuling123.com/openapi/api?key=KEY&info=TEXT

上面的KEY是在注册图灵机器人账号的时候得到的,是一串很长的数字加字母

TEXT是你的问话内容


Json数据解析


Newtonsoft提供的JSON解析器还是比较容易使用的。(要using Newtonsoft.Json;)

首先,用一个String类型的变量存放要解析的Json数据,之后,创建Json解析类

JsonReader reader = new JsonTextReader(new StringReader(data));

之后,调用reader.Read()进行解析。

每一次read,都取得了这一次解析的内容,

比如:

你输入“你好”,

得到的Json数据为:{"code":100000,"text":"你好啊,希望你今天过的快乐"}

在控制台程序中重复执行:

Console.WriteLine(reader.TokenType + "\t\t" + reader.ValueType + "\t\t" + reader.Value);

reader.Read();

得到的输出为:

StartObject
PropertyName System.Stringcode
Integer System.Int64100000
PropertyName System.Stringtext
String System.String你也好 嘻嘻
EndObject

参考官网提供的文档,如果返回码code为100000,则表明这是一个文本数据,text是返回的对话内容

图灵API还提供了诸如航班电影等一系列的返回形式,原理基本相同,这里只实现对于文本类型返回值的处理。

根据这个规则,就可以写一个很傻的解析程序:

            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.PropertyName
                    && reader.ValueType == Type.GetType("System.String")
                    && Convert.ToString(reader.Value) == "code")
                {
                    /* 如果当前Value是code,读取下一条,查看code的值 */
                    reader.Read();
                    switch (Convert.ToInt32(reader.Value))
                    {
                        case 100000:
                            /* 返回码为文本类数据 */
                            reader.Read();
                            reader.Read();
                            tbxHistory.AppendText("Robot: " + reader.Value + "\n");
                            break;
                        default:
                            break;
                    }
                }
            }
中间两个reader.Read();是用来跳过text标示的那一次数据,这里只是节约时间,后期可以根据官方文档做一个解析更全面,更安全的程序。


基本差不多了,最终附上所有代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;//json解析用
using System.IO;
using System.Net;

namespace ChatRobot
{
    public partial class ChatRobotForm : Form
    {
        const String KEY = "XXXXXXXXXXXXXXXXXXXXX"; //这里是注册时得到的key

        public ChatRobotForm()
        {
            InitializeComponent();
        }

        private void btnCommit_Click(object sender, EventArgs e)
        {
            String input = tbxInput.Text;
            string url = "http://www.tuling123.com/openapi/api?key=" + KEY + "&info=" + input;

            /* 清空输入框 */
            tbxInput.Text = "";
            /* 将输入内容放入聊天记录窗口中 */
            tbxHistory.AppendText("You: " + input + "\n");

            Encoding encoding = Encoding.GetEncoding("utf-8");

            String data = HttpGet(url, encoding);

            JsonReader reader = new JsonTextReader(new StringReader(data));

            while (reader.Read())
            {
                //tbxHistory.AppendText(reader.TokenType + "\t\t" + reader.ValueType + "\t\t" + reader.Value + "\n");
                if (reader.TokenType == JsonToken.PropertyName
                    && reader.ValueType == Type.GetType("System.String")
                    && Convert.ToString(reader.Value) == "code")
                {
                    /* 如果当前Value是code,读取下一条,查看code的值 */
                    reader.Read();
                    switch (Convert.ToInt32(reader.Value))
                    {
                        case 100000:
                            /* 返回码为文本类数据 */
                            reader.Read();
                            reader.Read();
                            tbxHistory.AppendText("Robot: " + reader.Value + "\n");
                            break;
                        default:
                            break;
                    }
                }
            }
        }


        public static string HttpGet(string url, Encoding encoding)
        {
            string data = "";
            try
            {
                WebRequest request; //使用url发出请求的类
                request = WebRequest.Create(url);
                request.Credentials = CredentialCache.DefaultCredentials;   //使用默认的身份验证
                request.Timeout = 10000;    //设定超时
                WebResponse response;   //提供响应的类
                response = request.GetResponse();
                data = new StreamReader(response.GetResponseStream(), encoding).ReadToEnd();    //获取数据
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }

            return data;
        }
    }
}
namespace ChatRobot
{
    partial class ChatRobotForm
    {
        /// 
        /// 必需的设计器变量。
        /// 
        private System.ComponentModel.IContainer components = null;

        /// 
        /// 清理所有正在使用的资源。
        /// 
        /// 如果应释放托管资源,为 true;否则为 false。
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// 
        /// 设计器支持所需的方法 - 不要
        /// 使用代码编辑器修改此方法的内容。
        /// 
        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ChatRobotForm));
            this.btnCommit = new System.Windows.Forms.Button();
            this.tbxInput = new System.Windows.Forms.TextBox();
            this.tbxHistory = new System.Windows.Forms.TextBox();
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
            this.SuspendLayout();
            // 
            // btnCommit
            // 
            this.btnCommit.Location = new System.Drawing.Point(303, 290);
            this.btnCommit.Name = "btnCommit";
            this.btnCommit.Size = new System.Drawing.Size(118, 27);
            this.btnCommit.TabIndex = 0;
            this.btnCommit.Text = "确定";
            this.btnCommit.UseVisualStyleBackColor = true;
            this.btnCommit.Click += new System.EventHandler(this.btnCommit_Click);
            // 
            // tbxInput
            // 
            this.tbxInput.Location = new System.Drawing.Point(12, 216);
            this.tbxInput.Multiline = true;
            this.tbxInput.Name = "tbxInput";
            this.tbxInput.Size = new System.Drawing.Size(409, 68);
            this.tbxInput.TabIndex = 1;
            // 
            // tbxHistory
            // 
            this.tbxHistory.Location = new System.Drawing.Point(109, 9);
            this.tbxHistory.Multiline = true;
            this.tbxHistory.Name = "tbxHistory";
            this.tbxHistory.ReadOnly = true;
            this.tbxHistory.Size = new System.Drawing.Size(311, 194);
            this.tbxHistory.TabIndex = 2;
            // 
            // pictureBox1
            // 
            this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
            this.pictureBox1.Location = new System.Drawing.Point(12, 12);
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.Size = new System.Drawing.Size(91, 87);
            this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
            this.pictureBox1.TabIndex = 3;
            this.pictureBox1.TabStop = false;
            // 
            // ChatRobotForm
            // 
            this.AcceptButton = this.btnCommit;
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(433, 329);
            this.Controls.Add(this.pictureBox1);
            this.Controls.Add(this.tbxHistory);
            this.Controls.Add(this.tbxInput);
            this.Controls.Add(this.btnCommit);
            this.Name = "ChatRobotForm";
            this.Text = "聊天机器人";
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Button btnCommit;
        private System.Windows.Forms.TextBox tbxInput;
        private System.Windows.Forms.TextBox tbxHistory;
        private System.Windows.Forms.PictureBox pictureBox1;
    }
}

好了,代码很短,只有不到100行,还是有很多功能有待实现,后续还会不断改进的(如果有时间的话。。。)


你可能感兴趣的:(C#)