aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.12k forks source link

Amazon Lex 2 Pluggable issue for React Native #11136

Closed kshitijgodara closed 1 year ago

kshitijgodara commented 1 year ago

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

Interactions

Amplify Categories

interactions

Environment information

``` # Put output below this line System: OS: macOS 12.6.3 CPU: (8) arm64 Apple M1 Memory: 98.86 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 19.8.1 - /opt/homebrew/bin/node npm: 9.5.1 - /opt/homebrew/bin/npm Watchman: 2023.03.13.00 - /opt/homebrew/bin/watchman Browsers: Chrome: 111.0.5563.110 Safari: 15.6.1 npmPackages: @aws-amplify/ui-react: ^4.4.1 => 4.4.1 @aws-amplify/ui-react-internal: undefined () @babel/core: ^7.20.0 => 7.21.0 @babel/preset-env: ^7.20.0 => 7.20.2 @babel/runtime: ^7.20.0 => 7.21.0 @react-native-async-storage/async-storage: ^1.17.12 => 1.17.12 @react-native-community/eslint-config: ^3.2.0 => 3.2.0 @react-native-community/netinfo: ^9.3.7 => 9.3.7 @react-native-masked-view/masked-view: ^0.2.8 => 0.2.8 @react-native-voice/voice: ^3.2.4 => 3.2.4 @react-navigation/native: ^6.1.6 => 6.1.6 @react-navigation/native-stack: ^6.9.12 => 6.9.12 @tsconfig/react-native: ^2.0.2 => 2.0.3 @types/jest: ^29.2.1 => 29.4.1 @types/react: ^18.0.24 => 18.0.28 @types/react-test-renderer: ^18.0.0 => 18.0.0 HelloWorld: 0.0.1 TextGradientExample: 0.0.1 amazon-cognito-identity-js: ^6.2.0 => 6.2.0 aws-amplify: ^5.0.22 => 5.0.22 aws-amplify-react-native: ^7.0.2 => 7.0.2 babel-jest: ^29.2.1 => 29.5.0 eslint: ^8.19.0 => 8.36.0 example: 0.0.1 jest: ^29.2.1 => 29.5.0 metro-react-native-babel-preset: 0.73.8 => 0.73.8 prettier: ^2.4.1 => 2.8.4 react: 18.2.0 => 18.2.0 react-native: 0.71.4 => 0.71.4 react-native-get-random-values: ^1.8.0 => 1.8.0 react-native-linear-gradient: ^2.6.2 => 2.6.2 react-native-linear-gradient-text: ^0.3.1 => 0.3.1 react-native-safe-area-context: ^4.5.0 => 4.5.0 react-native-screens: ^3.20.0 => 3.20.0 react-native-text-gradient: ^0.1.7 => 0.1.7 react-native-tts: ^4.1.0 => 4.1.0 react-native-url-polyfill: ^1.3.0 => 1.3.0 react-redux: ^7.2.6 => 7.2.9 react-test-renderer: 18.2.0 => 18.2.0 redux: ^4.1.2 => 4.2.1 redux-thunk: ^2.4.1 => 2.4.2 typescript: 4.8.4 => 4.8.4 npmGlobalPackages: @aws-amplify/cli: 11.0.2 expo-cli: 5.4.8 ios-deploy: 1.11.4 ngrok: 4.3.1 npm: 9.5.1 ```

Describe the bug

I am trying to use Amazon Lex2 for my app. I am able to integrate LexV1 successfully but Lex2 is giving me error for pluggable.

On Calling Lex 2 Bot, I am getting this error -

Bot AWSLexV2Provider does not have valid pluggin did you try addPluggable first?

How I am calling Bot -

useEffect(() => {
    const hello = async () => {
      let userInput = 'Book a hotel';
      // Provide a bot name and user input
      try {
        const response = await Interactions.send('BookTrip', userInput);
        console.log(response.message);
      } catch (error) {
        console.log('e--- ', error);
      }
      // Log chatbot response
    };
    hello();
  }, []);

