Это вторая часть статьи про голосового помощника. Первую часть можно наути тут.

База данных

Теперь про сохранение вопросов и ответов. Структура данных Trie хорошо подходит, чтобы быстро определять есть ли у нас такой вопрос в базе и каков ответ. Для хранения узлов дерева и связей между ними я воспользовался графовой базой данных Dgraph. Я создал бесплатное облачное хранилище на dgraph.io. Схема для TrieNode выглядит следующим образом:

type TrieNode  {
    id: ID! 
    text: String! 
    isEnd: Boolean!
    isAnswer: Boolean!
    isRoot: Boolean! @search 
    nodes: [TrieNode] 
}

Параметр search нужен, чтобы это поле индексировалось и можно было быстро найти корень дерева запустив запрос:

const query = `
   query {
     roots(func: eq(TrieNode.isRoot, true))
     {
       uid
     }
   }
`;

Для отправки запросов я воспользовался библиотекой dgraph-io/dgraph-js-http, а для получения всех дочерних элементов для узла запросом:

const query = `
   query all($a: string) {
     words(func: uid($a))
     {
       uid
       TrieNode.nodes {
         uid
         TrieNode.text
         TrieNode.isAnswer
         TrieNode.isEnd
         TrieNode.isRoot
       }
     }
   }
`;

Это всё, что потребовалось, чтобы обходить дерево в глубину. В случае, если вопрос заканчивается словом, для которого существует узел со свойством isEnd равным true, ответом будет его дочерний элемент со значением true для поля isAnswer. Кроме результатов запроса dgraph-js-http возвращает дополнительную информацию в поле extensions, например server_latency, которое можно мониторить по ходу наполнения базы данных большим количеством узлов.

Чтобы настроить доступ сервиса к базе данных нам нужен URL, его можно найти наверху главной страницы хранилища.

Второй необходимый параметр - это API ключ. Его нужно создать в разделе Settings, во вкладке API Keys:

Docker и Nginx

Для удобства разработки, я добавил docker и nginx. Соответствующие файлы конфигураций можно найти в github репозиторие qsAndAs. Три значения в разделе environment для сервиса, которые нужно заполнить, чтобы всё заработало - это

Ненормативная лексика

Нецензурные слова и выражения я решил взять из английского языка.

Для начала я проверил насколько Text-to-Speech защищён от использования английского мата. Заменил фразу “I don't have an answer for you!” на “F**k off! I don't have an answer for you!” и получил корректный аудио файл без какой-либо цензуры. Потоя я спросил “why did that son of a b*tch insult my family?” и опять получил полную расшифровку. Потом я попробовал несколько фраз из отрывка “Tony, you motherfkers!” из известного сериала и опять всё получилось.

Вместо заключения

  1. За всё время создания и тестирования моего проекта я не заплатил ни копейки; 

  2. За исключением случаев, когда аудио, которое отправлялось на расшифровку, я сам едва ли мог понять, Speech-to-Text отработал на отлично;

  3. Я попробовал расшифровать часовой диалог программистов, загрузив его в Google Cloud Storage. Результат получился не безупречным, но наличие возможности добавить адаптивные модели к расшифровке должно улучшить результат;

  4. Работать с google cloud было удобно, как через веб-интерфейс, так и через gcloud CLI, но я предпочитаю интерфейс;

  5. Приятно удивило меня наличие бесплатного аккаунта в облаке для Dgraph;

  6. Веб-интерфейс Dgraph оказался удобным, а возможность играть с запросами и мутациями через Ratel очень ускорила моё обучение. Должен сказать, что до этого я не имел возможности попробовать графовые базы данных;

  7. По трудоёмкости, оказалось, что рабочий прототип можно сделать за одни выходные. А с учётом наличия рабочих примеров для обращения к google cloud для Go, Java, Python и Node.js, технологии для прототипа можно выбрать из очень широкого списка;

  8. В дальнейшем можно заменить Trie на классификатор текста в Vertex AI;

Комментарии (2)


  1. Nomad1
    16.03.2022 03:20
    -5

    А что он говорит про П*тина?


  1. IMasha-bot
    17.03.2022 21:37

    Я вот тоже своего бота учил материться, на мой взгляд так веселее :) Интересно было сделать транслейт ту мат. Оказалось не так все это и просто... Ели у кого есть наработки, поделитесь. у меня пока получается типа того:

    test_phrase - 'сделали плохую, ракету. она очень быстро взлетела очень высоко, а потом упала'

    translate_to_mat - 'запиздюрили дерьмоебанную ракету она невзъебенно впизду блять быстро взлетела охуенно высоко а потом захуярилась', 'захуярили пиздопротивную ракету бля буду она ебанарот невзъебенно нахуй быстро взлетела впизду блять невзъебенно высоко а потом пизданулась бля буду', 'заебашили свинозалупастую ракету она охуенно быстро взлетела бля буду охуенно высоко а ебанарот потом пизданулась'

    красиво материться трудно... ну иногда весело получается