diff --git a/meilisearch/tests/vector/mod.rs b/meilisearch/tests/vector/mod.rs index dcefe2460..0343ab785 100644 --- a/meilisearch/tests/vector/mod.rs +++ b/meilisearch/tests/vector/mod.rs @@ -375,18 +375,92 @@ async fn user_provided_embeddings_error() { let (value, code) = index.add_documents(documents, None).await; snapshot!(code, @"202 Accepted"); let task = index.wait_task(value.uid()).await; + snapshot!(task["status"], @r###""succeeded""###); + + let documents = + json!({"id": 0, "name": "kefir", "_vectors": { "manual": { "regenerate": false }}}); + let (value, code) = index.add_documents(documents, None).await; + snapshot!(code, @"202 Accepted"); + let task = index.wait_task(value.uid()).await; + snapshot!(task["status"], @r###""succeeded""###); + + let documents = json!({"id": 0, "name": "kefir", "_vectors": { "manual": { "regenerate": false, "embeddings": [0.1, [0.2, 0.3]] }}}); + let (value, code) = index.add_documents(documents, None).await; + snapshot!(code, @"202 Accepted"); + let task = index.wait_task(value.uid()).await; snapshot!(task, @r###" { - "uid": 8, + "uid": 10, "indexUid": "doggo", - "status": "succeeded", + "status": "failed", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 1, - "indexedDocuments": 1 + "indexedDocuments": 0 + }, + "error": { + "message": "Bad embedder configuration in the document with id: `\"0\"`. Invalid value type at `.manual.embeddings[1]`: expected a number, but found an array: `[0.2,0.3]`", + "code": "invalid_vectors_type", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_vectors_type" + }, + "duration": "[duration]", + "enqueuedAt": "[date]", + "startedAt": "[date]", + "finishedAt": "[date]" + } + "###); + + let documents = json!({"id": 0, "name": "kefir", "_vectors": { "manual": { "regenerate": false, "embeddings": [[0.1, 0.2], 0.3] }}}); + let (value, code) = index.add_documents(documents, None).await; + snapshot!(code, @"202 Accepted"); + let task = index.wait_task(value.uid()).await; + snapshot!(task, @r###" + { + "uid": 11, + "indexUid": "doggo", + "status": "failed", + "type": "documentAdditionOrUpdate", + "canceledBy": null, + "details": { + "receivedDocuments": 1, + "indexedDocuments": 0 + }, + "error": { + "message": "Bad embedder configuration in the document with id: `\"0\"`. Invalid value type at `.manual.embeddings[1]`: expected an array, but found a number: `0.3`", + "code": "invalid_vectors_type", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_vectors_type" + }, + "duration": "[duration]", + "enqueuedAt": "[date]", + "startedAt": "[date]", + "finishedAt": "[date]" + } + "###); + + let documents = json!({"id": 0, "name": "kefir", "_vectors": { "manual": { "regenerate": false, "embeddings": [[0.1, true], 0.3] }}}); + let (value, code) = index.add_documents(documents, None).await; + snapshot!(code, @"202 Accepted"); + let task = index.wait_task(value.uid()).await; + snapshot!(task, @r###" + { + "uid": 12, + "indexUid": "doggo", + "status": "failed", + "type": "documentAdditionOrUpdate", + "canceledBy": null, + "details": { + "receivedDocuments": 1, + "indexedDocuments": 0 + }, + "error": { + "message": "Bad embedder configuration in the document with id: `\"0\"`. Invalid value type at `.manual.embeddings[0][1]`: expected a number, but found a boolean: `true`", + "code": "invalid_vectors_type", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_vectors_type" }, - "error": null, "duration": "[duration]", "enqueuedAt": "[date]", "startedAt": "[date]", diff --git a/milli/src/vector/parsed_vectors.rs b/milli/src/vector/parsed_vectors.rs index f934953fd..f555b39ae 100644 --- a/milli/src/vector/parsed_vectors.rs +++ b/milli/src/vector/parsed_vectors.rs @@ -258,7 +258,6 @@ impl Deserr for VectorOrArrayOfVectors { deserr::Value::Null => Ok(VectorOrArrayOfVectors { inner: None }), deserr::Value::Sequence(seq) => { let mut iter = seq.into_iter(); - let location = location.push_index(0); match iter.next().map(|v| v.into_value()) { None => { // With the strange way serde serialize the `Either`, we must send the left part @@ -266,10 +265,16 @@ impl Deserr for VectorOrArrayOfVectors { Ok(VectorOrArrayOfVectors { inner: Some(either::Either::Left(Vec::new())) }) } Some(val @ deserr::Value::Sequence(_)) => { - let first = Embedding::deserialize_from_value(val, location)?; + let first = Embedding::deserialize_from_value(val, location.push_index(0))?; let mut collect = vec![first]; let mut tail = iter - .map(|v| Embedding::deserialize_from_value(v.into_value(), location)) + .enumerate() + .map(|(i, v)| { + Embedding::deserialize_from_value( + v.into_value(), + location.push_index(i + 1), + ) + }) .collect::, _>>()?; collect.append(&mut tail); @@ -280,9 +285,15 @@ impl Deserr for VectorOrArrayOfVectors { | val @ deserr::Value::NegativeInteger(_) | val @ deserr::Value::Float(_), ) => { - let first = ::deserialize_from_value(val, location)?; + let first = ::deserialize_from_value(val, location.push_index(0))?; let mut embedding = iter - .map(|v| ::deserialize_from_value(v.into_value(), location)) + .enumerate() + .map(|(i, v)| { + ::deserialize_from_value( + v.into_value(), + location.push_index(i + 1), + ) + }) .collect::, _>>()?; embedding.insert(0, first); Ok(VectorOrArrayOfVectors { inner: Some(either::Either::Right(embedding)) }) @@ -293,7 +304,7 @@ impl Deserr for VectorOrArrayOfVectors { actual: value, accepted: &[deserr::ValueKind::Sequence, deserr::ValueKind::Float], }, - location, + location.push_index(0), ))), } }