I am able to call Lex 1 bot from above code very easily.

Expected behavior

It should work as expected.

Reproduction steps

I have followed same steps -

https://docs.amplify.aws/lib/interactions/getting-started/q/platform/react-native/#lex-v2-bot

Just with manual config.

Code Snippet

// Put your code below this line.
import {Amplify} from 'aws-amplify';
import {AWSLexV2Provider} from '@aws-amplify/interactions';

Amplify.addPluggable(new AWSLexV2Provider());

const interactionsConfig = {
  Auth: {
    identityPoolId: 'us-east-1:xyz',
    region: 'us-east-1',
  },
  Interactions: {
    bots: {
      // Lex1 Bot
      BookTrip_enIN: {
        name: 'BookTrip_enIN',
        alias: '$LATEST',
        region: 'us-east-1',
      },
      //Lex2 Bot
      BookTrip: {
        name: 'BookTrip',
        aliasId: 'DAP052WT2W',
        botId: 'ZS7UQ9CRA0',
        localeId: 'en-US',
        region: 'us-east-1',
        providerName: 'AWSLexV2Provider',
      },
    },
  },
};

Log output

``` // Put your logs below this line LOG e--- Bot AWSLexV2Provider does not have valid pluggin did you try addPluggable first? ```

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

Log Error

Screenshot 2023-03-25 at 11 23 28 AM

Lex 2 Console -

Screenshot 2023-03-25 at 11 35 33 AM

Lex 1 Console

Screenshot 2023-03-25 at 11 35 51 AM
tannerabread commented 1 year ago

Hi @kshitijgodara thanks for raising this issue. I have not been able to reproduce your error yet, but I did try to go through the V2 flow and noticed that our documentation is lacking some necessary steps to get this running. Part of what is missing is the response no longer sends back a message property but rather an array of messages objects that you can access like console.log(response.messages)

Regardless, your error seems more like there is some is configured incorrectly. I do not see anything from the code you have provided but could you list how you are configuring Amplify after you define the config? Mine is set as Amplify.configure(interactionsConfig)

The only other thing I saw that was different was how you listed localeId in the config. I have it working with localeId: "en_US" rather than "en-US".

One thing I noticed that might be unrelated is that you have aws-amplify-react-native and @aws-amplify/ui-react both installed. Just so you know we now have a new UI package for react-native that is in dev preview

kshitijgodara commented 1 year ago

Yes correct. It is supposed to be en-US. But issue is not because of this.

import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';
import React from 'react';
import AppNavigator from './src/navigation/appNavigator';
import {Provider} from 'react-redux';
import store from './src/store';
import {Amplify} from 'aws-amplify';
import {AWSLexV2Provider} from '@aws-amplify/interactions';

Amplify.addPluggable(new AWSLexV2Provider());

const interactionsConfig = {
  Auth: {
    identityPoolId: 'us-east-1:XYZ',
    region: 'us-east-1',
  },
  Interactions: {
    bots: {
      Reema: {
        name: 'Reema',
        aliasId: 'XYZ',
        botId: 'XYZ',
        localeId: 'en_US',
        region: 'us-east-1',
        providerName: 'AWSLexV2Provider',
      },
    },
  },
};

Amplify.configure(interactionsConfig);

const App = () => {
  return (
    <Provider store={store}>
      <AppNavigator />
    </Provider>
  );
};

export default App;

So for me this was not working. But after trying lot of things. I tried this on my entry screen say splash -

 const provider = new AWSLexV2Provider();
 Interactions.addPluggable(provider);

Things started working fine.

But question remains same, why do we have to plug again ? And not sure documents are helpful or not

tannerabread commented 1 year ago

You shouldn't have to addPluggable twice, but are you saying that original code was in App.tsx instead of index.js?

If so that could be a problem but I'm not 100% sure on that. We do however recommend that you configure your app at the root or entry point of your project which should be index.js for a React Native project built with their CLI.

This may be good feedback for our docs if that was the only issue, can you try moving all of the following into index.js instead of App.js/tsx:

