def test_checks(): tokenizer = MorphTokenizer() with pytest.raises(ValueError): gram('UNK').activate(tokenizer) with pytest.raises(ValueError): custom(lambda _: True, types='UNK').activate(tokenizer)
def test_checks(): tokenizer = MorphTokenizer() context = Context(tokenizer) with pytest.raises(ValueError): gram('UNK').activate(context) with pytest.raises(ValueError): custom(lambda _: True, types='UNK').activate(context)
def req_reflexive(reflexive_status: str = "?"): def is_reflexive_verb(verb: str): return verb.endswith("ся") or verb.endswith("сь") if reflexive_status == "1": return yp.custom(is_reflexive_verb) if reflexive_status == "0": return y.not_(yp.custom(is_reflexive_verb)) elif reflexive_status == "?": return yp.true() else: raise ValueError("Incorrect reflexive status")
def __init__(self): super(NerTimeCount, self).__init__() self.last_request = None self.last_result = [None, None, None] self.name = 'TimeCount' # переводим числа от 1 до 59 в текст n2t60 = [n2t(i) for i in range(1, 60)] # для поиска порядковых числительных def not_coll_numbers(x): return ('NUMR' in str(morph.parse(x)[0].tag) and ('Coll' not in str(morph.parse(x)[0].tag))) or x == 'один' # часы в словах hours_t = and_(dictionary(n2t60[:24] + ["полтора", "полдень"]), custom(not_coll_numbers)) # минуты в словах minutes_t = dictionary(n2t60) coll_numbers_dic = dictionary( ["двое", "трое", "четверо", "пятеро", "шестеро", "семеро"]) list_0n = {"00", "01", "02", "03", "04", "05", "06", "08", "09"} # часы в цифрах hours_n = or_(and_(gte(1), lte(23)), in_(list_0n)) # минуты в цифрах minutes_n = or_(and_(gte(1), lte(59)), in_(list_0n)) # разделитель в чч_мм two_points = dictionary([":"]) separator = dictionary([":", "."]) # определяем предлоги pr_v = rule("в") pr_ok = rule("около") pr_vrayone = morph_pipeline(["В районе"]) pr_k = rule("к") pr_na = rule("на") pr_c = rule("с") start_prepositions = or_(pr_ok, pr_v, pr_k, pr_na, pr_c, pr_vrayone) pr_vtech = morph_pipeline(["в течение"]) pr_do = rule("до") pr_po = rule("по") duration_prepositions = or_(pr_vtech, pr_do, pr_po) # отрезки времени суток day_periods = or_(rule(normalized("утро")), rule(normalized("день")), rule(normalized("вечер"))) # час - особый случай, т.к. сам обозначает определённое время или длительность(аналогично "человк") hour = rule(normalized("час")) people = rule(normalized("человек")) # слова перед временем начала start_syn = dictionary([ "начало", "старт", "встреча", "переговорную", "переговорку", "пропуск" ]) start_verbs = dictionary([ "начать", "прийти", "заказать", "забронировать", "выделить", "состоится" ]) # слова перед продолжительнотью duration_verbs = dictionary(["займёт", "продлится"]) # слова перед временем конца end_verbs = dictionary(["закончить", "уйдём", "завершим"]) end_syn = dictionary(["конец", "окончание", "завершение"]) # для поиска времени начала, которое выделяется с помощью : или - start_with_separator = or_(rule("начало"), rule("старт"), rule("время"), morph_pipeline(["начало встречи"]), morph_pipeline(["старт встречи"]), morph_pipeline(["время встречи"])) duration_with_separator = or_( rule("продолжительность"), morph_pipeline(["продолжительность встречи"])) end_with_separator = or_(rule("конец"), rule("окончание"), rule("завершение"), morph_pipeline(["конец встречи"]), morph_pipeline(["окончание встречи"]), morph_pipeline(["завершение встречи"])) # относительные указатели на день(относительно сегодняшнего) day_pointer = or_(rule("понедельник"), morph_pipeline(["пн."]), rule("пн"), rule("вторник"), morph_pipeline(["вт."]), rule("вт"), rule("среда"), rule("среду"), morph_pipeline(["ср."]), rule("ср"), rule("четверг"), morph_pipeline(["чт."]), rule("чт"), rule("пятница"), rule("пятницу"), morph_pipeline(["пт."]), rule("пт"), rule("суббота"), rule("субботу"), morph_pipeline(["сб."]), rule("сб"), rule("воскресение"), rule("воскресенье"), morph_pipeline(["вс."]), rule("вс"), rule("завтра"), rule("послезавтра"), rule("сегодня")) # чужие слова self._foreignWords = [ "этаж", "январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь" ] # количественные числительные в числа self._Counts = { "человек": 1, "1": 1, "один": 1, "два": 2, "2": 2, "двое": 2, "вдвоём": 2, "трое": 3, "три": 3, "3": 3, "втроём": 3, "четверо": 4, "четыре": 4, "4": 4, "вчетвером": 4, "5": 5, "пять": 5, "пятеро": 5, "впятером": 5, "6": 6, "шесть": 6, "шестеро": 6, "7": 7, "семь": 7, "семеро": 7, "8": 7, "восемь": 8, "9": 7, "девять": 9, "10": 7, "десять": 10 } # приведение времени к номальной форме self._ToNormalHours = { "08.00": "08:00", "8": "08:00", "восемь": "08:00", "09.00": "09:00", "9": "09:00", "девять": "09:00", "10.00": "10:00", "10": "10:00", "десять": "10:00", "11.00": "11:00", "11": "11:00", "одиннадцать": "11:00", "12.00": "12:00", "12": "12:00", "двенадцать": "12:00", "полдень": "12:00", "13.00": "13:00", "1": "13:00", "13": "13:00", "один": "13:00", "час": "13:00", "часу": "13:00", "14.00": "14:00", "2": "14:00", "14": "14:00", "два": "14:00", "15.00": "15:00", "3": "15:00", "15": "15:00", "три": "15:00", "16.00": "16:00", "4": "16:00", "16": "16:00", "четыре": "16:00", "17.00": "17:00", "5": "17:00", "17": "17:00", "пять": "17:00", "18.00": "18:00", "6": "18:00", "18": "18:00", "шесть": "18:00", "19.00": "19:00", "7": "19:00", "19": "19:00", "семь": "19:00" } # приведение промежутка времени к нормальной форме self._ToNormalDelta = { "1": "01:00", "один": "01:00", "час": "01:00", "1:5": "01:30", "полтора": "01:30", "2": "02:00", "два": "02:00", "3": "03:00", "три": "03:00", "4": "04:00", "четыре": "04:00", "5": "05:00", "пять": "05:00", "6": "06:00", "шесть": "06:00", "7": "7:00", "семь": "07:00" } # правила для времени в формате from time to time self._rulesFromTO = [ # from time to time rule(start_prepositions, or_(hour, rule(or_(hours_t, hours_n))), separator.optional(), minutes_n.optional(), or_(day_periods, hour).optional(), duration_prepositions, or_(hours_t, hours_n), separator.optional(), minutes_n.optional()), # чч:мм - чч:мм rule(hours_n, separator, minutes_n, "-", hours_n, separator, minutes_n), # day time to time rule(day_pointer, rule(or_(hours_t, hours_n)), separator.optional(), minutes_n.optional(), or_(day_periods, hour).optional(), duration_prepositions, or_(hours_t, hours_n), separator.optional(), minutes_n.optional()) ] # правила для времени в формате from time on time self._rulesFromOn = [ # from time on n hour rule(start_prepositions, or_(hours_t, hours_n), separator.optional(), minutes_n.optional(), or_(day_periods, hour).optional(), pr_na, or_(hours_t, hours_n), hour.optional()), # from time on hour rule(start_prepositions, or_(hours_t, hours_n), separator.optional(), minutes_n.optional(), or_(day_periods, hour).optional(), pr_na, hour) ] # правила для времени в формате on time from time self._rulesOnFrom = [ # on n hour from time rule(pr_na, or_(hours_t, hours_n), hour, start_prepositions, or_(hours_t, hours_n), separator.optional(), minutes_n.optional(), or_(day_periods, hour).optional()), # on hour from time rule(pr_na, hour, start_prepositions, or_(hours_t, hours_n), separator.optional(), minutes_n.optional(), or_(day_periods, hour).optional()) ] # правила для времени в формате from time self._rulesFrom = [ # day or start or start verb in time rule(or_(day_pointer, rule(start_syn), rule(start_verbs)), start_prepositions, or_(hours_t, hours_n), separator.optional(), minutes_n.optional()), # start with separator rule(start_with_separator, two_points, or_(rule(hours_t), rule(hours_n)), separator.optional(), minutes_n.optional()), # since time day or hour rule(pr_c, or_(rule(hours_t), rule(hours_n)), separator.optional(), minutes_n.optional(), or_(day_periods, hour)), # since hour rule(pr_c, hour), # on n часов day rule(pr_na, or_(hours_t, hours_n), hour.optional(), day_periods), # on час day rule(pr_na, hour, day_periods) ] # правила для времени окончания и продолжительности self._rulesTo = [ # end or end verb in time rule(or_(end_syn, end_verbs), start_prepositions, or_(rule(hours_t), rule(hours_n), hour), separator.optional(), minutes_n.optional()), # duration verb time-time rule(duration_verbs, hours_n.optional(), dictionary(["."]).optional(), minutes_n.optional(), "-", hours_n.optional(), dictionary(["."]).optional(), hour), # duration verb time rule(duration_verbs, or_(hours_t, hours_n), dictionary(["."]).optional(), minutes_n.optional(), hour), # end with separation rule(end_with_separator, two_points, or_(rule(hours_t), rule(hours_n)), separator.optional(), minutes_n.optional()), # duration with separation rule(duration_with_separator, two_points, or_(rule(hours_t), rule(hours_n)), separator.optional(), minutes_n.optional()) ] # общие правила для начального, конечного времени и продолжительности self._rulesCommon = [ # in time + hour or day period rule(or_(pr_v, pr_vrayone, pr_k), or_(hours_t, hours_n), or_(hour, day_periods)), # on time + day period rule(pr_na, or_(hours_t, hours_n), or_(day_periods)), # in hh:mm rule(pr_v, hours_n, separator, minutes_n), # hh:mm rule(hours_n, two_points, minutes_n, or_(day_periods, hour).optional()), # on n hour rule(pr_na, or_(hours_t, hours_n), hour), # on hour rule(pr_na, hour) ] # правила для количества людей self._rulesCount = [ # coll number rule(coll_numbers_dic), # n people rule(or_(hours_t, hours_n).optional()) ] # правила используемые в повторных запросах self._rulesTime = [ # всевозможные форматы времени rule(or_(rule(hours_t), rule(hours_n), hour), separator.optional(), minutes_n.optional()) ] self._rulesPeriod = [ # всевозможные интервалы времени rule(or_(rule(hours_t), rule(hours_n), hour), dictionary(["."]).optional(), minutes_n.optional()) ] self._rulesCountPeople = [ # количественные числительные rule(coll_numbers_dic), # n человек rule(or_(hours_t, hours_n).optional(), people) ]
gram('PRCL'), gram('INTJ'), ), gram('POST'), ).optional()) case = case_relation() GENT_GROUP = rule(gram('gent').match(case)).repeatable().optional() #ADJF ADJF_PREFIX_COUNTABLE = rule(or_(caseless('и'), eq(',')).optional(), ) ADJF_PREFIX_ADJF = and_(ADJF, TITLE).repeatable() ADJF_NORM = rule( and_(ADJF, custom(lambda s: EDUORG_DICT_REGEXP.search(s), types=(str)))).repeatable() ADJF_PREFIX = rule( ADJF_PREFIX_ADJF, ADJF.optional(), #Киевском государственном университете ADJF_PREFIX_COUNTABLE).repeatable() # ### ### 1-ST RING RULES R1_SIMPLE = rule(EDUORG_DICT, ).repeatable() R1_ADJF = rule(ADJF_NORM, ).repeatable() ### ### 2-ST RING RULES
import sys import re from yargy import or_, rule from yargy.interpretation import fact from yargy.pipelines import morph_pipeline from yargy.predicates import caseless, custom, eq, in_ from .common import TOKENIZER Time = fact('Time', ['hours', 'minutes']) hour_re = re.compile(r'([01]\d|\d|2[0-3])') is_hour = custom(hour_re.fullmatch).activate(TOKENIZER) minute_re = re.compile(r'[0-5]\d') is_minute = custom(minute_re.fullmatch).activate(TOKENIZER) HOUR_UNIT = rule(morph_pipeline(['ч', 'час', 'часы']), eq('.').optional()) MINUTE_UNIT = rule(morph_pipeline(['м', 'мин', 'минуты']), eq('.').optional()) # 17:02 ч. TIME_DIGITAL = rule( is_hour.means(Time.hours), in_(':-.'), is_minute.means(Time.minutes), or_(HOUR_UNIT, MINUTE_UNIT).optional(), ).means(Time) # 17ч 02
import yargy from yargy.tokenizer import MorphTokenizer from yargy import Parser, rule, and_, or_, not_ from yargy.predicates import gram, dictionary, custom, true from yargy.pipelines import morph_pipeline #проверка на то, число ли это def is_number(string): for c in string: if ((ord(c) < 48 or ord(c) > 57)): return False return True is_number_ = custom(is_number) #правило понимает дроби NUMBER_RULE = rule(or_(gram("NUMR"), is_number_)) #все приставки, означающие денки: MONEY_PIPE = morph_pipeline(["тыс", "к", "k", "м", "руб", "рублей", "тысяч"]) #поиск токенов, означающих цену #нижнюю границу PRICE_FROM = rule(morph_pipeline(["от", "дороже"]), NUMBER_RULE.repeatable(), MONEY_PIPE.optional().repeatable()) #верхнюю границу PRICE_TO = rule( morph_pipeline(["до", "дешевле", "дешевле чем", "дешевле, чем"]), NUMBER_RULE.repeatable(), MONEY_PIPE.optional().repeatable()) #точное значение PRICE_VALUE = rule(NUMBER_RULE.repeatable(),
from yargy import rule, and_, or_, not_ from yargy.predicates import eq, type as _type, normalized, custom from yargy.pipelines import morph_pipeline from yargy.interpretation import fact from .Street import StreetRule BuildingFact = fact('building', ['house', 'corpus', 'structure']) HouseNumber = rule( _type('INT'), rule( or_(rule(eq('/'), _type('INT')), rule(custom( lambda token: len(token) == 1)))).optional()).interpretation( BuildingFact.house) House = rule( rule( or_( StreetRule, rule( normalized('дом').repeatable(), normalized('номер').optional(), ))), HouseNumber) CorpusPrefix = morph_pipeline(['корпус', 'к']) Corpus = rule(CorpusPrefix, _type('INT').interpretation(BuildingFact.corpus)) StructurePrefix = morph_pipeline(['строение', 'ст'])