Creación de un cliente personalizado mediante la API
Si ninguna de las integraciones incorporadas satisface sus necesidades, puede implementar su asistente desarrollando una aplicación cliente personalizada que interactúe con sus usuarios y se comunique con el servicio de creación de asistentes de IA.
Los SDK de Watson te ayudan a escribir código que interactúa con el constructor de asistentes de IA. Para obtener más información sobre los SDK, consulte SDK deWatson.
Configuración del asistente
La aplicación de ejemplo que creamos en implementa varias funciones simples para ilustrar cómo una aplicación cliente interactúa con el AI assistant builder. El código de la aplicación recoge las entradas y las envía a un asistente, que envía las respuestas que la aplicación muestra al usuario.
Para probar este ejemplo usted mismo, primero tiene que configurar el sencillo asistente de ejemplo al que se conecta el cliente:
- Descargue el archivo JSON de las acciones.
- Crea un asistente.
- En el nuevo asistente, abra la configuración de la acción global. Vaya a la pestaña Cargar/Descargar e importe las acciones del archivo que ha descargado.
Las acciones de ejemplo incluyen una acción para saludar al cliente en la que se le pregunta su nombre, y acciones sencillas para concertar y cancelar citas.
Obtención de información del servicio
Para acceder a las API REST del constructor de asistentes de IA, su aplicación debe poder autenticarse con IBM Cloud® y conectarse al asistente en el entorno en el que está desplegada. Debe copiar las credenciales de servicio y el ID de entorno y pegarlos en el código de su aplicación. También necesita la dirección de la instancia de servicio ( URL ) (por ejemplo, https://api.us-south.assistant.watson.cloud.ibm.com).
Para encontrar esta información:
Vaya a la página Entornos y elija el entorno al que desea conectarse.
Haga clic en el icono Configuración '
' para abrir la configuración del entorno.Seleccione Detalles de API para ver los detalles del entorno, incluida la instancia de servicio URL y el ID del entorno. Para encontrar la clave API, siga el enlace de la sección Credenciales de servicio.
Comunicarse con el servicio AI assistant builder
Interactuar con el servicio AI assistant builder desde su aplicación cliente es sencillo. Comenzamos con un ejemplo que se conecta al servicio, envía un único mensaje vacío e imprime la salida en la consola:
// 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'])
El primer paso es crear un objeto de servicio, una especie de envoltorio para el servicio del constructor de asistentes de IA.
El objeto de servicio se utiliza para enviar información de entrada al servicio y para recibir información de salida de este. Al crear el objeto de servicio, se especifica la clave de API para la autenticación y la versión de la API del generador de asistentes de IA que se está utilizando.
En este ejemplo de Node.js, el objeto de servicio es una instancia de AssistantV2 almacenada en la variable assistant. Los SDK de Watson para otros idiomas proporcionan mecanismos equivalentes para crear una instancia de un objeto de servicio.
En este ejemplo de Python, el objeto de servicio es una instancia de watson_developer_cloud.AssistantV2, almacenada en la variable assistant. Los SDK de Watson para otros idiomas proporcionan mecanismos equivalentes para crear una instancia de un objeto de servicio.
Después de crear el objeto de servicio, lo utilizamos para enviar un mensaje al asistente, mediante el método sin estado ' message. En este ejemplo, el mensaje está vacío; queremos activar la acción Saluda al cliente para iniciar la conversación, por lo que no necesitamos ningún texto de entrada. A continuación, imprimimos cualquier respuesta de texto que se devuelva en la matriz ' generic ' en la salida devuelta.
Utilice el mandato node <filename.js> para ejecutar la aplicación de ejemplo.
Utilice el mandato python3 <filename.py> para ejecutar la aplicación de ejemplo.
'Nota: ' Asegúrese de instalar el ' Watson ' SDK for Node.js ' utilizando ' npm install ibm-watson.
Nota: Asegúrese de instalar el SDK de Watson para Python utilizando ' pip install --upgrade ibm-watson o ' easy_install --upgrade ibm-watson.
Suponiendo que todo funciona como se espera, el asistente devuelve la salida del asistente, que la aplicación imprime en la consola:
Welcome to the watsonx Assistant example. What's your name?
Esta salida nos dice que nos comunicamos con el asistente y recibimos el mensaje de saludo especificado por la acción Saludar al cliente. Pero aún no tenemos cómo responder a la pregunta del asistente.
Procesamiento de las entradas del usuario
Para poder procesar la entrada de usuario, debemos añadir una interfaz de usuario a nuestra aplicación cliente. Para este ejemplo, mantendremos las cosas simples y utilizaremos la entrada y salida estándar. ' Puedes usar el módulo prompt-sync Node.js. (Puede instalar prompt-sync utilizando ' npm install prompt-sync.) Puedes utilizar la función ' input ' Python 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
}
Esta versión de la aplicación empieza igual que antes: enviando un mensaje vacío al asistente para empezar la conversación.
La función ' processResult() ' muestra el texto de las respuestas recibidas del asistente. Luego solicita el texto que rodea la entrada de usuario.
A continuación, muestra el texto de las respuestas recibidas del asistente y solicita la siguiente ronda de entradas del usuario.
El ejemplo comprueba la variable contextual global " skip_user_input y solicita la entrada del usuario sólo si esta variable no tiene el valor " true " " True. La variable ' skip_user_input ' es fijada por el asistente en algunas situaciones en las que no es necesaria la intervención del usuario (por ejemplo, si el asistente ha llamado a un servicio externo pero aún está esperando el resultado). Es una buena práctica hacer siempre esta comprobación antes de solicitar la entrada del usuario.
Como necesitamos una forma de terminar la conversación, la aplicación cliente también está atenta al comando literal ' quit ' para indicar que el programa debe salir.
Pero aún hay algo que no es correcto:
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.
>>
El asistente empieza con el saludo correcto, pero no entiende cuando le dices tu nombre. Y si le dices que quieres concertar una cita, se desencadena la acción correcta; pero, de nuevo, no entiende cuando respondes a la pregunta de seguimiento.
La razón es que estamos utilizando el método sin estado ' message ', lo que significa que es responsabilidad de nuestra aplicación cliente mantener la información de estado para la conversación. Como todavía no estamos haciendo nada para mantener el estado, el asistente ve cada ronda de entrada del usuario como el primer turno de una nueva conversación. Como no recuerda haber hecho una pregunta, intenta interpretar tu respuesta como una nueva pregunta o petición.
Mantener el Estado
La información de estado de tu conversación se mantiene utilizando el contexto. El contexto es un objeto que se pasa de un lado a otro entre tu aplicación y el asistente, almacenando información que puede conservarse y actualizarse a medida que avanza la conversación. Dado que estamos utilizando el método message sin estado, el asistente no almacena el contexto, por lo que es responsabilidad de nuestra aplicación cliente mantenerla entre los distintos turnos de conversación.
El contexto incluye un identificador de sesión para cada conversación y un contador que se incrementa con cada turno de la conversación. El asistente actualiza el contexto y lo devuelve con cada respuesta. Sin embargo, nuestra versión anterior del ejemplo no conservó el contexto, por lo que se perdieron estas actualizaciones y cada serie de entrada parecía ser el inicio de una nueva conversación. Podemos solucionarlo guardando el contexto y devolviéndolo al asistente cada vez.
Además de mantener nuestro lugar en la conversación, el contexto puede contener variables de acción que almacenen otros datos que quieras pasar de un lado a otro entre tu aplicación y el asistente. Por ejemplo, puede incluir datos persistentes que desee mantener durante toda la conversación (como el nombre o el número de cuenta de un cliente), o cualquier otro dato que desee rastrear (como el contenido de un carrito de la compra o las preferencias del usuario).
// 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
}
El único cambio con respecto al ejemplo anterior es que ahora estamos almacenando el contexto que se recibe del asistente en una variable que se llama ' context, y lo estamos enviando de vuelta con la siguiente ronda de entrada del usuario:
El único cambio con respecto al ejemplo anterior es que ahora estamos almacenando el contexto que se recibe del asistente en una variable que se llama ' context, y lo estamos enviando de vuelta con la siguiente ronda de entrada del usuario:
assistant
.messageStateless({
assistantId,
input: messageInput,
context: context,
})
response = assistant.message_stateless(
assistant_id,
input = message_input,
context = context
).get_result()
Esto garantiza que el contexto se mantenga de un turno al siguiente, de modo que el servicio de construcción del asistente de IA ya no piense que cada turno es el primero:
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!
Correcto. La aplicación utiliza ahora el servicio de creación de asistentes de inteligencia artificial para comprender las entradas en lenguaje natural y muestra las respuestas adecuadas.
Este sencillo ejemplo ilustra cómo crear una aplicación cliente personalizada para comunicarse con el asistente. Una aplicación del mundo real utilizaría una interfaz de usuario más sofisticada y podría integrarse con otras aplicaciones, como una base de datos de clientes u otros sistemas empresariales. También tendría que enviar más datos al asistente, como un ID de usuario para identificar a cada usuario único. Pero los principios básicos de cómo interactúa la aplicación con el servicio de construcción del asistente de IA seguirían siendo los mismos.