CAntoniadis commited on
Commit
2cc3d75
·
verified ·
1 Parent(s): 1f03c0f

Rollback to remove reranker

Browse files
Files changed (1) hide show
  1. simple_search_engine/search_engine.py +4 -129
simple_search_engine/search_engine.py CHANGED
@@ -3,130 +3,9 @@ import json
3
  from typing import List, Dict
4
  from sklearn.feature_extraction.text import TfidfVectorizer
5
  from sklearn.metrics.pairwise import linear_kernel
6
- import re
7
 
8
  CORPUS_DIR = "../corpus" # Now points to the unified directory
9
 
10
- class HeuristicReranker:
11
- def __init__(
12
- self,
13
- coverage_weight: float = 1.0,
14
- length_penalty_weight: float = 0.2,
15
- ideal_length: int = 1500,
16
- ):
17
- self.coverage_weight = coverage_weight
18
- self.length_penalty_weight = length_penalty_weight
19
- self.ideal_length = ideal_length
20
-
21
- def _tokenize(self, text: str) -> list[str]:
22
- return re.findall(r"\b\w+\b", text.lower())
23
-
24
- def _is_entity_query(self, query_tokens: list[str], query: str) -> bool:
25
- if len(query_tokens) > 2:
26
- return False
27
-
28
- lowered = query.lower()
29
-
30
- forbidden_terms = {
31
- "vs", "episode", "season", "arc",
32
- "fight", "battle", "when", "what",
33
- "how", "why", "where"
34
- }
35
-
36
- if any(term in lowered for term in forbidden_terms):
37
- return False
38
-
39
- return True
40
-
41
- def _coverage_score(self, query_tokens, doc_tokens) -> float:
42
- if not query_tokens:
43
- return 0.0
44
-
45
- doc_token_set = set(doc_tokens)
46
- matched = sum(1 for t in query_tokens if t in doc_token_set)
47
- return matched / len(query_tokens)
48
-
49
- def _length_penalty(self, doc_length: int) -> float:
50
- if doc_length <= self.ideal_length:
51
- return 0.0
52
-
53
- return (doc_length - self.ideal_length) / self.ideal_length
54
-
55
- def _episodic_penalty(self, title: str, url: str) -> float:
56
- text = f"{title} {url}".lower()
57
-
58
- patterns = [
59
- "season",
60
- "episode",
61
- "transliteration",
62
- "list_of",
63
- ]
64
-
65
- penalty = 0.0
66
- for p in patterns:
67
- if p in text:
68
- penalty += 1.0
69
-
70
- digit_count = sum(c.isdigit() for c in text)
71
- penalty += digit_count * 0.1
72
-
73
- return penalty
74
-
75
- def _entity_title_match(self, query_tokens: list[str], title: str) -> float:
76
- if not title:
77
- return 0.0
78
-
79
- title_tokens = self._tokenize(title)
80
-
81
- if title_tokens == query_tokens:
82
- return 3.0
83
-
84
- if all(t in title_tokens for t in query_tokens):
85
- return 1.5
86
-
87
- return 0.0
88
-
89
- def _mention_spam_penalty(self, query_tokens: list[str], doc_tokens: list[str]) -> float:
90
- if len(query_tokens) != 1:
91
- return 0.0
92
-
93
- term = query_tokens[0]
94
- freq = doc_tokens.count(term)
95
-
96
- if freq <= 10:
97
- return 0.0
98
-
99
- return (freq - 10) * 0.05
100
-
101
- def rerank(self, query: str, candidates: list[dict]) -> list[dict]:
102
- query_tokens = self._tokenize(query)
103
- is_entity = self._is_entity_query(query_tokens, query)
104
-
105
- reranked = []
106
- for c in candidates:
107
- doc_text = c["text"]
108
- doc_tokens = self._tokenize(doc_text)
109
-
110
- if is_entity:
111
- score = 0.2 * c["score"]
112
- score += self._entity_title_match(query_tokens, c.get("title", ""))
113
- score -= self._episodic_penalty(c.get("title", ""), c.get("url", ""))
114
- score -= self._mention_spam_penalty(query_tokens, doc_tokens)
115
- score -= 0.1 * self._length_penalty(len(doc_text))
116
- else:
117
- score = c["score"]
118
- score += self.coverage_weight * self._coverage_score(
119
- query_tokens, doc_tokens
120
- )
121
- score -= self.length_penalty_weight * self._length_penalty(
122
- len(doc_text)
123
- )
124
-
125
- reranked.append({**c, "score": score})
126
-
127
- reranked.sort(key=lambda x: x["score"], reverse=True)
128
- return reranked
129
-
130
  class SimpleSearchEngine:
131
  def __init__(self, corpus_dir: str = CORPUS_DIR):
132
  self.corpus_dir = corpus_dir
@@ -209,14 +88,10 @@ class SimpleSearchEngine:
209
  "path": doc["path"],
210
  "text": doc["text"], # full text for reranking
211
  })
212
-
213
- # 2) Rerank using classic heuristics
214
- reranker = HeuristicReranker()
215
- reranked = reranker.rerank(query, candidates)
216
-
217
- # 3) Return final top_k results (same output format as before)
218
  results = []
219
- for doc in reranked[:top_k]:
220
  snippet = doc["text"][:200] + ("..." if len(doc["text"]) > 200 else "")
221
  results.append({
222
  "score": doc["score"],
@@ -225,7 +100,7 @@ class SimpleSearchEngine:
225
  "path": doc["path"],
226
  "snippet": snippet,
227
  })
228
-
229
  return results
230
 
231
  if __name__ == "__main__":
 
3
  from typing import List, Dict
4
  from sklearn.feature_extraction.text import TfidfVectorizer
5
  from sklearn.metrics.pairwise import linear_kernel
 
6
 
7
  CORPUS_DIR = "../corpus" # Now points to the unified directory
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  class SimpleSearchEngine:
10
  def __init__(self, corpus_dir: str = CORPUS_DIR):
11
  self.corpus_dir = corpus_dir
 
88
  "path": doc["path"],
89
  "text": doc["text"], # full text for reranking
90
  })
91
+
92
+ # 2) Return final top_k results
 
 
 
 
93
  results = []
94
+ for doc in candidates[:top_k]:
95
  snippet = doc["text"][:200] + ("..." if len(doc["text"]) > 200 else "")
96
  results.append({
97
  "score": doc["score"],
 
100
  "path": doc["path"],
101
  "snippet": snippet,
102
  })
103
+
104
  return results
105
 
106
  if __name__ == "__main__":