fabianonbfilho commited on
Commit
7a8ca74
·
verified ·
1 Parent(s): 827503f

Upload src/labdaps/retrieval/retriever.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. src/labdaps/retrieval/retriever.py +69 -0
src/labdaps/retrieval/retriever.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass
2
+ import numpy as np
3
+ from src.labdaps.config import TOP_K_CANDIDATES, TOP_K_FINAL
4
+ from src.labdaps.retrieval.vector_store import query_store
5
+ from src.labdaps.ingestion.embedder import Embedder
6
+
7
+
8
+ @dataclass
9
+ class RetrievedChunk:
10
+ text: str
11
+ source_file: str
12
+ page_number: int
13
+ score: float
14
+
15
+
16
+ def _cosine_similarity(a: list[float], b: list[float]) -> float:
17
+ a, b = np.array(a), np.array(b)
18
+ return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b) + 1e-9))
19
+
20
+
21
+ def _mmr(
22
+ query_embedding: list[float],
23
+ candidate_embeddings: list[list[float]],
24
+ candidates: list[dict],
25
+ top_k: int,
26
+ lambda_param: float = 0.6,
27
+ ) -> list[int]:
28
+ selected = []
29
+ remaining = list(range(len(candidates)))
30
+ query_sims = [_cosine_similarity(query_embedding, e) for e in candidate_embeddings]
31
+
32
+ while len(selected) < top_k and remaining:
33
+ if not selected:
34
+ best = max(remaining, key=lambda i: query_sims[i])
35
+ else:
36
+ selected_embeddings = [candidate_embeddings[i] for i in selected]
37
+ best = max(
38
+ remaining,
39
+ key=lambda i: lambda_param * query_sims[i]
40
+ - (1 - lambda_param) * max(
41
+ _cosine_similarity(candidate_embeddings[i], se)
42
+ for se in selected_embeddings
43
+ ),
44
+ )
45
+ selected.append(best)
46
+ remaining.remove(best)
47
+
48
+ return selected
49
+
50
+
51
+ def retrieve(query: str, embedder: Embedder) -> list[RetrievedChunk]:
52
+ query_embedding = embedder.embed_query(query)
53
+ documents, metadatas, distances = query_store(query_embedding, TOP_K_CANDIDATES)
54
+
55
+ if not documents:
56
+ return []
57
+
58
+ candidate_embeddings = embedder.embed_passages(documents)
59
+ selected_indices = _mmr(query_embedding, candidate_embeddings, metadatas, TOP_K_FINAL)
60
+
61
+ return [
62
+ RetrievedChunk(
63
+ text=documents[idx],
64
+ source_file=metadatas[idx]["source_file"],
65
+ page_number=metadatas[idx]["page_number"],
66
+ score=1.0 - distances[idx],
67
+ )
68
+ for idx in selected_indices
69
+ ]