File size: 6,115 Bytes
64b5d29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# src/analysis/network_builder.py (DÜZELTİLMİŞ TAM KOD)

import networkx as nx
import pandas as pd
import logging

# Yerel modüller
from src.data_management import storage

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# Grafı kaydetmek için dosya adı
GRAPH_FILENAME = "concept_network"
# Benzerlik dosyasının adı (Doğrudan burada tanımlayalım veya similarity'den import edelim)
# storage modülünde değil!
SIMILARITY_FILENAME = "concept_similarities"

def build_concept_network(similarity_threshold: float = 0.60,

                            include_similarity_edges: bool = True,

                            include_extracted_edges: bool = True) -> nx.Graph | None:
    """

    Konseptler, çıkarılmış ilişkiler ve anlamsal benzerliklerden bir NetworkX grafı oluşturur.



    Args:

        similarity_threshold (float): Grafiğe eklenecek minimum anlamsal benzerlik skoru.

        include_similarity_edges (bool): Benzerlik kenarlarını dahil et.

        include_extracted_edges (bool): Metinden çıkarılan ilişki kenarlarını dahil et.



    Returns:

        nx.Graph | None: Oluşturulan NetworkX grafı veya hata durumunda None.

    """
    logging.info("Konsept ağı oluşturuluyor...")
    if not include_similarity_edges and not include_extracted_edges:
        logging.warning("Hem benzerlik hem de çıkarılmış ilişki kenarları devre dışı bırakıldı.")

    # Temel verileri yükle
    concepts_df = storage.load_dataframe('concepts', storage.CONCEPT_COLUMNS)
    relationships_df = storage.load_dataframe('relationships', storage.RELATIONSHIP_COLUMNS)
    # *** DÜZELTME: SIMILARITY_FILENAME doğrudan kullanılıyor ***
    similarity_df = storage.load_dataframe(SIMILARITY_FILENAME, ['concept_id_1', 'concept_id_2', 'similarity'])

    if concepts_df is None or concepts_df.empty:
        logging.error("Ağ oluşturmak için konsept verisi bulunamadı.")
        return None

    G = nx.Graph()

    # 1. Adım: Konseptleri Düğüm Olarak Ekle
    node_count = 0
    valid_concept_ids = set() # Grafiğe eklenen geçerli ID'leri takip et
    for index, row in concepts_df.iterrows():
        concept_id = row['concept_id']
        concept_name = row['name']
        if pd.notna(concept_id) and pd.notna(concept_name):
             G.add_node(concept_id, name=concept_name)
             valid_concept_ids.add(concept_id)
             node_count += 1
        else:
             logging.warning(f"Geçersiz konsept verisi atlandı: ID={concept_id}, Name={concept_name}")
    logging.info(f"{node_count} konsept düğüm olarak eklendi.")

    edge_count_extracted = 0
    edge_count_similarity = 0
    updated_edge_count = 0

    # 2. Adım: Çıkarılmış İlişkileri Kenar Olarak Ekle
    if include_extracted_edges and relationships_df is not None and not relationships_df.empty:
        logging.info("Çıkarılmış ilişkiler kenar olarak ekleniyor...")
        for index, row in relationships_df.iterrows():
            source_id = row['source_concept_id']
            target_id = row['target_concept_id']
            rel_type = row['type'] or 'RELATED_TO'

            # Düğümlerin grafide olduğundan ve geçerli olduğundan emin ol
            if source_id in valid_concept_ids and target_id in valid_concept_ids:
                if G.has_edge(source_id, target_id):
                     G.edges[source_id, target_id]['relation_type'] = rel_type
                     G.edges[source_id, target_id]['type'] = 'extracted'
                else:
                     G.add_edge(source_id, target_id, type='extracted', relation_type=rel_type, weight=0.8)
                     edge_count_extracted += 1
            else:
                 logging.warning(f"İlişki için düğüm(ler) bulunamadı veya geçersiz: {source_id} -> {target_id}")
        logging.info(f"{edge_count_extracted} çıkarılmış ilişki kenarı eklendi.")

    # 3. Adım: Anlamsal Benzerlikleri Kenar Olarak Ekle
    if include_similarity_edges and similarity_df is not None and not similarity_df.empty:
        logging.info(f"Anlamsal benzerlikler (Eşik > {similarity_threshold:.2f}) kenar olarak ekleniyor...")
        filtered_similarity = similarity_df[(similarity_df['similarity'] >= similarity_threshold) & (similarity_df['similarity'] < 1.0)]
        logging.info(f"{len(similarity_df)} benzerlik çiftinden {len(filtered_similarity)} tanesi eşik değerinin üzerinde (ve < 1.0).")

        for index, row in filtered_similarity.iterrows():
            id1 = row['concept_id_1']
            id2 = row['concept_id_2']
            similarity = row['similarity']

            if id1 in valid_concept_ids and id2 in valid_concept_ids:
                if G.has_edge(id1, id2):
                     G.edges[id1, id2]['similarity'] = similarity
                     if 'weight' not in G.edges[id1, id2] or similarity > G.edges[id1, id2].get('weight', 0):
                          G.edges[id1, id2]['weight'] = similarity
                     # Eğer extracted ilişki varsa, tipi 'combined' yapabiliriz?
                     G.edges[id1, id2]['type'] = 'combined' if G.edges[id1, id2].get('type') == 'extracted' else G.edges[id1, id2].get('type', 'similarity') # Önceliği koru veya birleştir
                     updated_edge_count += 1
                else:
                     G.add_edge(id1, id2, type='similarity', weight=similarity)
                     edge_count_similarity += 1
            else:
                logging.warning(f"Benzerlik için düğüm(ler) bulunamadı veya geçersiz: {id1} <-> {id2}")
        logging.info(f"{edge_count_similarity} yeni benzerlik kenarı eklendi, {updated_edge_count} mevcut kenara benzerlik/tip bilgisi eklendi.")

    total_edges = G.number_of_edges()
    logging.info(f"Konsept ağı oluşturuldu. Düğüm sayısı: {G.number_of_nodes()}, Kenar sayısı: {total_edges}.")

    # 4. Adım: Grafı Kaydet
    storage.save_network(G, GRAPH_FILENAME)

    return G