В этой серии статей описывается, как обнаруживать и нормализовать временные выражения (выражения даты) в тексте на французском языке. В этой статье, последней в серии, описывается, как создать небольшое веб-приложение для решения этой проблемы. Приложение состоит из серверной части, написанной с помощью Python FastApi; интерфейс на Javascript. Мы не будем вдаваться в подробности о Javascript или внешнем интерфейсе. Вместо этого мы кратко опишем задачи, отвечающие за внешний интерфейс; затем мы покажем вам, как выглядит веб-страница.

5. Демонстрационное приложение

5.1 Пример использования

Предположим, у нас есть документы наших клиентов в нашей базе данных. Такими документами могут быть платежные сертификаты (для медицинской страховки), отчеты о действиях пользователей, пользовательская история торгов и т. д. Наши клиенты могут отправить нам сообщение по электронной почте или в Центр поддержки с просьбой предоставить свои документы, соответствующие периоду.

  • "Возьмите резюме по транзакциям в прошлом году".
  • "Требуется сертификат на 3 последних срока службы svp!"
  • "Je voudrais requireer un document pour décembre et janvier derniers svp."
  • Документ Pouvez-vous m’envoyer un document pour février à mars 2020 et depuis le mois d’octobre 2021 svp ?
  • Документ, который может быть отправлен мне, для того, чтобы semaine prochaine svp ?

Мы хотели бы иметь инструмент для преобразования всех этих требований в существенный период. Например, предположим, что сегодня 21 февраля 2022 года, тогда ответом на эти запросы должны быть следующие полузамкнутые интервалы (в формате ГГГГ-ММ-ДД):

  • [2022-02-21, 2022-02-22),
  • [2021-11-21, 2022-02-22),
  • [2021-12-01, 2022-01-01) и [2022-01-01, 2022-02-01) (или [2021-12-01, 2022-02-01), если мы объединим эти два интервала)
  • [2020-02-01, 2020-04-01) и [2021-10-01, 2022-02-02)
  • [2022-02-22, 2022-03-02)

5.2 Демонстрационное приложение

В следующем GIF мы представляем такое приложение.

Пользователь может ввести любой текст на французском языке в текстовом поле в левой половине экрана. Следующие разделы появятся в правой половине, когда они нажмут на «Посланник» (Отправить на французском языке).

  • (1) Графическое представление
  • (2) Прогноз по модели машинного обучения
  • (3) Прогноз по модели машинного обучения (в формате кортежа)
  • (4) Выведенные периоды

Рабочий процесс следующий.

ML Model (backend) -> (2) -> Convert to an object (like JSON) -> (3) -> Post process to retrieve absolute dates -> (4) -> Represent with graphics -> (1)

Точнее,

  • (2): мы извлекаем необработанные выходные данные из модели машинного обучения, которая представляет собой наши знаменитые нормализованные временные выражения, определенные в статье 2 и обученные, как описано в статье 3.
  • (3): тот же необработанный вывод, что и (2), но переписанный в формате структурированного объекта для лучшей обработки машиной.
  • (4): объекты в (3) подвергаются постобработке путем обращения к текущему дню для получения правильных периодов.
  • (1): Мы представляем объекты в (4) в виде удобных для пользователя графиков благодаря доступным библиотекам.

Раздел (1) предназначен для конечных пользователей, а (2), (3), (4) больше предназначен для разработчиков, чтобы понять рабочий процесс.

5.3 Реализация: серверная часть

Серверная часть приложения отвечает за получение запроса пользователя (некоторый свободный текст) и вызов модели машинного обучения для возврата прогнозов (то есть списка нормализованных временных выражений). Следовательно, нам нужно написать один API для этой цели. Мы хотели бы иметь такой API:

(Если вы знакомы с FastAPI, на приведенном выше рисунке показана известная документация Swagger, связанная с нашим приложением FastAPI).

Другими словами, мы пишем API, чтобы любой POST запрос к пути /api/v1/temporal_expressions в объекте JSON, содержащем запрос пользователя в поле «texts», должен был получить ответ, содержащий временные выражения в поле «preds», например:

