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:
parent
abd2890834
commit
2041fa8467
2 changed files with 20 additions and 13 deletions
|
|
@ -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"}}]}"#)]);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}));
|
||||
|
|
|
|||
Loading…
Reference in a new issue