Перейти к содержанию

События распознавания интентов

Виды обрабатываемых событий

onIntentRecognized

Данный обработчик вызывается, когда происходит успешное распознавание интента. Можно подписаться только на события с определенным ключом интента (intentKey) или вообще все. При обработке события доступен объект с результатами распознавания, строкой ввода пользователя и ключом интента. С помощью обработчика этого события можно, например, дополнительно проанализировать строку ввода пользователя, попробовать найти в ней нужную информацию (название магазина, имя пользователя, регион и т. п.) или заранее заполнить соответствующие переменные бота.

onIntentRecognized

TypeScript
1
2
3
4
5
6
function onIntentRecognized(
  intentKey: OptionalParameter<IntentKeyType>,
  callback: (
    botEvent: IntentRecognizedEvent
  ) => Promise<void>
): void
  • intentKey — ключ интента, после успешного распознавания которого срабатывает обработчик события (см. IntentKeyType). При указании null, undefined, "*" или пустой строки обработчик вызывается при распознавании любого интента (см. OptionalParameter).
  • callback — функция, которая будет вызвана после успешного распознавания.
  • botEvent — объект события, который можно использовать в теле функции (см. IntentRecognizedEvent).

В событии также доступны некоторые возможности управления выполнением сценариев бота: Управление выполнением. Например, можно проверить, находится ли пользователь в корневом сценарии: Текущие сценарии. Также можно отметить текущую активность как обработанную: activityProcessed.

Пример

В этом примере при срабатывании интента о запросе времени работы магазина происходит попытка извлечения названия магазина из исходной строки ввода пользователя. При этом из нее отбрасываются слова, которые могут часто встречаться в вопросе, а по оставшимся словам производится нечеткий поиск по заранее известному списку названий магазинов. Если подходящее название найдено с достаточной точностью (достаточной долей уверенности), оно сразу записывается в соответствующую переменную, и название можно не спрашивать.

TypeScript
onIntentRecognized("pokupka_prodazha__chasy_raboty_magazinov", async (botEvent) => {
    if (botEvent.intentKey == 'pokupka_prodazha__chasy_raboty_magazinov') {
        context.output.variables.fuse = null;

        const userInputWords = botEvent.userInputText.toLowerCase().split(' ');
        const filteredWords = userInputWords
          .filter(w => !['время', 'часы', 'магазина', 'магазин', 'работы', 'режим', 'рабочие', 'рабочее', 'работает', 'какое', 'как']
          .includes(w));

        if (!filteredWords.length) {
          return;
        }

        const query = filteredWords.join(' ');

        const searchOptions = {
          method: 'GET',
          url: baseUrl + storesEndpointRoute,
        };

        const response = await axios.request(searchOptions);

        const fuse = new Fuse(response.data, fuseOptions);

        const searchResults = fuse.search(query);

        if (searchResults.length == 1) {
          // Если подходящий результат один, записываем его
          // в переменную бота «Название магазина»
          context.output.variables.store_name = searchResults[0].item;
        }
        else {
          // Если подходящих результатов нет или их несколько,
          // можно будет уточнить название магазина
          // с помощью отдельного элемента ввода данных,
          // используя предварительный список результатов
          context.output.variables.fuse_results = searchResults;
        }
    }
})

onIntentUnrecognized

Данный обработчик вызывается, когда происходит неуспешное распознавание интента. Можно подписаться только на события с определенной причиной неудачи (reasonKey) или вообще все. При обработке события доступен объект с результатами попытки распознавания, строкой ввода пользователя и причиной неудачи. С помощью обработчика этого события можно, например, обратиться к LLM/GPT и сгенерировать с помощью нее ответ для пользователя.

onIntentUnrecognized

TypeScript
1
2
3
4
5
6
function onIntentUnrecognized(
  reasonKey: OptionalParameter<IntentUnrecognizedReasonKey>,
  callback: (
    botEvent: IntentUnrecognizedEvent
  ) => Promise<void>
): void
  • reasonKey — причина неудачного распознавания, после которого срабатывает обработчик события (см. IntentUnrecognizedReasonKeyType). При указании null, undefined, "*" или пустой строки обработчик вызывается при любой причине неудачи (см. OptionalParameter). Возможные значения:
    • no_utterance - пустой ввод пользователя;
    • no_intents - пустой список интентов;
    • low_score - низкий score интента;
    • common_unknown - ввод пользователя определен как неизвестный;
    • special_unknown - ввод пользователя определен как соответствующий специальному неизвестному интенту.
  • callback — функция, которая будет вызвана после успешного распознавания.
  • botEvent — объект события, который можно использовать в теле функции (см. IntentUnrecognizedEvent).

В событии также доступны некоторые возможности управления выполнением сценариев бота: Управление выполнением. Например, можно проверить, находится ли пользователь в корневом сценарии: Текущие сценарии. Также можно отметить текущую активность как обработанную: activityProcessed.

Пример

В это примере мы подписываемся на событие нераспознанного интента и передаем этот ввод в Yandex GPT. На основании ответа от Yandex GPT мы формируем ответное сообщение для пользователя.

TypeScript
// Импортируем Axios.
const axios = require('axios');

// Указываем учетные данны.
const iamToken = '********';
const folderId = '********';

// Создаем HTTP-клиент.
const httpClient = axios.create({
    baseURL: 'https://llm.api.cloud.yandex.net/foundationModels/v1/completion',
    timeout: 5000,
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${iamToken}`,
        'x-folder-id': folderId
    }
});

// Создаем запрос.
const buildRequest = (messages: {}[]) => {
    return {
        "modelUri": `gpt://${folderId}/yandexgpt-lite`,
        "completionOptions": {
            "stream": false,
            "temperature": 0.6,
            "maxTokens": "2000"
        },
        messages: messages,
    };
}

// Отправляем запрос.
const sendRequest = async (request: {}) => {
    const response = await httpClient.post('', request);
    return response.data;
};

// Отправляем сообщение.
const sendMessages = async (messages: {}[]) => {
    const request = buildRequest(messages);
    return await sendRequest(request);
}

// Отправляем ввод пользователя.
const sendUtterance = async (utterance: string) => {
  const messages = [
      {
          "role": "system",
          "text": "Пользователь задал вопрос, но мы не знаем на него ответ. Ответь на этот вопрос, пожалуйста."
      },
      {
          "role": "user",
          "text": utterance
      }
  ];
  return await sendMessages(messages);
};

// Подписываемся на событие нераспознанного интента.
onIntentUnrecognized('*', async (botEvent) => {
    // Отправляем ввод пользователя в LLM.
    const result = await sendUtterance(botEvent.userInputText);

    // Формируем сообщение на основании ответа LLM для отправки пользователю.
    context.output.activities.push({
        type: ScriptActivityTypes.Message,
        text: {
            format: TextFormatTypes.Plain,
            content: result.completion.text,
        },
    });
});