Files
qdrant-client/tests/fixtures/expressions.py
Luis Cossío e704e4fe02 [score boosting] Support datetime expressions (#930)
* gen grpc

* generate rest client

* use float for formula evaluation, match multivalue behavior

* support datetime expressions

* populate inspection cache

* review remarks

* support datetime_key

* fix: address AI comments

* fix: regen inspection cache

* regen inspection cache with pydantic 2.10

---------

Co-authored-by: George Panchuk <george.panchuk@qdrant.tech>
2025-04-03 14:51:14 +03:00

112 lines
4.5 KiB
Python

import random
import qdrant_client.models as models
from tests.fixtures.filters import one_random_condition_please
from tests.fixtures.payload import random_datetime
def one_random_expression_please(current_depth: int = 0, max_depth: int = 5) -> models.Expression:
"""Generate a random expression for testing purposes.
Args:
current_depth: Current depth of expression nesting
max_depth: Maximum allowed depth for nested expressions
Returns:
A random Expression object
"""
def rand_decay_params():
return models.DecayParamsExpression(
# limit nesting to avoid precision errors
x=one_random_expression_please(max_depth, max_depth),
target=one_random_expression_please(max_depth, max_depth),
midpoint=round(random.uniform(0.00001, 0.99999), 5),
scale=round(random.uniform(0.000_000_1, 1_000_000.0), 5),
)
# Choose a random expression type with possible nesting
expression_choices = [
# Terminal expressions (no nesting) with higher probability at deeper levels
lambda: round(random.uniform(-10.0, 10.0), 5), # Constant
lambda: random.choice( # Variable
[
"rand_number",
"rand_digit",
"rand_signed_int",
"nested.rand_digit",
"$score",
"$score[0]",
"mixed_type",
]
),
lambda: one_random_condition_please(), # Condition
lambda: models.GeoDistance(
geo_distance=models.GeoDistanceParams(
origin=models.GeoPoint(
lon=round(random.uniform(-180, 180), 5),
lat=round(random.uniform(-90, 90), 5),
),
to="city.geo", # Using a field that would contain geo coordinates
)
),
lambda: models.DatetimeExpression(datetime=str(random_datetime())),
lambda: models.DatetimeKeyExpression(datetime_key="rand_datetime"),
# Nested expressions
lambda: models.MultExpression(
mult=[
one_random_expression_please(current_depth + 1, max_depth)
for _ in range(random.randint(2, 3))
]
),
lambda: models.SumExpression(
sum=[
one_random_expression_please(current_depth + 1, max_depth)
for _ in range(random.randint(2, 3))
]
),
lambda: models.NegExpression(
neg=one_random_expression_please(current_depth + 1, max_depth)
),
lambda: models.AbsExpression(
abs=one_random_expression_please(current_depth + 1, max_depth)
),
lambda: models.DivExpression(
div=models.DivParams(
left=one_random_expression_please(current_depth + 1, max_depth),
right=one_random_expression_please(current_depth + 1, max_depth),
by_zero_default=round(random.uniform(0, 1), 5) if random.random() < 0.5 else None,
)
),
lambda: models.SqrtExpression(
sqrt=one_random_expression_please(current_depth + 1, max_depth)
),
lambda: models.PowExpression(
pow=models.PowParams(
base=one_random_expression_please(current_depth + 1, max_depth),
exponent=one_random_expression_please(current_depth + 1, max_depth),
)
),
lambda: models.ExpExpression(
exp=one_random_expression_please(current_depth + 1, max_depth)
),
lambda: models.Log10Expression(
log10=one_random_expression_please(current_depth + 1, max_depth)
),
lambda: models.LnExpression(ln=one_random_expression_please(current_depth + 1, max_depth)),
lambda: models.LinDecayExpression(lin_decay=rand_decay_params()),
lambda: models.ExpDecayExpression(exp_decay=rand_decay_params()),
lambda: models.GaussDecayExpression(gauss_decay=rand_decay_params()),
]
# If we've reached max depth, return a terminal expression (no nesting)
if current_depth >= max_depth: # Limit nesting depth
# Return a simple expression at max depth
return random.choice(expression_choices[:6])()
# Give higher weight to terminal expressions at deeper levels
if current_depth > 2:
# Add more terminal expressions to increase their probability
expression_choices = expression_choices[:6] * 3 + expression_choices[6:]
return random.choice(expression_choices)()