Oracle Cloud Infrastructureドキュメント

バックエンド統合

スキルは、カスタム・コンポーネントを介して「Oracle Human Capital Managementクラウド」Oracle Financials Cloudなどのバックエンド・サービスと統合できます。 たとえば、従業員が出張経費をOracle Financials Cloudに報告できるようにするスキルを作成する場合があります。

スキルをバックエンド・サービスと統合する手順は、次のとおりです:

  1. JavaScriptとOracle Digital Assistant Node.js SDKを使用して、SDKメタデータと対話オブジェクトを使用してデータをスキルとの間で転送するカスタム・コンポーネントを実装します。 「タスク1: カスタム・コンポーネントの実装」を参照してください。

  2. Digital Assistantの埋込みコンテナ、Oracle Mobile HubバックエンドまたはNode.jsサーバーにコンポーネント・パッケージをデプロイします。 「タスク2: サービスへのコンポーネント・パッケージのデプロイ」を参照してください。

  3. スキルのコンポーネント・サービスを構成します。 「タスク3: コンポーネント・サービスの構成」を参照してください。

タスク1: カスタム・コンポーネントの実装

カスタム・コンポーネントを実装するには、Oracle Digital Assistant Node.js SDKを使用して、Digital Assistantカスタム・コンポーネント・サービスとインタフェースします。

Digital Assistant埋込みコンテナ、「モバイル・ハブ」バックエンドまたはNode.jsサーバーにデプロイできるカスタム・コンポーネントを実装する方法は次のとおりです:

  1. 「カスタム・コンポーネントをビルドするためのソフトウェアをインストール」

  2. 「カスタム・コンポーネント・パッケージの作成」

  3. 「カスタム・コンポーネントの作成およびビルド」

最新の例やhttps://github.com/oracle/bots-node-sdk/tree/master/examples/custom-components/starterの詳細な手順を確認できます。

ステップ1: カスタム・コンポーネントをビルドするためのソフトウェアのインストール

カスタム・コンポーネント・パッケージをビルドするには、Node.js、ノード・パッケージ・マネージャ、およびOracle Digital Assistant Bots Node.js SDKが必要です。

埋込みコンテナにデプロイする場合、パッケージは、Node.js 8.11.5およびBots Node SDK 2.2.2.と互換性がある必要があります。

  1. https://nodejs.orgからNode.jsをまだダウンロードしていない場合は、グローバル・アクセスのためにインストールします。 ノード・パッケージ・マネージャ(npm)は、Node.jsに配布されます。

    Node.jsとnpmがインストールされているかどうかをテストするには、端末ウィンドウを開いて次のコマンドを入力します:

    node –v 
    npm –v
  2. グローバル・アクセス用のOracle Digital AssistantボットNode.js SDKをインストールするには、端末ウィンドウに次のコマンドを入力します:
    npm install -g @oracle/bots-node-sdk

    Macでは、次のsudoコマンドを使用します:

    sudo npm install -g @oracle/bots-node-sdk

    -g (グローバル)オプションを使用する場合、bots-node-sdkコマンドライン・インタフェースに直接アクセスできます。 それ以外の場合は、npx @oracle/bots-node-sdkを使用します。

  3. Oracle Digital AssistantボットNode.js SDKのインストールを確認するには、次のコマンドを入力します:
    bots-node-sdk -v
    コマンドはOracle Digital Assistant Bots Node.js SDKバージョンを印刷する必要があります。

ステップ2: カスタム・コンポーネント・パッケージの作成

SDKのコマンドライン・インタフェース(CLI)を使用して、必要なファイルとディレクトリ構造を作成します。

パッケージ・フォルダと必要なコンテンツを作成するには、端末ウィンドウで次のコマンドを入力します:

bots-node-sdk init <top-level folder path>

このコマンドは、次の処理を実行します:

  • 最上位フォルダを作成します。

  • componentsフォルダを作成し、hello.world.jsというサンプル・コンポーネントJavaScriptファイルを追加します。 コンポーネントJavaScriptファイルを配置する場所です。

  • package.jsonファイルを追加します。このファイルでは、main.jsをメイン・エントリ・ポイントとして指定し、@oracle/bots-node-sdkdevDependencyとしてリストします。 パッケージ・ファイルには、一部のbots-node-sdkスクリプトも指定します。

    {
      "name": "my-custom-component",
      "version": "1.0.0",
      "description": "Oracle Bots Custom Component Package",
      "main": "main.js",
      "scripts": {
        "bots-node-sdk": "bots-node-sdk",
        "help": "npm run bots-node-sdk -- --help",
        "prepack": "npm run bots-node-sdk -- pack --dry-run",
        "start": "npm run bots-node-sdk -- service ."
      },
      "repository": {},
      "dependencies": {},
      "devDependencies": {
        "@oracle/bots-node-sdk": "^2.2.2",
        "express": "^4.16.3"
      }
    }
  • パッケージ設定をエクスポートして、コンポーネントのロケーションのコンポーネント・フォルダを指すmain.jsファイルを最上位フォルダに追加します。

  • .npmignoreファイルを最上位フォルダに追加します。 このファイルは、コンポーネント・パッケージをエクスポートする際に使用されます。 パッケージから.tgzファイルを除外する必要があります。 例えば: *.tgz

  • Npmの一部のバージョンでは、package-lock.jsonファイルを作成します。

  • すべてのパッケージ依存性をnode_modulesサブフォルダにインストールします。

