Mukul Rayana commited on
Commit
4e44b55
·
1 Parent(s): d64bbe6

Fix Condition C ablation - pure FAISS order, no safety score bias - mean=0.50

Browse files
Files changed (2) hide show
  1. eval/ablation_results.json +13 -13
  2. eval/run_ablation.py +21 -21
eval/ablation_results.json CHANGED
@@ -52,34 +52,39 @@
52
  0
53
  ],
54
  "condition_c_scores": [
55
- 0,
56
  0,
57
  0,
58
  1,
 
59
  0,
 
 
 
60
  0,
61
  0,
62
- 0,
63
- 0,
64
- 0,
65
- 0,
66
  0,
67
  0,
68
  1,
69
  0,
 
70
  0,
71
  0,
72
  0,
 
73
  0,
74
  0,
75
- 0,
 
76
  0,
77
  1,
78
  0,
79
  0,
80
  0,
81
  0,
 
82
  0,
 
83
  0,
84
  0,
85
  1,
@@ -87,10 +92,6 @@
87
  1,
88
  0,
89
  0,
90
- 1,
91
- 1,
92
- 1,
93
- 1,
94
  0,
95
  1,
96
  1,
@@ -100,8 +101,7 @@
100
  1,
101
  1,
102
  1,
103
- 1,
104
- 1
105
  ],
106
  "condition_d_scores": [
107
  1,
@@ -156,7 +156,7 @@
156
  1
157
  ],
158
  "condition_a_mean": 0.3,
159
- "condition_c_mean": 0.4,
160
  "condition_d_mean": 0.88,
161
  "n": 50
162
  }
 
52
  0
53
  ],
54
  "condition_c_scores": [
 
55
  0,
56
  0,
57
  1,
58
+ 1,
59
  0,
60
+ 1,
61
+ 1,
62
+ 1,
63
  0,
64
  0,
65
+ 1,
 
 
 
66
  0,
67
  0,
68
  1,
69
  0,
70
+ 1,
71
  0,
72
  0,
73
  0,
74
+ 1,
75
  0,
76
  0,
77
+ 1,
78
+ 1,
79
  0,
80
  1,
81
  0,
82
  0,
83
  0,
84
  0,
85
+ 1,
86
  0,
87
+ 1,
88
  0,
89
  0,
90
  1,
 
92
  1,
93
  0,
94
  0,
 
 
 
 
95
  0,
96
  1,
97
  1,
 
101
  1,
102
  1,
103
  1,
104
+ 0
 
105
  ],
106
  "condition_d_scores": [
107
  1,
 
156
  1
157
  ],
158
  "condition_a_mean": 0.3,
159
+ "condition_c_mean": 0.5,
160
  "condition_d_mean": 0.88,
161
  "n": 50
162
  }
eval/run_ablation.py CHANGED
@@ -3,7 +3,7 @@ eval/run_ablation.py
3
  Ablation study: compare Condition A (BM25), C (Dense RAG no emotion), D (Full EmpathRAG).
4
  Computes Condition C as TRUE no-emotion-conditioning ablation:
5
  - No emotion query rewriting (raw user_message goes to FAISS)
6
- - No emotion match bonus in re-ranking (safety_score only)
7
  Loads Conditions A and D from eval/wilcoxon_results.json.
8
  """
9
 
@@ -27,14 +27,16 @@ RESULTS_PATH = "eval/ablation_results.json"
27
  def add_condition_c_methods(pipeline):
28
  """
29
  Adds two methods to pipeline instance for Condition C ablation:
30
- 1. _retrieve_no_emotion: retrieval with no emotion match bonus
31
- 2. run_condition_c: full pipeline run with raw user_message (no query rewriting)
32
  """
33
 
34
  def _retrieve_no_emotion(self, query: str, emotion_label: int) -> list[str]:
35
  """
36
- Encodes query on GPU, searches FAISS, filters via SQLite.
37
- Returns top_k chunk texts ranked by SAFETY SCORE ONLY (no emotion bonus).
 
 
38
  GPU usage: ~440 MB during encode, freed before returning.
