Spaces:
Sleeping
Sleeping
| """Build the baked-in demo index from data/corpus_sample.jsonl. | |
| Produces, under app/prebuilt/: | |
| - qdrant/ on-disk Qdrant collection with the dense vectors | |
| - lexical.pkl exported BM25 state (ids, tokens, metadata) | |
| Baking both into the image means the demo is never empty, even after the host | |
| restarts its ephemeral storage (spec, Phase 1 acceptance). | |
| Usage: | |
| python scripts/build_index.py | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import logging | |
| import pickle | |
| import sys | |
| from pathlib import Path | |
| # Make src/ importable when run as a script. | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) | |
| from streamsearch import config | |
| from streamsearch.schema import Document | |
| from streamsearch.search import HybridSearcher | |
| logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s") | |
| log = logging.getLogger("build_index") | |
| def load_corpus(path: Path) -> list[Document]: | |
| docs = [] | |
| with path.open(encoding="utf-8") as f: | |
| for line in f: | |
| line = line.strip() | |
| if line: | |
| docs.append(Document.from_json(json.loads(line))) | |
| return docs | |
| def main() -> None: | |
| if config.QDRANT_URL: | |
| log.info("QDRANT_URL set -> building into cloud Qdrant at %s", config.QDRANT_URL) | |
| else: | |
| # Fresh local build: wipe any stale on-disk index first. | |
| import shutil | |
| if config.QDRANT_LOCAL_PATH.exists(): | |
| shutil.rmtree(config.QDRANT_LOCAL_PATH) | |
| log.info("Building embedded on-disk index at %s", config.QDRANT_LOCAL_PATH) | |
| docs = load_corpus(config.CORPUS_PATH) | |
| log.info("Loaded %d documents from %s", len(docs), config.CORPUS_PATH) | |
| client = config.make_qdrant_client() | |
| searcher = HybridSearcher(client) | |
| searcher.ensure_collection() | |
| searcher.add_documents(docs) | |
| config.PREBUILT_DIR.mkdir(parents=True, exist_ok=True) | |
| with config.LEXICAL_PATH.open("wb") as f: | |
| pickle.dump(searcher.export_lexical(), f) | |
| log.info("Wrote lexical export to %s", config.LEXICAL_PATH) | |
| # Release the embedded client's file lock so the app can open it. | |
| del client | |
| log.info("Done. Indexed %d docs.", len(docs)) | |
| if __name__ == "__main__": | |
| main() | |