Проблемы выявления противоречий в документах в современных условиях
Защита через месяц, а работа не готова?
Наши эксперты выполнят ВКР по онтологическим моделям всего за 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 ? (
Визуализация онтологии:























