LangChain vector store and hybrid search for TopK. Keyword (BM25), semantic, vector and hybrid search, metadata filters, and isolated per-tenant partitions, all in one query against one index. TopK can also embed and rerank text on the server, so you don't need an embedding model.
pip install langchain-topkfrom langchain_topk import TopKVectorStore
store = TopKVectorStore(collection_name="docs") # TopK embeds text for you
store.add_texts(
["Error code E-4021 means the payment gateway timed out.",
"Quarterly revenue grew 12% thanks to cloud sales."],
metadatas=[{"source": "runbook"}, {"source": "report"}],
)
store.similarity_search("why did checkout fail?", k=3, search_mode="hybrid")Set TOPK_API_KEY (create one at console.topk.io) and TOPK_REGION (for example aws-us-east-1-elastica, see regions).
TopK is a hybrid retrieval engine for AI applications and agents. In a typical RAG stack, an embedding service, a vector database, a keyword engine and a reranker are separate pieces glued together in application code. TopK runs all of them in one system:
| Typical vector-database setup | TopK | |
|---|---|---|
| Embeddings | You run an embedding pipeline and store the vectors | semantic_index() embeds and reranks on the server (semantic search) |
| Hybrid search | Vector and keyword searches run separately, then get merged (often with Reciprocal Rank Fusion) | One query over one index, so the top results really are the top results (true hybrid search) |
| Retrieval types | Dense vectors, plus keyword search bolted on | Dense, sparse and multi-vector search, BM25, regex, filters and custom scoring in one query |
| Storage | Memory- or disk-bound nodes you size and scale | Object storage with memory and NVMe caching (architecture), which TopK says costs 10x less |
| Multi-tenancy | A tenant_id filter |
Fully isolated partitions per tenant (concepts) |
TopK publishes these figures: 1B+ documents per partition, under 100ms p99 query latency at 1B documents, and under 1 second data freshness (architecture). Retrieval benchmarks are at topk.io/benchmarks.
- No embedding model to run. Leave
embedding=Noneand TopK embeds and reranks text on the server. That means no OpenAI embeddings bill, no extra embedding API key, and no reranker in your chain. - Keyword search that actually filters. Agents look up exact strings like error codes, SKUs, function names and ticket IDs. Vector similarity ranks something first even when nothing matches; BM25 returns nothing.
search_mode="keyword"gives you that. - True hybrid search in one call.
search_mode="hybrid"scores dense similarity and BM25 together on the server. Documents with no shared keyword still rank on meaning, and keyword matches get boosted. - Agent memory per user or tenant.
store.with_partition("user-42")gives each user a fully isolated partition with no cross-tenant filter to forget. - It's a standard LangChain
VectorStore. It passes LangChain's standard vector store test suite (langchain-tests) in both embedding modes and works withas_retriever(), MMR,get_by_idsand async.
Every search method takes search_mode. as_retriever(search_kwargs={...}) passes it through too.
search_mode |
What it does | Use it for |
|---|---|---|
"semantic" |
TopK's built-in embeddings and reranking (default when embedding=None) |
Natural-language questions with no embedding model |
"vector" |
Your LangChain Embeddings (default when embedding=... is set) |
Your own or fine-tuned embedding model |
"keyword" |
BM25 full-text; returns only documents that share a term | Exact codes, names, identifiers |
"hybrid" |
Dense + BM25 in one query, weighted by hybrid_alpha (default 0.5) |
General RAG and agent retrieval |
store.keyword_search("E-4021", k=5) # BM25 only
store.hybrid_search("payment gateway timeout", alpha=0.7) # 70% semantic, 30% BM25
store.similarity_search_with_score("revenue", search_mode="semantic")Dense and BM25 scores sit on different scales. Print a few similarity_search_with_score(..., search_mode="hybrid") results before you tune hybrid_alpha.
from langchain_openai import OpenAIEmbeddings
store = TopKVectorStore(
collection_name="docs-openai",
embedding=OpenAIEmbeddings(model="text-embedding-3-small"),
metric="cosine", # or "dot_product", "euclidean"
)
store.max_marginal_relevance_search("diverse results please", k=4, fetch_k=20)In this mode the text field also gets a BM25 index, so "keyword" and "hybrid" work the same way (hybrid combines your vectors with BM25).
Pass MongoDB-style filters (the usual LangChain convention) to any search method or to delete:
store.similarity_search("refund policy", filter={"source": "faq"})
store.similarity_search("outage", filter={"year": {"$gte": 2024}, "tags": {"$contains": "payments"}})
store.similarity_search("x", filter={"$or": [{"source": "faq"}, {"author.name": {"$starts_with": "Ada"}}]})
store.delete(filter={"source": "stale-import"})Operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $contains (list fields), $starts_with, $exists, $and, $or, $not. Use dots for nested keys.
You can also pass a native TopK expression for anything else TopK supports:
from topk_sdk.query import field
store.similarity_search("x", filter=field("metadata.year").in_([2024, 2025]) & field("metadata.title").regexp_match("^RFC"))memories = TopKVectorStore(collection_name="agent-memory")
alice = memories.with_partition("user-alice")
bob = memories.with_partition("user-bob")
alice.add_texts(["Alice prefers window seats and vegetarian meals."])
bob.add_texts(["Bob is allergic to peanuts."])
alice.similarity_search("food preferences", search_mode="hybrid") # never sees Bob's dataA partition is created on its first write. Reading a partition that was never written returns [].
retriever = store.as_retriever(search_kwargs={"k": 5, "search_mode": "hybrid", "filter": {"source": "docs"}})
retriever.invoke("how do I rotate API keys?")from langchain_core.tools import tool
@tool
def search_docs(query: str) -> str:
"""Search the product docs. Good for exact error codes and for natural-language questions."""
return "\n\n".join(d.page_content for d in store.hybrid_search(query, k=5))- Reads see your own writes. The store passes the LSN of its last write to every read, so a search right after
add_textsincludes the new documents. - Text limit with server-side embeddings. A
semantic_index()field holds up to 4,096 characters per value, so split long documents first (for example withRecursiveCharacterTextSplitter(chunk_size=3000)). - Upserts replace whole documents. Adding a document with an existing id overwrites it.
- Use a new collection name after deleting one. Writes right after recreating a just-deleted collection under the same name can be lost.
- Metadata comes back exactly as you stored it. Values TopK can't filter on (for example mixed-type lists or custom objects) are still returned, just not filterable.
- Relevance scores.
similarity_score_thresholdretrievers work with bring-your-own embeddings. TopK's semantic scores aren't normalized to [0, 1], so pick thresholds from your own data withsimilarity_search_with_score.
Does TopK work with LangChain? Yes. langchain-topk provides TopKVectorStore, a standard LangChain VectorStore that passes the official langchain-tests suite.
Can I do hybrid search (BM25 + vectors) in LangChain without an ensemble retriever? Yes. search_mode="hybrid" ranks dense similarity and BM25 together in a single TopK query. You don't need EnsembleRetriever, Reciprocal Rank Fusion, or a separate BM25 index in memory.
Do I need OpenAI or another embedding provider? No. With embedding=None, TopK embeds and reranks on the server. You can still bring any LangChain Embeddings if you want.
How do I isolate data per user or tenant? Use partitions: store.with_partition("tenant-id"). Each partition is fully isolated and scales independently.
Is TopK open source? The SDKs (topk-io/topk) and this integration are MIT-licensed. TopK itself is a managed service (topk.io), and you can also deploy it in your own VPC.
uv venv && uv pip install -e . --group test
pytest tests/unit_tests
TOPK_API_KEY=... TOPK_REGION=aws-us-east-1-elastica pytest tests/integration_tests # runs against live TopK- TopK docs: https://docs.topk.io
- LangChain integration guide: https://docs.topk.io/integrations/langchain
- TopK Python SDK: https://pypi.org/project/topk-sdk/
- Coding agents:
npx skills add topk-io/topk --skill topkinstalls the TopK Agent Skill