natasha / yargy

Rule-based facts extraction for Russian language
MIT License
315 stars 40 forks source link

Как установить несколько атрибутов факта? #86

Open tonal opened 1 year ago

tonal commented 1 year ago

Пример - правило для ИНН Для физ.лиц - 12 цифр, для юр.лиц - 10

Хочется в конкретном правиле не только запомнить цифры, но и установить флаг - физ.лицо или юр.лицо

from yargy import and_, or_, rule
from yargy.interpretation import fact
from yargy.predicates import gte, length_eq, lte

Inn = fact(
  'INN', ['value', 'is_phis'])

INN12 = rule(
  and_(
    gte(0), lte(999999999999), length_eq(12)
  ).interpretation(Inn.value.custom(int)), #.interpretation(Inn.is_phis.const(True))
).interpretation(Inn)

INN10 = rule(
  and_(
    gte(0), lte(9999999999), length_eq(10)
  ).interpretation(Inn.value.custom(int)), #.interpretation(Inn.is_phis.const(False))
).interpretation(Inn)

INN = rule(
  rule('ИНН'), or_(INN12, INN10),
).interpretation(Inn)
kuk commented 1 year ago

Можно так

Inn = fact(
  'INN', ['value'])

class IpInn(Inn):
  type = 'ip'

class OooInn(Inn):
  type = 'ooo'

...

INN12 = ....interpretation(IpInn)
INN10 = ....interpretation(OooInn)
tonal commented 1 year ago

В этом случае после разбора тип факта будет <class 'yargy.interpretation.fact.INN'> и значение не будет содержать доп. атрибутов:

INN = rule(
  rule('ИНН'), or_(INN12, INN10),
).interpretation(Inn)

def main_test():
  from yargy import Parser
  txt = 'ИНН 7707083893'
  parser = Parser(INN)
  for match in parser.findall(txt):
    fact = match.fact
    print(type(fact), fact)

Выдача:

<class 'yargy.interpretation.fact.INN'> INN(value=7707083893)
tonal commented 1 year ago

Т. е. получается, что экземпляры фактов не переносятся, а каждый раз конструируются заново из набора изменённых атрибутов.

kuk commented 1 year ago

В этом случае после разбора тип факта будет <class 'yargy.interpretation.fact.INN'> и значение не будет содержать доп. атрибутов:


class IpInn(fact('IpInn', ['value'])):
  type = 'ip'

class OooInn(fact('OooInn', ['value'])):
  type = 'ooo'
tonal commented 1 year ago
INN = rule(
  rule('ИНН'), or_(INN12, INN10),
).interpretation(Inn) # < Вот здесь какой факт указывать?

Если указать общий предок - в нём не будет поля type. Если добавить атрибут - он не заполнится из дочерних.

kuk commented 1 year ago
Proxy = fact('Proxy', ['value'])

INN = rule(
  rule('ИНН'), or_(
    INN12.interpretation(IpInn),
    INN10.interpretation(OooInn)
  ).interpretation(Proxy.value),
).interpretation(Proxy)