| ... | ... | @@ -176,64 +176,58 @@ |
|
|
|
|
|
|
|
## 3.1 Загрузка данных Zulip и начальная предобработка
|
|
|
|
|
|
|
|
Для получения информации используется API Zulip. Полученный массив, включающий в себя темы, содержание сообщений и id авторов, записывается в текстовый файл. Далее этот файл поступает в модуль, взаимодействующий с моделью машинного обучения. В результате работы формируется рейтинг людей, которые участвовали в обсуждении определенной темы и которых сервис идентифицирует как экспертов в заданной области.
|
|
|
|
Для получения информации используется [`API` **Zulip**](https://zulip.com/api/). Полученный массив, включающий в себя темы, содержание сообщений и `id` авторов, записывается в текстовые файлы `messages.txt` и `ids.json` в директорию [`zulip/data`](https://git.miem.hse.ru/240/competence-search/-/tree/master/zulip/data).
|
|
|
|
|
|
|
|
Алгоритм получения сообщений выглядит следующим образом:
|
|
|
|
1) Программа получает id последнего сообщения, которое написано на момент выполнения программы, и записывает его в переменную «last_anchor»;
|
|
|
|
2) При помощи эндпоинта GET «/api/v1/messages» сервис циклично производит запрос на получение 4500 сообщений за раз (рисунок 17). Такое число обусловлено лимитом сервиса на единовременное получение сообщений. Вводится переменная anchor, которой присваивается id последнего написанного сообщения в запросе. Когда ее значение превышает значение параметра «last_anchor», запросы на сообщения прекращаются;
|
|
|
|
|
|
|
|

