(self, query_text, segment_similarity_threshold=0.1, page_similarity_threshold=0.1,
top_k_sessions=5, keyword_alpha=1.0, recency_tau_search=3600)
| 277 | return self.add_session(summary_for_new_pages, pages_to_insert, keywords_for_new_pages) |
| 278 | |
| 279 | def search_sessions(self, query_text, segment_similarity_threshold=0.1, page_similarity_threshold=0.1, |
| 280 | top_k_sessions=5, keyword_alpha=1.0, recency_tau_search=3600): |
| 281 | if not self.sessions: |
| 282 | return [] |
| 283 | |
| 284 | query_vec = get_embedding( |
| 285 | query_text, |
| 286 | model_name=self.embedding_model_name, |
| 287 | **self.embedding_model_kwargs |
| 288 | ) |
| 289 | query_vec = normalize_vector(query_vec) |
| 290 | query_keywords = set() # Keywords extraction removed, relying on semantic similarity |
| 291 | |
| 292 | candidate_sessions = [] |
| 293 | session_ids = list(self.sessions.keys()) |
| 294 | if not session_ids: return [] |
| 295 | |
| 296 | summary_embeddings_list = [self.sessions[s]["summary_embedding"] for s in session_ids] |
| 297 | summary_embeddings_np = np.array(summary_embeddings_list, dtype=np.float32) |
| 298 | |
| 299 | dim = summary_embeddings_np.shape[1] |
| 300 | index = faiss.IndexFlatIP(dim) # Inner product for similarity |
| 301 | index.add(summary_embeddings_np) |
| 302 | |
| 303 | query_arr_np = np.array([query_vec], dtype=np.float32) |
| 304 | distances, indices = index.search(query_arr_np, min(top_k_sessions, len(session_ids))) |
| 305 | |
| 306 | results = [] |
| 307 | current_time_str = get_timestamp() |
| 308 | |
| 309 | for i, idx in enumerate(indices[0]): |
| 310 | if idx == -1: continue |
| 311 | |
| 312 | session_id = session_ids[idx] |
| 313 | session = self.sessions[session_id] |
| 314 | semantic_sim_score = float(distances[0][i]) # This is the dot product |
| 315 | |
| 316 | # Keyword similarity for session summary |
| 317 | session_keywords = set(session.get("summary_keywords", [])) |
| 318 | s_topic_keywords = 0 |
| 319 | if query_keywords and session_keywords: |
| 320 | intersection = len(query_keywords.intersection(session_keywords)) |
| 321 | union = len(query_keywords.union(session_keywords)) |
| 322 | if union > 0: s_topic_keywords = intersection / union |
| 323 | |
| 324 | # Time decay for session recency in search scoring |
| 325 | # time_decay_factor = compute_time_decay(session["timestamp"], current_time_str, tau_hours=recency_tau_search) |
| 326 | |
| 327 | # Combined score for session relevance |
| 328 | session_relevance_score = (semantic_sim_score + keyword_alpha * s_topic_keywords) |
| 329 | |
| 330 | if session_relevance_score >= segment_similarity_threshold: |
| 331 | matched_pages_in_session = [] |
| 332 | for page in session.get("details", []): |
| 333 | page_embedding = np.array(page["page_embedding"], dtype=np.float32) |
| 334 | # page_keywords = set(page.get("page_keywords", [])) |
| 335 | |
| 336 | page_sim_score = float(np.dot(page_embedding, query_vec)) |
no test coverage detected