🏹Dynamic Parameters/Query Time weights
How you can use Qyver to achieve quality retrieval, through implementing query time weights - at both query definition and query execution.
Achieving High-Quality Retrieval with Qyver: Query Time Weighting
Getting high-quality results from a vector database query is challenging. Through real-world machine learning deployment, we’ve learned two fundamental truths:
1. The richer your dataset, the better your retrieval results—but only if your embeddings fully represent that dataset. 2. Different use cases emphasize different data attributes—your retrieval system must prioritize what matters most.
How Qyver Handles This Challenge
Instead of embedding all data as a single text string, Qyver’s Spaces allow you to:
Embed attributes separately rather than forcing everything into a single vector.
Concatenate attribute-specific embeddings into a multimodal vector.
Prioritize different data attributes dynamically at query time, avoiding the need for reranking.
The result? Faster, higher-quality retrieval—without expensive post-processing layers or reranking.
Two Ways to Weight a Query
Qyver enables query weighting in two ways:
1. Weighting at Query Definition
Set weights when defining a query—experiment and optimize without re-embedding your dataset.
2. Weighting at Query Execution
Set weights dynamically when running the query—fine-tune retrieval in real-time, without re-indexing.
Let’s see how both approaches work in Qyver.
1. Query Weighting at Definition
By structuring separate embeddings for different attributes, Qyver Spaces allow you to weight each attribute independently.
Example: Optimizing Search for Text vs. Popularity
Let’s define a schema and two Spaces:
@schema
class Paragraph:
id: IdField
body: String
like_count: Integer
paragraph = Paragraph()
# Define separate embeddings for text similarity and numerical ranking
body_space = TextSimilaritySpace(
text=paragraph.body, model="sentence-transformers/all-mpnet-base-v2"
)
like_space = NumberSpace(
number=paragraph.like_count, min_value=0, max_value=100, mode=Mode.MAXIMUM
)
# Combine Spaces into an index
paragraph_index = Index([body_space, like_space])
Adding Data to the System
source: InMemorySource = InMemorySource(paragraph)
executor = InMemoryExecutor(sources=[source], indices=[paragraph_index])
app = executor.run()
source.put([
{"id": "paragraph-1", "body": "Glorious animals live in the wilderness.", "like_count": 75},
{"id": "paragraph-2", "body": "Growing computation power enables advancements in AI.", "like_count": 10},
])
Now, let's define two different queries:
One that prioritizes text similarity (weights text 2x more than likes).
One that prioritizes likes (weights likes 2x more than text).
body_query = (
Query(
paragraph_index,
weights={
body_space: 1.0, # Text similarity weighted higher
like_space: 0.5,
},
)
.find(paragraph)
.similar(body_space.text, "What makes the AI industry go forward?")
)
like_query = (
Query(
paragraph_index,
weights={
body_space: 0.5,
like_space: 1.0, # Like count weighted higher
},
)
.find(paragraph)
.similar(body_space.text, "What makes the AI industry go forward?")
)
Running the Queries
1. Prioritizing Text Similarity
body_result = app.query(body_query)
body_result.to_pandas()
Expected Output:
Growing computation power enables advancements in AI
10
paragraph-2
Glorious animals live in the wilderness
75
paragraph-1
2. Prioritizing Like Count
like_result = app.query(like_query)
like_result.to_pandas()
Expected Output:
Glorious animals live in the wilderness
75
paragraph-1
Growing computation power enables advancements in AI
10
paragraph-2
Why is this better?
No re-embedding needed—just adjust query weights.
No reranking needed—Qyver retrieves relevant results upfront.
2. Dynamic Query Weighting at Execution
In production systems, query logic is typically predefined. But Qyver allows dynamic fine-tuning, so data scientists or users can adjust weighting at runtime—without modifying query definitions.
Defining a Query with Dynamic Parameters
query = (
Query(
paragraph_index,
weights={
body_space: Param("body_space_weight"),
like_space: Param("like_space_weight"),
},
)
.find(paragraph)
.similar(body_space.text, Param("query_text"))
)
Running the Query with Different Weights
1. Prioritizing Text Similarity
body_based_result = app.query(
query,
query_text="How computation power changed the course of AI?",
body_space_weight=1,
like_space_weight=0,
)
body_based_result.to_pandas()
Expected Output:
Growing computation power enables advancements in AI
10
paragraph-2
Glorious animals live in the wilderness
75
paragraph-1
2. Prioritizing Like Count
like_based_result = app.query(
query,
query_text="How computation power changed the course of AI?",
body_space_weight=0,
like_space_weight=1,
)
like_based_result.to_pandas()
Expected Output:
Glorious animals live in the wilderness
75
paragraph-1
Growing computation power enables advancements in AI
10
paragraph-2
Why is this powerful?
Fine-tune relevance dynamically without touching embeddings.
Empower users to control results without developer intervention.
Final Thoughts
Qyver’s Query Time Weighting:
Weighting at Query Definition → Experiment & optimize without re-embedding data.
Weighting at Query Execution → Allow real-time fine-tuning for data scientists and users.
What does this mean for you?
Faster, more relevant search results—without reranking overhead.
Greater flexibility & adaptability—retrieval adjusts dynamically.
No costly infrastructure changes—just tweak the query weights!
Like what we’re doing? Give us a star!
Last updated