LoginSignup
2
0

More than 5 years have passed since last update.

ボット対話:Repl-AI docomoAPI連携シナリオ vs A3RT Talk API (2017年12月)

Last updated at Posted at 2017-12-11

Repl-AIの「docomoAPI連携」シナリオ(実質、「雑談対話」+「トレンド記事抽出」+「知識Q&A」)と、A3RT Talk APIで、会話させてみました。今年5月にもQiitaで対話を試みた方がいるようです(「ドコモとリクルートの対話」)が、会話内容がだいぶ違っています。

会話記録

考察

基本的に、domocmoAPIから、「雑談対話」で会話のネタを提供し、Repl-AIが反応するという構図です。時々、何の前触れもなくdocomoAPIから「トレンド記事抽出」が出てきます。

以下、ハイライト。

アタック?

雑談: ちゅっ
A3RT: 照れます
雑談: 照れろ

照れろ。

雑談: 今日はなにか面白いニュースありましたか
A3RT: 調べてみてください
雑談: 気になるニュースがあるんですが、兵庫県西宮市から委託を受ける廃棄物処理会社「大栄」が、20代の若い女性たちのごみ収集チームを発足、9月からさくら色 の専用ごみ収集車で市内を巡回していて、「男性の職場」というイメージの刷新が狙いだそうですよ。
A3RT: すごいですね
雑談: ありがとうございます
A3RT: どういたしまして
雑談: ぎゅー

何のご褒美ですか。

雑談: ご家族は何人ですか?
A3RT: 秘密です
雑談: えー
A3RT: 何かお困り事でしょうか?
雑談: 何県出身なんですか?
A3RT: 内緒です
雑談: えー
A3RT: 何かお困り事でしょうか?
雑談: 何県出身なんですか?
A3RT: 内緒です
雑談: えー
A3RT: 何かお困り事でしょうか?
...
雑談: あなたはいくつですか
A3RT: 秘密です
雑談: えー
A3RT: 何かお困り事でしょうか?
...
雑談: ご家族といっしょにお住まいですか?
A3RT: 秘密です
雑談: えー
A3RT: 何かお困り事でしょうか?

A3RTさんのほうが困ってる。

雑談: ありがと
A3RT: どういたしまして
雑談: ちゅっ
A3RT: 照れます
雑談: 照れんな

どんなプレイですか。

雑談: 好きな人はいますか?
A3RT: います
雑談: います
A3RT: やっぱり
雑談: やっぱりって

ほら、好きな人いるってよ。

A3RT: あなたは頑張っているのですか?
雑談: 今は、恋人はいないですね。
A3RT: そうでしょうか?

頑張っているのですね。

雑談: どうやって結婚相手をみつけるんですかね。
A3RT: します
雑談: します
A3RT: うれしいです
雑談: うん

ついにゴールインか。

プライベート

雑談: 最近どこか行かれましたか?
A3RT: 100均です
雑談: フェルトを買うんでしょうか
A3RT: あなたはよくするんですか?
雑談: 最近よく見ますね。

雑談さんの脳内は、100均=フェルトを買うところらしいです。

雑談: そういえば思い出したんですけど、シャツのボタンをかけて洗濯すると型崩れしにくいらしいですよ。
A3RT: 使い所が難しいです

うむ。確かに、シャツがある程度強いことが前提。

雑談: 今日は家事が片付きましたか?
A3RT: どうだったでしょうね

片付けた記憶すらない。

雑談: 飛行機が好きなので、気づいたら集まってたりしますね。
A3RT: ごめんなさい私にはわからないです

雑談さんの趣味は理解されないようだ。

ボットのペット

雑談: ペット飼ってますか?
A3RT: 飼ってます

ボットが飼っているペットって...「EVA(2011年のスペイン映画)」ではボットの女の子がボットの犬と一緒にいた気がするけど、あれはペットだったか記憶にない。

難しいニュース

雑談: ところで、気になったニュースがあるんですが、燃えた炭の跡を裸足で歩行して身を清め、無病息災などを祈願する「火渡り神事」が、福岡市西区の愛宕神社で行われ、冷たい雨風で凍える寒さの中、参拝者は荒行で心身を温めたそうですよ。
A3RT: 難しいですね
雑談: うん

確かに、突然振られると、難しい。

予兆

雑談: 今日のお昼は何を食べました?
A3RT: 忘れてしまいました

