| |
| """ |
| EvoRM Ablation Study - All 6 modes |
| Uses ref_pairs order for entity selection (correct approach). |
| """ |
| import os, sys, json, time, shutil |
| from datetime import datetime |
|
|
| sys.path.insert(0, '/root/autodl-tmp/AdaCoAgentEA') |
| sys.path.insert(0, '/root/autodl-tmp/AdaCoAgentEA/Area2') |
|
|
| os.environ["OPENAI_API_BASE"] = "https://hk.xty.app/v1" |
| os.environ["OPENAI_API_KEY"] = "sk-7a7Ev4VcVyysPLT5hqtqIVD6PybzJ1ZlEIVZddIR3NtZvPgK" |
|
|
| DATA_DIR = "/root/autodl-tmp/AdaCoAgentEA/data/icews_wiki" |
| RESULTS_DIR = "/root/autodl-tmp/AdaCoAgentEA/results" |
| ALIGNED_FILE = os.path.join(DATA_DIR, "message_pool", "aligned_entities.txt") |
| REF_PAIRS_FILE = os.path.join(DATA_DIR, "ref_pairs") |
| IMPORTANT_FILE = os.path.join(DATA_DIR, "message_pool", "important_entities.txt") |
| RETRIEVER_FILE = os.path.join(DATA_DIR, "message_pool", "retriever_outputs.txt") |
| EVORM_STATE = os.path.join(DATA_DIR, "evorm_state") |
|
|
| os.makedirs(RESULTS_DIR, exist_ok=True) |
|
|
| def load_ref_pairs(): |
| pairs = {} |
| with open(REF_PAIRS_FILE, 'r') as f: |
| for line in f: |
| parts = line.strip().split('\t') |
| if len(parts) == 2: |
| try: |
| pairs[int(parts[0])] = int(parts[1]) |
| except: |
| pass |
| return pairs |
|
|
| def compute_metrics(ref_subset=None): |
| aligned = set() |
| if os.path.exists(ALIGNED_FILE): |
| with open(ALIGNED_FILE, 'r') as f: |
| for line in f: |
| parts = line.strip().split('\t') |
| if len(parts) == 2: |
| try: |
| aligned.add((int(parts[0]), int(parts[1]))) |
| except: |
| continue |
| if ref_subset: |
| ref_set = set(ref_subset.items()) |
| else: |
| ref_set = set(load_ref_pairs().items()) |
| if not ref_set: |
| return {'error': 'No ref pairs'} |
| tp = len(aligned & ref_set) |
| fp = len(aligned - ref_set) |
| fn = len(ref_set - aligned) |
| return { |
| 'Hits@1': round(tp / max(1, len(ref_set)), 4), |
| 'MRR': round(tp / max(1, len(ref_set)), 4), |
| 'Precision': round(tp / max(1, tp + fp), 4), |
| 'Recall': round(tp / max(1, tp + fn), 4), |
| 'F1': round(2*tp/max(1, 2*tp+fp+fn), 4), |
| 'TP': tp, 'FP': fp, 'FN': fn, |
| 'Total_Ref': len(ref_set), |
| 'Total_Aligned': len(aligned), |
| } |
|
|
| def clear_state(): |
| if os.path.exists(EVORM_STATE): |
| shutil.rmtree(EVORM_STATE) |
| if os.path.exists(ALIGNED_FILE): |
| os.remove(ALIGNED_FILE) |
|
|
| def create_subset_from_ref_order(n_entities, ref_map): |
| """Create subset using ref_pairs order (not retriever order).""" |
| |
| ref_order = [] |
| with open(REF_PAIRS_FILE, 'r') as f: |
| for line in f: |
| parts = line.strip().split('\t') |
| if len(parts) == 2: |
| try: |
| e1 = int(parts[0]) |
| if e1 not in ref_order: |
| ref_order.append(e1) |
| except: |
| pass |
| |
| actual_n = min(n_entities, len(ref_order)) |
| subset_kg1 = set(ref_order[:actual_n]) |
| |
| |
| subset_lines = [] |
| with open(RETRIEVER_FILE, 'r') as f: |
| for line in f: |
| parts = line.strip().split('\t') |
| if len(parts) == 2: |
| try: |
| if int(parts[0]) in subset_kg1: |
| subset_lines.append(line) |
| except: |
| pass |
| |
| with open(IMPORTANT_FILE, 'w') as f: |
| f.writelines(subset_lines) |
| |
| subset_ref = {e1: ref_map[e1] for e1 in subset_kg1 if e1 in ref_map} |
| print(f" Created subset: {len(subset_kg1)} entities, {len(subset_ref)} ref pairs, {len(subset_lines)} retriever lines") |
| return subset_ref |
|
|
| def main(): |
| n_entities = 200 |
| ref_map = load_ref_pairs() |
| print(f"Loaded {len(ref_map)} reference pairs") |
| |
| import tokens_cal |
| from LLM1_label_selector import align_entities |
| |
| configs = [ |
| ('Full System (EvoRM)', None), |
| ('w/o Stage-1 (Symbolic)', 'no_stage1'), |
| ('w/o Maintenance', 'no_maintenance'), |
| ('w/o MLP Gate', 'no_mlp_gate'), |
| ('w/o Hypergraph', 'no_hypergraph'), |
| ('w/o Mlight', 'no_mlight'), |
| ] |
| |
| results = {} |
| for config_name, ablation_mode in configs: |
| print(f"\n{'='*50}") |
| print(f" {config_name}") |
| print(f"{'='*50}") |
| |
| subset_ref = create_subset_from_ref_order(n_entities, ref_map) |
| clear_state() |
| |
| tokens_cal.global_tokens = 0 |
| start = time.time() |
| aligned_pairs = align_entities(DATA_DIR, from_m3=False, ablation_mode=ablation_mode) |
| elapsed = time.time() - start |
| tokens = tokens_cal.global_tokens |
| n_pairs = len(aligned_pairs) |
| metrics = compute_metrics(ref_subset=subset_ref) |
| |
| results[config_name] = { |
| 'aligned_pairs': n_pairs, |
| 'time_seconds': round(elapsed, 1), |
| 'tokens': tokens, |
| 'tokens_per_pair': round(tokens / max(1, n_pairs), 1), |
| 'metrics': metrics, |
| } |
| |
| print(f" Aligned: {n_pairs}, Time: {elapsed:.1f}s, Tokens: {tokens}") |
| print(f" Hits@1: {metrics['Hits@1']}, Precision: {metrics['Precision']}, Recall: {metrics['Recall']}") |
| |
| |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
| result_file = os.path.join(RESULTS_DIR, f"ablation_6modes_{timestamp}.json") |
| with open(result_file, 'w') as f: |
| json.dump({ |
| 'experiment': 'EvoRM Ablation Study (6 modes)', |
| 'dataset': 'ICEWS-WIKI', |
| 'n_entities': n_entities, |
| 'results': results, |
| }, f, indent=2) |
| |
| |
| print(f"\n{'='*70}") |
| print("ABLATION SUMMARY") |
| print(f"{'='*70}") |
| print(f"{'Configuration':<30} {'Hits@1':>8} {'Prec':>8} {'Recall':>8} {'F1':>8} {'Tok':>10}") |
| print("-" * 70) |
| for cname, _ in configs: |
| if cname in results: |
| m = results[cname]['metrics'] |
| print(f"{cname:<30} {m['Hits@1']:>8.4f} {m['Precision']:>8.4f} {m['Recall']:>8.4f} {m['F1']:>8.4f} {results[cname]['tokens']:>10}") |
| |
| print(f"\nResults saved to: {result_file}") |
|
|
| if __name__ == '__main__': |
| main() |
|
|