From 9d72c466dad817d7ebfea7ab8a9d37f553d1c1ee Mon Sep 17 00:00:00 2001 From: Aleksey Filippov Date: Tue, 16 May 2023 17:23:30 +0400 Subject: [PATCH] Add support of multipart terms --- main.py | 10 +- ontology-old.owl => ontology-0.owl | 0 ontology-1.owl | 651 ++++++++++++++++++ ontology.owl | 1030 ++++++++++++++++++++++------ src/myontology.py | 10 +- src/nlp.py | 53 +- 6 files changed, 1537 insertions(+), 217 deletions(-) rename ontology-old.owl => ontology-0.owl (100%) create mode 100644 ontology-1.owl diff --git a/main.py b/main.py index ad33283..49839a9 100644 --- a/main.py +++ b/main.py @@ -12,11 +12,17 @@ from src.syntax import Syntax def _main(wav_file: str): text: str = Speech().run_recognition(wav_file) + # text: str = 'как получить кредит на обучение' print(f'Text: {text}') parse_tree: ParseTree = Syntax().get_parse_tree(text) print(f'Parse tree:\n{parse_tree}') - terms: List[str] = NLP().get_by_template(parse_tree, ['NOUN', 'VERB', 'ADJ']) - print(f'Extracted terms:\n{" ".join(terms)}') + nlp: NLP = NLP() + terms: List[str] = [] + terms.extend(nlp.get_adj_noun(parse_tree)) + terms.extend(nlp.get_nouns(parse_tree)) + if len(terms) == 0: + terms.extend(nlp.get_terms_by_template(parse_tree, ['NOUN', 'VERB', 'ADJ'])) + print(f'Extracted terms:\n{", ".join(terms)}') result: str = MyOntology().get_event_description(terms) print(f'Test:\n{result}') diff --git a/ontology-old.owl b/ontology-0.owl similarity index 100% rename from ontology-old.owl rename to ontology-0.owl diff --git a/ontology-1.owl b/ontology-1.owl new file mode 100644 index 0000000..d9a0ccd --- /dev/null +++ b/ontology-1.owl @@ -0,0 +1,651 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Вывожу баланс карты + + + + + 1 + + + + + Открыть счет или заказать карту на сайте банка. + + + + + 1 + + + + + Сообщить сумму задолженности + + + + + 1 + + + + + Сообщить дату платежа по кредиту + + + + + 1 + + + + + Сообщить курсы валют + + + + + 1 + + + + + Сообщить доступный лимит на перевод денег + + + + + 1 + + + + + Сообщить доступный лимит на снятие денег в банкомате + + + + + 1 + + + + + Сообщить о количестве доступных трансферов + + + + + 1 + + + + + Сообщить про ограничения карты + + + + + 5 + + + + + Сообщить сумму ежемесячного платежа + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ontology.owl b/ontology.owl index d9a0ccd..b11f980 100644 --- a/ontology.owl +++ b/ontology.owl @@ -6,7 +6,7 @@ xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" ontologyIRI="http://www.semanticweb.org/alalf/ontologies/2022/0/untitled-ontology-5"> - + @@ -36,125 +36,248 @@ + + + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + - + - + - + - + - + + + + + + + + + + + + + + + + - + - + + + + + + + - + - + + + + - + - + - + + + + + + + + + + + + + - + - + + + + + + + + + + - + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + + + + + + + + + + @@ -165,45 +288,73 @@ + + + + - - - - - - - - - - + + - + - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -211,31 +362,63 @@ - + - - - - - + - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + @@ -243,11 +426,15 @@ - + - + + + + + @@ -255,15 +442,31 @@ - + - + - + + + + + + + + + + + + + + + + + @@ -271,7 +474,7 @@ - + @@ -279,7 +482,19 @@ - + + + + + + + + + + + + + @@ -287,7 +502,11 @@ - + + + + + @@ -295,11 +514,71 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -307,19 +586,31 @@ - + - + - + - + + + + + + + + + + + + + @@ -331,11 +622,6 @@ - - - - - @@ -343,83 +629,28 @@ - - + + - - + + - - - - - - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -429,87 +660,402 @@ - + + + + + + + + + + + - - - + + + - - - - - - - + + - - + + - - + + - - + + + + + + + + + + + + - - + + - + + + + + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -523,72 +1069,152 @@ - - Открыть счет или заказать карту на сайте банка. + + Вывожу действия при блокировке карты - + 1 - - Сообщить сумму задолженности + + Вывожу действия при получении денег с заблокированной карты - + 1 - - Сообщить дату платежа по кредиту + + Вывожу действия при разблокировке карты - + 1 - - Сообщить курсы валют + + Вывожу действия при утере карты - + 1 - - Сообщить доступный лимит на перевод денег + + Вывожу остаток по карте - + 1 - - Сообщить доступный лимит на снятие денег в банкомате + + Вывожу самую низкую ставку по кредиту - + 1 - - Сообщить о количестве доступных трансферов + + Вывожу срок ипотеки - + + 1 + + + + + Вывожу ставку кредита на образование + + + + + 1 + + + + + Вывожу ставку по ипотеке + + + + + 1 + + + + + Вывожу условия оформления кредита + + + + + 1 + + + + + Вывожу условия оформления кредита на обучение + + + + + 1 + + + + + Вывожу условия покупки в кредит + + + + + 1 + + + + + Вывожу условия покупки в рассрочку + + + + + 1 + + + + + Вывожу условия получения ипотеки + + + + + 1 + + + + + Вывожу условия рефинансирования кредита + + + + 1 @@ -601,16 +1227,6 @@ 5 - - - - Сообщить сумму ежемесячного платежа - - - - - 1 - @@ -647,5 +1263,5 @@ - + diff --git a/src/myontology.py b/src/myontology.py index 74c07c5..3db66c1 100644 --- a/src/myontology.py +++ b/src/myontology.py @@ -9,7 +9,7 @@ class MyOntology: def __find_str_in_list(self, string: str, string_list: List[str]) -> int: try: - string_list.index(string) + string_list.index(string.replace("_", " ")) return 1 except ValueError: return 0 @@ -28,18 +28,18 @@ class MyOntology: events.sort(key=lambda item: list(item.keys())[0], reverse=True) return events - def __find_instances_by_terms(self, nouns: List[str]) -> []: + def __find_instances_by_terms(self, my_terms: List[str]) -> []: instances = [] for instance in self.__onto.Concept.instances(): terms = instance.hasTerm match: int = 0 for term in terms: - match = match + self.__find_str_in_list(term.name, nouns) + match = match + self.__find_str_in_list(term.name, my_terms) if match >= 1: instances.append(instance) return instances - def get_event_description(self, nouns: List[str]) -> str: - instances: [] = self.__find_instances_by_terms(nouns) + def get_event_description(self, terms: List[str]) -> str: + instances: [] = self.__find_instances_by_terms(terms) events = self.__get_event_instance(instances) return '\n'.join(list(map(lambda item: f'{list(item.keys())[0]}: {list(item.values())[0]}', events))) diff --git a/src/nlp.py b/src/nlp.py index b311347..8cce3ad 100644 --- a/src/nlp.py +++ b/src/nlp.py @@ -1,19 +1,66 @@ -from typing import List +from typing import List, Set import ru_core_news_sm -from anytree import LevelOrderIter +from anytree import LevelOrderIter, Resolver, ChildResolverError, LevelOrderGroupIter, \ + ResolverError from src.parse_tree.parse_tree import ParseTree from src.parse_tree.parse_tree_node import ParseTreeNode class NLP: + @staticmethod + def __get_nodes_by_template(tree: ParseTree, template: str) -> list: + top = tree.get_tree_root() + r = Resolver('upos') + nodes: list = [] + try: + nodes.extend(r.glob(top, template)) + except (ChildResolverError, ResolverError): + print(f'Can\'t find some terms by template {template}') + return nodes + + def __get_terms_by_template(self, tree: ParseTree, template: str) -> List[str]: + terms: Set[str] = set() + nodes: list = [] + nodes.extend(self.__get_nodes_by_template(tree, f'/{template}')) + nodes.extend(self.__get_nodes_by_template(tree, template)) + for node in nodes: + if node.parent is None: + continue + terms.add(f'{self.lemmatizer(node.lemma)} {self.lemmatizer(node.parent.lemma)}') + return list(terms) + + def __get_terms_by_upos(self, tree: ParseTree, upos: str) -> List[str]: + terms: Set[str] = set() + for nodes in LevelOrderGroupIter(tree.get_tree_root()): + upos_terms: List[str] = [] + for node in nodes: + if node.upos != upos: + continue + upos_terms.append(self.lemmatizer(node.lemma)) + if len(upos_terms) < 2: + continue + terms.add(" ".join(upos_terms)) + if len(terms) == 0: + print(f'Can\'t find some terms by template NOUN/./NOUN') + return list(terms) + def lemmatizer(self, text: str): doc = ru_core_news_sm.load()(text) tokens = [token.lemma_ for token in doc] return ' '.join(tokens) - def get_by_template(self, tree: ParseTree, template: List[str]) -> List[str]: + def get_adj_noun(self, tree: ParseTree) -> List[str]: + return self.__get_terms_by_template(tree, 'NOUN/ADJ') + + def get_nouns(self, tree: ParseTree) -> List[str]: + terms: List[str] = [] + terms.extend(self.__get_terms_by_upos(tree, 'NOUN')) + terms.extend(self.__get_terms_by_template(tree, 'NOUN/NOUN')) + return terms + + def get_terms_by_template(self, tree: ParseTree, template: List[str]) -> List[str]: nouns: List[ParseTreeNode] = [] for node in LevelOrderIter(tree.get_tree_root()): if node.upos not in template: