Construire un client personnalisé en utilisant l'API

Si aucune des intégrations prêtes à l'emploi ne répond à vos besoins, vous pouvez déployer votre assistant en développant une application cliente personnalisée qui interagit avec vos utilisateurs et communique avec le service de création d'assistants IA.

Les SDK d' Watson s vous aident à écrire du code qui interagit avec l'outil de création d'assistants IA. Pour plus d'informations sur les SDK, consultez la page « SDK d' Watson ».

Mise en place de l'assistant

L'application exemple que nous créons met en œuvre plusieurs fonctions simples afin d'illustrer comment une application cliente interagit avec l'outil de création d'assistants IA. Le code de l'application recueille les données et les transmet à un assistant, qui envoie les réponses que l'application montre à l'utilisateur.

Pour tester cet exemple vous-même, vous devez d'abord configurer l'exemple d'assistant simple auquel le client se connecte :

  1. Téléchargez le fichier JSON des actions.

  2. Créer un assistant.

  3. Dans le nouvel assistant, ouvrez les paramètres des actions globales. Allez dans l'onglet Upload/Download et importez les actions du fichier que vous avez téléchargé.

Les exemples d'actions comprennent une action d'accueil du client qui demande le nom du client, et des actions simples de prise et d'annulation de rendez-vous.

Obtenir des informations sur le service

Pour accéder aux API REST du générateur d'assistants IA, votre application doit pouvoir s'authentifier auprès de IBM Cloud® et se connecter à l'assistant dans l'environnement où celui-ci est déployé. Vous devez copier les informations d'identification du service et l'identifiant de l'environnement et les coller dans le code de votre application. Vous devez également indiquer l' URL e de l'emplacement de votre instance de service (par exemple, https://api.us-south.assistant.watson.cloud.ibm.com).

Pour trouver ces informations :

  1. Allez à la page Environnements et choisissez l'environnement auquel vous voulez vous connecter.

  2. Cliquez sur Icône d'engrenage l'icône Paramètres pour ouvrir les paramètres de l'environnement.

  3. Sélectionnez Détails de l'API pour voir les détails de l'environnement, y compris l' URL s de l'instance de service et l'ID de l'environnement. Pour trouver la clé API, suivez le lien dans la section Service credentials.

Communiquer avec le service de création d'assistants IA

Il est très simple d'interagir avec le service de création d'assistants IA depuis votre application cliente. Nous commençons par un exemple qui se connecte au service, envoie un seul message vide et affiche la sortie sur la console :

// Example 1: Creates service object, sends initial message, and
// receives response.

const AssistantV2 = require('ibm-watson/assistant/v2');
const { IamAuthenticator } = require('ibm-watson/auth');

// Create Assistant service object.
const assistant = new AssistantV2({
  version: '2021-11-27',
  authenticator: new IamAuthenticator({
    apikey: '{apikey}', // replace with API key
  }),
  url: '{url}', // replace with URL
});

const assistantId = '{environment_id}'; // replace with environment ID

// Start conversation with empty message
messageInput = {
  messageType: 'text',
  text: '',
};
sendMessage(messageInput);

// Send message to assistant.
function sendMessage(messageInput) {
  assistant
    .messageStateless({
      assistantId,
      input: messageInput,
    })
    .then(res => {
      processResult(res.result);
    })
    .catch(err => {
      console.log(err); // something went wrong
    });
}

// Process the result.
function processResult(result) {
  // Print responses from actions, if any. Supports only text responses.
  if (result.output.generic) {
    if (result.output.generic.length > 0) {
      result.output.generic.forEach( response => {
        if (response.response_type == 'text') {
          console.log(response.text);
        }
      });
    }
  }
}
# Example 1: Creates service object, sends initial message, and
# receives response.

from ibm_watson import AssistantV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

# Create Assistant service object.
authenticator = IAMAuthenticator('{apikey}') # replace with API key
assistant = AssistantV2(
    version = '2021-11-27',
    authenticator = authenticator
)
assistant.set_service_url('{url}') # replace with service instance URL
assistant_id = '{environment_id}' # replace with environment ID

# Start conversation with empty message.
result = assistant.message_stateless(
    assistant_id,
).get_result()

# Print responses from actions, if any. Supports only text responses.
if result['output']['generic']:
    for response in result['output']['generic']:
        if response['response_type'] == 'text':
            print(response['text'])

La première étape consiste à créer un objet de service, une sorte d'enveloppe pour le service de création d'assistants IA.

Vous utilisez l'objet de service pour l'envoi de l'entrée et la réception de la sortie du service. Lorsque vous créez l'objet de service, vous devez indiquer la clé API pour l'authentification, ainsi que la version de l'API AI Assistant Builder que vous utilisez.

Dans cet exmple Node.js, l'objet de service est une instance de AssistantV2, stockée dans la variable assistant. Les SDK Watson pour d'autres langues fournissent des mécanismes équivalents pour l'instanciation d'un objet de service.

Dans cet exemple Python, l'objet de service est une instance de watson_developer_cloud.AssistantV2, stockée dans la variable assistant. Les SDK Watson pour d'autres langues fournissent des mécanismes équivalents pour l'instanciation d'un objet de service.

Après avoir créé l'objet de service, nous l'utilisons pour envoyer un message à l'assistant, en utilisant la méthode sans état " message. Dans cet exemple, le message est vide ; nous voulons déclencher l'action Accueillir le client pour entamer la conversation, nous n'avons donc pas besoin de texte en entrée. Nous imprimons ensuite toutes les réponses textuelles renvoyées dans le tableau 'generic dans la sortie renvoyée.

Utilisez la commande node <filename.js> pour exécuter l'exemple d'application.

Utilisez la commande python3 <filename.py> pour exécuter l'exemple d'application.

Remarque : Assurez-vous d'installer le 'Watson 'SDK for Node.js ' en utilisant le 'npm install ibm-watson.

Note : Assurez-vous d'installer le SDK Watson pour Python en utilisant 'pip install --upgrade ibm-watson ou 'easy_install --upgrade ibm-watson.

En supposant que tout fonctionne comme prévu, l'assistant renvoie la sortie de l'assistant, que l'application imprime ensuite dans la console :

Welcome to the watsonx Assistant example. What's your name?

Cette sortie nous indique que nous avons communiqué avec l'assistant et reçu le message d'accueil spécifié par l'action Greet customer. Mais nous n'avons pas encore la possibilité de répondre à la question de l'assistante.

Traitement des données de l'utilisateur

Pour pouvoir traiter les entrées utilisateur, nous devons ajouter une interface utilisateur à notre application client. Pour cet exemple, nous gardons les choses simples et utilisons l'entrée et la sortie standard. Vous pouvez utiliser le module `prompt-sync` de l' Node.js. (Vous pouvez installer prompt-sync à l'aide de npm install prompt-sync.) Vous pouvez utiliser la fonction « Pythoninput 3 ».

// Example 2: Adds user input.

const prompt = require('prompt-sync')();
const AssistantV2 = require('ibm-watson/assistant/v2');
const { IamAuthenticator } = require('ibm-watson/auth');

// Create Assistant service object.
const assistant = new AssistantV2({
  version: '2021-11-27',
  authenticator: new IamAuthenticator({
    apikey: '{apikey}', // replace with API key
  }),
  url: '{url}', // replace with URL
});
  
const assistantId = '{environment_id}'; // replace with environment ID

// Start conversation with empty message
messageInput = {
  messageType: 'text',
  text: '',
};
sendMessage(messageInput);

// Send message to assistant.
function sendMessage(messageInput) {
  assistant
    .messageStateless({
      assistantId,
      input: messageInput,
    })
    .then(res => {
      processResult(res.result);
    })
    .catch(err => {
      console.log(err); // something went wrong
    });
}

// Process the result.
function processResult(result) {

  // Print responses from actions, if any. Supports only text responses.
  if (result.output.generic) {
    if (result.output.generic.length > 0) {
      result.output.generic.forEach( response => {
        if (response.response_type === 'text') {
          console.log(response.text);
        }  
      });
    }
  }

  // Prompt for the next round of input unless skip_user_input is true.
  let newMessageFromUser = '';
  if (result.context.global.system.skip_user_input !== true) {
    newMessageFromUser = prompt('>> ');
  }
  
  if (newMessageFromUser !== 'quit') {
    newMessageInput = {
      messageType: 'text',
      text: newMessageFromUser,
    }
    sendMessage(newMessageInput);
  }
}
# Example 2: Adds user input.

from ibm_watson import AssistantV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

# Create Assistant service object.
authenticator = IAMAuthenticator('{apikey}') # replace with API key
assistant = AssistantV2(
    version = '2021-11-27',
    authenticator = authenticator
)
assistant.set_service_url('{url}') # replace with service instance URL
assistant_id = '{environment_id}' # replace with environment ID

# Initialize with empty value to start the conversation.
message_input = {
    'message_type:': 'text',
    'text': ''
    }

context = None
    
# Main input/output loop
while message_input['text'] != 'quit':

    # Send message to assistant.
    result = assistant.message_stateless(
        assistant_id,
        input = message_input,
        context=context
    ).get_result()
    context = response['context']

    # Print responses from actions, if any. Supports only text responses.
    if result['output']['generic']:
        for response in result['output']['generic']:
            if response['response_type'] == 'text':
                print(response['text'])

    # Prompt for the next round of input unless skip_user_input is True.
    if not result['context']['global']['system'].get('skip_user_input', False):
        user_input = input('>> ')
        message_input = {
            'text': user_input
        }

Avec cette version, l'application débute comme précédemment, en envoyant un message vide à l'assistant pour démarrer la conversation.

La fonction " processResult() affiche le texte de toute réponse reçue de l'assistant. Elle demande ensuite la série d'entrées utilisateur suivante.

Il affiche ensuite le texte de toutes les réponses reçues de l'assistant et invite l'utilisateur à passer à l'étape suivante.

Cet exemple vérifie la variable de skip_user_input contexte globale et ne demande une saisie à l'utilisateur que si cette variable n'est pas définie sur trueTrue. La skip_user_input variable est définie par l'assistant dans certaines situations où aucune intervention de l'utilisateur n'est requise (par exemple, si l'assistant a appelé un service externe mais attend toujours le résultat). Il est conseillé de toujours procéder à cette vérification avant de demander à l'utilisateur d'entrer des données.