埋込みコンテナにデプロイする場合、パッケージは、Node.js 8.11.5およびBots Node SDK 2.2.2.と互換性がある必要があります。

このステップでは、基本的なCLIコマンドを表示します。 詳細は、https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.mdを参照してください。

ステップ3: カスタム・コンポーネントの作成およびビルド

コンポーネントJavaScriptファイルの作成

SDK CLIを使用して、コンポーネントに必要な機能を備えたJavaScriptファイルを作成します。

ターミナル・ウィンドウからパッケージの最上位フォルダへのCDを実行し、次のコマンドを入力します:

bots-node-sdk init component –-name <component name> components

Oracle Digital Assistant Node.js SDKを使用するためのフレームワークを含む<component name>.jsファイルがコンポーネント・フォルダに追加されます。

ヒント:

コンポーネントとヘルパー・ファイルをサブフォルダに配置して、コンポーネントごとにファイルを編成できます。 bots-node-sdk init component --name <component name> components/<subfolder name>を使用して、コンポーネント・ファイルを作成します。

このステップでは、基本的なCLIコマンドを表示します。 詳細は、https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.mdを参照してください。

メタデータへのコードの追加および関数の呼出し

カスタム・コンポーネント実装に必要なインタフェースは次のとおりです:

// interface for a custom component implementation
{
  metadata(): {name: string, properties?: {[name:string]: string}, supportedActions?: string[]};
  invoke(conversation: Conversation, done: () => {}): void;
}
  1. metadata関数を更新します。

    この関数は、UIのコンポーネントタブに表示されるコンポーネントの説明を提供し、ダイアログ・フローでコンポーネントを使用する方法について説明します。 メタデータを変更して、コンポーネント名(一意である必要があります)、名前と必要な入力パラメータのタイプ、およびコンポーネントが返すことができるアクション(存在する場合)を指定します。

  2. RESTのコール、リクエスト・データへのアクセス、レスポンス・データの更新およびスキルへの戻るためのコードをinvokeファンクションに追加します。

    このinvoke関数は次の2つの引数を使用します:

    • conversation。これは、Digital Assistant Node.js SDKのConversationクラスのインスタンスです。 このクラスは、https://oracle.github.io/bots-node-sdk/のSDKドキュメントで説明されています。
    • done(コンポーネントが処理を終了したときに起動するコールバック)

次に例を示します。

'use strict';

module.exports = {
    metadata: () => ({
        name: 'hello.world',
        properties: {
            human: {
                required: true,
                type: 'string'
            },
        },
        supportedActions: []
    }),
    invoke: (conversation, done) => {
        // Perform conversation tasks.
        const { human } = conversation.properties();
        conversation
            .reply(`Greetings ${human}.`)
            .reply(`Today is ${new Date().toDateString()}.`)
            .transition();

        done();
    }
};
バックエンドへのアクセス

バックエンドへのアクセスに使用できるJavaScriptモジュールが多数あります。 いくつか例を挙げます。

次のステップでは、リクエスト・モジュールを使用します。

  1. サービスがAuthorizationヘッダーを必要とする場合は、必要な情報を渡すためにメタデータに入力パラメータを追加します。
    • Basic認証の場合、ユーザー名とパスワードまたはbase-64エンコード<username>:<password>のパラメータを追加します。
    • Oracle Identity Cloud ServiceまたはOracle Access Managementを含むOAuth2の場合、アクセス・キーのパラメータを追加します。 このスキルでは、System.OAuth2AccountLinkコンポーネントを使用してこのキーを取得できます。
    • その他すべての認可タイプについて、次の2つの選択肢があります:
      • 承認コードのパラメータを追加し、コンポーネントにコードを追加してアクセス・キーを取得します。 このスキルでは、System.OAuthAccountLinkコンポーネントを使用して、認可コードを取得できます。
      • 実装から認可コードとアクセス・キーを取得します。
  2. package.jsonファイルを含むフォルダに移動し、このコマンドを入力してNode.jsリクエスト・モジュールをインストールします。
    npm install -save request
  3. 次に示すように、Node.jsリクエスト・モジュールをコードに追加します:
    var request = require('request');
  4. invoke関数の内部で、サービスにリクエストを送信します。 次に例を示します。
    
        request('<url>', {json: true }, (err, res, body) => {
    
          var weatherResponse = body;
    
          if (res.statusCode == 200) {
            ...
            conversation.transition('<action>');
            done();
          } else if (res.statusCode == 401) { 
            ...
          } else if (res.statusCode == 404) {
            ...
            conversation.transition('<action>');
            done();
          } else {
            ...
            conversation.transition('<action>');
            done();
          }
        });
