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).

Вот способ сделать это. Он состоит из трех частей:

  1. Намерение (name.init на моем снимке экрана), которое используется для первого вызова webhook с действием name.entry и запустить цикл.
  2. Намерение (name.loop в моем снимке экрана), которое отвечает, когда name_loop контекст активен, чтобы получить имя и отправить его в webhook с тем же действием name.entry,
  3. Фрагмент кода для обработки name.entry намерение.

name.init

name.loop

Код

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").

Другие вопросы по тегам