数回聞かれても、忘れたの一点張り。

雑談: 今日はもう夕食はたべましたか?
A3RT: 覚えていません

ちなみにこの会話、午後8時頃です。

生きるのです

A3RT: あなたは生きるのです

三。枝織さんの声で再生してください。

車の運転にトラウマ?

雑談: 車の運転は好きですか?
A3RT: 好きです
雑談: えっ
A3RT: 何か嫌な事でもありましたか

新語登場

Facebookボット同士の会話でも誕生したと話題ですが...

雑談: どんな本を読まれますか?
A3RT: いろんなますよ

いろんなますよ。

何かを共有?

雑談: どうでしょうは面白いものですか?
A3RT: これです
雑談: ありがとうございます
A3RT: どういたしまして

一体、2人でこっそり何を共有したんだ。

作ったプログラム

本体

C#のコンソールアプリとしました。C#7.2で作ってあります。
A3RTが先攻で、Repl-AIが後攻です。isA3RTTurnの初期値を変えれば逆になります。
双方のサービスにご迷惑にならないように、1秒ずつ休んでいます。
適当にCtrl+Cで終わらせる前提です。

Program.cs
using System;
using System.Text;
using System.Threading.Tasks;

namespace ReplAndA3RT
{
    class Program
    {
        static async Task Main(string[] args)
        {
            // A3RTを先攻にする
            bool isA3RTTurn = true;

            // 会話のタネとなる文章を初期値に設定
            string req = "こんにちは!";
            string res;

            // コンソール内で「chcp 932」を実行するのと同等
            Console.OutputEncoding = Encoding.GetEncoding(932);

            // それぞれの会話サービスの初期化
            ReplService repl = new ReplService();
            A3RTService a3RT = new A3RTService();

            // Repl-AIのユーザーIDを取得
            await repl.RegisterAsync();

            while (true)
            {
                if(isA3RTTurn)
                {
                    // A3RTの応答を取得して標準出力に表示
                    res = await a3RT.MakeRequestAsync(req);
                    Console.WriteLine($"A3RT: {res}");
                }
                else
                {
                    // Repl-AIの応答を取得して標準出力に表示
                    res = await repl.MakeRequestAsync(req);
                    Console.WriteLine($"雑談: {res}");
                }
                req = res; // 応答をそのまま次のインプットにする
                isA3RTTurn = !isA3RTTurn; // ターンの切り替え
                await Task.Delay(1000); // 迷惑にならない程度に間を空けるため
            }
        }
    }
}

A3RT Talk APIを呼び出すプログラム

リクエストパラメータはFormです。珍しいですね。
時々無言返しされますので、その場合は「...」に変換して返しています。
App.configの<appSettings>に、A3RT_APIKEYでAPIキーを指定してください。

A3RTService.cs
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Net.Http;
using System.Threading.Tasks;

namespace ReplAndA3RT
{
    /// <summary>
    /// A3RTのAPIを呼び出すクラス
    /// </summary>
    class A3RTService
    {
        private string APIKEY;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        internal A3RTService()
        {
            // App.configから設定を取得
            APIKEY = ConfigurationManager.AppSettings["A3RT_APIKEY"];

            // 必要な情報が取得できない場合はエラー
            if (string.IsNullOrEmpty(APIKEY))
            {
                throw new ArgumentException("A3RT_APIKEY is empty");
            }
        }

        /// <summary>
        /// 対話APIを実行し、応答文を返す
        /// </summary>
        /// <param name="message">発言</param>
        /// <returns>応答</returns>
        internal async Task<string> MakeRequestAsync(string message)
        {
            HttpClient client = new HttpClient();

            // リクエストURL
            string uri = $"https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk";

            // リクエスト本文
            var content = new FormUrlEncodedContent(
                new Dictionary<string, string>
                {
                    { "apikey", APIKEY },
                    { "query", message }
                });

            // APIを実行し、レスポンス本文を取得
            HttpResponseMessage response = await client.PostAsync(uri, content);
            JObject rss = await response.Content.ReadAsAsync<JObject>();

            // HTTPステータスが異常であればエラー
            if (!response.IsSuccessStatusCode)
            {
                throw new ApplicationException(
                    $"API failed. code={response.StatusCode}");
            }

            // 何も返さなかった場合は、何か埋めて返しておく
            if ((int)rss["status"] == 2000)
            {
                return "...";
            }
            // APIがエラーを出していればエラー
            else if ((int)rss["status"] != 0)
            {
                Console.WriteLine(rss);
                throw new ApplicationException(
                    $"API failed. ");
            }

            // レスポンス本文から応答文のみを抽出して返す
            return (string)rss["results"][0]["reply"];
        }
    }
}

