forked from consolelogram/Super_Rag
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathphase6_text_kg_retrieval.py
More file actions
153 lines (114 loc) · 4.02 KB
/
Copy pathphase6_text_kg_retrieval.py
File metadata and controls
153 lines (114 loc) · 4.02 KB
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import os
import json
import argparse
import numpy as np
import networkx as nx
import torch
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
# =========================
# CONFIG
# =========================
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
EMB_DIR = os.path.join(BASE_DIR, "processed_data", "embeddings")
KG_PATH = os.path.join(BASE_DIR, "processed_data", "knowledge_graph.gml")
TEXT_EMB_PATH = os.path.join(EMB_DIR, "event_text_embeddings.npy")
TEXT_INDEX_PATH = os.path.join(EMB_DIR, "event_text_index.json")
OUT_PATH = os.path.join(BASE_DIR, "processed_data", "phase6_candidates.json")
TEXT_MODEL = "BAAI/bge-m3"
TOP_K = 10
# =========================
# LOADERS
# =========================
def load_embeddings():
print("[DEBUG] Current working directory:", os.getcwd())
print("[DEBUG] Expected embeddings dir:", EMB_DIR)
if not os.path.exists(EMB_DIR):
raise RuntimeError(f"Embeddings directory does not exist: {EMB_DIR}")
files = os.listdir(EMB_DIR)
print("[DEBUG] Files found in embeddings dir:", files)
# Locate text embedding file dynamically
text_emb_file = None
index_file = None
for f in files:
if "text" in f and f.endswith(".npy"):
text_emb_file = os.path.join(EMB_DIR, f)
if "text" in f and f.endswith(".json"):
index_file = os.path.join(EMB_DIR, f)
if text_emb_file is None:
raise RuntimeError("No text embedding .npy file found in embeddings dir")
if index_file is None:
raise RuntimeError("No text index .json file found in embeddings dir")
print("[INFO] Using text embeddings:", text_emb_file)
print("[INFO] Using text index:", index_file)
emb = np.load(text_emb_file)
with open(index_file) as f:
index = json.load(f)
return emb, index
def load_kg():
return nx.read_gml(KG_PATH)
# =========================
# RETRIEVAL
# =========================
def retrieve_text_candidates(query, embedder, embeddings, index):
query_vec = embedder.encode([query], normalize_embeddings=True)
sims = cosine_similarity(query_vec, embeddings)[0]
ranked = np.argsort(sims)[::-1][:TOP_K]
results = []
for i in ranked:
results.append({
"event_id": index[i],
"score": float(sims[i])
})
return results
def expand_via_kg(events, G, hops=1):
"""
Optional KG expansion: include neighbors of retrieved events.
"""
expanded = set(e["event_id"] for e in events)
for e in events:
node = e["event_id"]
if node not in G:
continue
for nbr in nx.single_source_shortest_path_length(G, node, cutoff=hops):
expanded.add(nbr)
return list(expanded)
# =========================
# MAIN
# =========================
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--query_plan", required=True)
parser.add_argument("--out", default=OUT_PATH)
args = parser.parse_args()
with open(args.query_plan) as f:
plan = json.load(f)
if not plan.get("use_text", False):
print("[INFO] Text retrieval not required by router.")
with open(args.out, "w") as f:
json.dump({"candidates": []}, f, indent=2)
return
print("[INFO] Loading text embedder...")
embedder = SentenceTransformer(TEXT_MODEL)
print("[INFO] Loading embeddings...")
embeddings, index = load_embeddings()
print("[INFO] Loading KG...")
G = load_kg()
print("[INFO] Retrieving candidates...")
initial = retrieve_text_candidates(
plan["text_query"],
embedder,
embeddings,
index
)
expanded = expand_via_kg(initial, G)
output = {
"query": plan["text_query"],
"initial_candidates": initial,
"expanded_candidates": expanded
}
with open(args.out, "w") as f:
json.dump(output, f, indent=2)
print(f"[OK] Phase 6 complete — {len(initial)} initial candidates")
if __name__ == "__main__":
main()