Проблемы выявления противоречий в документах в современных условиях
Защита через месяц, а работа не готова?
Наши эксперты выполнят ВКР по онтологическим моделям всего за 14 дней! Напишите в Telegram прямо сейчас и получите бесплатную консультацию по выбору архитектуры системы.
Современные организации ежедневно обрабатывают огромные объемы документов, что приводит к сложностям в выявлении противоречий и несоответствий между ними. Согласно исследованию IEEE Transactions on Knowledge and Data Engineering (2024), 68% юридических и технических документов содержат скрытые противоречия, которые не выявляются традиционными методами проверки. Это приводит к увеличению рисков в принятии решений, юридическим спорам и финансовым потерям. Традиционные методы анализа документов, основанные на ключевых словах и простых правилах, не способны понимать семантику и контекст, что делает их неэффективными для обнаружения сложных противоречий.
Актуальность выявления противоречий в документах на основе онтологических моделей и глубокого машинного обучения обусловлена растущей сложностью документооборота в различных сферах и необходимостью повышения точности анализа документов. Это особенно важно для студентов ФИТ НГУ, изучающих прикладную информатику и методы искусственного интеллекта, так как позволяет применить теоретические знания на практике и получить навыки работы с современными технологиями обработки естественного языка, онтологического моделирования и глубокого обучения.
В данной статье мы подробно рассмотрим современные подходы к выявлению противоречий в документах на основе онтологических моделей и глубокого машинного обучения. Вы узнаете о ключевых архитектурных решениях, практических методах реализации и рекомендациях по созданию эффективных систем анализа. Мы также разберем типичные ошибки, которые допускают студенты при работе с этой сложной темой, и предложим проверенные решения для успешного выполнения ВКР.
Эта тема особенно важна для студентов ФИТ НГУ, так как требует комплексного применения знаний в области обработки естественного языка, семантического веба и машинного обучения. Успешная реализация подобного проекта не только поможет в написании качественной выпускной квалификационной работы, но и станет ценным навыком для будущей профессиональной деятельности в области разработки систем анализа документов и интеллектуальных помощников.
Если вы испытываете трудности с пониманием онтологических моделей или реализацией конкретных компонентов системы, рекомендуем ознакомиться с нашими гарантиями и отзывами клиентов, которые подтверждают высокое качество наших услуг.
Дополнительный список тем для ВКР ФИТ НГУ на 2025-2026 учебный год можно найти здесь.
Срочная помощь по вашей теме: Получите консультацию за 10 минут! Telegram: @Diplomit Телефон/WhatsApp: +7 (987) 915-99-32, Email: admin@diplom-it.ru
Оформите заказ онлайн: Заказать ВКР ФИТ НГУ
Основы выявления противоречий в документах
Ключевые проблемы выявления противоречий в документах
Проблема | Описание | Требования к решению |
---|---|---|
Семантическая неоднозначность | Одинаковые термины могут иметь разное значение в разных контекстах | Контекстно-зависимый анализ с использованием онтологий и глубокого обучения |
Сложные противоречия | Противоречия, требующие понимания неявных связей между утверждениями | Графовые модели и рассуждения на основе онтологий |
Обработка длинных текстов | Сложность анализа больших документов с учетом всего контекста | Методы сегментации и иерархического анализа |
Интеграция различных источников | Анализ противоречий между документами из разных источников | Системы унификации терминологии и представления знаний |
Оценка уровня противоречия | Необходимость определения степени серьезности выявленного противоречия | Метрики и методы ранжирования противоречий по значимости |
Технические основы выявления противоречий
Выявление противоречий в документах на основе онтологических моделей и глубокого машинного обучения основывается на ряде ключевых концепций:
Основы выявления противоречий в документах
- Онтологические модели — структурированное представление знаний о предметной области с определением отношений между концептами
- Семантический анализ — понимание смысла текста и извлечение семантических отношений
- Глубокое обучение для NLP — использование трансформеров (BERT, RoBERTa) для понимания контекста и выявления несоответствий
- Логические рассуждения — применение правил вывода для обнаружения противоречий в знаниях
- Графовые нейронные сети — комбинация графовых структур онтологий с нейронными сетями
- Методы объяснения моделей — интерпретация результатов анализа для понимания причин выявленных противоречий
Эти концепции лежат в основе современных систем выявления противоречий и должны быть хорошо поняты при разработке таких систем.
Современные подходы к выявлению противоречий
В последние годы в области выявления противоречий в документах наблюдается несколько ключевых тенденций:
Подход | Описание | Примеры применения |
---|---|---|
Гибридные онтологические модели | Комбинация онтологий с методами глубокого обучения для повышения точности анализа | Анализ юридических документов, технических стандартов, медицинских протоколов |
Семантические графы знаний | Представление знаний в виде графов с семантическими отношениями для обнаружения несоответствий | Анализ научных статей, нормативных актов, бизнес-правил |
Контекстно-зависимый анализ | Учет контекста при интерпретации утверждений для обнаружения скрытых противоречий | Анализ договоров, регуляторных документов, технической документации |
Многоуровневый анализ | Анализ на разных уровнях: лексическом, синтаксическом, семантическом и прагматическом | Комплексный анализ сложных документов с множеством взаимосвязанных частей |
Объяснимый ИИ | Методы, обеспечивающие интерпретируемость результатов анализа противоречий | Юридические и медицинские приложения, где требуется объяснение выявленных противоречий |
Архитектура и реализация системы выявления противоречий
Выбор архитектурного подхода
Для эффективной реализации системы выявления противоречий в документах рекомендуется использовать следующую архитектуру:
Архитектура системы выявления противоречий в документах
- Слой предварительной обработки — очистка, нормализация и подготовка документов для анализа
- Слой извлечения знаний — извлечение сущностей, отношений и утверждений из документов
- Слой онтологического представления — представление извлеченных знаний в онтологической форме
- Слой семантического анализа — анализ семантических отношений и контекста
- Слой выявления противоречий — применение логических правил и моделей для обнаружения несоответствий
- Слой оценки и ранжирования — оценка степени уверенности и значимости выявленных противоречий
- Слой визуализации и объяснения — представление результатов анализа в понятном формате с объяснениями
Эта многоуровневая архитектура обеспечивает гибкость и возможность расширения функциональности без переработки всей системы.
Пример реализации системы выявления противоречий на Python
Рассмотрим пример реализации ключевых компонентов системы выявления противоречий в документах:
# contradiction_detection.py # Реализация системы выявления противоречий в документах на основе онтологических моделей и глубокого обучения import os import re import json import logging from typing import Dict, List, Tuple, Optional, Any import numpy as np import networkx as nx from sklearn.metrics.pairwise import cosine_similarity import torch from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline import spacy from rdflib import Graph, Namespace, RDF, RDFS, OWL, URIRef, Literal # Настройка логирования logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Загрузка NLP-модели try: nlp = spacy.load("en_core_web_lg") logger.info("Загружена модель NLP: en_core_web_lg") except OSError: logger.warning("Модель en_core_web_lg не найдена. Попробуйте установить: python -m spacy download en_core_web_lg") nlp = spacy.load("en_core_web_sm") logger.info("Загружена базовая модель NLP: en_core_web_sm") class DocumentProcessor: """Обработка документов для выявления противоречий""" def __init__(self): # Загрузка предобученной модели для обнаружения противоречий try: self.contradiction_tokenizer = AutoTokenizer.from_pretrained("textattack/bert-base-uncased-MNLI") self.contradiction_model = AutoModelForSequenceClassification.from_pretrained("textattack/bert-base-uncased-MNLI") self.contradiction_classifier = pipeline( "text-classification", model=self.contradiction_model, tokenizer=self.contradiction_tokenizer ) logger.info("Загружена модель для обнаружения противоречий") except Exception as e: logger.error(f"Ошибка при загрузке модели для обнаружения противоречий: {str(e)}") self.contradiction_classifier = None def process_document(self, text: str) -> Dict: """ Обработка документа для последующего анализа Args: text: Текст документа Returns: Словарь с результатами обработки """ # Обработка текста с помощью spaCy doc = nlp(text) # Извлечение сущностей entities = self._extract_entities(doc) # Извлечение утверждений statements = self._extract_statements(doc) # Анализ предложений на наличие противоречий contradictions = [] if self.contradiction_classifier and len(statements) > 1: for i in range(len(statements)): for j in range(i+1, len(statements)): contradiction = self._check_contradiction( statements[i]["text"], statements[j]["text"] ) if contradiction and contradiction["score"] > 0.7: contradictions.append({ "statement1": statements[i], "statement2": statements[j], "contradiction": contradiction }) return { "text": text, "entities": entities, "statements": statements, "contradictions": contradictions, "metadata": { "word_count": len(doc), "sentence_count": len(list(doc.sents)) } } def _extract_entities(self, doc: spacy.tokens.Doc) -> List[Dict]: """Извлечение сущностей из обработанного документа""" entities = [] for ent in doc.ents: entities.append({ "text": ent.text, "label": ent.label_, "start": ent.start_char, "end": ent.end_char, "context": self._get_context(ent, doc) }) return entities def _extract_statements(self, doc: spacy.tokens.Doc) -> List[Dict]: """Извлечение утверждений из документа""" statements = [] for sent in doc.sents: # Удаляем предложения, которые являются вопросами или командами if sent.text.strip().endswith(('.', '!', '?')) and not sent.text.strip().endswith('?'): statements.append({ "text": sent.text.strip(), "start": sent.start_char, "end": sent.end_char, "entities": self._get_entities_in_span(sent, doc) }) return statements def _get_entities_in_span(self, span, doc) -> List[Dict]: """Получение сущностей в пределах указанного промежутка""" entities = [] for ent in doc.ents: if ent.start_char >= span.start_char and ent.end_char <= span.end_char: entities.append({ "text": ent.text, "label": ent.label_, "start": ent.start_char - span.start_char, "end": ent.end_char - span.start_char }) return entities def _get_context(self, token, doc, window_size: int = 20) -> str: """Получение контекста вокруг токена""" start = max(0, token.i - window_size) end = min(len(doc), token.i + window_size) return doc[start:end].text def _check_contradiction(self, statement1: str, statement2: str) -> Optional[Dict]: """ Проверка наличия противоречия между двумя утверждениями Args: statement1: Первое утверждение statement2: Второе утверждение Returns: Словарь с результатами проверки или None, если противоречия нет """ if not self.contradiction_classifier: return None try: # Подготовка входных данных для модели MNLI # В задаче MNLI классы: entailment (следствие), neutral (нейтрально), contradiction (противоречие) result = self.contradiction_classifier( sequence_pair=(statement1, statement2), return_all_scores=True ) # Ищем вероятность класса "contradiction" contradiction_score = 0.0 for label in result[0]: if label["label"] == "contradiction": contradiction_score = label["score"] break if contradiction_score > 0.5: return { "score": contradiction_score, "explanation": f"Вероятность противоречия: {contradiction_score:.2f}" } return None except Exception as e: logger.error(f"Ошибка при проверке противоречия: {str(e)}") return None class OntologyBuilder: """Построение онтологии на основе извлеченных знаний""" def __init__(self, domain: str = "general"): self.domain = domain self.ontology = Graph() self.namespace = Namespace(f"http://example.org/ontology/{domain}#") self._initialize_ontology() def _initialize_ontology(self): """Инициализация базовой структуры онтологии""" # Определение пространства имен self.ontology.bind("owl", OWL) self.ontology.bind("rdf", RDF) self.ontology.bind("rdfs", RDFS) self.ontology.bind("ont", self.namespace) # Добавление базовых классов self.ontology.add((self.namespace.Document, RDF.type, RDFS.Class)) self.ontology.add((self.namespace.Statement, RDF.type, RDFS.Class)) self.ontology.add((self.namespace.Entity, RDF.type, RDFS.Class)) self.ontology.add((self.namespace.Contradiction, RDF.type, RDFS.Class)) # Добавление свойств self.ontology.add((self.namespace.hasStatement, RDF.type, RDF.Property)) self.ontology.add((self.namespace.hasStatement, RDFS.domain, self.namespace.Document)) self.ontology.add((self.namespace.hasStatement, RDFS.range, self.namespace.Statement)) self.ontology.add((self.namespace.hasEntity, RDF.type, RDF.Property)) self.ontology.add((self.namespace.hasEntity, RDFS.domain, self.namespace.Statement)) self.ontology.add((self.namespace.hasEntity, RDFS.range, self.namespace.Entity)) self.ontology.add((self.namespace.hasContradiction, RDF.type, RDF.Property)) self.ontology.add((self.namespace.hasContradiction, RDFS.domain, self.namespace.Statement)) self.ontology.add((self.namespace.hasContradiction, RDFS.range, self.namespace.Statement)) self.ontology.add((self.namespace.text, RDF.type, RDF.Property)) self.ontology.add((self.namespace.text, RDFS.domain, self.namespace.Statement)) self.ontology.add((self.namespace.text, RDFS.range, RDFS.Literal)) self.ontology.add((self.namespace.entityType, RDF.type, RDF.Property)) self.ontology.add((self.namespace.entityType, RDFS.domain, self.namespace.Entity)) self.ontology.add((self.namespace.entityType, RDFS.range, RDFS.Literal)) def add_document(self, doc_id: str, content: str): """Добавление документа в онтологию""" doc_uri = self.namespace[doc_id] self.ontology.add((doc_uri, RDF.type, self.namespace.Document)) self.ontology.add((doc_uri, self.namespace.text, Literal(content))) def add_statement(self, statement_id: str, text: str, doc_id: str): """Добавление утверждения в онтологию""" statement_uri = self.namespace[statement_id] doc_uri = self.namespace[doc_id] self.ontology.add((statement_uri, RDF.type, self.namespace.Statement)) self.ontology.add((statement_uri, self.namespace.text, Literal(text))) self.ontology.add((doc_uri, self.namespace.hasStatement, statement_uri)) def add_entity(self, entity_id: str, text: str, entity_type: str, statement_id: str): """Добавление сущности в онтологию""" entity_uri = self.namespace[entity_id] statement_uri = self.namespace[statement_id] self.ontology.add((entity_uri, RDF.type, self.namespace.Entity)) self.ontology.add((entity_uri, RDFS.label, Literal(text))) self.ontology.add((entity_uri, self.namespace.entityType, Literal(entity_type))) self.ontology.add((statement_uri, self.namespace.hasEntity, entity_uri)) def add_contradiction(self, contradiction_id: str, statement1_id: str, statement2_id: str, confidence: float): """Добавление противоречия в онтологию""" contradiction_uri = self.namespace[contradiction_id] statement1_uri = self.namespace[statement1_id] statement2_uri = self.namespace[statement2_id] self.ontology.add((contradiction_uri, RDF.type, self.namespace.Contradiction)) self.ontology.add((contradiction_uri, self.namespace.confidence, Literal(confidence))) self.ontology.add((statement1_uri, self.namespace.hasContradiction, statement2_uri)) self.ontology.add((statement2_uri, self.namespace.hasContradiction, statement1_uri)) def export_ontology(self, filename: str): """Экспорт онтологии в файл""" self.ontology.serialize(destination=filename, format="turtle") logger.info(f"Онтология экспортирована в {filename}") def find_contradictions(self) -> List[Dict]: """Поиск противоречий в онтологии""" contradictions = [] # Запрос SPARQL для поиска противоречий query = """ PREFIX ont: <http://example.org/ontology/general#> SELECT ?statement1 ?text1 ?statement2 ?text2 ?confidence WHERE { ?statement1 ont:hasContradiction ?statement2 . ?statement1 ont:text ?text1 . ?statement2 ont:text ?text2 . OPTIONAL { ?contradiction ont:confidence ?confidence . } } """ try: results = self.ontology.query(query) for row in results: contradictions.append({ "statement1": str(row.statement1), "text1": str(row.text1), "statement2": str(row.statement2), "text2": str(row.text2), "confidence": float(row.confidence) if row.confidence else 0.8 }) except Exception as e: logger.error(f"Ошибка при выполнении SPARQL-запроса: {str(e)}") return contradictions class ContradictionReasoner: """Система логических рассуждений для выявления скрытых противоречий""" def __init__(self, ontology: OntologyBuilder): self.ontology = ontology self.graph = nx.DiGraph() self._build_graph_from_ontology() def _build_graph_from_ontology(self): """Построение графа на основе онтологии""" # В реальной системе здесь будет сложный анализ онтологии # Для примера создадим простой граф for s, p, o in self.ontology.ontology: if p == self.ontology.namespace.hasContradiction: self.graph.add_edge(s, o, relation="contradiction") elif p == RDF.type: self.graph.add_node(s, type="class" if o == RDFS.Class else "instance") def detect_hidden_contradictions(self) -> List[Dict]: """ Обнаружение скрытых противоречий через логические рассуждения Returns: Список выявленных скрытых противоречий """ hidden_contradictions = [] # Анализ графа на наличие транзитивных противоречий for node in self.graph.nodes(): # Поиск всех узлов, к которым можно добраться от текущего reachable = nx.descendants(self.graph, node) # Проверка на наличие противоречий for target in reachable: if self.graph.has_edge(target, node) and self.graph[target][node]["relation"] == "contradiction": hidden_contradictions.append({ "source": str(node), "target": str(target), "path": nx.shortest_path(self.graph, node, target), "explanation": "Обнаружено транзитивное противоречие" }) return hidden_contradictions def explain_contradiction(self, statement1: str, statement2: str) -> str: """ Объяснение причины противоречия между утверждениями Args: statement1: URI первого утверждения statement2: URI второго утверждения Returns: Текстовое объяснение противоречия """ # В реальной системе здесь будет сложный анализ # Для примера создадим простое объяснение return ( f"Утверждения '{statement1}' и '{statement2}' противоречат друг другу, " "потому что они выражают взаимоисключающие условия или факты в рамках одной предметной области." ) class ContradictionDetectionSystem: """Основная система выявления противоречий в документах""" def __init__(self, domain: str = "legal"): self.document_processor = DocumentProcessor() self.ontology_builder = OntologyBuilder(domain) self.reasoner = None self.domain = domain self.documents = [] self.contradictions = [] def process_document(self, doc_id: str, text: str): """ Обработка документа и выявление противоречий Args: doc_id: Идентификатор документа text: Текст документа """ # Добавляем документ в онтологию self.ontology_builder.add_document(doc_id, text) # Обрабатываем документ result = self.document_processor.process_document(text) # Добавляем утверждения и сущности в онтологию for i, statement in enumerate(result["statements"]): statement_id = f"{doc_id}_stmt_{i}" self.ontology_builder.add_statement(statement_id, statement["text"], doc_id) for j, entity in enumerate(statement["entities"]): entity_id = f"{statement_id}_ent_{j}" self.ontology_builder.add_entity( entity_id, entity["text"], entity["label"], statement_id ) # Добавляем выявленные противоречия в онтологию for i, contradiction in enumerate(result["contradictions"]): contradiction_id = f"{doc_id}_contrad_{i}" self.ontology_builder.add_contradiction( contradiction_id, f"{doc_id}_stmt_{result['statements'].index(contradiction['statement1'])}", f"{doc_id}_stmt_{result['statements'].index(contradiction['statement2'])}", contradiction["contradiction"]["score"] ) # Сохраняем результаты self.documents.append({ "id": doc_id, "content": text, "analysis": result }) # Сохраняем противоречия for contradiction in result["contradictions"]: self.contradictions.append({ "document": doc_id, "statement1": contradiction["statement1"]["text"], "statement2": contradiction["statement2"]["text"], "score": contradiction["contradiction"]["score"], "explanation": contradiction["contradiction"]["explanation"] }) # Обновляем систему рассуждений self.reasoner = ContradictionReasoner(self.ontology_builder) def detect_hidden_contradictions(self) -> List[Dict]: """Обнаружение скрытых противоречий через логические рассуждения""" if not self.reasoner: return [] return self.reasoner.detect_hidden_contradictions() def explain_contradiction(self, contradiction: Dict) -> str: """Объяснение причины противоречия""" if not self.reasoner: return "Невозможно объяснить противоречие: система рассуждений не инициализирована" return self.reasoner.explain_contradiction(contradiction["statement1"], contradiction["statement2"]) def export_results(self, filename: str): """Экспорт результатов анализа""" results = { "domain": self.domain, "documents_processed": len(self.documents), "total_contradictions": len(self.contradictions), "contradictions": self.contradictions, "hidden_contradictions": self.detect_hidden_contradictions() } with open(filename, 'w', encoding='utf-8') as f: json.dump(results, f, ensure_ascii=False, indent=2) logger.info(f"Результаты экспортированы в {filename}") def get_summary(self) -> Dict: """Получение сводки по результатам анализа""" high_confidence = [c for c in self.contradictions if c["score"] > 0.8] medium_confidence = [c for c in self.contradictions if 0.6 <= c["score"] <= 0.8] low_confidence = [c for c in self.contradictions if c["score"] < 0.6] return { "total_documents": len(self.documents), "total_contradictions": len(self.contradictions), "high_confidence": len(high_confidence), "medium_confidence": len(medium_confidence), "low_confidence": len(low_confidence), "hidden_contradictions": len(self.detect_hidden_contradictions()) } # Пример использования if __name__ == "__main__": # Инициализация системы выявления противоречий contradiction_system = ContradictionDetectionSystem(domain="legal") # Примеры документов для анализа documents = [ ( "doc_001", "Все граждане имеют право на свободу передвижения. Никто не может быть лишен этого права. " "Однако, в случае чрезвычайного положения, свободное передвижение может быть ограничено." ), ( "doc_002", "Все граждане имеют право на свободу передвижения. Никто не может быть лишен этого права. " "Право на свободу передвижения является неотъемлемым правом человека и не может быть ограничено ни при каких обстоятельствах." ), ( "doc_003", "Компания предоставляет своим сотрудникам 28 дней оплачиваемого отпуска в год. " "Сотрудники, проработавшие менее года, получают пропорциональную часть отпуска. " "Сотрудники, проработавшие более 5 лет, получают дополнительные 5 дней отпуска." ), ( "doc_004", "Компания предоставляет своим сотрудникам 28 дней оплачиваемого отпуска в год. " "Сотрудники, проработавшие менее года, не имеют права на отпуск. " "Сотрудники, проработавшие более 5 лет, получают дополнительные 5 дней отпуска." ) ] # Обработка документов for doc_id, text in documents: contradiction_system.process_document(doc_id, text) # Получение результатов summary = contradiction_system.get_summary() print(f"Обработано документов: {summary['total_documents']}") print(f"Обнаружено противоречий: {summary['total_contradictions']}") print(f"Высокая уверенность: {summary['high_confidence']}") print(f"Средняя уверенность: {summary['medium_confidence']}") print(f"Низкая уверенность: {summary['low_confidence']}") print(f"Скрытые противоречия: {summary['hidden_contradictions']}") # Экспорт онтологии contradiction_system.ontology_builder.export_ontology("legal_ontology.ttl") # Экспорт результатов contradiction_system.export_results("contradiction_results.json") # Вывод выявленных противоречий print("\nВыявленные противоречия:") for i, contradiction in enumerate(contradiction_system.contradictions[:3], 1): print(f"{i}. [{contradiction['score']:.2f}]") print(f" Документ: {contradiction['document']}") print(f" Утверждение 1: {contradiction['statement1']}") print(f" Утверждение 2: {contradiction['statement2']}") print(f" Объяснение: {contradiction['explanation']}\n") # Вывод скрытых противоречий hidden_contradictions = contradiction_system.detect_hidden_contradictions() if hidden_contradictions: print("\nСкрытые противоречия:") for i, contradiction in enumerate(hidden_contradictions[:2], 1): print(f"{i}.") print(f" Источник: {contradiction['source']}") print(f" Цель: {contradiction['target']}") print(f" Путь: {' -> '.join(contradiction['path'])}") print(f" Объяснение: {contradiction['explanation']}\n")
// src/services/contradictionService.js // Сервис для взаимодействия с системой выявления противоречий import axios from 'axios'; class ContradictionService { constructor() { this.apiUrl = process.env.REACT_APP_CONTRADICTION_API_URL || 'http://localhost:5000/api/v1/contradiction'; this.headers = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.REACT_APP_CONTRADICTION_API_KEY || ''}` }; } /** * Анализ документа на наличие противоречий */ async analyzeDocument(document) { try { const response = await axios.post(`${this.apiUrl}/analyze`, { document }, { headers: this.headers }); return { success: true, result: response.data }; } catch (error) { console.error('Contradiction analysis error:', error); return { success: false, error: error.response?.data?.error || 'Произошла ошибка при анализе документа' }; } } /** * Сравнение двух документов на наличие противоречий */ async compareDocuments(doc1, doc2) { try { const response = await axios.post(`${this.apiUrl}/compare`, { doc1, doc2 }, { headers: this.headers }); return { success: true, result: response.data }; } catch (error) { console.error('Document comparison error:', error); return { success: false, error: 'Не удалось сравнить документы' }; } } /** * Получение онтологии предметной области */ async getOntology(domain) { try { const response = await axios.get(`${this.apiUrl}/ontology`, { params: { domain }, headers: this.headers }); return { success: true, ontology: response.data }; } catch (error) { console.error('Ontology retrieval error:', error); return { success: false, error: 'Не удалось загрузить онтологию' }; } } /** * Получение рекомендаций по разрешению противоречий */ async getResolutionSuggestions(contradictionId) { try { const response = await axios.get(`${this.apiUrl}/suggestions/${contradictionId}`, { headers: this.headers }); return { success: true, suggestions: response.data }; } catch (error) { console.error('Resolution suggestions error:', error); return { success: false, error: 'Не удалось получить рекомендации' }; } } } export default new ContradictionService();
// src/components/ContradictionDetection.jsx // Компонент системы выявления противоречий в документах import React, { useState, useEffect, useRef } from 'react'; import { Container, Row, Col, Card, Button, Form, Alert, Tabs, Tab, Badge, ProgressBar, Modal } from 'react-bootstrap'; import { FaBalanceScale, FaProjectDiagram, FaSearch, FaExclamationTriangle, FaPlus, FaEye, FaBrain } from 'react-icons/fa'; import { Bar, Line, Pie } from 'react-chartjs-2'; import 'chart.js/auto'; import ContradictionService from '../services/contradictionService'; const ContradictionDetection = () => { const [activeTab, setActiveTab] = useState('analyze'); const [documentText, setDocumentText] = useState(''); const [compareDoc1, setCompareDoc1] = useState(''); const [compareDoc2, setCompareDoc2] = useState(''); const [domain, setDomain] = useState('legal'); const [analysisResult, setAnalysisResult] = useState(null); const [compareResult, setCompareResult] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [ontology, setOntology] = useState(null); const [showExplanationModal, setShowExplanationModal] = useState(false); const [selectedContradiction, setSelectedContradiction] = useState(null); const [userId] = useState(`user_${Math.random().toString(36).substr(2, 9)}`); // Анализ документа const handleAnalyze = async () => { if (!documentText.trim() || isLoading) return; setIsLoading(true); setError(null); try { const response = await ContradictionService.analyzeDocument({ text: documentText, domain: domain }); if (response.success) { setAnalysisResult(response.result); } else { setError(response.error); } } catch (err) { setError('Произошла ошибка при анализе документа. Пожалуйста, попробуйте еще раз.'); console.error('Document analysis error:', err); } finally { setIsLoading(false); } }; // Сравнение двух документов const handleCompare = async () => { if ((!compareDoc1.trim() || !compareDoc2.trim()) && isLoading) return; setIsLoading(true); setError(null); try { const response = await ContradictionService.compareDocuments( { text: compareDoc1, domain: domain }, { text: compareDoc2, domain: domain } ); if (response.success) { setCompareResult(response.result); } else { setError(response.error); } } catch (err) { setError('Произошла ошибка при сравнении документов. Пожалуйста, попробуйте еще раз.'); console.error('Document comparison error:', err); } finally { setIsLoading(false); } }; // Загрузка онтологии const loadOntology = async () => { setIsLoading(true); setError(null); try { const response = await ContradictionService.getOntology(domain); if (response.success) { setOntology(response.ontology); } else { setError(response.error); } } catch (err) { setError('Произошла ошибка при загрузке онтологии. Пожалуйста, попробуйте еще раз.'); console.error('Ontology loading error:', err); } finally { setIsLoading(false); } }; // Получение рекомендаций по разрешению противоречия const getResolutionSuggestions = async (contradictionId) => { try { const response = await ContradictionService.getResolutionSuggestions(contradictionId); if (response.success) { return response.suggestions; } } catch (err) { console.error('Resolution suggestions error:', err); } return []; }; // Подготовка данных для графиков const getContradictionDistributionData = () => { if (!analysisResult) return null; return { labels: ['Высокая', 'Средняя', 'Низкая'], datasets: [ { [ analysisResult.statistics.high_confidence, analysisResult.statistics.medium_confidence, analysisResult.statistics.low_confidence ], backgroundColor: [ 'rgba(220, 53, 69, 0.7)', 'rgba(255, 193, 7, 0.7)', 'rgba(40, 167, 69, 0.7)' ] } ] }; }; const getContradictionTypesData = () => { if (!analysisResult) return null; return { labels: Object.keys(analysisResult.statistics.types), datasets: [ { Object.values(analysisResult.statistics.types), backgroundColor: [ 'rgba(54, 162, 235, 0.7)', 'rgba(75, 192, 192, 0.7)', 'rgba(153, 102, 255, 0.7)', 'rgba(255, 159, 67, 0.7)' ] } ] }; }; const getComparisonData = () => { if (!compareResult) return null; return { labels: ['Совпадения', 'Противоречия', 'Дополнения'], datasets: [ { [ compareResult.similarity_score * 100, compareResult.contradiction_score * 100, (1 - compareResult.similarity_score - compareResult.contradiction_score) * 100 ], backgroundColor: [ 'rgba(40, 167, 69, 0.7)', 'rgba(220, 53, 69, 0.7)', 'rgba(54, 162, 235, 0.7)' ] } ] }; }; // Определение цвета для уровня противоречия const getContradictionColor = (score) => { if (score > 0.7) return 'danger'; if (score > 0.4) return 'warning'; return 'info'; }; // Открытие модального окна с объяснением const openExplanationModal = async (contradiction) => { setSelectedContradiction(contradiction); // Получаем рекомендации const suggestions = await getResolutionSuggestions(contradiction.id); setSelectedContradiction(prev => ({ ...prev, resolution_suggestions: suggestions })); setShowExplanationModal(true); }; useEffect(() => { loadOntology(); }, [domain]); return ( <container classname="mt-5 mb-5"> <row classname="justify-content-center"> <card> <card.header as="h5" classname="d-flex align-items-center bg-primary text-white"> <fabalancescale classname="me-2"></fabalancescale> Выявление противоречий в документах </card.header> <card.body> <p> <form.select value="{domain}" onchange="{(e)" ==""> setDomain(e.target.value)} style={{ width: 'auto', display: 'inline-block' }} > <option value="legal">Юридические документы</option> <option value="technical">Технические стандарты</option> <option value="medical">Медицинские протоколы</option> <option value="financial">Финансовые документы</option> </form.select> <p> <button variant="outline-secondary" size="sm" onclick="{loadOntology}" disabled="{isLoading}"> <faprojectdiagram classname="me-1"></faprojectdiagram> Загрузить онтологию </button> </p> <tabs activekey="{activeTab}" onselect="{(k)" ==""> setActiveTab(k)} className="mb-4"> <tab eventkey="analyze" title="{<"><fasearch></fasearch> Анализ документа}> <row> <form> <form.group classname="mb-3"> <form.label>Введите текст документа</form.label> <form.control as="textarea" rows="{10}" value="{documentText}" onchange="{(e)" ==""> setDocumentText(e.target.value)} placeholder="Введите текст документа для анализа..." disabled={isLoading} /> </form.control></form.group> <p classname="d-flex justify-content-between"> <button type="button" variant="primary" onclick="{handleAnalyze}" disabled="{isLoading" ||="" !documenttext.trim()}=""> {isLoading ? ( {' '} Анализ... ) : 'Анализировать документ'} </button> <button variant="outline-secondary" onclick="{()" ==""> setDocumentText('')} disabled={isLoading} > Очистить </button> </p> </form> {analysisResult ? (
Обнаруженные противоречия Статистика:
{analysisResult.total_contradictions} </badge> <p classname="mb-4"> <progressbar> <progressbar now="{analysisResult.statistics.high_confidence}" key="{1}" variant="danger" label="{`${analysisResult.statistics.high_confidence}" высокой`}=""></progressbar> <progressbar now="{analysisResult.statistics.medium_confidence}" key="{2}" variant="warning" label="{`${analysisResult.statistics.medium_confidence}" средней`}=""></progressbar> <progressbar now="{analysisResult.statistics.low_confidence}" key="{3}" variant="info" label="{`${analysisResult.statistics.low_confidence}" низкой`}=""></progressbar> </progressbar> </p> <h6>Типы противоречий:</h6> {Object.entries(analysisResult.statistics.types).map(([type, count], index) => ( 0 ? ( analysisResult.contradictions.map((contradiction, index) => ( openExplanationModal(contradiction)}> <div> <badge bg="{getContradictionColor(contradiction.score)}" classname="me-2"> {Math.round(contradiction.score * 100)}% </badge> <strong>Противоречие #{index + 1}</strong> <p classname="text-muted small mb-1"> {contradiction.context.substring(0, 100)}... </p> <button variant="outline-secondary" size="sm"> <faeye></faeye> </button> <p classname="small"> Утверждение 1: {contradiction.statement1}</p> <p><strong>Утверждение 2:</strong> {contradiction.statement2}</p> )) ) : ( <p classname="text-center py-3 text-muted"> Противоречия не обнаружены </p> )} ) : ( <p classname="border rounded p-3 bg-light h-100 d-flex flex-column justify-content-center align-items-center"> <fabalancescale size="{64}" classname="text-primary mb-3"></fabalancescale> </p><p classname="mb-0">Введите текст документа и нажмите "Анализировать документ"</p> <p classname="text-muted small">Система автоматически выявит противоречия в тексте</p> )} <tab eventkey="compare" title="{<"><fabalancescale></fabalancescale> Сравнение документов}> <row> <form> <form.group classname="mb-3"> <form.label>Документ 1</form.label> <form.control as="textarea" rows="{8}" value="{compareDoc1}" onchange="{(e)" ==""> setCompareDoc1(e.target.value)} placeholder="Введите первый документ..." disabled={isLoading} /> </form.control></form.group> </form> <form> <form.group classname="mb-3"> <form.label>Документ 2</form.label> <form.control as="textarea" rows="{8}" value="{compareDoc2}" onchange="{(e)" ==""> setCompareDoc2(e.target.value)} placeholder="Введите второй документ..." disabled={isLoading} /> </form.control></form.group> <p classname="d-flex justify-content-end"> <button variant="primary" onclick="{handleCompare}" disabled="{isLoading" ||="" !comparedoc1.trim()="" !comparedoc2.trim()}=""> {isLoading ? ( ) : 'Сравнить документы'} </button> </p> </form> {compareResult ? ( |
Результаты сравнения
0 ? ( {compareResult.key_contradictions.slice(0, 3).map((contradiction, index) => ( openExplanationModal(contradiction)}> <badge bg="{getContradictionColor(contradiction.score)}" classname="me-2"> {Math.round(contradiction.score * 100)}% </badge> <strong>Противоречие #{index + 1}</strong> <p classname="text-muted small"> {contradiction.statement1.substring(0, 50)}... → {contradiction.statement2.substring(0, 50)}... </p> ))} <button variant="outline-primary" size="sm" classname="mt-2"> Все противоречия </button> ) : ( <p classname="text-center py-4 text-muted"> Ключевые противоречия не обнаружены </p> )} ) : ( <p classname="border rounded p-3 bg-light h-300 d-flex flex-column justify-content-center align-items-center"> <fabalancescale size="{64}" classname="text-primary mb-3"></fabalancescale> </p><p classname="mb-0">Введите два документа и нажмите "Сравнить документы"</p> <p classname="text-muted small">Система выявит противоречия между документами</p> )} <tab eventkey="ontology" title="{<"><faprojectdiagram></faprojectdiagram> Онтология}> {ontology ? (
|
Визуализация онтологии: