Статья актуальна для версий сервисов Ario 2020.11-2021.02
Сервисы Directum Fact Extractor Learn и Rules извлекают значения фактов в том виде, в котором они явно представлены в извлеченном текстовом слое. Поэтому в результатах работы данных сервисов можно получить, например:
Постобработка фактов позволяет:
Постобработка пишется на языке Python. Реализуется класс, в котором уже описывается вся логика по постобработке фактов. Для удобства в дальнейшем будем называть такие классы форматтерами.
В Directum Ario существует 2 вида постобработки фактов:
Основной вид постобработки, который применяется ко всем фактам определенного типа, независимо от того, какая грамматика сработала или для какого класса документа происходит извлечение.
В данном виде постобработки не следует фильтровать или удалять значения полей фактов. Основная цель такого способа - это привести все поля факта к единому формату, который однозначно будет восприниматься информационной системой, в которую попадут данные от Directum Ario.
Приведение к единому формату также подразумевает и очищение извлеченные значений от лишних распознанных символов, которые не относятся к факту.
Например, извлеченные факты «21.01.2020-» и «21 января 2020» таким образом приводятся к одному виду: «21.01.2020»
Для того, чтобы написать свой форматтер для определенного типа факта, необходимо:
Пример пути для установленных сервисов Ario: "C:\inetpub\Ario\FactExtractorService\formatters\fact_formatters"
Наименование файла может быть любым, но лучше придерживать стандарта наименования:
{наименование факта}_{наименование поля факта}_formatter.py
Пример: "document_currency_formatter.py"
Если в файле будет описана постобработка сразу для всех полей факта, то {наименование поля факта} нужно опустить.
Подробнее о шагах 3
и 4
будет рассказано далее.
Для разработки форматтера вам необходимы знания языка Python и понимание 3-х основных вещей:
Пример: "DocumentCurrencyFormatter"
from formatters.fact_formatters.fact_formatter_base import FactFormatterBase
__call__
.Данный метод получает на вход 2 аргумента:
Примечание. Для повышения читабельности вашего кода выносите большую по объему логику в отдельные методы.
Пример форматтера для постобработки поля Currency
факта DocumentAmount
:
"""Форматтер валюты суммы """
import re
from formatters.fact_formatters.fact_formatter_base import FactFormatterBase
class DocumentCurrencyFormatter(FactFormatterBase):
"""
Приведение валюты сумму к числовому коду
Валюта Код
руб 643
доллар 840
евро 978
йена 392
"""
def __init__(self):
super().__init__()
# код валюты: написание валюты
# буквы в большом регистре не используем, в форматере приводим строку к нижнему регистру
self.currency = {
'643': [
r'^[рp][yу][6бbоo]\.?$',
r'^[рp][yу][6бb][\.,][кk][оo0][пn][\.,]?$',
r'^[рp]\.?$',
r'^рубле[ий]\.?$',
r'^ру[б]?л[ья][х]?$',
r'^ru[br]$',
r'^[pр]осс[иы][йи]ский ру[б6оo]л[ьъ]\.?$',
r'^[pр]осси[йи]ский$',
r'^[yу6s]{2}\.?',
r'^[рp][yу][g]nen'
],
'840': [
r'[\$]',
r'^usd$',
r'^доллар$',
r'^доллар сша$',
r'^дол\.?$'
],
'978': [
'^евро;?$'
],
'392': [
'^jpy'
]
}
def __call__(self, fact):
currency_field = self.get_fact_field(fact, 'Currency')
if currency_field is not None:
for currency_code in self.currency.keys():
stop_flag = False
for pattern in self.currency[currency_code]:
pattern_obj = re.compile(pattern)
# проверяем currency_field.value, т.к. ранее был применен CleanValueFormatter
currency_field.value = pattern_obj.sub(currency_code, currency_field.value.lower())
if currency_field.value == currency_code:
stop_flag = True
break
if stop_flag:
break
После разработки форматтера остается только указать его в конфигурации сервиса:
Пример пути для установленных сервисов Ario: "C:\inetpub\Ario\FactExtractorService"
formatters.json
Рис. 1. Пример добавления класса DocumentCurrencyFormatter
для факта DocumentAmount
.
Данный вид постобработки применяется ко всем фактам, извлеченным для определенной грамматики. Основная цель - применить необходимую бизнес-логику на обработку извлеченных фактов. Примером может быть фильтрация/удаление значений тех полей фактов, которые по определенным причинам не должны попасть в конечную информационную систему.
Следует понимать, что постобработка по типу грамматики срабатывают после постобработки по типу факта. Благодаря этому при разработке форматтера для грамматик можно быть уверенным, что данные вам пришли уже в определенном формате.
Разработка форматтера по типу грамматики очень схожа с разработкой по типу факта. Далее представлен краткий алгоритм с описанием основных отличий между данными процессами:
Наименование файла: {наименование факта}_{наименование поля факта}_grammar_formatter.py
from formatters.formatter_base import FormatterBase
__call__
, но вместо аргумента fact на вход подается аргумент facts, который содержит данные по всем фактам и их полям, которые были извлечены данной грамматикой.Пример форматтера для удаления пустых значений поля Number
факта Document
, применяемый для множества грамматик:
"""Форматтер правил номера документа."""
from formatters.formatter_base import FormatterBase
class DocumentNumberGrammarFormatter(FormatterBase):
def __call__(self, facts):
self.facts = facts
self.process_document_number()
return self.facts
def process_document_number(self):
facts = []
# Список всех простых номеров
for fact in self.facts:
field = self.get_fact_field_by_type(fact, 'Number')
if field is not None:
facts.append(fact)
for fact in facts:
fields = self.get_fact_fields_by_type(fact, 'Number')
for field in fields:
if field.value is None or len(field.value) == 0:
fact.fields.remove(field)
if len(fact.fields) == 0:
self.facts.remove(fact)
return
Для добавления разработанного форматтера в конфигурацию грамматики:
formatters.json
добавляем наименование разработанного классаРис. 2. Пример добавления класса DocumentNumberGrammarFormatter
для грамматики Letter
.
Авторизуйтесь, чтобы написать комментарий