studyhub-app / studyhub /core /topic.py
parhamkhoshsolat's picture
Study features + Academy theme + threads + invite links + auto-ingest
981881b verified
Raw
History Blame Contribute Delete
2.14 kB
from __future__ import annotations
import numpy as np
from .answer import AnswerResult, generate_from, generate_in_thread
from .prompt import detect_language
from .retrieve import ScoredChunk
from .study import summarize_chunks
def retrieve_in_topic(query, index, chunk_ids, embedder, k: int = 6, reranker=None):
"""Like retrieve(), but only over a topic's own chunks (across all its sources)."""
qv = embedder.encode([query]).astype("float32")[0]
scored: list[ScoredChunk] = []
for cid in chunk_ids:
row = index.row_by_id.get(cid)
if row is None:
continue
vec = np.asarray(index.faiss_index.reconstruct(int(row)), dtype="float32")
scored.append(ScoredChunk(chunk=index.by_id[cid], score=float(np.dot(qv, vec))))
scored.sort(key=lambda s: s.score, reverse=True)
if reranker is not None and scored:
pool = scored[: max(k, 16)]
for sc, rs in zip(pool, reranker.scores(query, [s.chunk.text for s in pool])):
sc.score = float(rs)
pool.sort(key=lambda s: s.score, reverse=True)
return pool[:k]
return scored[:k]
def answer_topic(query, index, chunk_ids, embedder, llm, k: int = 6, token_budget: int = 4000, reranker=None):
scored = retrieve_in_topic(query, index, chunk_ids, embedder, k=k, reranker=reranker)
return generate_from(query, scored, llm, token_budget)
def answer_topic_in_thread(query, prior, index, chunk_ids, embedder, llm,
k: int = 6, token_budget: int = 4000, reranker=None):
"""answer_topic() with conversation context (same treatment as answer_in_thread)."""
scored = retrieve_in_topic(query, index, chunk_ids, embedder, k=k, reranker=reranker)
return generate_in_thread(query, prior, scored, llm, token_budget)
def topic_summary(index, chunk_ids, llm) -> AnswerResult:
chunks = [index.by_id[c] for c in chunk_ids if c in index.by_id]
if not chunks:
return AnswerResult("No material linked to this topic yet.", [], "")
lang = detect_language(" ".join(c.text for c in chunks[:3]))
return summarize_chunks(chunks, llm, lang=lang)