Run a self-hosted vector database with built-in hybrid (BM25 + vector) search, modular vectorizer modules, and GraphQL/REST APIs.
A vector database with a built-in librarian. Each chunk has vectors AND inverted-index text; the librarian combines them at query time.
POST /v1/objects # upsert with text + vectorizer
POST /v1/graphql # query by hybrid
{
Get {
WikiArticle(
hybrid: { query: "semantic search", alpha: 0.5 }
limit: 5
) { title content }
}
}
Weaviate stores both vector embeddings AND inverted-index terms. Its hybrid search linearly combines BM25 and vector scores using a tunable alpha. Built-in modules connect to OpenAI, Cohere, HuggingFace for embeddings. Schema-first design with classes (akin to tables) and properties (columns). Use Weaviate for self-hosted vector + lexical search.
import weaviate
client = weaviate.Client('http://localhost:8080')
schema = {'classes':[{'class':'Article',
'vectorizer':'text2vec-openai',
'properties':[{'name':'title','dataType':['string']},
{'name':'content','dataType':['text']}]}]}
client.schema.create(schema)
vectorizer module auto-embedds — one less service in the stack.
client.data_object.create({'title':'RAG intro','content':'...'}, 'Article')
res = client.query.get('Article', ['title','content']).with_hybrid(
query='RAG tutorial', alpha=0.5).with_limit(5).do()
print(res)
hybrid query with alpha=0.5 balances BM25 (exact terms) and vector (semantic).
# pure vector search
res = client.query.get('Article', ['title','content']).with_near_text(
{'concepts':['vector search tutorial']}).with_limit(5).do()
with_near_text is the pure-vector path; near_object uses an existing item’s vector.
Skipping schema design. Weaviate is schema-first; mistakes in property types are hard to migrate later.
Weaviate = vector + BM25 + schema. Use modules to embed; tune alpha for hybrid; design schema carefully up-front.