SDKを使用したリクエストおよびレスポンス・ペイロードへのアクセス

Conversationインスタンス・メソッドを使用して、呼出しのコンテキストを取得し、変数を変更し、結果をダイアログ・エンジンに戻します。

いくつかの一般的なタスクにこれらのメソッドを使用するメソッドを次に示します:

操作方法 これを実行
コンポーネント・プロパティ値を取得します。 conversation.properties()をコールすると、すべてのコンポーネント・プロパティを含むオブジェクトが取得されます。
const MyCustomComponent = {module.exports = {
   metadata: () => ({
     name: 'greeting',
     properties: {
       "name": {        
         "type": "string",
         "required": true
     }    
  }   
}),
invoke: (conversation, done) => {
  // Get property values
  const { name: _name = '' } = conversation.properties();
  conversation.reply('Hello ${_name}');
  conversation.transition();
  done();
  }
}
コンテキスト変数の値を取得します。 変数名を渡すmetadataプロパティを追加してから、conversation.variable(<variable name>)をコールして値を取得します。
const { latitudeVariable } = conversation.properties();
let _latitude = conversation.variable(latitudeVariable);
プロファイル変数の値を取得します。 conversation.variable('profile.<name>')を呼び出して値を取得します。
コンテキスト変数の値を設定します。 変数名を渡すmetadataプロパティを追加してから、conversation.variable(<variable name>, <value>)をコールして値を設定します。
if (latitudeVariable) {conversation.variable(latitudeVariable, _coordinates.x);}
オブジェクトを使用して、ADDRESSなどのエンティティ・タイプである変数を更新し、エンティティ・タイプに設定されているentityNameプロパティを含めます。
if (addressVariable){
  let _AddressObject = {};
  _AddressObject['entityName'] = 'ADDRESS';
  _AddressObject['postCode'] = _zip;
  _AddressObject['state'] = _state; 
  conversation.variable(conversation.properties().addressVariable, _addressObject);
}
返信またはメッセージ・レスポンスを送信します。 conversation.reply(<payload>)を呼び出します。 ペイロードは、文字列、オブジェクトまたはMessageModelです。 この関数は複数回呼び出すことができます。 この関数を呼び出すと、keepTurnは自動的にfalseに設定されます。
ダイアログ・フローに戻ります。 transition(<optional state>)に続いてdone()を呼び出して、ダイアログ・フローに戻り、別の状態に遷移します。 transition()を使用して、フロー内の次の状態に遷移します。 それ以外の場合は、transition(<action>)(<action>はメタデータ内のsupportedActionsの1つ)を使用します。
module.exports = {
  metadata: () => ({
    name: 'verify',
    properties: {
      "address": {
        "type": "string",
        "required": false
      }
    },
    supportedActions: ['valid', 'invalid']
  }),
  invoke: (conversation, done) => {
    ...
    conversation.transition('valid');
    done();
    ...
}};
カスタム・コンポーネントにJSONオブジェクトを渡します。 カスタム・コンポーネント・メタデータで、タイプが文字列またはマップのプロパティを指定します(どちらも機能します)。 ダイアログ・フローで、次のようなFreeMarker式を使用してJSONオブジェクトを渡します:
    properties:
                object: "${myJSONObjectVarName.value}"

SDKのドキュメント全体は、https://github.com/oracle/bots-node-sdkにあります。

Digital Assistantsでコンポーネントが動作することを確認

デジタル・アシスタントの会話で、ユーザーはサブジェクトを変更することで会話フローを中断できます。 たとえば、ユーザーが購入を行うためのフローを開始した場合、ギフト・カードの残高を確認するために、そのフローを中断できます。 これは、順序が正しくないことを示します。 ユーザーの発話のレスポンスがコンポーネントのコンテキストで認識されない場合に、デジタル・アシスタントが順序なしを識別して処理できるようにするには、conversation.invalidInput(payload)メソッドを呼び出します。

デジタル会話では、ランタイムは、すべてのスキルでレスポンス一致を検索して、無効な入力がものかどうかを判断します。 一致が見つかった場合は、フローを再ルーティングします。 入力しない場合はメッセージが表示され、入力を求められた場合は、コンポーネントが再度実行されます。 新しい入力は、textプロパティのコンポーネントに渡されます。

スタンドアロン・スキル会話では、ランタイムはメッセージを表示し、入力をユーザーに要求してから、コンポーネントを再度実行します。 新しい入力は、textプロパティのコンポーネントに渡されます。

このサンプル・コードでは、入力が数値に変換されない場合は常にconversation.invalidInput(payload)がコールされます。

"use strict"
 
module.exports = {
 
    metadata: () => ({
        "name": "AgeChecker",
        "properties": {
            "minAge": { "type": "integer", "required": true }
        },
        "supportedActions": [
            "allow",
            "block",
            "unsupportedPayload"
        ]
    }),
 
    invoke: (conversation, done) => {
        // Parse a number out of the incoming message
        const text = conversation.text();
        var age = 0;
        if (text){
          const matches = text.match(/\d+/);
          if (matches) {
              age = matches[0];
          } else {
              conversation.invalidUserInput("Age input not understood. Please try again");
              done();
              return;
          }
        } else {
          conversation.transition('unsupportedPayload");
          done();
          return;
        }
 
        conversation.logger().info('AgeChecker: using age=' + age);
 
        // Set action based on age check
        let minAge = conversation.properties().minAge || 18;
        conversation.transition( age >= minAge ? 'allow' : 'block' );
 
        done();
    }
};

次に、デジタル・アシスタントが実行時に無効な入力を処理する方法の例を示します。 最初の年齢のレスポンス(twentyfive)では、デジタル・アシスタントに登録されているスキルに一致するものがないため、会話には指定されたconversation.invalidUserInputメッセージが表示されます。 2ページ目のレスポンス(send money)では、デジタル・アシスタントは一致を検出して、そのフローに再度ルーティングするかどうかを確認します。


components-nonsequitur-conversation.pngの説明が続きます
「図components-nonsequitur-conversation.pngの説明」

conversation.invalidInput()またはconversation.transition()のいずれかをコールする必要があります。 両方の操作を呼び出す場合は、追加メッセージを送信する場合は、system.invalidUserInput変数が設定されていることを確認してください。 また、System.CommonResponseSystem.TextSystem.ListSystem.ResolveEntitiesリセットsystem.invalidUserInputなどのユーザー入力コンポーネントも注意してください。

たとえば、次に示すようにAgeCheckerコンポーネントを変更して、conversation.invalidInput()の後にconversation.transition()をコールするとします。

if (matches) {  age = matches[0]; } else { 
      conversation.invalidUserInput("Age input not understood. Please try again"); 
      conversation.transition("invalid"); 
      conversation.keepTurn(true);
      done();
      return;
}

この場合、ユーザーが2つの出力メッセージを取得するように、データ・フローをaskageに戻す必要があります。 - ""Age input not understood. Please try again"に"How old are you?"が続きます。

  askage:
    component: "System.Output"
    properties:
      text: "How old are you?"
    transitions: {}
  checkage:
    component: "AgeChecker"
    properties:
      minAge: 18
    transitions:
      actions:
        allow: "crust"
        block: "underage"
        invalid: "askage"

開発環境でのコンポーネント・サービスの実行

開発フェーズ中に、ローカル・サービスを起動してカスタム・コンポーネント・パッケージを公開できます。

  1. 最上位レベルのフォルダから、ターミナル・ウィンドウを開いて、次のコマンドを実行してサービスを起動します:
    npm install
    npm start
  2. サービスが実行中であることを確認するには、ブラウザに次のURLを入力します:
    localhost:3000/components

    ブラウザにコンポーネント・メタデータが表示されます。

  3. インターネットに直接アクセスできる場合は、スキルから開発環境にアクセスできます:
    1. ngrokやLocaltunnelなどのトンネルをインストールします。
    2. プロキシの背後である場合は、プロキシの外部IPアドレスを取得するためにhttp://www.whatismyproxy.com/に移動し、トンネルの起動に使用するターミナル・ウィンドウで次のコマンドを入力します:
      export https_proxy=http://<external ip>:80
      export http_proxy=http://<external ip>:80
    3. トンネルを起動して、ポート3000を公開するように構成します。
    4. Oracle Digital Assistantで、スキルのコンポーネント・「コンポーネント」アイコンタブに移動し、メタデータURLがhttps://<tunnel-url>/componentsに設定された「外部」コンポーネント・サービスを追加します。
      ユーザー名とパスワードには任意の値を使用できます。
これで、サービス・コンポーネントの状態をダイアログ・フローに追加し、スキル・テスターからテストできます。

タスク2: サービスへのコンポーネント・パッケージのデプロイ

Digital Assistant埋込みコンテナ、「モバイル・ハブ」、またはNode.jsサーバーからカスタム・コンポーネント・パッケージをホストできます。

埋込みコンテナからコンポーネント・パッケージをホストする場合、実行する必要があるのは、コンポーネント・サービスを作成するために必要なコンポーネント・パッケージの準備のみです。 後でコンポーネント・サービスを作成して、埋込みコンテナオプションを選択すると、Digital Assistantではコンポーネント・パッケージが自動的にホストされます。 埋込みコンテナを使用しない場合は、「モバイル・ハブ」またはNode.jsサーバーにパッケージをデプロイする必要があります。

埋込みコンテナ・サービスのパッケージの準備

コンポーネント・パッケージをホストする最も簡単な方法は、パッケージしてDigital Assistant埋込みコンテナ・サービスにアップロードすることです。

埋込みコンテナ・サービスにアップロードするためのパッケージを準備するには:

  1. ボットNode.jsコマンドライン・ツールの最新バージョンがあることを確認します。

    以前のバージョンでは、パッケージとdependenciesはバンドルされていません。 埋込みコンテナでは、パッケージにすべてのdependenciesが含まれている必要があります。

  2. main.jsファイルが格納されているディレクトリで、パッケージが依存するモジュールごとに次のコマンドを実行します。 Bots Node SDKのようなdevDependenciesの場合、この操作を行う必要はありません。

    このコマンドによって、モジュールがnode_modulesフォルダに追加され、package.jsonに依存関係として追加されます。

    npm install <module>
  3. 次のコマンドを実行します。

    bots-node-sdk pack

    このコマンドでは、コンポーネント・パッケージが検証されてからTGZファイルが作成されます。このファイルは、スキルのコンポーネント・タブから埋込みコンテナ用のサービスを作成するとアップロードされます。

    コマンドは、package.jsondependenciesとしてリストされるすべてのライブラリをバンドルします。 埋込みコンテナには、devDependenciesであるBots Node SDKおよびExpressを除き、パッケージが依存するすべてのライブラリをTGZファイルに含める必要があります。

ノート

パッケージは、Node.js 8.11.5およびBots Node SDK 2.2.2.と互換性がある必要があります。

packコマンドの詳細は、https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.mdを参照してください。

モバイル・ハブにデプロイ

「モバイル・ハブ」でカスタム・コンポーネント・パッケージをホストするには、bots-node-sdk pack CLIを使用してコンポーネント・パッケージ・フォルダをコピーし、RAMLファイルを含む「モバイル・ハブ」に固有の変更をいくつか行います。 次に、RAMLファイルからカスタムAPIを作成し、コンポーネント・パッケージのZIPをカスタムAPIにアップロードします。

  1. カスタム・コンポーネント・パッケージの最上位フォルダ(main.jsファイルを含むフォルダ)から、端末ウィンドウに次のコマンドを入力します:

    bots-node-sdk pack --service mobile-api

    このコマンドは、次の操作を実行します:

    • ファイルとサブフォルダをservice-mobile-api-<package version>にコピーします。
    • 必要なエンドポイントと操作を含むcomponent.service.ramlファイルを追加します。
    • main.js用の「モバイル・ハブ」ラッパーであるapi.jsファイルを作成します。
    • メイン・ファイルをapi.jsに設定し、依存性を設定し、「モバイル・ハブ」ノード構成を追加するようにpackage.jsonファイルを変更します。

    このステップでは、基本的なCLIコマンドを表示します。 詳細は、https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.mdを参照してください。

  2. package.jsonファイルをレビューし、パッケージ名が「モバイル・ハブ」制約に準拠していることを確認します:
    • 名前は文字(A-Za-z)、数字(0-9)およびアンダースコア(_)でのみ構成される必要があります。
    • 名前は文字で開始する必要があります。
    • 名前は100文字以下にしてください。
  3. 「モバイル・ハブ」 APIページから、新規API > APIをクリックし、component.service.ramlファイルをアップロードしてカスタムAPIを作成します。

  4. セキュリティ・タブからログインが必要ですをオフにして、保存をクリックします。

  5. service-mobile-api-<package version>フォルダをZIPし、カスタム「APIの実装」タブからZIPファイルをアップロードします。