Spaces:
Runtime error
Runtime error
Commit ·
54c31f0
1
Parent(s): e12c660
Fix chroma retrieval
Browse files- src/backend/rag.py +79 -15
src/backend/rag.py
CHANGED
|
@@ -4,53 +4,117 @@ from src.backend.llm import llm_generate
|
|
| 4 |
|
| 5 |
EMBED_MODEL = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
|
| 6 |
|
|
|
|
| 7 |
def retrieve(username: str, notebook_id: str, query: str, k=6):
|
| 8 |
col = get_collection(username, notebook_id)
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
hits = []
|
| 12 |
-
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
return hits
|
| 15 |
|
|
|
|
| 16 |
def format_sources(hits):
|
| 17 |
lines = []
|
|
|
|
| 18 |
for i, h in enumerate(hits, start=1):
|
| 19 |
-
m = h["meta"]
|
|
|
|
| 20 |
loc = ""
|
| 21 |
-
if m.get("page"):
|
| 22 |
-
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
return "\n".join(lines)
|
| 25 |
|
|
|
|
| 26 |
def context_block(hits):
|
| 27 |
blocks = []
|
|
|
|
| 28 |
for i, h in enumerate(hits, start=1):
|
| 29 |
-
m = h["meta"]
|
|
|
|
| 30 |
loc = ""
|
| 31 |
-
if m.get("page"):
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
return "\n\n---\n\n".join(blocks)
|
| 35 |
|
|
|
|
| 36 |
def rag_answer(query: str, hits):
|
|
|
|
| 37 |
if not hits:
|
| 38 |
return "Not found in the provided sources. (No indexed chunks yet.)"
|
|
|
|
| 39 |
prompt = f"""
|
| 40 |
-
You are a research assistant.
|
|
|
|
|
|
|
|
|
|
| 41 |
Every non-trivial claim must end with citations like [S1] or [S2].
|
| 42 |
-
|
|
|
|
|
|
|
| 43 |
|
| 44 |
Question:
|
| 45 |
{query}
|
| 46 |
|
|
|
|
| 47 |
Sources list:
|
| 48 |
{format_sources(hits)}
|
| 49 |
|
|
|
|
| 50 |
Source excerpts:
|
| 51 |
{context_block(hits)}
|
| 52 |
|
|
|
|
| 53 |
Answer with citations:
|
| 54 |
"""
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
return f"{ans}\n\nSources:\n{format_sources(hits)}"
|
|
|
|
| 4 |
|
| 5 |
EMBED_MODEL = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
|
| 6 |
|
| 7 |
+
|
| 8 |
def retrieve(username: str, notebook_id: str, query: str, k=6):
|
| 9 |
col = get_collection(username, notebook_id)
|
| 10 |
+
|
| 11 |
+
qemb = EMBED_MODEL.encode(
|
| 12 |
+
[query],
|
| 13 |
+
normalize_embeddings=True
|
| 14 |
+
).tolist()
|
| 15 |
+
|
| 16 |
+
# Compatible with HF Chroma version
|
| 17 |
+
res = col.query(
|
| 18 |
+
query_embeddings=qemb,
|
| 19 |
+
n_results=k,
|
| 20 |
+
include=["documents", "metadatas", "distances"]
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
# Safe extraction (prevents crashes)
|
| 24 |
+
ids = res.get("ids", [[]])[0]
|
| 25 |
+
docs = res.get("documents", [[]])[0]
|
| 26 |
+
mets = res.get("metadatas", [[]])[0]
|
| 27 |
+
dists = res.get("distances", [[]])[0]
|
| 28 |
+
|
| 29 |
hits = []
|
| 30 |
+
|
| 31 |
+
for i in range(len(docs)):
|
| 32 |
+
hits.append({
|
| 33 |
+
"id": ids[i] if i < len(ids) else f"chunk_{i}",
|
| 34 |
+
"doc": docs[i],
|
| 35 |
+
"meta": mets[i] if i < len(mets) else {},
|
| 36 |
+
"distance": dists[i] if i < len(dists) else None
|
| 37 |
+
})
|
| 38 |
+
|
| 39 |
return hits
|
| 40 |
|
| 41 |
+
|
| 42 |
def format_sources(hits):
|
| 43 |
lines = []
|
| 44 |
+
|
| 45 |
for i, h in enumerate(hits, start=1):
|
| 46 |
+
m = h["meta"] or {}
|
| 47 |
+
|
| 48 |
loc = ""
|
| 49 |
+
if m.get("page"):
|
| 50 |
+
loc = f"p.{m['page']}"
|
| 51 |
+
|
| 52 |
+
if m.get("slide"):
|
| 53 |
+
loc = f"slide {m['slide']}"
|
| 54 |
+
|
| 55 |
+
title = m.get("source_title", "source")
|
| 56 |
+
|
| 57 |
+
lines.append(f"[S{i}] {title} {loc}".strip())
|
| 58 |
+
|
| 59 |
return "\n".join(lines)
|
| 60 |
|
| 61 |
+
|
| 62 |
def context_block(hits):
|
| 63 |
blocks = []
|
| 64 |
+
|
| 65 |
for i, h in enumerate(hits, start=1):
|
| 66 |
+
m = h["meta"] or {}
|
| 67 |
+
|
| 68 |
loc = ""
|
| 69 |
+
if m.get("page"):
|
| 70 |
+
loc = f"(page {m['page']})"
|
| 71 |
+
|
| 72 |
+
if m.get("slide"):
|
| 73 |
+
loc = f"(slide {m['slide']})"
|
| 74 |
+
|
| 75 |
+
title = m.get("source_title", "source")
|
| 76 |
+
|
| 77 |
+
blocks.append(
|
| 78 |
+
f"[S{i}] {title} {loc}\n{h['doc']}"
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
return "\n\n---\n\n".join(blocks)
|
| 82 |
|
| 83 |
+
|
| 84 |
def rag_answer(query: str, hits):
|
| 85 |
+
|
| 86 |
if not hits:
|
| 87 |
return "Not found in the provided sources. (No indexed chunks yet.)"
|
| 88 |
+
|
| 89 |
prompt = f"""
|
| 90 |
+
You are a research assistant.
|
| 91 |
+
|
| 92 |
+
Answer ONLY using the sources below.
|
| 93 |
+
|
| 94 |
Every non-trivial claim must end with citations like [S1] or [S2].
|
| 95 |
+
|
| 96 |
+
If not present in sources say:
|
| 97 |
+
Not found in the provided sources.
|
| 98 |
|
| 99 |
Question:
|
| 100 |
{query}
|
| 101 |
|
| 102 |
+
|
| 103 |
Sources list:
|
| 104 |
{format_sources(hits)}
|
| 105 |
|
| 106 |
+
|
| 107 |
Source excerpts:
|
| 108 |
{context_block(hits)}
|
| 109 |
|
| 110 |
+
|
| 111 |
Answer with citations:
|
| 112 |
"""
|
| 113 |
+
|
| 114 |
+
ans = llm_generate(
|
| 115 |
+
prompt,
|
| 116 |
+
max_new_tokens=450,
|
| 117 |
+
temperature=0.2
|
| 118 |
+
)
|
| 119 |
+
|
| 120 |
return f"{ans}\n\nSources:\n{format_sources(hits)}"
|