97 lines
4.3 KiB
Python
97 lines
4.3 KiB
Python
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}") |