Алиса, пойдём во фронтенд!

Никита Дубко, Яндекс

Алиса, пойдём во фронтенд!

Никита Дубко
разработчик интерфейсов, Яндекс

Кто я?

Я не работаю в Яндекс.Диалогах

Эволюция чат-ботов: от душки Элизы до агрессивного параноика Тая

Eliza, 1966

A.L.I.C.E., 1995

IBM Watson, 2006

Tay, 2016

twitter.com/tayandyou

Боты в Telegram, 2015

Telegram Bot Platform

Голосовые ассистенты

В каждой третьей семье в США есть умная колонка

One Third of U.S. Homes Own a Smart Speaker

Алиса,
10 октября 2017

Представляем голосового помощника Алису

Встроена в

Почему?

⌨️ 30 слов в минуту

🗣 120 слов в минуту

В месяц Алисой пользуются
35 000 000 человек

Население Беларуси —
9 475 600 человек

Население Беларуси 2019
În 2021 asistenţii digitali vor fi folosiţi de 1,8 miliarde de persoane

Навыки
от разработчиков

amazon.com/alexa-skills
developers.google.com/actions
dialogs.yandex.ru/store
alice.voice-ui.ru
Создаём голосовое приложение на примере Google Assistant
Первая видеоигра для Алисы, или голосовой помощник как игровой контроллер

⏳ 1.5 секунды

Не все ли равно, о чем спрашивать, если ответа все равно не получишь, правда?

Время для демо

github.com/web-standards-ru/calendar

Технологии

import express from 'express';
import { router } from 'routes';

const app = express();

app.use('/', router);

const port = process.env.PORT || 8000;
app.listen(port, () => {
    console.log(`Server started on :${port}`);
});
dialogs.yandex.ru/development
Яндекс.Диалоги / Диалоги Алисы / Документация
// services/vendors/web-standards.js
import axios from 'axios';

const axiosInstance = axios.create({
    baseURL: 'https://web-standards.ru/',
});

export function getRemoteCal() {
    return axiosInstance.get('calendar.ics');
}
import { Router } from 'express';
import * as wst from 'services/vendors/web-standards';

export const router = Router();
router.get('/', function(req, res, next) {
    wst
        .getRemoteCal()
        .then(vendorResponse => parseCalendar(vendorResponse.data))
        .then(events => {
            res.json({ events });
        })
        .catch(next);
});
import ical from 'node-ical';

function parseCalendar(str) {
    return new Promise((resolve, reject) => {
        ical.parseICS(str, function(err, data) {
            if (err) {
                reject(err);
            }
            resolve(data);
        });
    });
}
{
    "2018-10-04-frontendconf@https://web-standards.ru/": {
        "type": "VEVENT",
        "params": [],
        "uid": "2018-10-04-frontendconf@https://web-standards.ru/",
        "sequence": "0",
        "dtstamp": "2019-05-25T21:23:50.000Z",
        "start": "2018-10-04T00:00:00.000Z",
        "datetype": "date",
        "end": "2018-10-06T00:00:00.000Z",
        "MICROSOFT-CDO-ALLDAYEVENT": "TRUE",
        "MICROSOFT-MSNCALENDAR-ALLDAYEVENT": "TRUE",
        "summary": "FrontendConf",
        "location": "Москва",
        "description": "http://frontendconf.ru/moscow/2018"
    }
}
{
    "2018-10-04-frontendconf@https://web-standards.ru/": {
        "type": "VEVENT",
        "params": [],
        "uid": "2018-10-04-frontendconf@https://web-standards.ru/",
        "sequence": "0",
        "dtstamp": "2019-05-25T21:23:50.000Z",
        "start": "2018-10-04T00:00:00.000Z",
        "datetype": "date",
        "end": "2018-10-06T00:00:00.000Z",
        "MICROSOFT-CDO-ALLDAYEVENT": "TRUE",
        "MICROSOFT-MSNCALENDAR-ALLDAYEVENT": "TRUE",
        "summary": "FrontendConf",
        "location": "Москва",
        "description": "http://frontendconf.ru/moscow/2018"
    }
}

Формат входных данных

{
    "meta": {...},
    "request": {...},
    "session": {...},
    "version": "1.0"
}
Яндекс.Диалоги / Диалоги Алисы / Документация
{
    "meta": {
        "locale": "ru-RU",
        "timezone": "Europe/Moscow",
        "client_id": "ru.yandex.searchplugin/5.80 ...",
        "interfaces": {
            "screen": {}
        }
    }
}
{
  "request": {
    "command": "закажи пиццу на улицу льва толстого 16",
    "original_utterance": "закажи пиццу на улицу льва толстого, 16",
    "type": "SimpleUtterance",
    "nlu": {
      "tokens": [ "закажи", "пиццу", "на", "льва", "толстого", "16"],
      "entities": [...]
    }
  }
}

Как она ни пыталась, она не могла найти тут ни тени смысла, хотя все слова были ей совершенно понятны.

The Turing test: Can a computer pass for a human? - Alex Gendler
[15:46:05] Judge: My favourite music is contemporary Jazz,
what do you prefer?
[15:46:14] Eugene: To be short I’ll only say that I HATE
Britnie [sic] Spears. All other music is OK compared to her.
[15:47:06] Judge: do you like to play any musical instruments
[15:47:23] Eugene: I’m tone deaf, but my guinea pig likes to
squeal Beethoven’s Ode to Joy every morning. I suspect our
neighbors want to cut his throat … Could you tell me about
your job, by the way?
[15:48:02] Judge: Guinea pig? Are you an animal lover
[15:48:08] Eugene: Yeah. A nice little guinea pig. Not some
annoying chatter bot.
Женя Густман: первый чат-бот, прошедший тест на человечность

Сценарная работа

Designing Voice User Interfaces: Principles of Conversational Experiences

Пока думаешь, что сказать, — делай реверанс! Это экономит время.

Лёгкий диалог

ЛЁГКИЙ диалог: проектируем навык для голосового помощника
book.glvrd.ru

Варкалось. Хливкие шорьки
Пырялись по наве.
И хрюкотали зелюки.
Как мюмзики в мове.

Непонятно? Уточни

Стоп-слово

Время для демо

Фразы

{
  "request": {
    "nlu": {
      "entities": [
        {
          "tokens": { "start": 2, "end": 6 },
          "type": "YANDEX.GEO",
          "value": {
            "house_number": "16",
            "street": "льва толстого",
            "city": "москва"
          }
        }
      ]
    }
  }
}

Ответ пользователю

{
    "response": {
        "text": "Привет! Это мы, JS-разработчики.",
        "tts": "Привет! Это мы, джи +эс разработчики.",
    },
    "session": {
        "session_id": "2eac4854-fce721f3-b845abba-20d60",
        "message_id": 4,
        "user_id": "AC9WC3DF6FCE052E45..."
    },
    "version": "1.0"
}

TTS

Ударение:
остр+ота, мн+ого пр+офильный.

Пауза:
Смелость - - - - - - город+а берет.

Кнопки

{
    "response": {
        "buttons": [
            {
                "title": "Frontend Conf",
                "payload": {},
                "url": "https://frontendconf.ru/moscow-rit/2019",
                "hide": false
            }
        ]
    }
}

Голоса

Завершение навыка

{
    "response": {
        "end_session": true
    }
}

Публикация навыка

dialogs.yandex.ru/developer

Тестирование

Функциональное тестирование навыков Яндекс Алисы на Node.js
const assert = require('assert');
const User = require('alice-tester');

it('should show help', async () => {
    const user = new User('http://localhost:3000');
    await user.enter();
    await user.say('Что ты умеешь?');

    assert.equal(user.response.text, 'Я умею играть в города.');
    assert.equal(user.response.tts, 'Я умею играть в город+а.');
    assert.deepEqual(user.response.buttons, [{title: 'Понятно', hide: true}]);
});
github.com/vitalets/alice-tester
Консоль разработчика
Симулятор Яндекс Станции

Локальное тестирование

https://dialogs.home.popstas.ru/?use=http://localhost:8080

dialogs.popstas.ru
Тест прокси

Приватный навык + говорить ртом

Коридорное
тестирование

Разработка без кода

Dialogflow
Dialogflower

Ещё инструменты

Как применить для сайта

FAQ

Автоматизация ответов на часто задаваемые вопросы в навыке для «Алисы»
Как создать своего бота без навыков программирования и подключить его к Яндекс.Алисе

Техподдержка

Предварительное заполнение информации

Как применить для дома

«Умный дом» с Яндекс.Алисой
Умный дом в Яндекс Алиса через IFTTT
Умный дом с Алисой. Яндекс открывает платформу для всех разработчиков

Советы

Используйте максимум информации

Думайте о приватности

Будьте креативными


github.com/MeFoDy/web-standards-calendar-alice

Полезности

Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!

Спасибо за внимание!

mefody.github.io/talks/alisa/
@dark_mefody
mefody@yandex-team.ru