#![deny(clippy::unwrap_used)]
use std::sync::Arc;
use arrow_array::{ArrayRef, FixedSizeListArray, Float32Array, LargeStringArray, RecordBatch};
use arrow_schema::{DataType, Field, Schema};
use infino::{
VectorSearchOptions,
storage::{LocalFsStorageProvider, StorageProvider},
superfile::builder::FtsConfig,
supertable::{Supertable, SupertableOptions},
test_helpers::{default_tokenizer, default_vector_config, served_shortlist_probe},
};
use tempfile::TempDir;
const DIM: usize = 16;
const VECTOR_ROT_SEED: u64 = 41;
const N_ROWS: usize = 64;
const K: usize = 8;
const CALLER_RM: usize = 3;
fn fixed_list_f32(dim: usize) -> DataType {
DataType::FixedSizeList(
Arc::new(Field::new("item", DataType::Float32, true)),
dim as i32,
)
}
fn vector_options() -> SupertableOptions {
let schema = Arc::new(Schema::new(vec![
Field::new("title", DataType::LargeUtf8, false),
Field::new("emb", fixed_list_f32(DIM), false),
]));
SupertableOptions::new(
schema,
vec![FtsConfig {
column: "title".into(),
positions: false,
}],
vec![default_vector_config("emb", VECTOR_ROT_SEED)],
Some(default_tokenizer()),
)
.expect("valid options")
}
fn row_vec(i: usize) -> Vec<f32> {
(0..DIM)
.map(|d| ((i * 31 + d * 17 + 7) % 97) as f32 / 97.0 + 0.05)
.collect()
}
fn corpus_batch(schema: Arc<Schema>) -> RecordBatch {
let mut flat = Vec::<f32>::with_capacity(N_ROWS * DIM);
let mut titles = Vec::with_capacity(N_ROWS);
for i in 0..N_ROWS {
flat.extend(row_vec(i));
titles.push(format!("row{i:03}"));
}
let fsl = FixedSizeListArray::try_new(
Arc::new(Field::new("item", DataType::Float32, true)),
DIM as i32,
Arc::new(Float32Array::from(flat)) as ArrayRef,
None,
)
.expect("FSL");
RecordBatch::try_new(
schema,
vec![
Arc::new(LargeStringArray::from(titles)) as ArrayRef,
Arc::new(fsl),
],
)
.expect("batch")
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn law_stamped_table_serves_the_law_not_the_constant() {
let dir = TempDir::new().expect("tempdir");
let storage: Arc<dyn StorageProvider> =
Arc::new(LocalFsStorageProvider::new(dir.path()).expect("provider"));
let st =
Supertable::create(vector_options().with_storage(Arc::clone(&storage))).expect("create");
let schema = st.options().schema.clone();
let mut w = st.writer().expect("writer");
w.append(&corpus_batch(schema)).expect("append");
w.commit().expect("commit");
drop(w);
st.drain_vectors_to_cells_sync().expect("drain");
let query = row_vec(3);
served_shortlist_probe::drain();
st.vector_search("emb", &query, K, VectorSearchOptions::new(), None, None)
.expect("default search");
let recs = served_shortlist_probe::drain();
assert!(
recs.iter()
.any(|&(limit, floor)| limit > 0 && limit < K * 256 && floor == 0),
"default must serve a law budget below the K*256 constant with no \
floor; recorded: {recs:?}"
);
st.vector_search(
"emb",
&query,
K,
VectorSearchOptions::new().with_rerank_mult(CALLER_RM),
None,
None,
)
.expect("caller-rm search");
let recs = served_shortlist_probe::drain();
assert!(
recs.contains(&(K * CALLER_RM, 0)),
"caller rerank_mult must override the law exactly; recorded: {recs:?}"
);
st.vector_search(
"emb",
&query,
K,
VectorSearchOptions::new().with_nprobe(2),
None,
None,
)
.expect("pinned-nprobe search");
let recs = served_shortlist_probe::drain();
assert!(
recs.iter()
.any(|&(limit, floor)| floor == limit && floor > K),
"explicit nprobe must arm the per-cell floor at the full \
k x rerank_mult budget (== the pooled limit, > k on this \
fixture); recorded: {recs:?}"
);
}