Мой блог

Консоль Сети намерений

Консоль Сети Намерений

Для того, чтобы понять как работает сеть намерений нам потребуется консоль https://intention.tech.

Взаимодействие между компонентами консоли построено на основе сети намерений. Во вкладке Намерения вы можете увидеть все намерения про которые консоль знает. Сеть намерений не предполагает наличие единого центрального сервера. Она раздается только сервером статики. Вместо этого она будет работать с Хранилищем намерений, которое ей предоставите вы.

Консоль рассчитана на голосовое управление и использует google speech recognition. Пожалуйста, разрешите ей работать с вашим микрофоном.

Начало работы
  • Понадобится nodejs https://nodejs.org
  • Создайте проект в вашей любимой IDE. С одним пустым файлом main.js
  • В рабочей папке проекта, в консоле выполните npm init, чтобы создать package.json
  • Через консоль установите npm пакет "Хранилище намерений"
     npm i intention-storage
                        
Собственное хранилище намерений

Добавьте этот код в файл main.js Таким образом вы создадите сервер и хранилище намерений

    const { IntentionStorage } = require('intention-storage');
    const intentionStorage = new IntentionStorage();
    const storageServer = intentionStorage.createServer({ address: 'localhost' });
    console.log(`Server listens on port ${storageServer.port}`);
            

В рабочей папке проекта запустите проект на выполнение

    node main.js
            

Если все прошло без ошибок вы должны увидеть запись "Server listens on port 10010"
10010 - это порт по-умолчанию для всех хранилищ намерений.

Чтобы консоль могла работать с вашей сетью намерений - она должна знать хотя бы один сервер из вашей инфраструктуры

Для этого попросите консоль добавить хранилище
Вы можете сказать: "Добавить хранилище локалхост"
Не обязательно передавать команду дословно. Важно передать смысл
Такой вариант тоже сойдет: "Уважаемая консоль. Не добавишь ли ты хранилище локалхост"
Если все пройдет успешно. То вы переключитесь на вкладку Хранилища.
Во вкладке появится запись localhost:10010 online

Распознавание голоса

Следующим шагом мы научимся забирать голосовой и текстовый ввод из консоли. Для этого нам необходимо зайти в консоль, открыть вкладку "Намерения" и найти Намерение "Забираю пользовательский ввод с микрофона или клавиатуры"
Обратите внимание на ключ HTMLTextAreaElement - Recognition
Это означает, что на вход это намерение хочет получить HTML элемент textarea, из которого будет забирать пользовательский ввод с клавиатуры. А на выходе оно выдает распознавание голоса с микрофона или пользовательский ввод в html элемент, если таковой был передан.
Чтобы подключиться к этому намерению - нам нужно создать встречное намерение с противоположным ключем на нашем хранилище.

    intentionStorage.createIntention({
        title: {
            en: 'Recognition test',
            ru: 'Тест распознавания'
        },
        input: 'Recognition',
        output: 'HTMLTextAreaElement',
        onData: async function onData(status, intention, value) {
            if (status != 'data') return;
            console.log(value);
        }
    });
            

Перезапустите проект
Как только ваше хранилище снова окажется в статусе online все, что вы говорите в микрофон или пишете в окне пользовательского ввода, выведется в консоль вашего проекта.

Вывод данных в консоли

Допустим, необходимо вывести сообщение во все консоли, которые мы найдем.
Сейчас у нас только одна консоль - intention.tech. Но в роли консоли может выступать сервер, подключенный к большому экрану, почтовый клиент, мобильный телефон. Дла этого в консоли управления необходимо найти намерение с текстом "Отправляю данные в пользовательскую консоль". Это намерение пишет данные в диалоговое окно в правом нижнем углу. Обратите внимание на его ключ ContextText - None. Он означает, что на входе это намерение ожидает получить текст и контекст диалога, а на выход оно ничего не отправляет.
Нам необходимо создать намерение в проекте с обратным ключем.

const iPost = intentionStorage.createIntention({
    title: {
        en: 'Console test',
        ru: 'Тест консоли'
    },
    input: 'None',
    output: 'ContextText',
    onData: async function onData(status, intention, value) {
        console.log(status, intention.title);
    }
});


let count = 0;
setInterval(() => {
    count++;
    iPost.accepted.send({
        context: 'Test',
        text: `Hello${count}`,
    })
}, 10000);
        

Для простоты будем слать сообщение, с увеличивающимся индексом во все подключенные консоли.
Перезапустите проект и через некоторое время вы увидите, как консоль управления медленно заполняется бестолковыми сообщениями.
А теперь возьмите вкладку в браузере, в котором открыта консоль управления и продублируйте ее. Или откройте на другом устройстве. Вы увидите увидите как сообщения начинают поступать во все открытые консоли.

Структуризация

В действительности, при распознавании голоса, консоль не пытается напрямую извлечь команды из распознанного текста. Вместо этого она пытается извлечь из текста сущности, которые она знает и сопоставить их с намерениями пользователя, о которых она знает. Это позволяет строить контекстно-зависимые диалоги. Соответственно, первый вопрос, который возникает - "Как преобразовать текст в известные сущности?"
Откройте консоль управления и найдите намерение с текстом "Я возвращаю известные сущности из пользовательского ввода".
Обратите внимание на его ключ Recognition - Entities. Это значит, что на вход намерение принимает распознанный текст, а на выходе возвращает известные сущности. Добавьте следующий код.

intentionStorage.createIntention({
    title: {
        en: 'Structuring test',
        ru: 'Тест структурирования'
    },
    input: 'Entities',
    output: 'Recognition',
    onData: async function onData(status, intention, value) {
        if (status == 'accept')
            intention.send('data', this,
            { text: `Уважаемая консоль не могла бы ты добавить,
                     пожалуйста, хранилище локалхост`
            });

        if (status == 'data')
            console.log(value);
    }
});
        

Все просто. Мы отправляем Намерению текст, а обратно получаем массив распознанных сущностей.

Своя структуризация

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

intentionStorage.createIntention({
    title: {
        en: 'My structurization',
        ru: 'Моя структуризация'
    },
    input: 'Recognition',
    output: 'Entities',
    onData: async function onData(status, intention, recognition) {
        if (status != 'data') return;
        //recognition - может быть строкой с текстом;
        console.log(recognition);
        //Может быть объектом и тогда поле text будет содержать распознанный текст
        if (recognition.text != null)
            console.log(recognition.text);
        //Если текст распознан, то в поле alternatives будет массив
        //с другими возможными вариантами.
        if (recognition.alternatives != null)
            console.log(recognition.alternatives);
        const text = (recognition.text != null) ? recognition.text : recognition;
        //На этом этапе можно сделать, например, полнотекстовый поиск в
        //базе данных в таблице городов.
        const ltext = text.toLowerCase();
        const res = [];
        //Но здесь я просто привожу к нижнему регистру
         //и делаю прямой поиск вхождения подстроки
        if (ltext.indexOf('москва') != -1) {
            res.push({
                type: 'city', // - Сообщаем, что это город.
                name: { // - имя объекта
                    general: 'Moscow',
                    en: 'Moscow',
                    ru: 'Москва'
                },
                //Здесь можно вернуть любую дополнительную информацию,
                //связанную с объектом
                longitude: 55.753215,
                latitude: 37.622504
            });
        }
        if (res.length > 0) {
            //Как только сущности определены, возвращаем результат обратно.
            intention.send('data', this, res);
        }
    }
});
        

Теперь зайдите в intention.tech и скажите фразу содержащую город Москва. Этот код обнаружит город и вернет соответствующий объект. Кроме того, если вы не стерли предыдущий пример, то вы обнаружите, что он тоже реагирует на вашу структуризацию. Измените отправляемый текст и добавьте туда слово "Москва". Вы получите в ответе объект города.

Итоги

Консоль работает в окружении браузера
Ваше приложение исполняется у вас на компьютере в окружении node.js

11 мая2019