Technical Articles
Node.jsでSAP Conversational AIへWebhookでReplyを設定
SAP Cloud SDK for JavaScriptを使ってアプリを作成してSAP Cloud Foundry Application Runtimeへデプロイする方法のメモです。
Node.jsとSAP Cloud SDK for JavaScriptについては、別記事「SAP Cloud SDK for JavaScriptを使ってSAP CP CFへアプリをデプロイ」を参照ください。
Node.jsプログラムはGitHubに置いています。
開発環境
以下の環境で実行しています。
- OS: Ubuntu18.04.01 LTS
- Node.js: 12.14.1
- npm: 6.13.4
- CF cli: 6.49.0+d0dfa93bb.2020-01-07
- SAP Cloud SDK for JavaScript:1.16
手順
1. Node.js開発
1.1. プロジェクト作成
以下のコマンドでProjectフォルダが作成される。
途中project nameを入れ、anonymous usage analyticsはNo
# Node.jsのプロジェクトを管理したいディレクトリから
$ sap-cloud-sdk init node-sdk-chat
This folder does not contain a `package.json`.
Should a new `nest.js` project be initialized in this folder? (y|n): y
Building application scaffold... done
Enter project name (for use in manifest.yml) [node-sdk-chat]: node-sdk-chat
Do you want to provide anonymous usage analytics to help us improve the SDK? (y|n): n
✔ Creating files
✔ Modifying test config
✔ Adding dependencies to package.json
✔ Installing dependencies
✔ Modifying `.gitignore`
+--------------------------------------------------------------+
✅ Init finished successfully.
? Next steps:
- Run the application locally (`npm run start:dev`)
- Deploy your application (`npm run deploy`)
? Consider setting up Jenkins to continuously build your app.
Use `sap-cloud-sdk add-cx-server` to create the setup script.
+--------------------------------------------------------------+
1.2. プロジェクト作成確認
プロジェクトディレクトリに移動し、nodeを起動します。
# プロジェクトディレクトリに移動しstart:devを実行
$ cd node-sdk-chat && npm run start:dev
1:23:58 AM - Starting compilation in watch mode...
11:24:02 AM - Found 0 errors. Watching for file changes.
[Nest] 64793 - 02/13/2020, 11:24:02 AM [NestFactory] Starting Nest application...
[Nest] 64793 - 02/13/2020, 11:24:02 AM [InstanceLoader] AppModule dependencies initialized +15ms
[Nest] 64793 - 02/13/2020, 11:24:02 AM [RoutesResolver] AppController {/}: +4ms
[Nest] 64793 - 02/13/2020, 11:24:02 AM [RouterExplorer] Mapped {/, GET} route +2ms
[Nest] 64793 - 02/13/2020, 11:24:02 AM [NestApplication] Nest application successfully started +2ms
CURLでリクエスト送り、正常にレスポンスを受け取れることを確認
$ curl localhost:3000
Hello World!
1.3. コントローラ作成
nest cliでchatのコントローラ生成。
$ nest g controller chat
CREATE /src/chat/chat.controller.spec.ts (479 bytes)
CREATE /src/chat/chat.controller.ts (97 bytes)
UPDATE /src/app.module.ts (322 bytes)
chat.cotroller.tsを変更します(拙いコードで失礼します)。出力フォーマットは公式ヘルプを参考にしています。
import { Controller, Get, Req, Post, Param } from '@nestjs/common';
import { Request } from 'express';
@Controller('chat')
export class ChatController {
@Get()
Reply(@Req() request: Request) {
//console.log(request)
console.log('Receive Get Request!!!!')
console.log('-----body-----')
console.log(request.body)
const test = {
"replies": [
{
"type": "quickReplies",
"content": {
"title": "Select Message Type",
"buttons": [
{
"title": "Button",
"value": "Show Buttonnest"
},
{
"title": "Picture",
"value": "Show Picture"
}
]
}
}]
}
;
return test
//return this.chatService.Reply();
};
@Post(':type')
ReplyPost(@Req() request: Request, @Param('type') type: string) {
console.log(type)
console.log('Receive Post Request!!!!')
console.log('-----body-----')
console.log(request.body)
var reply = { "replies": [] }
switch (type) {
case 'pict':
reply.replies.push(
{
"type": "picture",
"content": "https://www.sap.com/dam/application/shared/logos/sap-logo-svg.svg.adapt.svg/1493030643828.svg",
}
);
break;
case 'button':
reply.replies.push(
{
"type": "buttons",
"content": {
"title": "BUTTON_TITLE",
"buttons": [
{
"title": "BUTTON_TITLE",
"type": "BUTTON_TYPE",
"value": "BUTTON_VALUE"
}
]
}
});
break;
}
return reply
}
}
curlで確認します。
$ curl localhost:3000/chat
{"replies":[{"type":"quickReplies","content":{"title":"Select Message Type","buttons":[{"title":"Button","value":"Show Buttonnest"},{"title":"Picture","value":"Show Picture"}]}}]}
$ curl -X POST -H "Content-Type: application/json" -d '{"key": "value"}' localhost:3000/chat/pict
{"replies":[{"type":"picture","content":"https://www.sap.com/dam/application/shared/logos/sap-logo-svg.svg.adapt.svg/1493030643828.svg"}]}
1.4. CFへデプロイ
CFにデプロイする前にいくつか調整ごとをします。
1.4.1 package.json変更
まずはpackage.jsonを変更。”scripts”以下ににあるci-packageの中身を変更。CFへアップロードする元の”deployment”フォルダにnode_modulesがコピーされてしまうので削除します(node_modulesが重いくせに何もしていない気がする)。
"ci-package": "sap-cloud-sdk package && rm -r -f deployment/node_modules",
1.4.2. manifest.yml変更
manifest.ymlを少し変更します。random_routeを削除し、routeを固定します(<route>部分を変更)。試行錯誤していく中で、routeをcfのquotaに対して使い切ってしまったので、固定にしました。
applications:
- name: node-sdk-chat
path: deployment/
buildpacks:
- nodejs_buildpack
memory: 256M
command: npm run start:prod
routes:
- route: <route>.eu10.hana.ondemand.com
1.4.3.CFにデプロイ
あとはコマンド”npm run deploy”で、ビルドとパッケージ、cf pushを一気にやってしまいます。具体的にdeployが何をしているかは、package.jsonに定義されています。
$ npm run deploy
2. SAP Conversational AI
Botの作成部分は省略します。英語で登録しています。特別な設定はありません。
2.1. インテント登録
“start-api-test”というインテントを登録。こんな感じのexpression。
2.2. エンティティ
エンティティとして登録した”type”の一覧。
2.3. スキル”test”
スキル”test”を登録。
2.3.1. Trigger
Triggerは先程登録したインテント。
2.3.2. Requirement
Requirementにtypeを入れます。
typeがなかった場合にWebhookを使います(今回は権限なし)。
2.3.3. Action
今度はActionです。
type.valueが”picture”の場合のWebhookです。先程と違ってhttpメソッドはPOSTにして、URLの最後のパスをpictにしています。
ほぼ同じでpictureがbuttonに変わっただけです。
最後に条件なしでメモリ情報を出し、メモリをすべてクリアします。これでCAI側も完成です。
実装イメージ
チャットのテストをします。
“run api”とすると、メッセージタイプを選択させるquick repliesが動きます。
“Button”ボタンを押すことでButtonのサンプルを出します。Buttonの選択を待たずして、次のメモリ情報も表示されます。
メモリをクリアしていきなり”show picture”とすると、メッセージタイプ選択をせずに画像表示まで一気に行きます。