{
  "preds": [
    "REL DIR - CURRENT D0"
  ],
  "context": {
    ...
  }
}

(Некоторая дополнительная информация о времени обработки, коде состояния и т. д. может быть добавлена ​​в context. В любом случае они не являются основными.)

Пишем API в одном main.py файле:

5.4 Реализация: внешний интерфейс

Серверная часть возвращает только нормализованные выражения (например, REL DIR - CURRENT D0). Все задачи постобработки в потоке:

ML Model (backend) -> (2) -> Convert to an object (like JSON) -> (3) -> Post process to retrieve absolute dates -> (4) -> Represent with graphics -> (1)

(упомянутые в разделе 5.2) делегированы внешнему интерфейсу (все написаны на TypeScript). Кратко опишу алгоритмы для каждого шага и дам ссылку на исходный код:

  • 5.4.1. Преобразование нормализованных выражений в объекты JSON. Мы преобразуем такие строки, как
ABS DIR - PAST M2

в объект как

{
    "type": "ABS",
    "value": [
      {
        "unit": "M",
        "value": 2
      }
    ],
    "mode": "DIR",
    "tense": "PAST"
  }

Алгоритм прост: разбиваем строку на элементы и ищем в словаре:

{
    ABS:    "type",
    REL:    "type",
    DUR:    "type",
    FREQ:   "type",
    NONE:   "type",
    DIR:    "mode",
    IND:    "mode",
    FROM:   "anchor",
    TO:     "anchor",
    BEFORE: "anchor",
    AFTER:  "anchor",
    PREV:   "tense",
    NEXT:   "tense",
    PAST:   "tense",
    FUTURE: "tense",
    CURRENT:"tense",
    START:  "partial",
    MID:    "partial",
    END:    "partial",
    LESS:   "approximation",
    MORE:   "approximation",
    APPROX: "approximation",
    FIRST:  "ordinal",
    LAST:   "ordinal"
}

Если термин присутствует в словаре, поместите его в соответствующее поле (например, «время»: «ПОСТ»). В противном случае проверьте, имеет ли он формат единица + число, затем поместите эти значения в поле «значение» (например: «M10 D7» должно стать «value: [{unit: M, value: 10}, {unit: D, value: 7}]».

Исходный код: Функция getNormalizedTempExp в этом файле.

  • 5.4.2 Постобработка для получения абсолютных дат: чтобы получить окончательные даты из временных выражений и исходной даты (например, сегодня): никакого волшебства, нам нужно рассмотреть каждый отдельный случай type , tense и value, как описано в таблице в конце раздела 3.

Исходный код: Функция getRealDate в этом файле.

Обратите внимание, что мы не обрабатываем ключевые слова. BEFORE, AFTER (для анкеров); START, MID, END (для частичного); LESS, MORE, APPROX (для приближения) здесь. Кроме того, мы не имеем дело со временем (час, минута, секунда) и днями недели, как указано в разделе 2. Понятие «первая, вторая неделя в месяце» также лениво представлено как «день с 1 по 7», "день с 8 по 14" соответствующего месяца, тогда как мы должны изучить его более внимательно.

  • 5.4.3 Графическое представление: Наконец, для представления периодов под графиком мы используем временные шкалы библиотеки apexcharts. Библиотека поддерживает фреймворки Angular, ReactJS и VueJS, а также чистый JS. Можете посмотреть, если интересно.

Резюме

Мы подошли к концу серии «Обнаружение и нормализация темпоральных выражений во французском тексте». Мы надеемся, что дорожная карта, которой мы следовали, понятна нашим читателям: создание набора данных с нуля, определение формата этикетки и аннотации, моделирование (обучение) и создание приложения для практического применения. Некоторая идея обобщения по теме с нашей стороны продолжается: более интересные варианты использования, связи между временем и временем или временем и событиями — мы надеемся вскоре увидеть вас в следующей серии.

Ссылки

Подтверждение

Спасибо нашим коллегам Al Houceine KILANI и Ismail EL HATIMI за рецензию на статью.

О

Нхут ДОАН НГУЕН работает специалистом по данным в La Javaness с марта 2021 года.