mirror of
https://github.com/qdrant/qdrant.git
synced 2026-07-25 20:21:08 -05:00
* Add per-query IDF corpus for sparse vector search
Let the caller choose, per query, which population sparse IDF statistics
are computed over. `params.idf` is either `"global"` (default, unchanged
behavior) or `{"corpus": <filter>}`, where the corpus filter is
independent of - and usually broader than - the retrieval filter.
Decoupling the two keeps the score scale stable when the retrieval
filter tightens: term importance is measured against a population the
user names, not against whatever subset the filter happens to select.
Design decisions:
- Corpus grammar is restricted to a conjunction (`must`) of `match`
conditions on payload fields; loosening later is backward compatible.
- Strict mode validates the corpus filter like a read filter
(unindexed fields rejected).
- `idf` on a vector without the IDF modifier is a validation error,
never silently ignored.
- An empty corpus yields degenerate but corpus-scoped scores (smoothed
IDF over N=0), never a fallback to global statistics - in multi-tenant
collections a fallback would leak term statistics across tenants.
Implementation:
- QueryContext IDF stats are keyed by corpus, so one batch can mix
requests with different corpora.
- Statistics come from the sparse index: df(term) is counted over the
query terms' posting lists only, never by scanning stored vectors.
Small corpora (under ~1/32 of the segment, by cardinality estimate)
are kept as a sorted id list galloping through posting lists via
skip_to; large ones as a dense membership mask filled streaming from
the filtered-points iterator. A misestimated small corpus degrades
into the mask.
- Exposed uniformly: REST (`params.idf`), gRPC (`IdfParams` message),
edge python bindings; OpenAPI schema regenerated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Apply rustfmt
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Fix clippy manual_is_multiple_of in sparse IDF corpus test.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Allow any filter as IDF corpus
Drop the must+match grammar restriction on the corpus filter. A
restriction enforced only as a validation step over the full Filter
type buys nothing; if a narrower corpus syntax is ever wanted, it
should be a dedicated API-level type instead.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Fix build: add memory field to SparseIndexConfig in idf corpus test
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: root <111755117+qdrant-cloud-bot@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
498 lines
30 KiB
Rust
498 lines
30 KiB
Rust
use std::path::PathBuf;
|
|
use std::process::Command;
|
|
use std::{env, fs, str};
|
|
|
|
use common::defaults;
|
|
use tonic_prost_build::Builder;
|
|
|
|
fn main() -> std::io::Result<()> {
|
|
// Ensure Qdrant version is configured correctly
|
|
assert_eq!(
|
|
defaults::QDRANT_VERSION.to_string(),
|
|
env!("CARGO_PKG_VERSION"),
|
|
"crate version does not match with defaults.rs",
|
|
);
|
|
|
|
// Since `tonic` 0.14 (when `tonic-build` was refactored into `tonic-prost-build`),
|
|
// `tonic_prost_build` *does not* emit `cargo:rerun-if-changed=` directives, which forces Cargo
|
|
// to recompile `api` (and any other crate that *uses* `api`; which is most crates in Qdrant)
|
|
// on every `cargo check`/`cargo build`/`cargo run`.
|
|
//
|
|
// As a workaround, we emit `cargo:rerun-if-changed=` explicitly. 🤷♀️
|
|
//
|
|
// See:
|
|
// - https://github.com/grpc/grpc-rust/issues/2415
|
|
// - https://github.com/grpc/grpc-rust/issues/2511
|
|
|
|
#[expect(
|
|
clippy::disallowed_methods,
|
|
reason = "std::fs is allowed in build-script"
|
|
)]
|
|
for result in fs::read_dir("src/grpc/proto").unwrap() {
|
|
let proto = result.unwrap();
|
|
|
|
if proto.path().extension().and_then(|str| str.to_str()) == Some("proto") {
|
|
println!("cargo:rerun-if-changed={}", proto.path().display());
|
|
}
|
|
}
|
|
|
|
let build_out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
// Build gRPC bits from proto file
|
|
tonic_prost_build::configure()
|
|
// Because we want to attach all validation rules to the generated gRPC types, we must do
|
|
// so by extending the builder. This is ugly, but better than manually implementing
|
|
// `Validation` for all these types and seems to be the best approach. The line below
|
|
// configures all attributes.
|
|
.configure_validation()
|
|
.file_descriptor_set_path(build_out_dir.join("qdrant_descriptor.bin"))
|
|
.out_dir("src/grpc/") // saves generated structures at this location
|
|
.compile_protos(
|
|
&["src/grpc/proto/qdrant.proto"], // proto entry point
|
|
&["src/grpc/proto"], // specify the root location to search proto dependencies
|
|
)?;
|
|
|
|
// Append trait extension imports to generated gRPC output
|
|
append_to_file(
|
|
"src/grpc/qdrant.rs",
|
|
"use super::validate::ValidateExt;\nuse validator::Validate;",
|
|
);
|
|
|
|
// Fetch git commit ID and pass it to the compiler
|
|
let git_commit_id = option_env!("GIT_COMMIT_ID").map(String::from).or_else(|| {
|
|
match Command::new("git").args(["rev-parse", "HEAD"]).output() {
|
|
Ok(output) if output.status.success() => {
|
|
Some(str::from_utf8(&output.stdout).unwrap().trim().to_string())
|
|
}
|
|
_ => {
|
|
println!("cargo:warning=current git commit hash could not be determined");
|
|
None
|
|
}
|
|
}
|
|
});
|
|
|
|
if let Some(commit_id) = git_commit_id {
|
|
println!("cargo:rustc-env=GIT_COMMIT_ID={commit_id}");
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Extension to [`Builder`] to configure validation attributes.
|
|
trait BuilderExt {
|
|
fn configure_validation(self) -> Self;
|
|
fn validates(self, fields: &[(&str, &str)], extra_derives: &[&str]) -> Self;
|
|
fn derive_validate(self, path: &str) -> Self;
|
|
fn derive_validates(self, paths: &[&str]) -> Self;
|
|
fn field_validate(self, path: &str, constraint: &str) -> Self;
|
|
fn field_validates(self, paths: &[(&str, &str)]) -> Self;
|
|
}
|
|
|
|
impl BuilderExt for Builder {
|
|
fn configure_validation(self) -> Self {
|
|
configure_validation(self)
|
|
}
|
|
|
|
fn validates(self, fields: &[(&str, &str)], extra_derives: &[&str]) -> Self {
|
|
// Build list of structs to derive validation on, guess these from list of fields
|
|
let mut derives = fields
|
|
.iter()
|
|
.map(|(field, _)| field.split_once('.').unwrap().0)
|
|
.collect::<Vec<&str>>();
|
|
derives.extend(extra_derives);
|
|
derives.sort_unstable();
|
|
derives.dedup();
|
|
|
|
self.derive_validates(&derives).field_validates(fields)
|
|
}
|
|
|
|
fn derive_validate(self, path: &str) -> Self {
|
|
self.type_attribute(path, "#[derive(validator::Validate)]")
|
|
}
|
|
|
|
fn derive_validates(self, paths: &[&str]) -> Self {
|
|
paths.iter().fold(self, |c, path| c.derive_validate(path))
|
|
}
|
|
|
|
fn field_validate(self, path: &str, constraint: &str) -> Self {
|
|
if constraint.is_empty() {
|
|
self.field_attribute(path, "#[validate(nested)]")
|
|
} else {
|
|
self.field_attribute(path, format!("#[validate({constraint})]"))
|
|
}
|
|
}
|
|
|
|
fn field_validates(self, fields: &[(&str, &str)]) -> Self {
|
|
fields.iter().fold(self, |c, (path, constraint)| {
|
|
c.field_validate(path, constraint)
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Configure additional attributes required for validation on generated gRPC types.
|
|
///
|
|
/// These are grouped by service file.
|
|
#[rustfmt::skip]
|
|
fn configure_validation(builder: Builder) -> Builder {
|
|
builder
|
|
// prost_wkt_types needed for serde support
|
|
.extern_path(".google.protobuf.Timestamp", "::prost_wkt_types::Timestamp")
|
|
// Service: collections.proto
|
|
.validates(&[
|
|
("GetCollectionInfoRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("CollectionExistsRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("CreateCollection.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name\")"),
|
|
("CreateCollection.hnsw_config", ""),
|
|
("CreateCollection.wal_config", ""),
|
|
("CreateCollection.optimizers_config", ""),
|
|
("CreateCollection.vectors_config", ""),
|
|
("CreateCollection.quantization_config", ""),
|
|
("CreateCollection.shard_number", "range(min = 1)"),
|
|
("CreateCollection.replication_factor", "range(min = 1)"),
|
|
("CreateCollection.write_consistency_factor", "range(min = 1)"),
|
|
("CreateCollection.strict_mode_config", ""),
|
|
("UpdateCollection.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("UpdateCollection.optimizers_config", ""),
|
|
("UpdateCollection.params", ""),
|
|
("UpdateCollection.timeout", "range(min = 1)"),
|
|
("UpdateCollection.hnsw_config", ""),
|
|
("UpdateCollection.vectors_config", ""),
|
|
("UpdateCollection.quantization_config", ""),
|
|
("UpdateCollection.strict_mode_config", ""),
|
|
("CollectionParamsDiff.replication_factor", "range(min = 1)"),
|
|
("CollectionParamsDiff.write_consistency_factor", "range(min = 1)"),
|
|
("DeleteCollection.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("DeleteCollection.timeout", "range(min = 1)"),
|
|
("CollectionParams.vectors_config", ""),
|
|
("ChangeAliases.timeout", "range(min = 1)"),
|
|
("ListCollectionAliasesRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("HnswConfigDiff.ef_construct", "range(min = 4)"),
|
|
("WalConfigDiff.wal_capacity_mb", "range(min = 1)"),
|
|
("WalConfigDiff.wal_retain_closed", "range(min = 1)"),
|
|
("OptimizersConfigDiff.deleted_threshold", "range(min = 0.0, max = 1.0)"),
|
|
("OptimizersConfigDiff.vacuum_min_vector_number", "range(min = 100)"),
|
|
("OptimizersConfigDiff.max_segment_size", "range(min = 1)"),
|
|
("VectorsConfig.config", ""),
|
|
("VectorsConfigDiff.config", ""),
|
|
("VectorParams.size", "range(min = 1, max = 65536)"),
|
|
("VectorParams.hnsw_config", ""),
|
|
("VectorParams.quantization_config", ""),
|
|
("VectorParamsMap.map", ""),
|
|
("VectorParamsDiff.hnsw_config", ""),
|
|
("VectorParamsDiff.quantization_config", ""),
|
|
("VectorParamsDiffMap.map", ""),
|
|
("QuantizationConfig.quantization", ""),
|
|
("QuantizationConfigDiff.quantization", ""),
|
|
("ScalarQuantization.quantile", "range(min = 0.5, max = 1.0)"),
|
|
("SparseIndexConfig.datatype", "custom(function = \"crate::grpc::validate::validate_sparse_datatype\")"),
|
|
("UpdateCollectionClusterSetupRequest.timeout", "range(min = 1)"),
|
|
("UpdateCollectionClusterSetupRequest.operation", ""),
|
|
("StrictModeConfig.max_query_limit", "range(min = 1)"),
|
|
("StrictModeConfig.max_timeout", "range(min = 1)"),
|
|
("StrictModeConfig.max_points_count", "range(min = 1)"),
|
|
("StrictModeConfig.read_rate_limit", "range(min = 1)"),
|
|
("StrictModeConfig.write_rate_limit", "range(min = 1)"),
|
|
("StrictModeConfig.max_resident_memory_percent", "range(min = 1, max = 100)"),
|
|
("StrictModeConfig.max_disk_usage_percent", "range(min = 1, max = 100)"),
|
|
("StrictModeConfig.multivector_config", ""),
|
|
("StrictModeConfig.sparse_config", ""),
|
|
("StrictModeSparseConfig.sparse_config", ""),
|
|
("StrictModeSparse.max_length", "range(min = 1)"),
|
|
("StrictModeMultivectorConfig.multivector_config", ""),
|
|
("StrictModeMultivector.max_vectors", "range(min = 1)"),
|
|
], &[
|
|
"ListCollectionsRequest",
|
|
"ListAliasesRequest",
|
|
"CollectionClusterInfoRequest",
|
|
"UpdateCollectionClusterSetupRequest",
|
|
"ProductQuantization",
|
|
"BinaryQuantization",
|
|
"TurboQuantization",
|
|
"Disabled",
|
|
"QuantizationConfigDiff",
|
|
"quantization_config_diff::Quantization",
|
|
"Replica",
|
|
"ListShardKeysRequest",
|
|
])
|
|
// Service: collections_internal.proto
|
|
.validates(&[
|
|
("GetCollectionInfoRequestInternal.get_collection_info_request", ""),
|
|
("InitiateShardTransferRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("WaitForShardStateRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("WaitForShardStateRequest.timeout", "range(min = 1)"),
|
|
("GetShardRecoveryPointRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("UpdateShardCutoffPointRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("GetShardOptimizationsRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("GetShardMemoryReportRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
], &[])
|
|
// Service: points.proto
|
|
.validates(&[
|
|
("AcornSearchParams.max_selectivity", "range(min = 0.0, max = 1.0)"),
|
|
("PointsSelector.points_selector_one_of", ""),
|
|
("UpsertPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("UpsertPoints.points", ""),
|
|
("UpsertPoints.update_filter", ""),
|
|
("DeletePoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("UpdatePointVectors.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("UpdatePointVectors.points", ""),
|
|
("UpdatePointVectors.update_filter", ""),
|
|
("DeletePointVectors.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("DeletePointVectors.vector_names", "length(min = 1, message = \"must specify vector names to delete\")"),
|
|
("DeletePointVectors.points_selector", ""),
|
|
("PointVectors.vectors", ""),
|
|
("GetPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("SetPayloadPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("SetPayloadPoints.points_selector", ""),
|
|
("DeletePayloadPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("DeletePayloadPoints.points_selector", ""),
|
|
("ClearPayloadPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("ClearPayloadPoints.points", ""),
|
|
("UpdateBatchPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("UpdateBatchPoints.operations", "length(min = 1)"),
|
|
("CreateFieldIndexCollection.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("CreateFieldIndexCollection.field_name", "length(min = 1)"),
|
|
("CreateFieldIndexCollection.field_index_params", ""),
|
|
("PayloadIndexParams.index_params", ""),
|
|
("DeleteFieldIndexCollection.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("DeleteFieldIndexCollection.field_name", "length(min = 1)"),
|
|
("CreateVectorNameRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("CreateVectorNameRequest.vector_config", ""),
|
|
("DenseVectorCreationConfig.size", "range(min = 1, max = 65536)"),
|
|
("SparseVectorCreationConfig.datatype", "custom(function = \"crate::grpc::validate::validate_sparse_datatype\")"),
|
|
("DeleteVectorNameRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("SearchPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("SearchPoints.filter", ""),
|
|
("SearchPoints.limit", "range(min = 1)"),
|
|
("SearchPoints.params", ""),
|
|
("SearchPoints.timeout", "range(min = 1)"),
|
|
("SearchBatchPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("SearchBatchPoints.search_points", ""),
|
|
("SearchBatchPoints.timeout", "range(min = 1)"),
|
|
("SearchPointGroups.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("SearchPointGroups.group_by", "length(min = 1)"),
|
|
("SearchPointGroups.filter", ""),
|
|
("SearchPointGroups.params", ""),
|
|
("SearchPointGroups.group_size", "range(min = 1)"),
|
|
("SearchPointGroups.limit", "range(min = 1)"),
|
|
("SearchPointGroups.timeout", "range(min = 1)"),
|
|
("SearchParams.hnsw_ef", "range(min = 1)"),
|
|
("SearchParams.quantization", ""),
|
|
("SearchParams.acorn", ""),
|
|
("SearchParams.idf", ""),
|
|
("IdfParams.corpus", ""),
|
|
("QuantizationSearchParams.oversampling", "range(min = 1.0)"),
|
|
("ScrollPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("ScrollPoints.filter", ""),
|
|
("ScrollPoints.limit", "range(min = 1)"),
|
|
("RecommendPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("RecommendPoints.filter", ""),
|
|
("RecommendPoints.params", ""),
|
|
("RecommendPoints.timeout", "range(min = 1)"),
|
|
("RecommendPoints.positive_vectors", ""),
|
|
("RecommendPoints.negative_vectors", ""),
|
|
("RecommendBatchPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("RecommendBatchPoints.recommend_points", ""),
|
|
("RecommendBatchPoints.timeout", "range(min = 1)"),
|
|
("RecommendPointGroups.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("RecommendPointGroups.filter", ""),
|
|
("RecommendPointGroups.group_by", "length(min = 1)"),
|
|
("RecommendPointGroups.group_size", "range(min = 1)"),
|
|
("RecommendPointGroups.limit", "range(min = 1)"),
|
|
("RecommendPointGroups.params", ""),
|
|
("RecommendPointGroups.timeout", "range(min = 1)"),
|
|
("RecommendPointGroups.positive_vectors", ""),
|
|
("RecommendPointGroups.negative_vectors", ""),
|
|
("DiscoverPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("DiscoverPoints.filter", ""),
|
|
("DiscoverPoints.params", ""),
|
|
("DiscoverPoints.limit", "range(min = 1)"),
|
|
("DiscoverPoints.timeout", "range(min = 1)"),
|
|
("DiscoverBatchPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("DiscoverBatchPoints.discover_points", ""),
|
|
("DiscoverBatchPoints.timeout", "range(min = 1)"),
|
|
("CountPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("CountPoints.filter", ""),
|
|
("GeoBoundingBox.bottom_right", ""),
|
|
("GeoBoundingBox.top_left", ""),
|
|
("GeoLineString.points", ""),
|
|
("GeoPolygon.exterior", "custom(function = \"crate::grpc::validate::validate_geo_polygon_exterior\"), nested"),
|
|
("GeoPolygon.interiors", "custom(function = \"crate::grpc::validate::validate_geo_polygon_interiors\"), nested"),
|
|
("GeoRadius.center", ""),
|
|
("Filter.should", ""),
|
|
("Filter.must", ""),
|
|
("Filter.must_not", ""),
|
|
("NestedCondition.filter", ""),
|
|
("Condition.condition_one_of", ""),
|
|
("Filter.min_should", ""),
|
|
("MinShould.conditions", ""),
|
|
("MinShould.min_count", "range(min = 1, message = \"min_count must be greater than 0\")"),
|
|
("PointStruct.vectors", ""),
|
|
("Vectors.vectors_options", ""),
|
|
("NamedVectors.vectors", ""),
|
|
("DatetimeRange.lt", "custom(function = \"crate::grpc::validate::validate_timestamp\")"),
|
|
("DatetimeRange.gt", "custom(function = \"crate::grpc::validate::validate_timestamp\")"),
|
|
("DatetimeRange.lte", "custom(function = \"crate::grpc::validate::validate_timestamp\")"),
|
|
("DatetimeRange.gte", "custom(function = \"crate::grpc::validate::validate_timestamp\")"),
|
|
("VectorInput.variant", ""),
|
|
("RecommendInput.positive", ""),
|
|
("RecommendInput.negative", ""),
|
|
("DiscoverInput.target", ""),
|
|
("DiscoverInput.context", ""),
|
|
("ContextInputPair.positive", ""),
|
|
("ContextInputPair.negative", ""),
|
|
("ContextInput.pairs", ""),
|
|
("RelevanceFeedbackInput.target", ""),
|
|
("RelevanceFeedbackInput.feedback", ""),
|
|
("RelevanceFeedbackInput.strategy", ""),
|
|
("FeedbackStrategy.variant", ""),
|
|
("FeedbackItem.example", ""),
|
|
("NaiveFeedbackStrategy.b", "range(min = 0.0)"),
|
|
("Formula.expression", ""),
|
|
("Expression.variant", ""),
|
|
("MultExpression.mult", ""),
|
|
("SumExpression.sum", ""),
|
|
("DivExpression.left", ""),
|
|
("DivExpression.right", ""),
|
|
("PowExpression.base", ""),
|
|
("PowExpression.exponent", ""),
|
|
("DecayParamsExpression.x", ""),
|
|
("DecayParamsExpression.target", ""),
|
|
("NearestInputWithMmr.nearest", ""),
|
|
("NearestInputWithMmr.mmr", ""),
|
|
("Mmr.diversity", "range(min = 0.0, max = 1.0)"),
|
|
("Mmr.candidates_limit", "range(max = 16_384)"),
|
|
("Rrf.k", "range(min = 1)"),
|
|
("Query.variant", ""),
|
|
("PrefetchQuery.prefetch", ""),
|
|
("PrefetchQuery.query", ""),
|
|
("PrefetchQuery.filter", ""),
|
|
("PrefetchQuery.params", ""),
|
|
("PrefetchQuery.limit", "range(min = 1)"),
|
|
("QueryPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("QueryPoints.limit", "range(min = 1)"),
|
|
("QueryPoints.prefetch", ""),
|
|
("QueryPoints.query", ""),
|
|
("QueryPoints.filter", ""),
|
|
("QueryPoints.params", ""),
|
|
("QueryPoints.timeout", "range(min = 1)"),
|
|
("QueryBatchPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("QueryBatchPoints.query_points", ""),
|
|
("QueryBatchPoints.timeout", "range(min = 1)"),
|
|
("QueryPointGroups.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("QueryPointGroups.prefetch", ""),
|
|
("QueryPointGroups.query", ""),
|
|
("QueryPointGroups.group_by", "length(min = 1)"),
|
|
("QueryPointGroups.filter", ""),
|
|
("QueryPointGroups.params", ""),
|
|
("QueryPointGroups.group_size", "range(min = 1)"),
|
|
("QueryPointGroups.limit", "range(min = 1)"),
|
|
("QueryPointGroups.timeout", "range(min = 1)"),
|
|
("FacetCounts.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("FacetCounts.key", "length(min = 1)"),
|
|
("FacetCounts.filter", ""),
|
|
("FacetCounts.timeout", "range(min = 1)"),
|
|
("SearchMatrixPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("SearchMatrixPoints.filter", ""),
|
|
("SearchMatrixPoints.sample", "range(min = 2)"),
|
|
("SearchMatrixPoints.limit", "range(min = 1)"),
|
|
("SearchMatrixPoints.timeout", "range(min = 1)")
|
|
], &[
|
|
"SparseVectorCreationConfig",
|
|
])
|
|
.type_attribute(".", "#[derive(serde::Serialize)]")
|
|
// Service: points_internal_service.proto
|
|
.validates(&[
|
|
("UpsertPointsInternal.upsert_points", ""),
|
|
("DeletePointsInternal.delete_points", ""),
|
|
("UpdateVectorsInternal.update_vectors", ""),
|
|
("DeleteVectorsInternal.delete_vectors", ""),
|
|
("SetPayloadPointsInternal.set_payload_points", ""),
|
|
("DeletePayloadPointsInternal.delete_payload_points", ""),
|
|
("ClearPayloadPointsInternal.clear_payload_points", ""),
|
|
("CreateFieldIndexCollectionInternal.create_field_index_collection", ""),
|
|
("DeleteFieldIndexCollectionInternal.delete_field_index_collection", ""),
|
|
("CreateVectorNameInternal.create_vector_name", ""),
|
|
("DeleteVectorNameInternal.delete_vector_name", ""),
|
|
("UpdateOperation.update", ""),
|
|
("UpdateBatchInternal.operations", ""),
|
|
("SearchPointsInternal.search_points", ""),
|
|
("SearchBatchPointsInternal.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("SearchBatchPointsInternal.search_points", ""),
|
|
("CoreSearchPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("CoreSearchPoints.filter", ""),
|
|
("CoreSearchPoints.limit", "range(min = 1)"),
|
|
("CoreSearchPoints.params", ""),
|
|
("CoreSearchBatchPointsInternal.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("CoreSearchBatchPointsInternal.search_points", ""),
|
|
("RecoQuery.positives", ""),
|
|
("RecoQuery.negatives", ""),
|
|
("ContextPair.positive", ""),
|
|
("ContextPair.negative", ""),
|
|
("DiscoveryQuery.target", ""),
|
|
("DiscoveryQuery.context", ""),
|
|
("ContextQuery.context", ""),
|
|
("RecommendPointsInternal.recommend_points", ""),
|
|
("ScrollPointsInternal.scroll_points", ""),
|
|
("GetPointsInternal.get_points", ""),
|
|
("CountPointsInternal.count_points", ""),
|
|
("SyncPointsInternal.sync_points", ""),
|
|
("SyncPoints.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("QueryBatchPointsInternal.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("QueryBatchPointsInternal.timeout", "range(min = 1)"),
|
|
("FacetCountsInternal.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("FacetCountsInternal.timeout", "range(min = 1)"),
|
|
], &[])
|
|
// Service: raft_service.proto
|
|
.validates(&[
|
|
("AddPeerToKnownMessage.uri", "custom(function = \"common::validation::validate_not_empty\")"),
|
|
("AddPeerToKnownMessage.port", "range(min = 1)"),
|
|
], &[])
|
|
// Service: snapshot_service.proto
|
|
.validates(&[
|
|
("CreateSnapshotRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("ListSnapshotsRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("DeleteSnapshotRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("DeleteSnapshotRequest.snapshot_name", "length(min = 1)"),
|
|
("DeleteFullSnapshotRequest.snapshot_name", "length(min = 1)"),
|
|
("CreateShardSnapshotRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("ListShardSnapshotsRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("DeleteShardSnapshotRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("DeleteShardSnapshotRequest.snapshot_name", "length(min = 1)"),
|
|
("RecoverShardSnapshotRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("RecoverShardSnapshotRequest.snapshot_name", "length(min = 1)"),
|
|
("RecoverShardSnapshotRequest.checksum", "custom(function = \"common::validation::validate_sha256_hash\")"),
|
|
("SnapshotDescription.creation_time", "custom(function = \"crate::grpc::validate::validate_timestamp\")"),
|
|
], &[
|
|
"CreateFullSnapshotRequest",
|
|
"ListFullSnapshotsRequest",
|
|
])
|
|
// Service: storage_read_service.proto
|
|
.validates(&[
|
|
("FileExistsRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("FileExistsRequest.path", "length(min = 1)"),
|
|
("ListFilesRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("ListFilesRequest.prefix_path", "length(min = 1)"),
|
|
("FileLengthRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("FileLengthRequest.path", "length(min = 1)"),
|
|
("ReadBytesRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("ReadBytesRequest.path", "length(min = 1)"),
|
|
("ReadBytesStreamRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("ReadBytesStreamRequest.path", "length(min = 1)"),
|
|
("ReadWholeRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("ReadWholeRequest.path", "length(min = 1)"),
|
|
("ReadBatchRequest.collection_name", "length(min = 1, max = 255), custom(function = \"common::validation::validate_collection_name_legacy\")"),
|
|
("ReadBatchRequest.path", "length(min = 1)"),
|
|
("ReadBatchRequest.ranges", "length(min = 1)"),
|
|
], &[])
|
|
}
|
|
|
|
fn append_to_file(path: &str, line: &str) {
|
|
use std::io::prelude::*;
|
|
#[expect(clippy::disallowed_types, reason = "build script, ok to use std::fs")]
|
|
writeln!(
|
|
std::fs::OpenOptions::new().append(true).open(path).unwrap(),
|
|
"{line}",
|
|
)
|
|
.unwrap()
|
|
}
|