IDEに戻って、Spring Bootのプロジェクトに作業を行う。
プロジェクトファイル(ルートフォルダ)のpom.xmlファイルの <dependencies>〜</dependencies>
の中に、下の内容を追加する。
<dependencies>
(中略。すでにあるものはそのままにしておく)
<dependency>
<groupId>com.linecorp.clova</groupId>
<artifactId>clova-extension-boot-web</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
Clovaからのリクエストを受け付けるサーバーのファイルパスを設定する。
その他のソース(src/main/resources)の application.properties ファイルに追記する。
cek.api-path=/clova
これで、 https://xxxx.../clova でClovaからのPOSTリクエストを受け取れるように設定される。
ClovaからのPOSTリクエストを処理するリクエストハンドラクラスを作成する。
このクラスは、Clova CEK SDK Javaの実装例 を参考に作っている。
package com.example.clova;
import com.linecorp.clova.extension.boot.handler.annnotation.*;
import com.linecorp.clova.extension.boot.message.response.CEKResponse;
import com.linecorp.clova.extension.boot.message.speech.OutputSpeech;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Optional;
@CEKRequestHandler
public class IntentHandler {
private static final Logger log = LoggerFactory.getLogger(IntentHandler.class);
// スキル起動時の処理
@LaunchMapping
CEKResponse handleLaunch() {
// Clovaが話す。スキル(Session)は終了しない
return CEKResponse.builder()
.outputSpeech(OutputSpeech.text("部屋の名前を使って、どこそこの環境を教えて、と聞いてください。"))
.shouldEndSession(false)
.build();
}
// EnvIntent 発生時の処理。引数をスロット名と一致させること!
@IntentMapping("EnvIntent")
CEKResponse handleIntent(@SlotValue Optional<String> area) {
// areaのスロットタイプが聞き取れていれば callbackEnvメソッド を呼び出す
// 聞き取れていなければ 聞き取れませんでした を結果にする
String outputSpeechText = area
.map(value -> callbackEnv(value))
.orElse("聞き取れませんでした");
// Clovaに callbackEnv の結果を話させる。スキル(Session)は終了しない
return CEKResponse.builder()
.outputSpeech(OutputSpeech.text(outputSpeechText))
.shouldEndSession(false)
.build();
}
// 聞き取れたスロットタイプの内容から、回答を作る
private String callbackEnv(String area) {
switch (area) {
case "食堂":
return "二酸化炭素濃度は1000ppm、温度は20度です。";
case "学生ホール":
return "二酸化炭素濃度は1500ppm、温度は25度です。";
default:
return "";
}
}
// 「キャンセル」と言われたときの処理
@IntentMapping("Clova.CancelIntent")
CEKResponse handleCancelIntent() {
// Clovaに話させる。スキル(Session)も終了する。
return CEKResponse.builder()
.outputSpeech(OutputSpeech.text("部屋の環境スキルを終了します。"))
.shouldEndSession(true)
.build();
}
// スキルの終了時の処理
@SessionEndedMapping
CEKResponse handleSessionEnded() {
log.info("部屋の環境スキルを終了しました。");
return CEKResponse.empty();
}
}
ClovaApplication を起動する。
Clova Developer Center β のスキルの作成ページから、画面丈夫の テスト メニューを押す。
テストしたい内容を入力してください
欄に 食堂の環境を教えて
と入力し、 テスト ボタンを押す。
テスト結果の以下の項目を確認する。
- サンプル発話
食堂の環境を教えて
- サービスの応答
二酸化炭素濃度は1000ppm、温度は20度です。
- 実行されるイベント
IntentRequest
- 解析されたインテント
EnvIntent
- 解析されたスロット
- スロット名
area
- 解析されたスロットデータ
食堂
- スロット名
学生ホールの環境を教えて
と入力すると、サンプル会話、サービスの応答、解析されたスロットデータ が変わる。
LINEアプリでスキルストアを開き、「部屋の環境」が表示されていることを確認する。
「部屋の環境」スキルをタップし、「利用開始」をタップする。
- あなた「部屋の環境を起動して」
- Clova「部屋の名前を使って、どこそこの環境を教えて、と聞いてください」
- あなた「食堂の環境を教えて」
- Clova「二酸化炭素濃度は1000ppm、温度は20度です」
- あなた「学生ホールの環境を教えて」
- Clova「二酸化炭素濃度は1500ppm、温度は25度です」
- あなた「体育館の環境を教えて」
- Clova「場所が聞き取れないか、登録されていない場所です」
- あなた「キャンセル」
- Clova「部屋の環境スキルを終了します」
@IntentMapping
は、カスタムインテント名・ビルトインインテント名に対応する処理(メソッド)に付与するアノテーション。
※ビルトインテントは、Clovaに最初から備わっている。
@IntentMapping(EnvIntent)
の handleIntent(@SlotValue...)
メソッドは、前準備で作成した「○○の環境を教えて」というClovaへの対話(EnvIntent)に対応する。引数名がスロット名と同じでなければいけないことに注意。
@IntentMapping(Clova.CancelIntent)
の handleCancelIntent()
メソッドは、スキルがキャンセル(終了)された時のビルトインインテント Clova.CancelIntent
に対応する。
これらのメソッドの引数の @SlotValue
は、スロットの値が渡される引数であることを表す。この例では、「○○の環境を教えて」の area
スロットの値が引数に渡される。
戻り値に設定されている CEKResponse
クラスは、Clovaが返答する内容を表す。builderパターンでインスタンス化する。
outputSpeech
は、返答する文字列。shouldEndSession
は、スキルの終了を行うべきかどうかを true/false で設定する。
@LaunchMapping
は、スキルの起動時に対応するメソッドに付与する。
@SessionEndedMapping
は、スキルの終了時に対応するメソッドに付与する。