Qdrant search: the test parses the request body as JSON; the live smoke excludes a non-member

filter and params are asserted by value, so must_not and a top-level exact
fail. live_index_smoke searches a strict subset that leaves out the nearest
point. Unverified at this commit: built and tested once at the end of the batch.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-25 21:05:02 +01:00
commit 2041fa8467
2 changed files with 20 additions and 13 deletions

View file

@ -1101,16 +1101,13 @@ fn qdrant_search_scores_only_the_members_exactly_and_reads_ids_kinds_and_scores(
);
let seen = answering.seen.lock().unwrap();
assert_eq!((seen[0].0.as_str(), seen[0].1.as_str()), ("POST", format!("/collections/{name}/points/search").as_str()));
for expected in [
"\"vector\":[0.5,1.0,2.0,3.0]",
"\"has_id\":[\"p1\",\"p2\"]",
"\"exact\":true",
"\"limit\":12",
"\"with_vector\":false",
] {
assert!(seen[0].2.contains(expected), "{expected} in {}", seen[0].2);
}
assert!(!seen[0].2.contains("\"kind\":{"), "membership is ids alone, no predicate on a payload field: {}", seen[0].2);
let body: serde_json::Value = serde_json::from_str(&seen[0].2).expect("the request body is JSON");
assert_eq!(body["vector"], serde_json::json!([0.5, 1.0, 2.0, 3.0]));
assert_eq!(body["filter"], serde_json::json!({ "must": [{ "has_id": ["p1", "p2"] }] }), "members are included, by id alone");
assert_eq!(body["params"], serde_json::json!({ "exact": true }), "exact search, under params");
assert_eq!(body["limit"], 12);
assert_eq!(body["with_vector"], false);
assert!(body.get("exact").is_none(), "a top-level exact is ignored by Qdrant: {body}");
drop(seen);
let nameless = stub(&[("POST /collections/", 200, r#"{"result":[{"id":"p","score":0.5,"payload":{"kind":"question"}}]}"#)]);

View file

@ -46,9 +46,13 @@ fn the_adapters_embed_write_query_and_clean_up_a_scratch_collection() {
let mut embedder = OllamaEmbedder::new(&ollama, &model);
let identity = embedder.model_identity(Duration::from_secs(60)).expect("the model is listed");
println!("identity: {identity:?}");
let texts = ["The organ owns the mind.".to_string(), "A recipe for lentil soup.".to_string()];
let vectors = embedder.embed(&texts, Duration::from_secs(60)).expect("two texts embed");
assert_eq!(vectors.len(), 2);
let texts = [
"The organ owns the mind.".to_string(),
"A recipe for lentil soup.".to_string(),
"How to keep a sourdough starter alive.".to_string(),
];
let vectors = embedder.embed(&texts, Duration::from_secs(60)).expect("three texts embed");
assert_eq!(vectors.len(), 3);
assert!(vectors.iter().all(|vector| vector.len() == identity.dimensions as usize));
let meta = CollectionMeta {
@ -102,6 +106,12 @@ Query: Who is responsible for keeping the memory?");
assert_eq!(hits.len(), 2, "{hits:?}");
assert_eq!((hits[0].doc_id.as_str(), hits[0].kind.as_str()), ("smoke:doc:0", "question"), "{hits:?}");
assert!(hits[0].score > hits[1].score, "{hits:?}");
// The members are a strict subset that leaves out the nearest point:
// the filter must exclude it, not merely rank it.
let subset: Vec<String> = points[1..].iter().map(|point| point.id.clone()).collect();
let hits = store.search(name, &query, &subset, 3, Duration::from_secs(60)).unwrap();
let docs: BTreeSet<&str> = hits.iter().map(|hit| hit.doc_id.as_str()).collect();
assert_eq!(docs, BTreeSet::from(["smoke:doc:1", "smoke:doc:2"]), "only the members are scored: {hits:?}");
println!("{name}: described, created, upserted {} points, queried, searched: {hits:?}", points.len());
}
}));