Comme nous avons besoin d'un moyen de mettre fin à la conversation, l'application client est également à l'affût de la commande littérale " quit pour indiquer que le programme doit se terminer.

Mais, il y a quelque chose qui ne va pas :

Welcome to the watsonx Assistant example. What's your name?
>> Robert
I'm afraid I don't understand. Please rephrase your question.
>> I want to make an appointment.
What day would you like to come in?
>> Thursday
I'm afraid I don't understand. Please rephrase your question.
>>

L'assistant commence par saluer correctement, mais il ne comprend pas quand vous lui dites votre nom. Et si vous lui dites que vous voulez prendre un rendez-vous, l'action correcte est déclenchée ; mais là encore, il ne comprend pas quand vous répondez à la question de suivi.

La raison en est que nous utilisons la méthode " message sans état, ce qui signifie qu'il incombe à notre application cliente de maintenir les informations d'état pour la conversation. Comme nous ne faisons encore rien pour maintenir l'état, l'assistant considère chaque entrée de l'utilisateur comme le premier tour d'une nouvelle conversation. Comme il ne se souvient pas avoir posé une question, il tente d'interpréter votre réponse comme une nouvelle question ou demande.

Maintien de l'état

Les informations relatives à l'état de votre conversation sont gérées en utilisant le contexte. Le contexte est un objet qui est transmis entre votre application et l'assistant, stockant des informations qui peuvent être conservées et mises à jour au fur et à mesure de la conversation. Étant donné que nous utilisons la méthode message sans état, l'assistant ne stocke pas le contexte, il est donc de la responsabilité de notre application client de le maintenir à partir d'un moment de la conversation vers le suivant.

Le contexte comprend un identifiant de session pour chaque conversation et un compteur qui est incrémenté à chaque tour de la conversation. L'assistant met à jour le contexte et le renvoie avec chaque réponse. Mais notre version précédente de l'exemple n'a pas préservé le contexte, de sorte que ces mises à jour ont été perdues, et chaque série de commentaires semble être le début d'une nouvelle conversation. Nous pouvons y remédier en sauvegardant le contexte et en le renvoyant à l'assistant à chaque fois.

