When Keywords Are No Longer Enough to “Understand” Users
Over six months ago, I was assigned a rather “tough” task: building a search engine for a repository of over 50,000 legal documents. Initially, I used traditional Full-text search on PostgreSQL. The results were disappointing. When staff searched for “tax regulations,” the system worked fine. But when they typed “financial obligations to the state,” it returned zero results, even though these two concepts are virtually identical.
The problem is that traditional databases only process data based on characters (lexical). To fix this, I tried switching to pure Vector Search using the FAISS library. However, Vector Search had the opposite weakness. While it excelled at semantic search, it often missed exact matches like specific document codes such as “Circular 123/2023”.
Why Pure Vector Search Isn’t Enough
After much trial and error, I realized that modern RAG (Retrieval-Augmented Generation) systems need a blend of both: Keyword Search for precision and Vector Search for context. This is where Hybrid Search proves its worth.
If you build a vector database system from scratch, you’ll run into three major pitfalls:
- Data synchronization between text and vectors is extremely complex.
- Managing embedding models (OpenAI, HuggingFace) consumes significant coding resources.
- Scalability issues when data hits millions of records.
I’ve used Qdrant and Pinecone before. However, Weaviate became my final choice for projects prioritizing flexibility and self-hosting (on-premise) for data security.
Weaviate: A Storage Ecosystem for AI Applications
Weaviate isn’t just a place to store vectors. The biggest plus after 6 months of real-world use is its built-in AI modules. Instead of writing code to call the OpenAI API for vectors and then saving them to the DB, Weaviate automates this process through vectorizers.
Its Hybrid Search mechanism combines the BM25 algorithm and Vector Search using a flexible alpha weight. This was the “weapon” that helped me fully resolve the complex legal document search problem mentioned earlier.
Deploying Weaviate with Docker in 5 Minutes
For fast and stable deployment, Docker is the optimal choice. Below is a streamlined docker-compose.yml file I used to run Weaviate with the text2vec-openai module.
version: '3.4'
services:
weaviate:
command:
- --host
- 0.0.0.0
- --port
- '8080'
- --scheme
- http
image: semitechnologies/weaviate:1.24.1
ports:
- 8080:8080
- 50051:50051
restart: on-failure:0
environment:
QUERY_DEFAULTS_LIMIT: 25
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true'
PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
DEFAULT_VECTORIZER_MODULE: 'text2vec-openai'
ENABLE_MODULES: 'text2vec-openai,generative-openai,qna-openai'
CLUSTER_HOSTNAME: 'node1'
OPENAI_APIKEY: 'sk-xxxxxxxxxxxxxxxxxxxxxxxx' # Replace with your key
Pro tip: If you want to experiment for free, replace text2vec-openai with text2vec-transformers to run embedding models locally. Then, start the system with the command:
docker-compose up -d
Executing Hybrid Search with Python Client
Once the container is ready, we use the weaviate-client library to interact with it. Here is how to define a Schema and perform a real-world Hybrid Search query.
import weaviate
import json
client = weaviate.Client("http://localhost:8080")
# 1. Initialize Schema
class_obj = {
"class": "Document",
"vectorizer": "text2vec-openai",
"properties": [
{"name": "title", "dataType": ["text"]},
{"name": "content", "dataType": ["text"]}
]
}
if not client.schema.exists("Document"):
client.schema.create_class(class_obj)
# 2. Query Hybrid Search
# alpha = 1.0: Pure Vector | alpha = 0.0: Pure Keyword
query_text = "financial obligations to the state"
result = (
client.query
.get("Document", ["title", "content"])
.with_hybrid(query=query_text, alpha=0.5)
.with_limit(3)
.do()
)
print(json.dumps(result, indent=2, ensure_ascii=False))
Real-world Experience After 6 Months of Operation
When taking Weaviate to production, there are technical details that documentation often overlooks. Here are some points to keep in mind to prevent system crashes.
1. The Resource Management Problem
Vector databases are very RAM-hungry. The HNSW index always resides in memory to ensure search speeds under 100ms. For 1 million vectors (1536 dimensions from OpenAI), you should prepare at least 16GB of RAM. If using Product Quantization (PQ) compression, this can be reduced to 4-8GB, but at a slight cost to accuracy.
2. Backup Strategy
Never just copy the Docker data folder. Weaviate supports specific backup modules for S3 or GCS. I once lost all my data due to a disk failure, and only the S3 backup saved the day.
3. Fine-tuning the Alpha Index
There is no one-size-fits-all formula for alpha. For legal data, I prioritize semantics, so I set it to 0.7. Conversely, for e-commerce data where SKU codes are essential, I often lower it to 0.3. You need to run tests on sample datasets to find the “sweet spot”.
4. Optimizing RAG with the Generative Module
Take advantage of the generative-openai module. Instead of retrieving search results and then sending them to GPT-4, you can have Weaviate synthesize the answer directly in a single query. This significantly reduces network latency and makes the code cleaner.
Conclusion
Weaviate is a powerful tool, but it’s not a silver bullet. You need to understand the specifics of your data to configure the index correctly. Deploying via Docker is the perfect stepping stone to take your AI applications from demo environments to professional production.