import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';

import {Amplify} from 'aws-amplify';
import {AWSLexV2Provider} from '@aws-amplify/interactions';

Amplify.addPluggable(new AWSLexV2Provider());

const interactionsConfig = {
  Auth: {
    identityPoolId: 'us-east-1:XYZ',
    region: 'us-east-1',
  },
  Interactions: {
    bots: {
      Reema: {
        name: 'Reema',
        aliasId: 'XYZ',
        botId: 'XYZ',
        localeId: 'en_US',
        region: 'us-east-1',
        providerName: 'AWSLexV2Provider',
      },
    },
  },
};

Amplify.configure(interactionsConfig);
kshitijgodara commented 1 year ago

I did tried as you said to move to index.js but same thing. Still error is same as -

WARN Possible Unhandled Promise Rejection (id: 0): "Bot AWSLexV2Provider does not have valid pluggin did you try addPluggable first?" LOG finish {"utteranceId": 105553147102464}

tannerabread commented 1 year ago

Would you be able to provide a sample repo showing this behavior so that I can see the error? I have not been able to reproduce on my own and don't see anything wrong with the code you are now using.

tannerabread commented 1 year ago

@kshitijgodara can you try importing and logging Interactions before calling addPluggable?

Now your index.js would be like:

import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';

import {Amplify, Interactions} from 'aws-amplify';
import {AWSLexV2Provider} from '@aws-amplify/interactions';

console.log(!!Interactions);
Amplify.addPluggable(new AWSLexV2Provider());

const interactionsConfig = {
  Auth: {
    identityPoolId: 'us-east-1:XYZ',
    region: 'us-east-1',
  },
  Interactions: {
    bots: {
      Reema: {
        name: 'Reema',
        aliasId: 'XYZ',
        botId: 'XYZ',
        localeId: 'en_US',
        region: 'us-east-1',
        providerName: 'AWSLexV2Provider',
      },
    },
  },
};

Amplify.configure(interactionsConfig);
cwomack commented 1 year ago

@kshitijgodara, did you get a chance to try the recommendations above? Want to circle back and see if you're still experiencing this issue.

cwomack commented 1 year ago

Hello again, @kshitijgodara. Wanted to provide some additional feedback after doing another review of this issue. In previous comments, you had mentioned that adding the Lex V2 pluggable Interactions.addPluggable(provider); to your splash screen actually works. If that's the case, it's possible this is an issue with the order of operations:

  1. await Interactions.send('BookTrip', userInput); gets called first
  2. Amplify.addPluggable(new AWSLexV2Provider()); is called after

But the proper sequence should be the following:

  1. add pluggable and configure amplify first
    
    import {Amplify} from 'aws-amplify';
    import {AWSLexV2Provider} from '@aws-amplify/interactions';
    Amplify.addPluggable(new AWSLexV2Provider());

const interactionsConfig = { Auth: { identityPoolId: 'us-east-1:XYZ', region: 'us-east-1', }, Interactions: { bots: { Reema: { name: 'Reema', aliasId: 'XYZ', botId: 'XYZ', localeId: 'en_US', region: 'us-east-1', providerName: 'AWSLexV2Provider', }, }, }, }; Amplify.configure(interactionsConfig);



2. The `send` call  should be made after the above, such as: 

`const response = await Interactions.send('BookTrip', userInput);`

For some additional context, the Interactions category supports Lex V1 by default and adding a pluggable is **_NOT_** required. However, Lex V2 is exposed as a pluggable and you would have to add the pluggable in order to access the API's it provides.  

**TLDR - This issue appears to be related to the "order of operations" and how there's default support for Lex V1 out of the box (and why it's working), but Lex V2 requires a pluggable before API's can be used.**  

Hopefully this clears everything up for you and anyone else that comes across similar issues regarding Lex V2 and Amplify's Interactions category.  I'll close out the issue at this point, but feel free to comment back with any further problems you experience.  We appreciate you opening this issue!