Outre le maintien de notre place dans la conversation, le contexte peut contenir des variables d'action qui stockent d'autres données que vous souhaitez transmettre entre votre application et l'assistant. Par exemple, vous pouvez inclure des données persistantes que vous souhaitez conserver tout au long de la conversation (comme le nom ou le numéro de compte d'un client), ou toute autre donnée que vous souhaitez suivre (comme le contenu d'un panier d'achat ou les préférences d'un utilisateur).

// Example 3: Preserves context to maintain state.

const prompt = require('prompt-sync')();
const AssistantV2 = require('ibm-watson/assistant/v2');
const { IamAuthenticator } = require('ibm-watson/auth');

// Create Assistant service object.
const assistant = new AssistantV2({
  version: '2021-11-27',
  authenticator: new IamAuthenticator({
    apikey: '{apikey}', // replace with API key
  }),
  url: '{url}', // replace with URL
});

const assistantId = '{environment_id}'; // replace with environment ID

// Start conversation with empty message
messageInput = {
  messageType: 'text',
  text: '',
};
context = {};
sendMessage(messageInput);

// Send message to assistant.
function sendMessage(messageInput, context) {
  assistant
    .messageStateless({
      assistantId,
      input: messageInput,
      context: context,
    })
    .then(res => {
      processResult(res.result);
    })
    .catch(err => {
      console.log(err); // something went wrong
    });
}

// Process the result.
function processResult(result) {

  let context = result.context;

  // Print responses from actions, if any. Supports only text responses.
  if (result.output.generic) {
    if (result.output.generic.length > 0) {
      result.output.generic.forEach( response => {
        if (response.response_type === 'text') {
          console.log(response.text);
        }  
      });
    }
  }

  // Prompt for the next round of input unless skip_user_input is true.
  let newMessageFromUser = '';
  if (result.context.global.system.skip_user_input !== true) {
    newMessageFromUser = prompt('>> ');
  }

  if (newMessageFromUser !== 'quit') {
    newMessageInput = {
      messageType: 'text',
      text: newMessageFromUser,
    }
    sendMessage(newMessageInput, context);
  }
}
# Example 3: Preserves context to maintain state.

from ibm_watson import AssistantV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

# Create Assistant service object.
authenticator = IAMAuthenticator('{apikey}') # replace with API key
assistant = AssistantV2(
    version = '2021-11-27',
    authenticator = authenticator
)
assistant.set_service_url('{url}') # replace with service instance URL
assistant_id = '{environment_id}' # replace with environment ID

# Initialize with empty message to start the conversation.
message_input = {
    'message_type:': 'text',
    'text': ''
    }
context = {}

# Initialize with empty message to start the conversation.
message_input = {
    'message_type:': 'text',
    'text': ''
    }
context = {}

# Main input/output loop
while message_input['text'] != 'quit':

    # Send message to assistant.
    result = assistant.message_stateless(
        assistant_id,
        input = message_input,
        context = context
    ).get_result()

    context = result['context']

    # Print responses from actions, if any. Supports only text responses.
    if result['output']['generic']:
        for response in result['output']['generic']:
            if response['response_type'] == 'text':
                print(response['text'])

    # Prompt for the next round of input unless skip_user_input is True.
    if not result['context']['global']['system'].get('skip_user_input', False):
        user_input = input('>> ')
        message_input = {
            'text': user_input
        }

Le seul changement par rapport à l'exemple précédent est que nous stockons maintenant le contexte reçu de l'assistant dans une variable appelée " context et que nous le renvoyons avec la prochaine série d'entrées de l'utilisateur :

Le seul changement par rapport à l'exemple précédent est que nous stockons maintenant le contexte reçu de l'assistant dans une variable appelée " context et que nous le renvoyons avec la prochaine série d'entrées de l'utilisateur :

  assistant
    .messageStateless({
      assistantId,
      input: messageInput,
      context: context,
    })
response = assistant.message_stateless(
    assistant_id,
    input = message_input,
    context = context
).get_result()

Cela permet de conserver le contexte d'un tour à l'autre, de sorte que le service de création d'assistants IA ne considère plus chaque tour comme le premier :

Welcome to the watsonx Assistant example. What's your name?
>> Robert
Hi, Robert! How can I help you?
>> I want to make an appointment.
What day would you like to come in?
>> Next Monday
What time works for you?
>> 10 AM
OK, Robert. You have an appointment for 10:00 AM on Sep 12. See you then!

L'opération a abouti ! L'application utilise désormais le service de création d'assistants IA pour comprendre les entrées en langage naturel et afficher les réponses appropriées.

Cet exemple simple montre comment vous pouvez créer une application client personnalisée pour communiquer avec l'assistant. Une application réelle utiliserait une interface utilisateur plus sophistiquée et pourrait s'intégrer à d'autres applications telles qu'une base de données clients ou d'autres systèmes d'entreprise. Il devrait également envoyer davantage de données à l'assistant, par exemple un identifiant permettant d'identifier chaque utilisateur. Mais les principes fondamentaux régissant l'interaction entre l'application et le service de création d'assistants IA resteraient inchangés.