api.ai зацикливает одно и то же намерение с другим вводом
Я использую API.AI для реализации приложения-помощника, но теперь я обнаружил, что трудно зацикливаться на одном и том же намерении собирать разные пользовательские данные (поправьте меня, если мое выражение неверно, объясню это подробно.) Проблема в том, что я У меня есть список элементов, и каждый раз, когда я хочу назначить один элемент точно одному человеку (собранный с помощью input Assistant.getArgument()), я хочу, чтобы он каждый раз говорил с пользователем как "кому вы хотите назначить" элемент X к? (X относится к названию элемента в списке). Моя текущая реализация состоит в том, чтобы создать отдельную функцию, заставить ее задать вопрос, а затем выполнить сбор ввода / присваивания в другой функции, используя цикл while, в конце которого body вызывает функцию ask, но она не работает как API.AI выдает Not Available в ответе. Есть идеи, как это сделать? Дайте мне знать, если что-то неясно.
Вот лишь краткий фрагмент кода, показывающий, в чем проблема и чего я хочу достичь. Я хочу, чтобы он запрашивал 4 раза в API.AI, получал пользовательский ввод и сохранял их все в выходной строке.
var output = '';
function do_sth(assistant){
let get_name_input = assistant.getArgument('name');
output = output + get_name_input + '.';
}
function test_repeat(assistant){
for(let i = 0; i < 4; i++){
assistant.ask('What is the name?');
do_sth(assistant);
}
}
2 ответа
Проблема в том, что программирование для Assistant - это система, управляемая событиями (каждый Намерение - это событие), и вы заканчиваете обработку события на сервере с помощью assistant.ask()
или же assistant.tell()
, Это отправляет ваш ответ обратно пользователю. ask()
будет ждать другого события, пока tell()
указывает на то, что разговор окончен.
Это означает, что вы не можете поставить ask()
внутри цикла, и вы не можете сохранить результаты в локальной переменной, так как каждый ответ будет возвращаться к вам как новое событие (то есть - каждый раз новый вызов вашего webhook).
Вот способ сделать это. Он состоит из трех частей:
- Намерение (name.init на моем снимке экрана), которое используется для первого вызова webhook с действием
name.entry
и запустить цикл. - Намерение (name.loop в моем снимке экрана), которое отвечает, когда
name_loop
контекст активен, чтобы получить имя и отправить его в webhook с тем же действиемname.entry
, - Фрагмент кода для обработки
name.entry
намерение.
Код
var loopAction = function( assistant ){
const CONTEXT = 'name_loop';
const PARAM = 'name';
const VALUE = 'index';
const NUM_NAMES = 4;
// Get the context, which contains the loop counter index, so we know
// which name we're getting and how many times we've been through the loop.
var index;
var context = assistant.getContext( CONTEXT );
if( !context ){
// If no context was set, then we are just starting the loop, so we
// need to initialize it.
index = 0;
} else {
// The context is set, so get the invex value from it
index = context.parameters[VALUE];
// Since we are going through the loop, it means we were prompted for
// the name, so get the name.
var name = assistant.getArgument( PARAM );
// Save this all, somehow.
// We may want to put it back in a context, or save it in a database,
// or something else, but there are things to be aware of:
// - We can't save it in a local variable - they will go out of scope
// after we send the next reply.
// - We can't directly save it in a global variable - other users who
// call the Action will end up writing to the same place.
loopSave( index, name );
// Increment the counter to ask for the next name.
index++;
}
if( index < NUM_NAMES ){
// We don't have all the names yet, ask for the next one
// Build the outgoing context and store the new index value
var contextValues = {};
contextValues[VALUE] = index;
// Save the context as part of what we send back to API.AI
assistant.setContext( CONTEXT, 5, contextValues );
// Ask for the name
assistant.ask( `Please give me name ${index}` );
} else {
// We have reached the end of the loop counter.
// Clear the context, making sure we don't continue through the loop
// (Not really needed in this case, since we're about to end the
// conversation, but useful in other cases, and a good practice.)
assistant.setContext( CONTEXT, 0 );
// End the conversation
assistant.tell( `I got all ${index}, thanks!` );
}
};
Не вдаваясь в сложности, позвольте мне предложить вам простое решение, если я правильно понимаю, чего вы пытаетесь достичь.
Пользователю предоставляется возможность выбора из 3 домашних животных, собаки, кошки и кролика. И просят назвать их по-разному. Вы хотите достичь этого одним намерением, скажем, pet_name. Название акции pet.name.
Решение довольно простое. Создайте 3 параметра в этих целях (и сделайте все из них "обязательными", установив флажок). 3 параметра - имя собаки, имя кошки, имя кролика.
Теперь включите выполнение для этого намерения и получите все параметры в вашем веб-хуке. Теперь вы можете использовать их прямо в тексте. Например: outputtext = $dog_name."Отличное имя для вашего щенка. Расскажите подробнее"; (Вы можете активировать его, только когда action=="pet.name").