From 711be5e5bbe23b130458bc65045763ee0962bcf0 Mon Sep 17 00:00:00 2001 From: Research Assistant Date: Mon, 18 May 2026 17:16:51 +0800 Subject: [PATCH] feat(embedding): add API-only retrieve_chunks() semantic search --- paperforge/embedding/search.py | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 paperforge/embedding/search.py diff --git a/paperforge/embedding/search.py b/paperforge/embedding/search.py new file mode 100644 index 00000000..2ea1d866 --- /dev/null +++ b/paperforge/embedding/search.py @@ -0,0 +1,39 @@ +from __future__ import annotations + +import logging +from pathlib import Path + +from paperforge.embedding._chroma import get_collection +from paperforge.embedding.providers.openai_compatible import OpenAICompatibleProvider + +logger = logging.getLogger(__name__) + + +def retrieve_chunks(vault: Path, query: str, limit: int = 5, expand: bool = True) -> list[dict]: + """Search chunks via API embedding. Returns list with metadata and similarity scores.""" + collection = get_collection(vault) + provider = OpenAICompatibleProvider(vault) + query_embedding = provider.encode_single(query) + + results = collection.query( + query_embeddings=[query_embedding], + n_results=limit * 3 if expand else limit, + include=["documents", "metadatas", "distances"], + ) + + chunks = [] + for i, (doc, meta, dist) in enumerate(zip( + results["documents"][0], + results["metadatas"][0], + results["distances"][0], + )): + chunks.append({ + "paper_id": meta["paper_id"], + "section": meta.get("section", "Text"), + "page_number": meta.get("page_number", 1), + "chunk_index": meta.get("chunk_index", 0), + "chunk_text": doc, + "score": round(1.0 - dist, 4), + }) + + return chunks