{"slug": "multi-hop-questions-break-vector-search-here-is-a-graph-layer-for-qdrant-that", "title": "Multi-hop questions break vector search. Here is a graph layer for Qdrant that fixes them.", "summary": "A new open-source library, hubmesh, adds a graph layer on top of Qdrant to answer multi-hop questions that stymie vector search. The library builds an entity-document graph at index time and uses Personalized PageRank to fuse graph reachability with cosine similarity, improving recall@10 by up to 5.9 points on HotpotQA and outperforming HippoRAG-style PPR-only retrieval by 29.8 points. No LLM is used at query time, keeping retrieval deterministic and fast.", "body_md": "Qdrant answers \"which vectors are near this query?\" in milliseconds at\n\nbillion scale. But there's a class of questions where nearness is the\n\nwrong criterion entirely:\n\n\"Where did the founder of the company that acquired Slack study?\"\n\nThe passage that answers this talks about Marc Benioff and USC. It\n\nnever mentions Slack. Cosine similarity — any similarity — ranks it\n\nlow, because the answer doesn't *look like* the question. It's\n\n*connected to* the question, three entity-hops away: Slack → acquired\n\nby Salesforce → founded by Benioff → studied at USC. That's a topology\n\nproblem, and no amount of ANN speed solves a topology problem.\n\n[hubmesh](https://github.com/DemigodDSK/hubmesh) is a small MIT\n\nlibrary that adds the topology layer on top of your existing Qdrant\n\ncollection. Qdrant keeps doing what it's best at (first-pass ANN);\n\nhubmesh builds an entity–document graph at index time and, at query\n\ntime, diffuses Personalized PageRank from the question's entities over\n\nthat graph, fusing graph reachability with your cosine scores. No LLM\n\nis involved at query time — retrieval is one sparse matrix iteration,\n\ndeterministic, roughly 100ms on a 30K-document corpus.\n\n```\npip install \"hubmesh[qdrant,kg]\"\npython -m spacy download en_core_web_sm\npython\nfrom hubmesh import Planner\nfrom hubmesh.adapters import QdrantStore\nfrom hubmesh.kg import build_entity_kg\nimport spacy\n\nembed = ...  # your embedding callable: text -> np.ndarray\n\n# any of: in-memory, on-disk, or your running Qdrant server\nstore = QdrantStore.from_documents(docs, url=\"http://localhost:6333\")\n\n# entity-document graph via spaCy NER — zero LLM tokens to build\nnlp = spacy.load(\"en_core_web_sm\")\nkg = build_entity_kg(store.get_many(store.all_ids()), nlp=nlp)\n\nplanner = Planner(store=store, kg=kg, nlp=nlp, embed=embed)\nresult = planner.retrieve(\n    \"Where did the founder of the company that acquired Slack study?\",\n    top_k=10,\n)\nfor path in result.reasoning:\n    print(f\"{path.score:.3f}  \" + \" -> \".join(path.node_ids))\n# 0.031  ent:slack -> doc:acquisition -> ent:salesforce -> doc:benioff_bio\n```\n\nThat `reasoning`\n\nfield is not a post-hoc explanation — it's the actual\n\ngraph route that surfaced each document, which means your RAG pipeline\n\ncan show *why* a passage was retrieved.\n\nEach candidate document gets a composite of three signals, normalized\n\nand combined (the formula descends from a network-topology paper —\n\nNNSI, ICOMP'25 — where the same lesson appeared: no single centrality\n\nmetric identifies important nodes, but a weighted composite does):\n\n| Benchmark | recall@10 vs naive cosine, same embeddings |\n|---|---|\n| HotpotQA full dev (7,405 q) | 75.2% vs 69.3% (+5.9 pts) |\n| MuSiQue 2/3/4-hop | +6.0 / +3.2 / +5.0 pts |\n| vs HippoRAG-style PPR-only, same graph | +29.8 pts |\n\nDisclosed trade-off: the convergence term buys depth recall with\n\ntop-rank precision — recall@2 is 0.75 pts below naive on full dev. If\n\nyou retrieve with `top_k=2`\n\n, disable it (`use_convergence=False`\n\n).\n\nEverything above reproduces with the scripts in `benchmarks/`\n\n.\n\n`retrieve`\n\naccepts `seed_entities`\n\nand `exclude_docs`\n\n, so an agent can\n\niterate: retrieve, read, then aim hop two at the entity it just\n\ndiscovered. There's an MCP server included (`hubmesh-mcp`\n\n, listed in\n\nthe official MCP Registry) — the repo contains a field report of\n\nPerplexity driving a 3-hop chain through it, tool call by tool call.\n\nSingle-hop corpora where similarity already wins; corpus-wide summary\n\nquestions (\"what are the main themes?\") — that's community-summary\n\nterritory (Microsoft GraphRAG's use case), a different query class.\n\nhubmesh is for multi-hop factual retrieval, and it deliberately keeps\n\nQdrant as the geometry engine underneath.\n\n*Repo: github.com/DemigodDSK/hubmesh · PyPI: pip install hubmesh · MIT*", "url": "https://wpnews.pro/news/multi-hop-questions-break-vector-search-here-is-a-graph-layer-for-qdrant-that", "canonical_source": "https://dev.to/demigoddsk/multi-hop-questions-break-vector-search-here-is-a-graph-layer-for-qdrant-that-fixes-them-35cl", "published_at": "2026-08-05 01:45:45+00:00", "updated_at": "2026-08-05 02:11:25.495035+00:00", "lang": "en", "topics": ["machine-learning", "artificial-intelligence", "natural-language-processing", "ai-infrastructure", "developer-tools"], "entities": ["Qdrant", "hubmesh", "HotpotQA", "MuSiQue", "HippoRAG", "Microsoft GraphRAG", "spaCy", "Salesforce"], "alternates": {"html": "https://wpnews.pro/news/multi-hop-questions-break-vector-search-here-is-a-graph-layer-for-qdrant-that", "markdown": "https://wpnews.pro/news/multi-hop-questions-break-vector-search-here-is-a-graph-layer-for-qdrant-that.md", "text": "https://wpnews.pro/news/multi-hop-questions-break-vector-search-here-is-a-graph-layer-for-qdrant-that.txt", "jsonld": "https://wpnews.pro/news/multi-hop-questions-break-vector-search-here-is-a-graph-layer-for-qdrant-that.jsonld"}}