Первоначальное проектирование
[!important] Что если в принципе иметь только один сервис разметки? Он может обслуживать MSP и Witisi. Мы хотим одну базу тегаторов, имеем один аккаунт VkVision и один аккаунт Eldarius. Только CompetitorService поднимается свой для каждого инстанса. Здесь только CompetitorService является проблемой. Но можно сходить в нужный CompetitorService, в зависимости от настроек распознавания для этого проекта.
С приоритетом не до конца достигаем цели. Например, одновременно льют два альбома, а мы обрабатываем подписки последовательно.
Постановка
Репозиторий: https://rr-git.gitlab.yandexcloud.net/media/recognitionservicenew Беклог: http://tfs/RR/RR/_workitems/edit/47667 Проектирование интеграции с новой системой распознавания Задача: http://tfs/RR/RR/_workitems/edit/50100 Объединение сервисов распознавания и тегирования "сервис разметки" https://docs.google.com/document/d/1BxIAsX0BpxIKpPsCMcgQtCGHLRXZcTZihhutXtueOs/edit?tab=t.0#heading=h.xs5i51uyprw6 Первоначальное проектирование: https://www.notion.so/akolgashkin/2a2cc2338ce7805cadf5f35a782bf7f9
Косвенная связь: [[Очистить таблицы Photo и PhotoTag в PhotoService от лишних данных (TagatorId)]]
Сейчас мы размечаем фотографии тремя сервисами - RecognitionService (распознавание лиц), TaggingService (делегирование задач на автотегирование и ручное тегирование), TagatorService (ручное тегирование).
- RecognitionService
- Подписывается на событие PhotoPublished из фотосервиса.
- Создает у себя фотографию.
- Распознает фотографию в VkVision или Eldarius и отправляет персоны в PhotoService.
- TaggingService
- Подписывается на событие PhotoPublished из фотосервиса.
- Создает у себя фотографию.
- Запускает обработку фотографии.
- Создает таски на авто и ручное тегирование, если их нет.
- Меняет статус фотографии на Processing.
- Получает стратегию альбома и отдает ей фотографию на обработку.
- При завершении любой задачи (авто или ручное):
- Получает стратегию альбома и отдает ей фотографию на обработку.
- Стратегия, получив фотографию на обработку, делегирует нужную задачу (авто или ручное) исполнителю, или же, если все нужные задачи завершены, переводит фотографию в статус Processed.
- Отправляет теги с обработанных фотографий в PhotoService.
- TagatorService
- Получает задачи от TaggingService.
- В порядке приоритета распределяет задачи между активными тегаторами, разделяя их на работы по 10 задач и выделяя тегатору на обработку одной работы около 6-10 минут.
- Если работа не завершена тегатором в установленное время, она автоматически завершается, незавершенные задачи попадают в общий пулл и будут переданы другим тегаторам.
- Предоставляет API/инструменты для работы кабинета тегатора.
Необходимо объединить сервисы TaggingService и RecognitionService в один "сервис разметки". Распознавание лиц и номеров на фотографиях должны происходить в ==едином сценарии==.
Множественность реализаций распознавания. Лица можно распознать с помощью ==VkVision== или ==Eldarius==. Номера можно распознать с помощью ==Eldarius== или ==ручного тегирования==. При этом внешний провайдер может выбираться в зависимости от настроек на альбоме. VkVision распознает только лица и возвращает результат сразу в ответе на запрос распознавания. Eldarius может распознавать лица и номера, при этом позволяет распознать их одним вызовом, но результаты не возвращаются сразу, а поступают асинхронным колбеком.
Стратегии распознавания. Варианты "стратегий", которые работают сейчас:
- Лицо
- Лицо; Авто и ручное вместе
- Лицо; Сначала авто, потом ручное (при плохом результате авто)
- Лицо; Только авто
- Лицо; Только ручное ==Распознавание лиц должно быть необязательным.==
Изменение стратегии распознавания. Сейчас при изменении стратегии тегирования запускается джоба, которая ==перебирает все фотографии== этого альбома. Этот процесс может быть длительным, и высок риск проблем в это время с этим альбомом. В новой реализации нужно ==избежать== перебора всех фотографий. Необходимо минимизировать нагрузку на БД и систему. При изменении настроек распознавания получить только фотографии, которые потребуется распознавать. Для этого необходимо иметь возможность по записи фотографии в базе понять, требуется ее обработка или нет. Тогда провайдер обработки должен сам получать фотографии из базы, т.к. только он знает критерии выборки. Сами параметры можно хранить в отдельных полях фотографии (например, FaceRecognized, NumberRecognized, и т.д.). Важно, что стратегия (настройки распознавания) тегирования может измениться в любой момент, даже в процессе обработки этого альбома. Тогда текущий процесс обработки должен остановиться, а новый начаться, при этом новый процесс не должен заново делать ту работу, которая уже сделана предыдущим процессом.
Валидация результатов. Сейчас при авто тегировании мы получаем результат и проверяем его по стартовому списку. При этом проверка простейшая - в результатах оставляем только номера, имеющиеся в стартовом списке, и если после этого остался хоть один номер, принимаем этот результат корректным. При плохом результате распознавания фотография может уйти на ручное тегирование, как реализовано сейчас, в зависимости от стратегии. При доступности результатов распознавания всех типов в одном месте появятся дополнительные возможности валидации данных.
[!info] Перспективная доработка Возможен сценарий, когда на фото несколько персон, но после валидации мы оставили только один номер. Возможно, такой результат нужно считать некорректным и отправить фотографию на ручное тегирование. Это мы можем понять, сравнив количество полученных номеров и количество лиц.
Разрядность. Также сейчас используем механизм учета разрядности номера. В Eldarius передаем разрядность, и если Eldarius видит в номере меньше символов, чем указано в разрядности, он не присылает этот номер в результатах.
Custom tags. Этот механизм необходимо сохранить.
Приоритет распознавания. Приоритет нужно распространить на любой тип распознавания, в том числе на распознавание лиц и автоматическое распознавание стартовых номеров.
Большой объем и бесконечное хранение данных. В сезон за неделю загружаются сотни тысяч фотографий, и все фотографии дублируются в TaggingService, RecognitionService, TagatorService. Таким образом, и без того большие объемы данных многократно дублируются. Эти данные нужны только для распознавания альбома и в дальнейшем для различных отчетов. Результаты распознавания попадают в PhotoService в виде тегов и хранятся там вечно, а данные отчетов нужно в течение некоторого времени, пока не завершили обработку альбома и не рассчитались с тегаторами. После этого в сервисе распознавания эти данные не нужны. Нужно понять, в течение какого времени нужны эти данные (например, для отчетов, для взаиморассчетов с тегаторами и с Eldarius), реализовать механизмы агрегирования данных для отчетов (для их долгосрочного хранения) и автоматического удаления данных, потерявших актуальность.
- Мы периодически удаляем руками данные тегирования.
- Маркетолог предложил идею агрегировать данные.
- Нужно узнать у менеджеров, какие данные им нужны длительное время, а какие можно удалить, через какой период можно удалить, и как часто или по каким триггерам агрегировать данные и удалять исходные данные.
Синхронизация данных. Многократное дублирование данных приводит к необходимости синхронизации изменений между разными базами. Это расходует ресурсы и создает нагрузку на базу данных. Примеры синхронизации:
- При удалении фотографии нужно забирать работу у тегаторов.
- При удалении тегов одного тегатора в фотосервисе нужно удалять их в TagatorService, чтобы не оплачивать эту работу тегатора.
- При удалении плохой работы тегатора хорошо бы передать эти фотографии другому тегатору.
[!caution] Перспективная доработка (или уже реализовано?) При удалении плохой работы тегатора хорошо бы передать эти фотографии другому тегатору.
Оптимизация работы с базой данных. При создании фотографии в TaggingService сейчас создаются таски и фото переводится в статус Processing - это чтение из базы и запись в нее. После этого по подписке фото уже обрабатывается - это новое чтение из базы и запись в нее. Нужно избавиться от этого промежуточного статуса. Поскольку мы уже прочитали фото из базы и будем писать в нее, между этими процессами нужно сделать максимум полезной работы. Например, при этом можно распознать фото в VkVision и сразу сохранить результат, или делегировать фото на распознавание в Eldarius.
Оптимизация работы с Redis, минимизация использования задач Hangfire. При создании фотографии создаем джобу Hangfire. Таким образом, для обработки большого количества фотографий нужно много памяти в Redis. Если она закончится, обработка фотографий тоже сломается. Однако, при получении фотографии сервис разметки может обрабатывать ее сразу. Если обработка завершилась ошибкой, запланировать обработку джобой, а подписку завершить. При этом, если Redis недоступен, и не получилось запланировать джобу, подписка упадет и выполнится снова. Таким образом, при недоступности Redis мы продолжим обработку фотографий.
Механизм задач. Сейчас лица можно распознать с помощью VkVision, а номера - с помощью Eldarius и ручного тегирования. До сих пор это ложилось на архитектуру с тасками. Но теперь Eldarius может распознавать и лица, и номера. В таком случае, если лица распознаем в VkVision, то нужна отдельная таска на это. Но если распознаем в Eldarius, и при этом нужно распознать еще и номера, нужна условная "таска", с которой можно получить и лица и номера одновременно. Исходя из этого, текущая реализация задач должна быть пересмотрена.
Сложность реализации. Текущая реализация процесса распознавания избыточно сложная. Необходимо поддерживать работоспособность длинной цепочки обработки фотографии между несколькими сервисами.
Почему не следует объединять TagatorService
Этот сервис предоставляет функционал, специфический для ручного тегирования. Тезисы против объединения:
- TagatorService может в единственном экземпляре обслуживать потребности MSP, ByMSP, Witisi.
- TagatorService может стать отдельным направлением бизнеса и обслуживать интересы любых внешних сервисов.
- TagatorService может быть заменен на любой сторонний сервис, и интересы продукта Media от этого никак не пострадают.
[!info] Единая база тегаторов Мы регулярно копируем учетки тегаторов с прода MSP на прод Witisi. Фотографии Witisi всегда тегируются общим пулом тегаторов. Давно просится разработка с единой базой тегаторов. Было бы неплохо реализовать это в новой архитектуре.
Разрядность
Почему разрядность оставляем на стороне Eldarius?
Нам выгоднее иметь разрядность на нашей стороне.
- Таким образом мы можем получить от Eldarius и сохранить у себя все видимые теги, а уже на нашей стороне отсечь их по разрядности. В том числе можем отсекать в любой момент, подгоняя результат распознавания под наиболее приемлемый.
- Иногда менеджеры ошибаются с разрядностью, и в таком случае приходится менять разрядность и распознавать альбом снова, что требует сложной ручной работы, т.к. у нас нет системных инструментов повторного распознавания альбома.
[!caution] Нужно оценить необходимость инструментов повторного распознавания альбома. Например, если менеджер ошибся с разрядностью, или существовала и была исправлена какая-либо ошибка на стороне Eldarius, и т.д. Такая же проблема с тегаторами. Если они сделали работу, но мы объяснили им неправильно, меняем описание и снова отправляем альбом на повторное тегирование, при этом первоначальную работу оплачиваем.
Но в таком случае возникает проблема с взаиморасчетами. Для нас приемлемыми считаются только теги, подходящие по разрядности. Если будем учитывать разрядность на нашей стороне, у Eldarius не будет валидных данных, какие теги мы приняли к учету. Поэтому разрядность оставляем на стороне Eldarius.
Пайплайны:
- Сначала авто, потом ручное
- Забери лица у VkVision
- Забери номера у Eldarius
- Результаты Eldarius проверь по стартовому списку, отсутствующие номера удали
- Если получено 0 номеров
- Забери номера у ручных тегаторов
- Отключено
- Ничего не делай
- Только авто (VkVision и Eldarius)
- Забери лица у VkVision
- Забери номера у Eldarius
- Только авто (Eldarius)
- Забери лица и номера у Eldarius
Приоритет
Приоритет реализуется на нашей стороне в сервисе разметки. Таски в TagatorService и Eldarius мы отдаем в порядке приоритета. TagatorService учитывает приоритет, Eldarius - нет. Из этого вытекают проблемы:
- Проблема 1. Если мы сгрузили в Eldarius много тасок, и в Eldarius скопилась большая очередь обработки, при смене приоритета определенного альбома это не повлияет на Eldarius. ====Мы этим не управляем.====
- Проблема 2. Если у нас есть отдельная таблица Callback. Если Eldarius сгрузил нам много тасок, и у нас скопилась большая очередь на обработку колбеков. Сейчас мы подписываемся на событие и обрабатываем сразу, поэтому при смене приоритета определенного альбома это не повлияет на очередь обработки событий. Можно обрабатывать не по событиям, а сделать pooling таблицы колбеков. В таком случае в этой части приоритет будет учитываться, но ====это усложняет реализацию====.
- Проблема 3. Если поменяли разрядность, и если есть фича переотправки фото на авто распознавание при изменении разрядности. Тогда фотки переотправим, но у Eldarius нет приоритета, и если у него большая очередь распознавания, эти фотографии будут распознаны после этой очереди без приоритета.
Приоритет используется на нашей стороне только для передачи в TagatorService. При загрузке фотографии в фотосервис - RecognitionService получает событие PhotoPublished и создает фотографию. После этого получает доменное событие PhotoCreated и запускает обработку. Здесь приоритет не учитывается. Из этого вытекают проблемы:
- Проблема 1. Если нам грузят очень много фотографий, мы не успеваем их обрабатывать и имеем большую очередь, обрабатывать фотографии будем в порядке их создания, без учета приоритета. Соответственно, и в Eldarius отдадим фотографии без учета приоритета. Чтобы это исправить, нужно сделать pooling таблицы фотографий с учетом приоритета. ====Это усложняет реализацию====.
Похоже на то, что с учетом всех этих проблем, при реализации сервиса мы не получаем дополнительной ценности в плане приоритета - учитываем его только в TagatorService, как и сейчас. А поскольку решение этих проблем требует значительных усложнений, проговорили, что приоритет выносим отдельно и продумаем после реализации сервиса.
Как прокинуть PhotographerId и ShootingDate в TagatorService
В сервисе разметки эти данные не нужны, но для ручного тегирования необходимы.
Какие плюсы от объединения сервисов?
Tenant или Project
Заявлена идея, что этот сервис может распознавать фото не только продукта Media, но и любого другого продукта. Тогда понятие Tenant лучше заменить на понятие Project. Тогда сервис становится полностью универсальным и независимым, и может быть как частью продукта, так и внешним по отношению к продукту провайдером.
Идея для реализации
Пример реализации в репозитории https://rr-git.gitlab.yandexcloud.net/media/recognitionservicenew.