import difflib import os import re from Generator.LogGenerator import LogGenerator from Processor.StreamingLogCluster import StreamingLogCluster from Tester.RegressionMetricsCalculator import RegressionMetricsCalculator def evaluate_template_similarity(gt_template: str, gen_template: str) -> dict: """ Оценивает схожесть сгенерированного шаблона (gen) с эталонным (gt - Ground Truth). """ # 1. Разбиваем шаблоны на сегменты (текст и теги <...>) gt_parts = [p for p in re.split(r'(<[^>]+>)', gt_template) if p] gen_parts = [p for p in re.split(r'(<[^>]+>)', gen_template) if p] # --- СТРОГАЯ ПРОВЕРКА (Regex) --- # Создаем регулярное выражение из эталона: # Текст должен совпасть жестко, а переменные эталона могут проглотить что угодно (.*) regex_pattern = '^' for part in gt_parts: if part.startswith('<') and part.endswith('>'): regex_pattern += '(.*)' else: regex_pattern += re.escape(part) regex_pattern += '$' # Подготавливаем Gen: заменяем его переменные на нулевой байт, # чтобы они поглотились `(.*)`, но не совпали с реальным текстом случайно gen_string_for_regex = re.sub(r'<[^>]+>', '\x00', gen_template) is_perfect_structure = bool(re.match(regex_pattern, gen_string_for_regex, flags=re.DOTALL)) # --- МЯГКАЯ ОЦЕНКА В ПРОЦЕНТАХ (Preservation Score) --- # Достаем только жесткие константы, выбрасывая все переменные gt_consts = "".join(p for p in gt_parts if not (p.startswith('<') and p.endswith('>'))) gen_consts = "".join(p for p in gen_parts if not (p.startswith('<') and p.endswith('>'))) # Сравниваем, насколько "скелет" Gen содержит внутри себя "скелет" Эталона matcher = difflib.SequenceMatcher(None, gt_consts, gen_consts) # Считаем сумму символов эталона, которые остались на своих местах matched_chars = sum(block.size for block in matcher.get_matching_blocks()) # Считаем процент от 0.0 до 1.0 preservation_score = matched_chars / len(gt_consts) if gt_consts else 1.0 return { "is_perfect": is_perfect_structure, # True, если структура не нарушена вообще "score": round(preservation_score, 4), # 1.0 = Идеал, < 1.0 = Переменные "съели" константы } if __name__ == '__main__': gen = LogGenerator() metrics = RegressionMetricsCalculator() MODEL_PATH = '../Resources/model' DB_FILE = "../Resources/logs.db" if os.path.exists(DB_FILE): os.remove(DB_FILE) print("--- ЗАПУСК: Delta Mode ---") clusterer = StreamingLogCluster(MODEL_PATH, db_path=DB_FILE) # Генерируем 10 примеров for i in range(1): # 1. Получаем объект Term term = gen.generate() # 3. Используем данные (например, сохраняем в JSON для обучения) print(f"--- Sample {i + 1} ---") template = term.structure().text print(f"Template :{template}") for j in range(10): # 2. Рендерим его в строку и метаданные log = term.render(0.5) processed = clusterer.process(log.text) eval_result = evaluate_template_similarity(template, processed['template_view']) score = eval_result['score'] metrics.add_sample(score) print(f"Positive {j}: {processed['template_view']}") #print(score) print(f"Template : {template}") # # --- ВЫВОДИТ ИТОГОВЫЕ МЕТРИКИ В КОНЦЕ СКРИПТА --- # print("\n" + "=" * 40) # print("Метрики:") # print("=" * 40) # results = metrics.calculate() # for metric_name, value in results.items(): # print(f"{metric_name:<10}: {value}")