В своем выступлении по API машинного обучения на Google I / O я показал демонстрацию Twitter в реальном времени. Демонстрация отображает поток твитов на определенную тему в реальном времени с частями речи и настроениями последнего твита, а также некоторыми агрегированными данными по всем твитам, просмотренным на данный момент:
В этом посте я подробно расскажу о демоверсии и дам вам обзор Natural Language API. Если вы хотите перейти к коду, перейдите в репозиторий GitHub (он находится в подкаталоге nl-firebase-twitter
).
Как работает демо
На бэкэнде я написал сервер Node, который транслирует твиты с помощью API потоковой передачи Twitter. Он отправляет текст каждого твита в Natural Language API и записывает ответ NL API как в Firebase для нашей панели мониторинга в реальном времени, так и в BigQuery для анализа, когда мы закончим сбор данных. Архитектура выглядит примерно так:
Потоковая передача твитов в реальном времени
Давайте рассмотрим несколько фрагментов кода с каждого шага диаграммы, начиная с сервера Node. Используя пакет twitter npm, я создаю клиента со своими учетными данными API и транслирую твиты, содержащие несколько поисковых запросов:
const searchTerms = 'googleio,googlecloud,firebase'; client.stream('statuses/filter', {track: searchTerms, language: 'en'}, function(stream) { stream.on('data', function(event) { callNlApi(event); }); });
Когда я получаю новый твит, API возвращает данные для каждого твита, включая текст, пользователя, хэштеги, часовой пояс и т. Д.
Вызов API естественного языка
Имея текст твита, я готов вызвать NL API с помощью модуля npm request. Мой запрос JSON выглядит так:
{ "document": { "type": "PLAIN_TEXT", "content": tweet.text }, "features": { "extractSyntax": true, "extractEntities": true, "extractDocumentSentiment": true } }
Я использую все 3 функции NL API: аннотацию синтаксиса, извлечение сущностей и анализ тональности (подробнее об этом в следующем разделе). Получив ответ, я форматирую его, чтобы записать результаты в Firebase и BigQuery - для каждого из них формат будет немного другим.
Сохранение данных NL в Firebase
Я объединяю данные, возвращаемые из Twitter API (текст твита и местоположение), с данными из NL API (синтаксис, сущности, тональность) и сохраняю их в объекте для записи в Firebase:
let tweetDataForFirebase = { id: tweet.id_str, text: tweet.text, user: tweet.user.screen_name, user_time_zone: tweet.user.time_zone, user_followers_count: tweet.user.followers_count, hashtags: tweet.entities.hashtags, tokens: body.tokens, score: body.documentSentiment.score, magnitude: body.documentSentiment.magnitude, entities: body.entities }
Сохранить его в Firebase очень просто. Сначала нам нужно инициализировать модуль firebase-admin
для нашего приложения для записи в нашу базу данных Firebase:
var admin = require("firebase-admin"); var serviceAccount = require("./service-acct.json"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "https://your-firebase-project-id.firebaseio.com" });
Затем мы создадим ссылку на путь в нашей базе данных, где мы хотим сохранить твит:
const db = admin.database(); const latestTweetRef = db.ref('latest');
Я буду хранить только полные данные JSON для последнего твита. Запись этого в Firebase - это всего лишь одна строка кода:
latestTweetRef.set(tweetDataForFirebase);
У меня есть слушатель на этом /latest
пути, и всякий раз, когда добавляется новый твит, я проверяю прилагательные и хэштеги, подсчитываю их и веду общий счет каждого прилагательного и хэштега, обнаруженного в Firebase:
Сохранение данных NL в BigQuery
Мы будем записывать в BigQuery те же данные, что и в Firebase, но JSON.stringify()
хэштеги, токены и объекты, поэтому они будут строками в нашей таблице BigQuery. С инициализированным BigQuery (документация о том, как это сделать здесь), мы можем записать данные твита в нашу таблицу:
table.insert(bqRow, function(error, insertErr, apiResp) { if (error) { console.log('err', error); } else { console.log('successfully added the row!'); } });
Теперь мы можем запросить данные, чтобы найти, например, наиболее распространенные прилагательные, используемые для описания машинного обучения. Поскольку данные наших токенов хранятся в виде строк JSON, мы воспользуемся функцией UDF BigQuery для их анализа:
SELECT COUNT(*) as adj_count, adjective FROM JS( (SELECT tokens FROM [sara-bigquery:googlenext_17.tweets] ), tokens, "[{ name:'adjective', type: 'string'}]", "function(row, emit) { try { x = JSON.parse(row.tokens); x.forEach(function(token) { if (token.partOfSpeech.tag === 'ADJ') { emit({ adjective: token.lemma.toLowerCase() }); } }); } catch (e) {} }" ) GROUP BY adjective ORDER BY adj_count DESC LIMIT 100Visualizing tweet data in realtime
Визуализация данных твита в реальном времени
Помните, как наш сервер Node хранил данные для последнего твита, а также количество каждого хэштега и прилагательного в Firebase? Пора визуализировать эти данные на клиенте! Полный код находится здесь, я лишь выделю несколько ключевых моментов.
Сначала я прикрепляю слушателя к узлу /latest
в моей базе данных Firebase, чтобы обновлять пользовательский интерфейс последнего твита всякий раз, когда приходит новый:
database.ref('latest').on('value', function(data) { let tweet = data.val(); let currentScore = tweet.score; // Display the latest nouns, verbs, and adjectives in the UI // Update the currentScore scale to reflect latest tweet sentiment });
Затем я прикрепляю слушателя к пути /tokens/ADJ
в своей базе данных, чтобы обновить диаграмму прилагательных (диаграмма построена с использованием Chart.js):
adjRef.orderByValue().limitToLast(10).once('value', function(data) { let chartLabels = []; let chartData = []; data.forEach(function(token) { let word = token.key; chartLabels.push(word); chartData.push(token.val()); }); var ctx = document.getElementById("adjChart"); // Create ChartJS chart here });
Я делаю то же, что и выше, для пути /hashtags
, чтобы создать аналогичную диаграмму. Вот и все!
Что такое API естественного языка?
Если вы зашли так далеко, вам может быть интересно: что это за NL API и что я могу с ним делать? NL API помогает понять значение текста с помощью одного вызова API. В частности, он предоставляет три метода:
- Анализировать объекты: извлекать из текста такие объекты, как люди, достопримечательности и организации. Этот метод возвращает данные о типе объекта, его важности в контексте документа и URL-адрес Википедии для объекта, если он существует.
- Анализируйте тональность: узнайте, является ли ваш текст положительным или отрицательным, и насколько сильна общая тональность текста. Также есть новая бета-функция, которая обеспечивает тональность на основе сущностей, чтобы получить представление о конкретных сущностях в вашем тексте. Вот пример предложения Мне понравились суши, но обслуживание было ужасным:
- Аннотировать синтаксис: получайте лингвистические данные о своем тексте, такие как части речи, деревья зависимостей (какие слова зависят друг от друга) и дополнительные данные морфологии. Это полезно для анализа того, как люди говорят на определенную тему.
Начните работу с NL API
Вот несколько ресурсов, чтобы начать использовать NL API:
- "Документация"
- Раздел из моего выступления по вводу-выводу о NL API
- Код для демонстрации панели управления Twitter (см. Подкаталог
nl-firebase-twitter
)
Я хотел бы услышать, что вы думаете! Дайте мне знать в комментариях или найдите меня в Twitter @SRobTweets.