Spaces:
Running
Running
| """Sparse vector search over panel OCR/dialogue text.""" | |
| import os | |
| from pinecone import Pinecone | |
| _INCLUDE_FIELDS = [ | |
| "ocr_text", "search_text", "comic_id", "book_id", | |
| "page_id", "page_num", "panel_num", "image_path", "source", "is_ad_page", | |
| ] | |
| def search_sparse(index, namespace: str, query_sparse: dict, top_k: int = 20, filters: dict | None = None) -> dict: | |
| response = index.documents.search( | |
| namespace=namespace, | |
| top_k=top_k, | |
| score_by=[{"type": "sparse_vector", "field": "text_sparse", "sparse_values": query_sparse}], | |
| filter=filters or {}, | |
| include_fields=_INCLUDE_FIELDS, | |
| ) | |
| return {"result": {"hits": [h.to_dict() for h in response.matches]}} | |
| def main(): | |
| import argparse | |
| from src.embeddings.embed_sparse_text import embed_sparse_query | |
| parser = argparse.ArgumentParser(description="Sparse text search") | |
| parser.add_argument("--query", required=True) | |
| parser.add_argument("--top-k", type=int, default=10) | |
| parser.add_argument("--no-ads", action="store_true", default=True) | |
| args = parser.parse_args() | |
| pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"]) | |
| index = pc.preview.index(name=os.environ.get("PINECONE_INDEX_NAME", "comic-panels")) | |
| namespace = os.environ.get("PINECONE_NAMESPACE", "comics-v1") | |
| query_sparse = embed_sparse_query(args.query) | |
| if not query_sparse: | |
| print("Empty query — no sparse vector produced") | |
| return | |
| filters = {"is_ad_page": False} if args.no_ads else {} | |
| response = search_sparse(index, namespace, query_sparse, top_k=args.top_k, filters=filters) | |
| hits = response.get("result", {}).get("hits", []) | |
| print(f"Query: {args.query!r} ({len(hits)} hits)") | |
| for i, hit in enumerate(hits, 1): | |
| fields = hit.get("fields", {}) | |
| print(f" {i}. [{hit.get('_score', 0):.4f}] {hit['_id']} | {fields.get('ocr_text', '')[:80]}") | |
| if __name__ == "__main__": | |
| main() | |