「もっと簡単に」呼び出せるようにパッケージ化しました。
詳細はこちら
Watson Assisantとは
会話系のインターフェースを提供してくれるIBMのサービスです。
とりあえずデモ
※デモ内ではWatson AssistantとIBM Cloud Function(ICF)を連携させて、天気予報を取得しています。
Watson AssistantとICFの連携については別記事で書こうと思います。
システム概要
Watson AssistantをWebアプリケーションでどうやって使うか。
WatsonのサービスはREST APIで簡単に利用することが出来ます。
以前の記事ではNode.js
でWatson Assistantとの連携をしましたが、
今回はLaravel
とGuzzle
を使ってWebアプリケーションとWatson Assistantを連携する方法について
書きたいと思います。
Watson AssistantのCall処理
<?php
namespace App\Services;
use GuzzleHttp\Client;
class CallWatsonAssistant{
/**
* Watson Assistantを呼び出すモジュール
*
* @param string $spokenWord ユーザーが入力した文字列
* @param array $context watson assistantのcontextデータ
* @return json Watson AssistantをCallした結果
*/
public function call(string $spokenWord,array $context)
{
if(count($context)>0){
//以前から継続されている会話の場合
$requestData = json_encode(['input'=>['text'=>$spokenWord],'context'=>$context]);
}else{
$requestData = json_encode(['input'=>['text'=>$spokenWord]]);
}
$headers = ['Content-Type' => 'application/json','Content-Length' => strlen($requestData)];
$curlOpts = [
CURLOPT_USERPWD => config('watson.user_name').':'.config('watson.password'),
CURLOPT_POSTFIELDS => $requestData,
];
$guzzleClient = new Client(['base_uri'=>'https://gateway-fra.watsonplatform.net/assistant/api/v1/workspaces/']);
$path = config('watson.workspace_id') . '/message?version=2018-07-10';
return $guzzleClient->request('POST',$path,['headers'=> $headers,'curl'=>$curlOpts])->getBody()->getContents();
}
}
Guzzleを使う事で、curlを使うよりも簡潔にWatson Assistantを呼び出すことが出来ます。
envファイルに定義を追加する
セキュリティの観点より、APIをCallする為のユーザー名やパスワード、workspace_idについては、
envファイルに書くと良いと思います。
WATSON_WORKSPACEID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
WATSON_USER_NAME=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
WATSON_PASSWORD=XXXXXXXXXXXX
configファイル(watson.php)を作成する。
私はconfig
フォルダ直下にwatson.php
というファイルを作っています。
これにより、呼び出すときの処理でconfig('watson.workspace_id')
という書き方が出来るようになります。
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Workspace ID
|--------------------------------------------------------------------------
| IBM CloudでのWORKSPACE IDを指定します。
*/
'workspace_id' => env('WATSON_WORKSPACEID'),
/*
|--------------------------------------------------------------------------
| Default UserName/Password
|--------------------------------------------------------------------------
| IBM Cloudで取得したサービス資格情報を指定します。
*/
'user_name' => env('WATSON_USER_NAME'),
'password' => env('WATSON_PASSWORD')];
Controllerに記述する
上記で作成したWatson Assistant呼び出し処理をインジェクション
して使っています。
Watson Assistantでは、ユーザーと連続した会話を成立させるために、APIのパラメータに
context
を持たせる必要があるので、これはsession
に格納しています。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\CallWatsonAssistant;
class WatsonCallController extends Controller
{
/**
* セッションを初期化し、初期画面を表示する。
* @param Request $request
* @return response 入力初期画面
*/
public function index(Request $request)
{
$request->session()->flush();
return view("talkWatson");
}
/**
* WatsonAssistantを呼び出してjson形式で返却する。
* 継続した会話を実現する為、contextはセッションに保管しておく
*
* @param Request リクエストデータ
* @param CallWatsonAssistant WatsonAssistant呼び出しモジュール
* @return json Watson Assistantからの受信データ
*/
public function talkToWatson(Request $request,CallWatsonAssistant $CWA)
{
$response = $CWA->call($request->spokenword,session('context')?session('context'):[]);
$responseArray = json_decode($response,true);
$request->session()->put('context',$responseArray['context']);
return $response;
}
}
ルーティングを定義する
web.php
Route::get('/', 'WatsonCallController@index')->name('index');
api.php
Route::post('talk_to_watson','WatsonCallController@talkToWatson')->name('talk_to_watson');
上記の処理ではWeb画面の表示とAPIの定義を同じControllerに書いていますが、
本来は分けた方が良いと思います。
サンプルView
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-6">
<input type="text" id="message_to_watson" placeholder="何か入れて下さい" class="form-control"/>
</div>
<div class="col-md-2">
<input type="button" id="send_message" value="聞いてみる" class="btn btn-primary"/>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>ユーザー入力</label>
<ul id="input"></ul>
</div>
<div class="col-md-6">
<label>Watsonからの返答</label>
<ul id="responseFromWatson"></ul>
</div>
</div>
</div>
@endsection
@section('script')
<script>
$("#send_message").click(function(){
$('#input').append('<li>'+$("#message_to_watson").val()+'</li>')
$('#responseFromWatson').append('<li>'+'Watson is thinking...'+'</li>')
$.ajax({
type: "POST",
url: "{{route('talk_to_watson')}}",
data: {spokenword:$("#message_to_watson").val()},
dataType: 'json'
}).done(function(response){
for (var i = 0, len = response.output.text.length; i < len; i++) {
if(response.output.text[i] !== ''){
$('#responseFromWatson li:last-child').text(response.output.text[i]);
}
}
}).fail(function(){
alert(errorHandler(arguments));
});
});
</script>
@endsection
これで、上記のデモ画面まで表示する事が出来ると思います。
こちらの方法でも簡単にChat bot等の実装が出来そうですね。