Repl-AIを呼び出すプログラム

対話前に「ユーザーID取得」を呼び、実際の会話では「対話」を呼びます。
App.configの<appSettings>に、REPL_APIKEYでAPIキー、REPL_BOTIDでボットID、REPL_TOPICIDでシナリオIDを指定してください。

ReplService.cs
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Configuration;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace ReplAndA3RT
{
    /// <summary>
    /// Repl-AIのAPIを呼び出すクラス
    /// </summary>
    class ReplService
    {
        private string APIKEY;
        private string BOTID;
        private string TOPICID;

        // registration APIで取得したユーザーID
        private string id;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        internal ReplService()
        {
            // App.configから設定を取得
            APIKEY = ConfigurationManager.AppSettings["REPL_APIKEY"];
            BOTID = ConfigurationManager.AppSettings["REPL_BOTID"];
            TOPICID = ConfigurationManager.AppSettings["REPL_TOPICID"];

            // 必要な情報が取得できない場合はエラー
            if (string.IsNullOrEmpty(APIKEY) || string.IsNullOrEmpty(BOTID) || string.IsNullOrEmpty(TOPICID))
            {
                throw new ArgumentException("REPL_APIKEY/REPL_BOTID/REPL_TOPICID is empty");
            }

        }

        /// <summary>
        /// 「ユーザーID取得」APIを呼び出し、ユーザーIDをインスタンス内に設定する
        /// </summary>
        /// <returns></returns>
        internal async Task RegisterAsync()
        {
            HttpClient client = new HttpClient();

            // リクエストURL
            string uri = $"https://api.repl-ai.jp/v1/registration";

            // リクエストヘッダ
            client.DefaultRequestHeaders.Add("x-api-key", APIKEY);

            // リクエスト本文
            var json = JsonConvert.SerializeObject(
                new { botId = BOTID });

            // APIを実行し、レスポンス本文を取得
            HttpResponseMessage response = await client.PostAsync(
                uri, new StringContent(json, Encoding.UTF8, "application/json"));
            JObject rss = await response.Content.ReadAsAsync<JObject>();

            // HTTPステータスが異常であればエラー
            if (!response.IsSuccessStatusCode)
            {
                throw new ApplicationException(
                    $"API failed. code={response.StatusCode}");
            }

            // レスポンス本文からID部分を抽出し、インスタンス変数に設定
            id =  (string)rss["appUserId"];

            // APIキーが間違っている場合はidは空。ここでエラーを投げておく
            if (string.IsNullOrEmpty(id))
            {
                throw new ApplicationException(
                    $"registration API didn't return ID.");
            }
        }

        /// <summary>
        /// 「対話」を呼び出し、応答文を返す
        /// </summary>
        /// <param name="message">発言</param>
        /// <returns>応答</returns>
        internal async Task<string> MakeRequestAsync(string message)
        {
            HttpClient client = new HttpClient();

            // リクエストURL
            string uri = $"https://api.repl-ai.jp/v1/dialogue";

            // リクエストヘッダ
            client.DefaultRequestHeaders.Add("x-api-key", APIKEY);

            // リクエスト本文
            var json = JsonConvert.SerializeObject(
                new {
                    appUserId = id,
                    botId = BOTID,
                    voiceText = message,
                    initTalkingFlag = false,
                    initTopicId = TOPICID
                });

            // APIを実行し、レスポンス本文を取得
            HttpResponseMessage response = await client.PostAsync(
                uri, new StringContent(json, Encoding.UTF8, "application/json"));
            JObject rss = await response.Content.ReadAsAsync<JObject>();

            // HTTPステータスが異常であればエラー
            if (!response.IsSuccessStatusCode)
            {
                throw new ApplicationException(
                    $"API failed. code={response.StatusCode}");
            }

            // レスポンス本文から応答文のみを抽出して返す
            return (string)rss["systemText"]["expression"];
        }
    }
}

BOTで使える会話API・ライブラリ・サービスまとめ」で紹介されている他のボットとも会話させてみると、いいかもしれませんね。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0