|
|
|
|
Далее этот файл поступает в модуль, взаимодействующий с моделью машинного обучения ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/trainer/train_model.py#L10)) и модель машинного обучения начинает обучаться.
|
|
|
|
|
|
|
|
3) При получении массива сообщений каждое из них обрабатывается в отдельной функции «preprocess_message». В ней происходит удаление HTML-тегов и специальных слов и предложений, которые часто повторяются в Zulip и не несут ценности для разрабатываемого сервиса, что показано на рисунке;
|
|
|
|
Алгоритм получения сообщений выглядит следующим образом:
|
|
|
|
1. Программа получает `id` последнего сообщения, которое написано на момент выполнения программы, и записывает его в переменную `last_anchor` ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/trainer/fetch_data.py#L67));
|
|
|
|
2. При помощи эндпоинта `GET` **/api/v1/messages** ([`API` **Zulip**](https://zulip.com/api/get-messages)) сервис циклично производит запрос на получение `4500` сообщений за раз ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/trainer/fetch_data.py#L40)). Такое число обусловлено лимитом сервиса на единовременное получение сообщений. Вводится переменная `anchor`, которой присваивается `id` последнего написанного сообщения в запросе. Когда ее значение превышает значение параметра `last_anchor` ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/trainer/fetch_data.py#L80)), запросы на сообщения прекращаются;
|
|
|
|
|
|
|
|

|
|
|
|
3. При получении массива сообщений каждое из них обрабатывается в отдельной функции `preprocess_message` ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/trainer/preprocess.py#L67)). В ней происходит удаление `HTML`-тегов и специальных слов и предложений, которые часто повторяются в **Zulip** и не несут ценности для разрабатываемого сервиса;
|
|
|
|
|
|
|
|
4) Если в результате сообщение является непустым и содержит больше одного слова, оно записывается в текстовый файл, в котором указываются тема и содержание сообщения. Данное действие показано на рисунке. Для определения оптимального варианта работы модели производилась запись в файл как сообщений с указанием темы, так и с ее отсутствием;
|
|
|
|
4. Если в результате сообщение является непустым и содержит больше одного слова, оно записывается в текстовый файл `messages.txt` в директорию [`zulip/data`](https://git.miem.hse.ru/240/competence-search/-/tree/master/zulip/data), в котором указываются _тема_ и _содержание_ сообщения ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/trainer/preprocess.py#L91));
|
|
|
|
|
|
|
|

|
|
|
|
5. После обработки всех сообщений, полученных при запросе, переменной `anchor` присваивается идентификатор последнего полученного сообщения.
|
|
|
|
|
|
|
|
5) После обработки всех сообщений, полученных при запросе, переменной «anchor» присваивается идентификатор последнего полученного сообщения.
|
|
|
|
## 3.2 Загрузка данных МИЭМ Wiki и начальная предобработка
|
|
|
|
|
|
|
|
## 3.2 Загрузка данных «МИЭМ Wiki» и начальная предобработка
|
|
|
|
Принцип интеграции **МИЭМ Wiki** в сервис **Поисковик компетенций** следующий: сервис собирает тексты страниц и идентификаторы авторов, затем загружает их в модель машинного обучения и, найдя наиболее релевантные статьи под запрос, выдает список их авторов.
|
|
|
|
|
|
|
|
Принцип интеграции «МИЭМ Wiki» в сервис «Поисковик компетенций» следующий: сервис собирает тексты страниц и идентификаторы авторов, затем загружает их в модель машинного обучения и, найдя наиболее релевантные статьи под запрос, выдает список их авторов.
|
|
|
|
Для сбора информации о статьях, которые пользователи пишут непосредственно в **МИЭМ Wiki**, разрабатываемый сервис использует `GraphQL API`.
|
|
|
|
|
|
|
|
Для сбора информации о статьях, которые пользователи пишут непосредственно в «МИЭМ Wiki», разрабатываемый сервис использует GraphQL API.
|
|
|
|
Специфика данного сервиса заключается в том, что помимо оригинальных страниц, написанных студентами и преподавателями, он также агрегирует информацию из сервиса «Taiga» – инструмента для управления проектами. Соответственно, при получении данных из «МИЭМ Wiki» мы по-разному обрабатываем их.
|
|
|
|
**Специфика** данного сервиса заключается в том, что помимо оригинальных страниц, написанных студентами и преподавателями, он также агрегирует информацию из сервиса **Taiga** – инструмента для управления проектами. Соответственно, при получении данных из **МИЭМ Wiki** следует обрабатывать их по-разному.
|
|
|
|
|
|
|
|
Данные из сервиса «Taiga» являются наиболее полезными, так как содержат проектную документацию, в тексте которой возможно найти фразы, подтверждающие компетентность авторов (предполагается, что, например, если человек написал руководство администратора, то он имеет компетенции в решении вопросов администрирования). Однако существуют авторы таких статей, которые не авторизованы в «МИЭМ Wiki», поэтому мы не можем напрямую брать информацию о их. Для этого мы анализируем содержание страниц на предмет наличия специального блока текста, который указывает, что данная страница поступила из сервиса «Taiga».
|
|
|
|
> Данные из сервиса **Taiga** являются наиболее полезными, так как содержат проектную документацию, в тексте которой возможно найти фразы, подтверждающие компетентность авторов (предполагается, что, например, если человек написал руководство администратора, то он имеет компетенции в решении вопросов администрирования). Однако существуют авторы таких статей, которые не авторизованы в **МИЭМ Wiki**, поэтому брать информацию о их не представляется возможным. Для этого анализируется содержание страниц на предмет наличия специального блока текста, который указывает, что данная страница поступила из сервиса **Taiga**.
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
Первоначально в модель машинного обучения загружались страницы как единые документы. Однако средняя страница содержит слишком много тем в объеме текста, что не подходит для точного выделения компетенций. Поэтому было принято решение делить страницы на более мелкие документы по подзаголовкам. Так как для создания страниц в «МИЭМ Wiki» используются два способа: HTML и Markdown разметки – программа выделяет отдельные документы по тегам заголовков.
|
|
|
|
|
|
|
|
В результате модуль по работе с моделью машинного обучения передается два файла: текстовый массив с содержанием статей и файл в формате JSON, в котором порядок документов в первом файле соответствует данным об идентификаторе самой страницы и списке ее авторов.
|
|
|
|
> Первоначально в модель машинного обучения загружались страницы как единые документы. Однако средняя страница содержит слишком много тем в объеме текста, что не подходит для точного выделения компетенций. Поэтому было принято решение делить страницы на более мелкие документы по подзаголовкам. Так как для создания страниц в **МИЭМ Wiki** используются два способа: `HTML` и `Markdown` разметки – программа выделяет отдельные документы по тегам заголовков.
|
|
|
|
|
|
|
|
Итоговый алгоритм получения данных из «МИЭМ Wiki» выглядит следующим образом:
|
|
|
|
1) Получение списка идентификаторов всех страниц «МИЭМ Wiki», используя запрос GraphQL API. Для отправки запросов используется библиотека Python «requests»;
|
|
|
|
2) Цикличное получение данных о заголовке, содержании, идентификатора страницы, email авторов каждой страницы;
|
|
|
|
3) Проверка, что идентификатор автора не равен единице (1 – это id административного аккаунта, а эта информация является нерелевантной для нашего проекта);
|
|
|
|
4) Если страница содержит специальный блок с именами авторов, характерный для документации из сервиса «Taiga», то производится обработка данных, чтобы получить список идентификаторов авторов из сервиса «Taiga»;
|
|
|
|
5) Предобработка страницы. Помимо других изменений, в этом блоке удаляются все HTML-теги, кроме тегов заголовков, так как они нужны для последующего разбиения страницы на отдельные документы;
|
|
|
|
6) Поиск авторов страниц, которые создавали или редактировали их непосредственно в «МИЭМ Wiki». Для этого программа вызывает функцию получения редакторов страницы из API «МИЭМ Wiki», показанной на рисунке.
|
|
|
|
В результате модуль по работе с моделью машинного обучения передается **два** файла: текстовый массив с содержанием статей - `wiki.txt` в директории [`wiki/data`](https://git.miem.hse.ru/240/competence-search/-/tree/master/wiki/data) , и файл в формате `JSON` - `ids.json` в директории [`wiki/data`](https://git.miem.hse.ru/240/competence-search/-/tree/master/wiki/data), в котором порядок документов в первом файле (`id` документа, или же номер строки в файле) соответствует данным об идентификаторе самой страницы в **МИЭМ Wiki** и списке ее авторов.
|
|
|
|
|
|
|
|

|
|
|
|
Итоговый алгоритм получения данных из **МИЭМ Wiki** выглядит следующим образом:
|
|
|
|
|
|
|
|
7) Добавление id пользователей Wiki в финальный список авторов;
|
|
|
|
8) Вызов функции, которая находит документы в заданной странице;
|
|
|
|
9) Разделение страницы на документы по HTML или Markdown заголовкам;
|
|
|
|
10) Обработка документа, удаление из него HTML и Markdown тегов. Функция, осуществляющая это, показана на рисунке;
|
|
|
|
1. Получение списка идентификаторов всех страниц **МИЭМ Wiki**, используя запрос `GraphQL API` ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/trainer/fetch_data.py#L82));
|
|
|
|
2. Цикличное получение данных о заголовке, содержании, идентификатора страницы, email авторов каждой страницы ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/trainer/fetch_data.py#L91));
|
|
|
|
3. Проверка, что идентификатор автора не равен единице (`1` – это `id` административного аккаунта, а эта информация является нерелевантной для нашего проекта);
|
|
|
|
4. Если страница содержит специальный блок с именами авторов, характерный для документации из сервиса **Taiga**, то производится обработка данных, чтобы получить список идентификаторов авторов из сервиса **Taiga**;
|
|
|
|
5. Предобработка страницы ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/trainer/fetch_data.py#L110)). Помимо других изменений, в этом блоке удаляются все `HTML`-теги, кроме тегов заголовков, так как они нужны для последующего разбиения страницы на отдельные документы;
|
|
|
|
6. Поиск авторов страниц, которые создавали или редактировали их непосредственно в **МИЭМ Wiki**. Для этого программа вызывает функцию получения редакторов страницы из `API` **МИЭМ Wiki** ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/trainer/fetch_data.py#L113));
|
|
|
|
7. Добавление `id` пользователей **Wiki** в финальный список авторов;
|
|
|
|
8. Вызов функции, которая находит документы в заданной странице ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/trainer/fetch_data.py#L122));
|
|
|
|
9. Разделение страницы на документы по `HTML` или `Markdown` заголовкам;
|
|
|
|
10. Обработка документа, удаление из него `HTML` и `Markdown` тегов ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/trainer/fetch_data.py#L24));
|
|
|
|
11. Запись каждого документ в текстовый файл;
|
|
|
|
12. Запись в `JSON`-файл идентификатора страницы и префиксов почт ее авторов ([код](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/trainer/fetch_data.py#L139)).
|
|
|
|
|
|
|
|

|
|
|
|
## 3.3 Загрузка данных сервиса Личный кабинет МИЭМ и начальная предобработка
|
|
|
|
|
|
|
|
11) Запись каждого документ в текстовый файл;
|
|
|
|
12) Запись в JSON-файл идентификатора страницы и префиксов почт ее авторов.
|
|
|
|
**Личный кабинет МИЭМ** хранит информацию об исследовательских и прикладных проектах факультета. Для каждого проекта программа получает его описание, список участников и набор их компетенций («вакансии»).
|
|
|
|
|
|
|
|
## 3.3 Загрузка данных сервиса «Личный кабинет МИЭМ» и начальная предобработка
|
|
|
|
«Личный кабинет МИЭМ» хранит информацию об исследовательских и прикладных проектах факультета. Для каждого проекта программа получает его описание, список участников и набор их компетенций («вакансии»).
|
|
|
|
В функции предобработки из описаний проектов программа удаляет изображения, ссылки и дополнительные символы, которые снижают качество работы модели.
|
|
|
|
|
|
|
|
В функции предобработки из описаний проектов программа удаляет изображения, ссылки, дополнительные символы, которые снижают качество работы модели.
|
|
|
|
В модель передаются три типа документов: текстовый массив с описанием каждого проекта, JSON-файл, в котором помещены данные с id проекта и соответствующему ему списком id участников, а также файл с информацией о компетенциях каждого пользователя Личного кабинета.
|
|
|
|
В модель передаются три типа документов: текстовый массив с описанием каждого проекта `projects.txt` в директории [`cabinet/data`](https://git.miem.hse.ru/240/competence-search/-/tree/master/cabinet/data), `JSON`-файл `projects_info.json` в директории [`cabinet/data`](https://git.miem.hse.ru/240/competence-search/-/tree/master/cabinet/data), в котором помещены данные с `id` проекта и соответствующему ему списком `id` участников, а также файл с информацией о компетенциях каждого пользователя Личного кабинета - `students_info.txt` в директории [`cabinet/data`](https://git.miem.hse.ru/240/competence-search/-/tree/master/cabinet/data).
|
|
|
|
|
|
|
|
# 4 Размещение приложения на сервере
|
|
|
|
|
| ... | ... | @@ -264,7 +258,7 @@ |
|
|
|
|
|
|
|
Также модель имеет внутренние методы, необходимые для работы описанных ранее основных методов. Одним из них является метод _c_tf_idf, помогающий найти слова, которые максимально ясно описывают каждый из топиков, за счёт использования информации о других группах. То есть выделяются слова, которые имеются в документах одной группы, но редко или никогда не встречаются в документах других групп.
|
|
|
|
|
|
|
|
# 5 Описание модели "Личнный кабинет МИЭМ"
|
|
|
|
# 5.2 Описание тематической модели обработки данных Личнного Кабинета МИЭМ
|
|
|
|
Для составления оценок релевантности пользователей по данным сервиса «Личный кабинет МИЭМ» был разработан программный модуль, осуществляющий поиск по ключевым словам в проектных «вакансиях» студентов.
|
|
|
|
Работа модели основана на векторизации документов с использованием TF-IDF меры. Для этого данные в «вакансиях» проходят через несколько этапов обработки:
|
|
|
|
1) Токенизация (с учетом специальных символов);
|
| ... | ... | @@ -277,4 +271,4 @@ |
|
|
|
Те же методы применяются к входному запросу, состоящему из набора слов — желаемых компетенций. Компетенции каждого пользователя сервиса «Личный кабинет МИЭМ» представляются единым документом. Из этого следует, что по токену из запроса можно обратиться ко всему столбцу TF-IDF матрицы и посчитать релевантность каждого пользователя по запрашиваемому токену. Просуммировав оценки для каждого токена из запроса, можно вычислить итоговую релевантность пользователя по всему запросу. На выходе модели итоговая оценка для каждого пользователя проходит через min-max нормализацию, чтобы иметь одинаковый вес с оценками других моделей.
|
|
|
|
Модель возвращает словарь, в котором ключи — это идентификаторы пользователей, а в значениях записаны финальные оценки релевантности пользователей вместе со списками всех проектов, в которых они участвовали.
|
|
|
|
В модели реализован метод fit, создающий и сохраняющий в памяти векторные представления всех документов в корпусе и другие необходимые для работы модели данные. Это позволяет экономить время и вычислительные мощности при запросе, так как основные вычисления и преобразования данных должны быть произведены всего один раз (до следующей подгрузки данных из сервиса).
|
|
|
|
На случай, если работа сервера будет неожиданно приостановлена, были реализованы методы save и load, позволяющие хранить все необходимые данные и параметры модели в постоянной памяти или, наоборот, загружать их. |
|
|
|
На случай, если работа сервера будет неожиданно приостановлена, были реализованы методы save и load, позволяющие хранить все необходимые данные и параметры модели в постоянной памяти или, наоборот, загружать их. |
|
|
\ No newline at end of file |