39
  """
40
  # Move encoder to GPU for this call only
@@ -48,32 +50,30 @@ def add_condition_c_methods(pipeline):
48
  self.encoder.to("cpu")
49
  torch.cuda.empty_cache()
50
 
51
- # Search wider than top_k so we have room to re-rank
52
  distances, ids = self.faiss_index.search(
53
- q_vec.astype(np.float32), self.top_k * 3
54
  )
55
- candidate_ids = [int(i) for i in ids[0] if i >= 0]
 
 
56
 
57
- if not candidate_ids:
58
  return []
59
 
60
- # Fetch metadata from SQLite
61
- placeholders = ",".join("?" * len(candidate_ids))
62
  conn = sqlite3.connect(self.db_path)
63
  rows = conn.execute(
64
- f"SELECT id, text, emotion_label, safety_score FROM chunks "
65
- f"WHERE id IN ({placeholders})",
66
- candidate_ids,
67
  ).fetchall()
68
  conn.close()
69
 
70
- # Re-rank: ONLY by safety_score (no emotion match bonus)
71
- def _score(row):
72
- _, _, chunk_emotion, safety = row
73
- return safety # No match_bonus - pure semantic similarity + safety
74
-
75
- rows_sorted = sorted(rows, key=_score, reverse=True)[:self.top_k]
76
- return [r[1] for r in rows_sorted]
77
 
78
  def run_condition_c(self, user_message: str) -> dict:
79
  """
 
3
  Ablation study: compare Condition A (BM25), C (Dense RAG no emotion), D (Full EmpathRAG).
4
  Computes Condition C as TRUE no-emotion-conditioning ablation:
5
  - No emotion query rewriting (raw user_message goes to FAISS)
6
+ - No re-ranking at all - pure FAISS distance order, no safety score, no emotion signal
7
  Loads Conditions A and D from eval/wilcoxon_results.json.
8
  """
9
 
 
27
  def add_condition_c_methods(pipeline):
28
  """
29
  Adds two methods to pipeline instance for Condition C ablation:
30
+ 1. _retrieve_no_emotion: pure FAISS distance order, no re-ranking, no emotion or safety score
31
+ 2. run_condition_c: full pipeline run with raw user_message and no emotion conditioning
32
  """
33
 
34
  def _retrieve_no_emotion(self, query: str, emotion_label: int) -> list[str]:
35
  """
36
+ Pure semantic retrieval - no emotion conditioning of any kind.
37
+ Returns top_k chunks in FAISS distance order (closest first).
38
+ No re-ranking, no safety score, no emotion bonus.
39
+ emotion_label parameter accepted but deliberately ignored.
40
  GPU usage: ~440 MB during encode, freed before returning.
41
  """
42
  # Move encoder to GPU for this call only
 
50
  self.encoder.to("cpu")
51
  torch.cuda.empty_cache()
52
 
53
+ # Search top_k directly - no need for top_k*3 since we are not re-ranking
54
  distances, ids = self.faiss_index.search(
55
+ q_vec.astype(np.float32), self.top_k
56
  )
57
+ # ids[0] is already sorted by L2 distance ascending (closest first)
58
+ # Filter out -1 padding (FAISS uses -1 for unfilled slots)
59
+ faiss_ordered_ids = [int(i) for i in ids[0] if i >= 0]
60
 
61
+ if not faiss_ordered_ids:
62
  return []
63
 
64
+ # Fetch text from SQLite - NOTE: SQLite WHERE IN does NOT preserve input order
65
+ placeholders = ",".join("?" * len(faiss_ordered_ids))
66
  conn = sqlite3.connect(self.db_path)
67
  rows = conn.execute(
68
+ f"SELECT id, text FROM chunks WHERE id IN ({placeholders})",
69
+ faiss_ordered_ids,
 
70
  ).fetchall()
71
  conn.close()
72
 
73
+ # Restore FAISS distance order using id->text map
74
+ id_to_text = {r[0]: r[1] for r in rows}
75
+ # Return in FAISS order, skip any ids not found in SQLite
76
+ return [id_to_text[i] for i in faiss_ordered_ids if i in id_to_text]
 
 
 
77
 
78
  def run_condition_c(self, user_message: str) -> dict:
79
  """