Время прочтения: 3 мин.

У меня возникла необходимость автоматизированного анализа текста постов на habr.com. Рассмотрю задачу, которая позволяет находить в заданном тексте ответы на вопросы (Context Question Answering, далее CQA).

В процессе работы над решением задачи оказался полезным сервис HuggingFace, предлагающий множество мультиязычных передобученных NLP моделей. Однако, при обработке текста на русском языке предпочтение было отдано российскому инструменту DeepPavlov, специализирующемуся на задачах NLP. Тем более, что DeepPavlov позволяет работать с NLP-моделями, представленными на HuggingFace «из коробки».

Разобью задачу на три этапа:

  1. Загрузить текст поста с habr.com.
  2. Подготовить набор вопросов из ответов.
  3. Настроить deepPavlov для решения задачи CQA.

Для получения текста постов с habr.com воспользуюсь библиотеками urllib для загрузки html-документа с сайта и bs4 для доступа к элементам. Библиотека urllib входит в состав предустановленных библиотек языка Python, а библиотеку bs4 можно установить с помощью команды:

pip install beautifulsoup4

Код для получения текста по заданному url представлю в виде функций getHtmlDocument и getTextFromHtml:

from urllib import request
def getHtmlDocument(url):
    """ Получаем html-документ с сайта по url. """
    fp = request.urlopen(url)
    mybytes = fp.read()
    fp.close()
    return mybytes.decode('utf8')
from bs4 import BeautifulSoup
def getTextFromHtml(HtmlDocument):
    """ Получаем текст из html-документа. """
    soup = BeautifulSoup(HtmlDocument,
                                                             features='html.parser')
    content = soup.find('div', {'id': 'post-content-body'})
    return content.text

Набор вопросов из ответов выглядит следующим образом:

questions = (
    'О чём пост?',
    'Какая цель поста?',
    'Какая задача решалась?',
    'Что использовалось в работе?',
    'Какие выводы?',
    'Что использовалось?',
    'Какие алгоритмы использовались?',
    'Какой язык программирования использовали?',
    'В чём отличия?',
    'Что особенного проявилось?',
    'Какова область применения?',
    'Что получено?',
    'Каков результат?',
    'Что получено в заключении?',
)

Далее перейду к настройке deepPavlov для решения задачи СQA. Установлю библиотеку deeppavlov в соответствии с официальным сайтом проекта:

pip install deeppavlov, transformers

Импортирую объекты configs и build_model с помощью команд:

from deeppavlov import configs, build_model

Далее инициализирую загрузку модели squad_ru_bert командой:

model = build_model('squad_ru_bert', download=True)

Модель squad_ru_bert — это модель глубокого обучения на основе архитектуры BERT, обученная на наборе данных SQuAD-Ru, который содержит пары вопрос-ответ на русском языке.

Выберу посты с habr.com:

paper_urls = (
'https://habr.com/ru/articles/339914/',
'https://habr.com/ru/articles/339915/',
'https://habr.com/ru/articles/339916/',
)

и воспользуюсь моделью squad_ru_bert для построения ответов на указанные выше вопросы (questions) для каждого поста из списка paper_urls:

for url in paper_urls:
    content = getTextFromHtml(getHtmlDocument(url))
    for q in questions:
       answer = model([content], [q])
       if abs(answer[2] – 1) > 1e-6:
    print(q, ' ', answer[0])

Результатом работы модели является:

— фрагмент текста, который является ответом на заданный вопрос на основании текста,

— позиция этого ответа в тексте и качество полученного результата. Примеры «удачных» ответов, по моему мнению, на вопросы отмечены зелёным цветом на рисунках 1-3.

Рисунок 1 — Результат, полученный для статьи https://habr.com/ru/articles/339914
Рис. 1 Результат, полученный для https://habr.com/ru/articles/339914
Рисунок 2 — Результат, полученный для статьи https://habr.com/ru/articles/737312
Рисунок 2 — Результат, полученный для https://habr.com/ru/articles/737312
Рисунок 3 — Результат, полученный для статьи https://habr.com/ru/articles/267733
Рисунок 3 — Результат, полученный для https://habr.com/ru/articles/267733

Итак, я рассказал о решении задачи авто анализа текста на habr.com с помощью deepPavlov и модели squad_ru_bert.