mirror of
https://github.com/qdrant/landing_page.git
synced 2026-10-04 18:38:30 +02:00
Docs: Score boosting (#1506)
* Add score boosting section to hybrid queries * add decay formulas docs * Add datetime function to formula operators and update limitations * add datetime_key expression * use the name of the decay function in interface for the table * update to use snippets in a dedicated folder * mention that payload index is desired * add python and rust snippets * update snippets * docs: Go snippets Signed-off-by: Anush008 <anushshetty90@gmail.com> * docs: C# snippets Signed-off-by: Anush008 <anushshetty90@gmail.com> * docs: Java snippets Signed-off-by: Anush008 <anushshetty90@gmail.com> * chore: Updated formula defaut C#, GO Signed-off-by: Anush008 <anushshetty90@gmail.com> * docs: Update C# snippets as per new changes Signed-off-by: Anush008 <anushshetty90@gmail.com> * add typescript snippets * minor fixes * Use score function in Rust client --------- Signed-off-by: Anush008 <anushshetty90@gmail.com> Co-authored-by: Anush008 <anushshetty90@gmail.com> Co-authored-by: generall <andrey@vasnetsov.com> Co-authored-by: timvisee <tim@visee.me>
This commit is contained in:
co-authored by
Anush008
generall
timvisee
parent
8c71ed6924
commit
5698658bf3
@@ -88,21 +88,122 @@ It is possible to combine all the above techniques in a single query:
|
||||
|
||||
{{< code-snippet path="/documentation/headless/snippets/query-points/hybrid-rescoring-multistage/" >}}
|
||||
|
||||
## Score boosting
|
||||
|
||||
## Re-ranking with payload values
|
||||
_Available as of v1.14.0_
|
||||
|
||||
The Query API can retrieve points not only by vector similarity but also by the content of the payload.
|
||||
When introducing vector search to specific applications, sometimes business logic needs to be considered for ranking the final list of results.
|
||||
|
||||
There are two ways to make use of the payload in the query:
|
||||
A quick example is [our own documentation search bar](https://github.com/qdrant/page-search).
|
||||
It has vectors for every part of the documentation site. If one were to perform a search by "just" using the vectors, all kinds of elements would be equally considered good results.
|
||||
However, when searching for documentation, we can establish a hierarchy of importance:
|
||||
|
||||
* Apply filters to the payload fields, to only get the points that match the filter.
|
||||
* Order the results by the payload field.
|
||||
`title > content > snippets`
|
||||
|
||||
Let's see an example of when this might be useful:
|
||||
One way to solve this is to weight the results based on the kind of element.
|
||||
For example, we can assign a higher weight to titles and content, and keep snippets unboosted.
|
||||
|
||||
{{< code-snippet path="/documentation/headless/snippets/query-points/hybrid-rescoring-with-payload/" >}}
|
||||
Pseudocode would be something like:
|
||||
|
||||
In this example, we first fetch 10 points with the color `"red"` and then 10 points with the color `"green"`.
|
||||
Then, we order the results by the price field.
|
||||
`score = score + (is_title * 0.5) + (is_content * 0.25)`
|
||||
|
||||
This is how we can guarantee even sampling of both colors in the results and also get the cheapest ones first.
|
||||
Query API can rescore points with custom formulas. They can be based on:
|
||||
- Dynamic payload values
|
||||
- Conditions
|
||||
- Scores of prefetches
|
||||
|
||||
To express the formula, the syntax uses objects to identify each element.
|
||||
Taking the documentation example, the request would look like this:
|
||||
|
||||
{{< code-snippet path="/documentation/headless/snippets/query-points/score-boost-tags/" >}}
|
||||
|
||||
There are multiple expressions available, check the [API docs for specific details](https://api.qdrant.tech/v-1-13-x/api-reference/search/query-points#request.body.query.Query%20Interface.Query.Formula%20Query.formula).
|
||||
- **constant** - A floating point number. e.g. `0.5`.
|
||||
- `"$score"` - Reference to the score of the point in the prefetch. This is the same as `"$score[0]"`.
|
||||
- `"$score[0]"`, `"$score[1]"`, `"$score[2]"`, ... - When using multiple prefetches, you can reference specific prefetch with the index within the array of prefetches.
|
||||
- **payload key** - Any plain string will refer to a payload key. This uses the jsonpath format used in every other place, e.g. `key` or `key.subkey`. It will try to extract a number from the given key.
|
||||
- **condition** - A filtering condition. If the condition is met, it becomes `1.0`, otherwise `0.0`.
|
||||
- **mult** - Multiply an array of expressions.
|
||||
- **sum** - Sum an array of expressions.
|
||||
- **div** - Divide an expression by another expression.
|
||||
- **abs** - Absolute value of an expression.
|
||||
- **pow** - Raise an expression to the power of another expression.
|
||||
- **sqrt** - Square root of an expression.
|
||||
- **log10** - Base 10 logarithm of an expression.
|
||||
- **ln** - Natural logarithm of an expression.
|
||||
- **exp** - Exponential function of an expression (`e^x`).
|
||||
- **geo distance** - Haversine distance between two geographic points. Values need to be `{ "lat": 0.0, "lon": 0.0 }` objects.
|
||||
- **decay** - Apply a decay function to an expression, which clamps the output between 0 and 1. Available decay functions are **linear**, **exponential**, and **gaussian**. [See more](#boost-points-closer-to-user).
|
||||
- **datetime** - Parse a datetime string (see formats [here](/documentation/concepts/payload/#datetime)), and use it as a POSIX timestamp, in seconds.
|
||||
- **datetime key** - Specify that a payload key contains a datetime string to be parsed into POSIX seconds.
|
||||
|
||||
It is possible to define a default for when the variable (either from payload or prefetch score) is not found. This is given in the form of a mapping from variable to value.
|
||||
If there is no variable, and no defined default, a default value of `0.0` is used.
|
||||
|
||||
<aside role="status">
|
||||
|
||||
**Considerations when using formula queries:**
|
||||
|
||||
- Formula queries can only be used as a rescoring step.
|
||||
- Formula results are always sorted in descending order (bigger is better). **For euclidean scores, make sure to negate them** to sort closest to farthest.
|
||||
- If a score or variable is not available, and there is no default value, it will return an error.
|
||||
- If a value is not a number (or the expected type), it will return an error.
|
||||
- To leverage payload indices, single-value arrays are considered the same as the inner value. For example: `[0.2]` is the same as `0.2`, but `[0.2, 0.7]` will be interpreted as `[0.2, 0.7]`
|
||||
- Multiplication and division are lazily evaluated, meaning that if a 0 is encountered, the rest of operations don't execute (e.g. `0.0 * condition` won't check the condition).
|
||||
- Payload variables used within the formula also benefit from having payload indices. Please try to always have a payload index set up for the variables used in the formula for better performance.
|
||||
</aside>
|
||||
|
||||
### Boost points closer to user
|
||||
Another example. Combine the score with how close the result is to a user.
|
||||
|
||||
Considering each point has an associated geo location, we can calculate the distance between the point and the request's location.
|
||||
|
||||
Assuming we have cosine scores in the prefetch, we can use a helper function to clamp the geographical distance between 0 and 1, by using a decay function. Once clamped, we can sum the score and the distance together. Pseudocode:
|
||||
|
||||
`score = score + gauss_decay(distance)`
|
||||
|
||||
In this case we use a **gauss_decay** function.
|
||||
|
||||
{{< code-snippet path="/documentation/headless/snippets/query-points/score-boost-closer-to-user/" >}}
|
||||
|
||||
For all decay functions, there are these parameters available
|
||||
|
||||
| Parameter | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `x` | N/A | The value to decay |
|
||||
| `target` | 0.0 | The value at which the decay will be at its peak. For distances it is usually set at 0.0, but can be set to any value. |
|
||||
| `scale` | 1.0 | The value at which the decay function will be equal to `midpoint`. This is in terms of `x` units, for example, if `x` is in meters, `scale` of 5000 means 5km. Must be a non-zero positive number |
|
||||
| `midpoint` | 0.5 | Output is `midpoint` when `x` equals `scale`. Must be in the range (0.0, 1.0), exclusive |
|
||||
|
||||
The formulas for each decay function are as follows:
|
||||
|
||||
|
||||
<iframe src="https://www.desmos.com/calculator/idv5hknwb1?embed" width="600" height="400" style="border: 1px solid #ccc" frameborder=0 class="mx-auto d-block"></iframe>
|
||||
|
||||
|
||||
#### Decay functions
|
||||
|
||||
|
||||
**`lin_decay`** (green), range: `[0, 1]`
|
||||
|
||||
$$ \text{lin_decay}(x) = \max\left(0,\ -\frac{\left(1-m_{idpoint}\right)}{s_{cale}}\cdot {abs}\left(x-t_{arget}\right)+1\right) $$
|
||||
|
||||
**`exp_decay`** (red), range: `(0, 1]`
|
||||
|
||||
$$ \text{exp_decay}(x) = \exp\left(\frac{\ln\left(m_{idpoint}\right)}{s_{cale}}\cdot {abs}\left(x-t_{arget}\right)\right) $$
|
||||
|
||||
**`gauss_decay`** (purple), range: `(0, 1]`
|
||||
|
||||
$$ \text{gauss_decay}(x) = \exp\left(\frac{\ln\left(m_{idpoint}\right)}{s_{cale}^{2}}\cdot \left(x-t_{arget}\right)^{2}\right) $$
|
||||
|
||||
## Grouping
|
||||
|
||||
*Available as of v1.11.0*
|
||||
|
||||
It is possible to group results by a certain field. This is useful when you have multiple points for the same item, and you want to avoid redundancy of the same item in the results.
|
||||
|
||||
REST API ([Schema](https://api.qdrant.tech/master/api-reference/search/query-points-groups)):
|
||||
|
||||
{{< code-snippet path="/documentation/headless/snippets/query-groups/basic/" >}}
|
||||
|
||||
For more information on the `grouping` capabilities refer to the reference documentation for search with [grouping](/documentation/concepts/search/#search-groups) and [lookup](/documentation/concepts/search/#lookup-in-groups).
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
The snippet demonstrates how to use decay functions and geo distance functions to boost the score of points closer to a user. Function will boost the scores of points, that are closer to specified location `x`. Point locations is taken from the `geo.location` field. If the field is not present, the `defaults` parameter can be used to fill in the missing values. Scale parameter is used to control the decay rate.
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
```csharp
|
||||
using Qdrant.Client;
|
||||
using Qdrant.Client.Grpc;
|
||||
using static Qdrant.Client.Grpc.Expression;
|
||||
|
||||
var client = new QdrantClient("localhost", 6334);
|
||||
|
||||
await client.QueryAsync(
|
||||
collectionName: "{collection_name}",
|
||||
prefetch:
|
||||
[
|
||||
new PrefetchQuery { Query = new float[] { 0.01f, 0.45f, 0.67f }, Limit = 100 },
|
||||
],
|
||||
query: new Formula
|
||||
{
|
||||
Expression = new SumExpression
|
||||
{
|
||||
Sum =
|
||||
{
|
||||
"$score",
|
||||
FromExpDecay(
|
||||
new()
|
||||
{
|
||||
X = new GeoDistance
|
||||
{
|
||||
Origin = new GeoPoint { Lat = 52.504043, Lon = 13.393236 },
|
||||
To = "geo.location",
|
||||
},
|
||||
Scale = 5000,
|
||||
}
|
||||
),
|
||||
},
|
||||
},
|
||||
Defaults =
|
||||
{
|
||||
["geo.location"] = new Dictionary<string, Value>
|
||||
{
|
||||
["lat"] = 48.137154,
|
||||
["lon"] = 11.576124,
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
```
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
```go
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/qdrant/go-client/qdrant"
|
||||
)
|
||||
|
||||
client, err := qdrant.NewClient(&qdrant.Config{
|
||||
Host: "localhost",
|
||||
Port: 6334,
|
||||
})
|
||||
|
||||
client.Query(context.Background(), &qdrant.QueryPoints{
|
||||
CollectionName: "{collection_name}",
|
||||
Prefetch: []*qdrant.PrefetchQuery{
|
||||
{
|
||||
Query: qdrant.NewQuery(0.2, 0.8),
|
||||
},
|
||||
},
|
||||
Query: qdrant.NewQueryFormula(&qdrant.Formula{
|
||||
Expression: qdrant.NewExpressionSum(&qdrant.SumExpression{
|
||||
Sum: []*qdrant.Expression{
|
||||
qdrant.NewExpressionVariable("$score"),
|
||||
qdrant.NewExpressionExpDecay(&qdrant.DecayParamsExpression{
|
||||
X: qdrant.NewExpressionGeoDistance(&qdrant.GeoDistance{
|
||||
Origin: &qdrant.GeoPoint{
|
||||
Lat: 52.504043,
|
||||
Lon: 13.393236,
|
||||
},
|
||||
To: "geo.location",
|
||||
}),
|
||||
}),
|
||||
},
|
||||
}),
|
||||
Defaults: qdrant.NewValueMap(map[string]any{
|
||||
"geo.location": map[string]any{
|
||||
"lat": 48.137154,
|
||||
"lon": 11.576124,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
})
|
||||
```
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
```http
|
||||
POST /collections/{collection_name}/points/query
|
||||
{
|
||||
"prefetch": { "query": [0.2, 0.8, ...], "limit": 50 },
|
||||
"query": {
|
||||
"formula": {
|
||||
"sum": [
|
||||
"$score",
|
||||
{
|
||||
"gauss_decay": {
|
||||
"x": {
|
||||
"geo_distance": {
|
||||
"origin": { "lat": 52.504043, "lon": 13.393236 }
|
||||
"to": "geo.location"
|
||||
}
|
||||
},
|
||||
"scale": 5000 // 5km
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"defaults": { "geo.location": {"lat": 48.137154, "lon": 11.576124} }
|
||||
}
|
||||
}
|
||||
```
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
```java
|
||||
import static io.qdrant.client.ExpressionFactory.expDecay;
|
||||
import static io.qdrant.client.ExpressionFactory.geoDistance;
|
||||
import static io.qdrant.client.ExpressionFactory.sum;
|
||||
import static io.qdrant.client.ExpressionFactory.variable;
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
import static io.qdrant.client.QueryFactory.formula;
|
||||
import static io.qdrant.client.QueryFactory.nearest;
|
||||
import static io.qdrant.client.ValueFactory.value;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.DecayParamsExpression;
|
||||
import io.qdrant.client.grpc.Points.Formula;
|
||||
import io.qdrant.client.grpc.Points.GeoDistance;
|
||||
import io.qdrant.client.grpc.Points.GeoPoint;
|
||||
import io.qdrant.client.grpc.Points.PrefetchQuery;
|
||||
import io.qdrant.client.grpc.Points.QueryPoints;
|
||||
import io.qdrant.client.grpc.Points.SumExpression;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.queryAsync(
|
||||
QueryPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.addPrefetch(
|
||||
PrefetchQuery.newBuilder()
|
||||
.setQuery(nearest(0.01f, 0.45f, 0.67f))
|
||||
.setLimit(100)
|
||||
.build())
|
||||
.setQuery(
|
||||
formula(
|
||||
Formula.newBuilder()
|
||||
.setExpression(
|
||||
sum(
|
||||
SumExpression.newBuilder()
|
||||
.addSum(variable("$score"))
|
||||
.addSum(
|
||||
expDecay(
|
||||
DecayParamsExpression.newBuilder()
|
||||
.setX(
|
||||
geoDistance(
|
||||
GeoDistance.newBuilder()
|
||||
.setOrigin(
|
||||
GeoPoint.newBuilder()
|
||||
.setLat(52.504043)
|
||||
.setLon(13.393236)
|
||||
.build())
|
||||
.setTo("geo.location")
|
||||
.build()))
|
||||
.setScale(5000)
|
||||
.build()))
|
||||
.build()))
|
||||
.putDefaults(
|
||||
"geo.location",
|
||||
value(
|
||||
Map.of(
|
||||
"lat", value(48.137154),
|
||||
"lon", value(11.576124))))
|
||||
.build()))
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
```python
|
||||
from qdrant_client import models
|
||||
|
||||
|
||||
geo_boosted = client.query_points(
|
||||
collection_name="{collection_name}",
|
||||
prefetch=models.Prefetch(
|
||||
query=[0.2, 0.8, ...], # <-- dense vector
|
||||
limit=50
|
||||
),
|
||||
query=models.FormulaQuery(
|
||||
formula=models.SumExpression(sum=[
|
||||
"$score",
|
||||
models.GaussDecayExpression(
|
||||
gauss_decay=models.DecayParamsExpression(
|
||||
x=models.GeoDistance(
|
||||
geo_distance=models.GeoDistanceParams(
|
||||
origin=models.GeoPoint(
|
||||
lat=52.504043,
|
||||
lon=13.393236
|
||||
), # Berlin
|
||||
to="geo.location"
|
||||
)
|
||||
),
|
||||
scale=5000 # 5km
|
||||
)
|
||||
)
|
||||
]),
|
||||
defaults={"geo.location": models.GeoPoint(lat=48.137154, lon=11.576124)} # Munich
|
||||
)
|
||||
)
|
||||
```
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
```rust
|
||||
use qdrant_client::qdrant::{
|
||||
GeoPoint, DecayParamsExpressionBuilder, Expression, FormulaBuilder, PrefetchQueryBuilder, QueryPointsBuilder,
|
||||
};
|
||||
use qdrant_client::Qdrant;
|
||||
|
||||
let client = Qdrant::from_url("http://localhost:6334").build()?;
|
||||
|
||||
let _geo_boosted = client.query(
|
||||
QueryPointsBuilder::new("{collection_name}")
|
||||
.add_prefetch(
|
||||
PrefetchQueryBuilder::default()
|
||||
.query(vec![0.01, 0.45, 0.67])
|
||||
.limit(100u64),
|
||||
)
|
||||
.query(
|
||||
FormulaBuilder::new(Expression::sum_with([
|
||||
Expression::score(),
|
||||
Expression::exp_decay(
|
||||
DecayParamsExpressionBuilder::new(Expression::geo_distance_with(
|
||||
// Berlin
|
||||
GeoPoint { lat: 52.504043, lon: 13.393236 },
|
||||
"geo.location",
|
||||
))
|
||||
.scale(5_000.0),
|
||||
),
|
||||
]))
|
||||
// Munich
|
||||
.add_default("geo.location", GeoPoint { lat: 48.137154, lon: 11.576124 }),
|
||||
)
|
||||
.limit(10),
|
||||
)
|
||||
.await?;
|
||||
```
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
```typescript
|
||||
import { QdrantClient } from "@qdrant/js-client-rest";
|
||||
|
||||
const client = new QdrantClient({ host: "localhost", port: 6333 });
|
||||
|
||||
const distance_boosted = await client.query(collectionName, {
|
||||
prefetch: {
|
||||
query: [0.2, 0.8, ...],
|
||||
limit: 50
|
||||
},
|
||||
query: {
|
||||
formula: {
|
||||
sum: [
|
||||
"$score",
|
||||
{
|
||||
gauss_decay: {
|
||||
x: {
|
||||
geo_distance: {
|
||||
origin: { lat: 52.504043, lon: 13.393236 }, // Berlin
|
||||
to: "geo.location"
|
||||
}
|
||||
},
|
||||
scale: 5000 // 5km
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
defaults: { "geo.location": { lat: 48.137154, lon: 11.576124 } } // Munich
|
||||
}
|
||||
});
|
||||
|
||||
```
|
||||
+1
@@ -0,0 +1 @@
|
||||
The snippet demonstrates how to boost the score of points based on their tag field. If the tag field is one of the headers, it will be more relevant to the query. Tags are located in the payload and included in the boost formula as a filtering condition.
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
```csharp
|
||||
using Qdrant.Client;
|
||||
using Qdrant.Client.Grpc;
|
||||
using static Qdrant.Client.Grpc.Conditions;
|
||||
|
||||
var client = new QdrantClient("localhost", 6334);
|
||||
|
||||
await client.QueryAsync(
|
||||
collectionName: "{collection_name}",
|
||||
prefetch:
|
||||
[
|
||||
new PrefetchQuery { Query = new float[] { 0.01f, 0.45f, 0.67f }, Limit = 100 },
|
||||
],
|
||||
query: new Formula
|
||||
{
|
||||
Expression = new SumExpression
|
||||
{
|
||||
Sum =
|
||||
{
|
||||
"$score",
|
||||
new MultExpression
|
||||
{
|
||||
Mult = { 0.5f, Match("tag", ["h1", "h2", "h3", "h4"]) },
|
||||
},
|
||||
new MultExpression { Mult = { 0.25f, Match("tag", ["p", "li"]) } },
|
||||
},
|
||||
},
|
||||
},
|
||||
limit: 10
|
||||
);
|
||||
```
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
```go
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/qdrant/go-client/qdrant"
|
||||
)
|
||||
|
||||
client, err := qdrant.NewClient(&qdrant.Config{
|
||||
Host: "localhost",
|
||||
Port: 6334,
|
||||
})
|
||||
|
||||
client.Query(context.Background(), &qdrant.QueryPoints{
|
||||
CollectionName: "{collection_name}",
|
||||
Prefetch: []*qdrant.PrefetchQuery{
|
||||
{
|
||||
Query: qdrant.NewQuery(0.01, 0.45, 0.67),
|
||||
},
|
||||
},
|
||||
Query: qdrant.NewQueryFormula(&qdrant.Formula{
|
||||
Expression: qdrant.NewExpressionSum(&qdrant.SumExpression{
|
||||
Sum: []*qdrant.Expression{
|
||||
qdrant.NewExpressionVariable("$score"),
|
||||
qdrant.NewExpressionMult(&qdrant.MultExpression{
|
||||
Mult: []*qdrant.Expression{
|
||||
qdrant.NewExpressionConstant(0.5),
|
||||
qdrant.NewExpressionCondition(qdrant.NewMatchKeywords("tag", "h1", "h2", "h3", "h4")),
|
||||
},
|
||||
}),
|
||||
qdrant.NewExpressionMult(&qdrant.MultExpression{
|
||||
Mult: []*qdrant.Expression{
|
||||
qdrant.NewExpressionConstant(0.25),
|
||||
qdrant.NewExpressionCondition(qdrant.NewMatchKeywords("tag", "p", "li")),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
}),
|
||||
})
|
||||
```
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
```http
|
||||
POST /collections/{collection_name}/points/query
|
||||
{
|
||||
"prefetch": {
|
||||
"query": [0.2, 0.8, ...], // <-- dense vector
|
||||
"limit": 50
|
||||
}
|
||||
"query": {
|
||||
"formula": {
|
||||
"sum": [
|
||||
"$score,
|
||||
{
|
||||
"mult": [
|
||||
0.5,
|
||||
{
|
||||
"key": "tag",
|
||||
"match": { "any": ["h1", "h2", "h3", "h4"] } }
|
||||
]
|
||||
},
|
||||
{
|
||||
"mult": [
|
||||
0.25,
|
||||
{
|
||||
"key": "tag",
|
||||
"match": { "any": ["p", "li"] }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.matchKeywords;
|
||||
import static io.qdrant.client.ExpressionFactory.condition;
|
||||
import static io.qdrant.client.ExpressionFactory.constant;
|
||||
import static io.qdrant.client.ExpressionFactory.mult;
|
||||
import static io.qdrant.client.ExpressionFactory.sum;
|
||||
import static io.qdrant.client.ExpressionFactory.variable;
|
||||
import static io.qdrant.client.QueryFactory.formula;
|
||||
import static io.qdrant.client.QueryFactory.nearest;
|
||||
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.Formula;
|
||||
import io.qdrant.client.grpc.Points.MultExpression;
|
||||
import io.qdrant.client.grpc.Points.PrefetchQuery;
|
||||
import io.qdrant.client.grpc.Points.QueryPoints;
|
||||
import io.qdrant.client.grpc.Points.SumExpression;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.queryAsync(
|
||||
QueryPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.addPrefetch(
|
||||
PrefetchQuery.newBuilder()
|
||||
.setQuery(nearest(0.01f, 0.45f, 0.67f))
|
||||
.setLimit(100)
|
||||
.build())
|
||||
.setQuery(
|
||||
formula(
|
||||
Formula.newBuilder()
|
||||
.setExpression(
|
||||
sum(
|
||||
SumExpression.newBuilder()
|
||||
.addSum(variable("$score"))
|
||||
.addSum(
|
||||
mult(
|
||||
MultExpression.newBuilder()
|
||||
.addMult(constant(0.5f))
|
||||
.addMult(
|
||||
condition(
|
||||
matchKeywords(
|
||||
"tag",
|
||||
List.of("h1", "h2", "h3", "h4"))))
|
||||
.build()))
|
||||
.addSum(mult(MultExpression.newBuilder()
|
||||
.addMult(constant(0.25f))
|
||||
.addMult(
|
||||
condition(
|
||||
matchKeywords(
|
||||
"tag",
|
||||
List.of("p", "li"))))
|
||||
.build()))
|
||||
.build()))
|
||||
.build()))
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
```python
|
||||
from qdrant_client import models
|
||||
|
||||
|
||||
tag_boosted = client.query_points(
|
||||
collection_name="{collection_name}",
|
||||
prefetch=models.Prefetch(
|
||||
query=[0.2, 0.8, ...], # <-- dense vector
|
||||
limit=50
|
||||
),
|
||||
query=models.FormulaQuery(
|
||||
formula=models.SumExpression(sum=[
|
||||
"$score",
|
||||
models.MultExpression(mult=[0.5, models.FieldCondition(key="tag", match=models.MatchAny(any=["h1", "h2", "h3", "h4"]))]),
|
||||
models.MultExpression(mult=[0.25, models.FieldCondition(key="tag", match=models.MatchAny(any=["p", "li"]))])
|
||||
]
|
||||
))
|
||||
)
|
||||
```
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
```rust
|
||||
use qdrant_client::qdrant::{
|
||||
Condition, Expression, FormulaBuilder, PrefetchQueryBuilder, QueryPointsBuilder,
|
||||
};
|
||||
use qdrant_client::Qdrant;
|
||||
|
||||
let client = Qdrant::from_url("http://localhost:6334").build()?;
|
||||
|
||||
let _tag_boosted = client.query(
|
||||
QueryPointsBuilder::new("{collection_name}")
|
||||
.add_prefetch(PrefetchQueryBuilder::default()
|
||||
.query(vec![0.01, 0.45, 0.67])
|
||||
.limit(100u64)
|
||||
)
|
||||
.query(FormulaBuilder::new(Expression::sum_with([
|
||||
Expression::score(),
|
||||
Expression::mult_with([
|
||||
Expression::constant(0.5),
|
||||
Expression::condition(Condition::matches("tag", ["h1", "h2", "h3", "h4"])),
|
||||
]),
|
||||
Expression::mult_with([
|
||||
Expression::constant(0.25),
|
||||
Expression::condition(Condition::matches("tag", ["p", "li"])),
|
||||
]),
|
||||
])))
|
||||
.limit(10)
|
||||
).await?;
|
||||
```
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
```typescript
|
||||
import { QdrantClient } from "@qdrant/js-client-rest";
|
||||
|
||||
const client = new QdrantClient({ host: "localhost", port: 6333 });
|
||||
|
||||
const tag_boosted = await client.query(collectionName, {
|
||||
prefetch: {
|
||||
query: [0.2, 0.8, 0.1, 0.9],
|
||||
limit: 50
|
||||
},
|
||||
query: {
|
||||
formula: {
|
||||
sum: [
|
||||
"$score",
|
||||
{
|
||||
mult: [ 0.5, { key: "tag", match: { any: ["h1", "h2", "h3", "h4"] }} ]
|
||||
},
|
||||
{
|
||||
mult: [ 0.25, { key: "tag", match: { any: ["p", "li"] }} ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user