klydekushy commited on
Commit
f820864
·
verified ·
1 Parent(s): 5b0daa9

Update src/Algorithms/vector_search.py

Browse files
Files changed (1) hide show
  1. src/Algorithms/vector_search.py +20 -76
src/Algorithms/vector_search.py CHANGED
@@ -1,101 +1,45 @@
1
  """
2
- MODULE: VECTOR SEARCH ENGINE (CONTEXT AWARE)
3
- ============================================
4
- Amélioration : Le vecteur d'un nœud inclut désormais ses voisins et ses relations.
5
  """
6
  import faiss
7
  import numpy as np
8
  from sentence_transformers import SentenceTransformer
9
- import networkx as nx
10
 
11
  class SemanticIndex:
12
  def __init__(self, model_name='all-MiniLM-L6-v2'):
13
- # Chargement du modèle (rapide sur CPU)
14
  self.model = SentenceTransformer(model_name)
15
  self.index = None
16
  self.uris = []
17
- self.metadatas = []
18
- self.is_ready = False
19
 
20
- def build_from_networkx(self, G):
21
- """
22
- Vectorisation Contextuelle :
23
- Texte = Attributs du Nœud + Relations Sortantes (Voisins)
24
- """
25
- print("⏳ [VECTOR] Génération des embeddings contextuels...")
26
- corpus = []
27
- self.uris = []
28
- self.metadatas = []
29
 
30
- # On parcourt chaque nœud
31
- for node, data in G.nodes(data=True):
32
- # 1. Texte de base (Interne)
33
- # On prend toutes les valeurs textuelles du nœud
34
- internal_attrs = [
35
- str(v) for k, v in data.items()
36
- if k not in ['group', 'label', 'color', 'shape', 'x', 'y', 'size', 'title']
37
- and v and str(v).lower() != 'nan'
38
- ]
39
- base_text = f"{data.get('group', '')} {data.get('label', '')} {' '.join(internal_attrs)}"
40
 
41
- # 2. Texte du Voisinage (Relations Sortantes)
42
- # "travaille_chez X", "habite_ville Y"
43
- neighbors_text = []
44
- for neighbor in G.successors(node):
45
- # Récupération du type de lien (ex: 'habite_ville')
46
- edge_data = G.get_edge_data(node, neighbor)
47
- rel_label = edge_data.get('label', 'lié_à')
48
-
49
- # Récupération du nom du voisin (ex: 'Dakar')
50
- neighbor_label = G.nodes[neighbor].get('label', str(neighbor))
51
-
52
- # On ajoute la phrase de contexte
53
- neighbors_text.append(f"{rel_label} {neighbor_label}")
54
-
55
- # 3. Fusion (Soup)
56
- # Ex: "Client Jean Dupont. habite_ville Dakar. secteur_act Commercial."
57
- full_context = f"{base_text}. {' '.join(neighbors_text)}"
58
-
59
- # Nettoyage
60
- full_context = full_context.lower().replace('_', ' ')
61
-
62
- corpus.append(full_context)
63
- self.uris.append(node)
64
-
65
- # Méta-données pour l'affichage dans le chat
66
- meta_desc = f"{data.get('group', 'Entité')} - {data.get('label', str(node))}"
67
- self.metadatas.append(meta_desc)
68
-
69
- if not corpus:
70
- print("⚠️ Graphe vide, pas de vectorisation.")
71
- return
72
-
73
- # 4. Encodage Batch (Rapide)
74
  embeddings = self.model.encode(corpus, show_progress_bar=True)
75
-
76
- # 5. Création Index FAISS
77
  dimension = embeddings.shape[1]
78
  self.index = faiss.IndexFlatL2(dimension)
79
  self.index.add(np.array(embeddings).astype('float32'))
80
 
81
- self.is_ready = True
82
- print(f"✅ [VECTOR] Index FAISS Contextuel prêt : {len(self.uris)} entités.")
83
- return len(self.uris)
84
-
85
- def search(self, query, top_k=10):
86
- """Retourne les nœuds les plus proches sémantiquement"""
87
- if not self.is_ready:
88
- return []
89
 
90
- query_vec = self.model.encode([query.lower()]).astype('float32')
91
- distances, indices = self.index.search(query_vec, top_k)
 
 
92
 
93
  results = []
94
- for i, idx in enumerate(indices[0]):
95
- if idx < len(self.uris) and idx >= 0:
 
96
  results.append({
97
- "uri": self.uris[idx], # C'est l'ID NetworkX (ex: CLI-001)
98
- "meta": self.metadatas[idx],
99
- "score": float(1 / (1 + distances[0][i]))
100
  })
101
  return results
 
1
  """
2
+ MODULE: VECTOR SEARCH ENGINE (OG-RAG VERSION)
3
+ =============================================
 
4
  """
5
  import faiss
6
  import numpy as np
7
  from sentence_transformers import SentenceTransformer
 
8
 
9
  class SemanticIndex:
10
  def __init__(self, model_name='all-MiniLM-L6-v2'):
 
11
  self.model = SentenceTransformer(model_name)
12
  self.index = None
13
  self.uris = []
14
+ self.content_map = {} # Pour retrouver le texte du bloc
 
15
 
16
+ def build_from_ontology_blocks(self, blocks):
17
+ """Vectorise les Hyper-blocs enrichis"""
18
+ print(f"⏳ [VECTOR] Indexation de {len(blocks)} Hyper-blocs...")
 
 
 
 
 
 
19
 
20
+ corpus = [b['text'] for b in blocks]
21
+ self.uris = [b['uri'] for b in blocks]
22
+ self.content_map = {b['uri']: b['text'] for b in blocks}
 
 
 
 
 
 
 
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  embeddings = self.model.encode(corpus, show_progress_bar=True)
 
 
25
  dimension = embeddings.shape[1]
26
  self.index = faiss.IndexFlatL2(dimension)
27
  self.index.add(np.array(embeddings).astype('float32'))
28
 
29
+ print("✅ [VECTOR] Index OG-RAG prêt.")
 
 
 
 
 
 
 
30
 
31
+ def search(self, query, top_k=3):
32
+ if not self.index: return []
33
+ query_vec = self.model.encode([query]).astype('float32')
34
+ dist, indices = self.index.search(query_vec, top_k)
35
 
36
  results = []
37
+ for idx in indices[0]:
38
+ if idx != -1:
39
+ uri = self.uris[idx]
40
  results.append({
41
+ "uri": uri,
42
+ "text": self.content_map[uri],
43
+ "score": float(dist[0][0])
44
  })
45
  return results