use zeppelin_embed::epoch::EpochIdentity;
use zeppelin_embed::lifecycle::{ScanRescoreOptions, SearchTier};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
#[repr(u8)]
pub enum Legs {
Dense = 1,
Lexical = 2,
#[default]
Hybrid = 3,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QueryOptions {
pub(crate) k: usize,
pub(crate) legs: Legs,
pub(crate) tier: Option<SearchTier>,
pub(crate) scan_rescore: Option<ScanRescoreOptions>,
}
impl QueryOptions {
#[must_use]
pub const fn new(k: usize) -> Self {
Self {
k,
legs: Legs::Hybrid,
tier: None,
scan_rescore: None,
}
}
#[must_use]
pub const fn with_legs(mut self, legs: Legs) -> Self {
self.legs = legs;
self
}
#[must_use]
pub const fn with_tier(mut self, tier: SearchTier) -> Self {
self.tier = Some(tier);
self.scan_rescore = None;
self
}
#[must_use]
pub const fn with_scan_rescore(mut self, options: ScanRescoreOptions) -> Self {
self.tier = Some(SearchTier::Scan);
self.scan_rescore = Some(options);
self
}
#[must_use]
pub const fn with_optional_tier(mut self, tier: Option<SearchTier>) -> Self {
self.tier = tier;
self.scan_rescore = None;
self
}
}
impl Default for QueryOptions {
fn default() -> Self {
Self::new(10)
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
#[repr(C)]
pub struct ObservedComputeUnits {
pub cpu_ops: u64,
pub gpu_ops: u64,
pub neural_engine_ops: u64,
pub other_ops: u64,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QueryBackend {
pub runtime: crate::runtime::RuntimeIdentity,
pub requested_compute_units: zeppelin_embed::epoch::ComputeUnits,
pub observed_compute_units: Option<ObservedComputeUnits>,
pub sequence_length: Option<usize>,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct TextQueryTimings {
pub tokenization: std::time::Duration,
pub lexical_analysis: std::time::Duration,
pub embedding_queue: std::time::Duration,
pub embedding_evaluation: std::time::Duration,
pub embedding_normalization: std::time::Duration,
pub retrieval: std::time::Duration,
pub materialization: std::time::Duration,
pub end_to_end: std::time::Duration,
}
#[derive(Debug)]
pub struct TextQueryOutcome {
pub hits: Vec<TextHit>,
pub diagnostics: Option<zeppelin_embed::diag::QueryDiagnostics>,
pub timings: Option<TextQueryTimings>,
pub backend: Option<QueryBackend>,
pub query_tokens: usize,
pub embedding_calls: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct TextHit {
pub doc_id: u128,
pub revision: u64,
pub chunk: u32,
pub text: String,
pub score: f64,
pub vector_squared_l2: Option<f64>,
pub lexical_bm25: Option<f64>,
pub epoch: EpochIdentity,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn query_options_default_to_hybrid_ten_and_allow_an_explicit_leg() {
let default = QueryOptions::default();
assert_eq!(default.k, 10);
assert_eq!(default.legs, Legs::Hybrid);
assert_eq!(default.tier, None);
let dense = QueryOptions::new(3).with_legs(Legs::Dense);
assert_eq!(dense.k, 3);
assert_eq!(dense.legs, Legs::Dense);
}
}