-
Notifications
You must be signed in to change notification settings - Fork 693
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Move construct-test to ElasticFieldBuilderFnTest * Add MaxInnerProduct similarity metric * Support element_type parameter * Add dims and index methods * Simplify DenseVectorIndexOptions * Don't set similarity if index is false * Simplify tests * Add indexOptions method * Introduce new DenseVectorField apply method and deprecate old DenseVectorField apply methods * Make confidenceInterval a float
- Loading branch information
Showing
4 changed files
with
141 additions
and
145 deletions.
There are no files selected for viewing
132 changes: 38 additions & 94 deletions
132
...s-core/src/test/scala/com/sksamuel/elastic4s/requests/mappings/DenseVectorFieldTest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,116 +1,60 @@ | ||
package com.sksamuel.elastic4s.requests.mappings | ||
|
||
import com.sksamuel.elastic4s.{ElasticApi, JacksonSupport} | ||
import com.sksamuel.elastic4s.fields.{DenseVectorField, FlatIndexOptions, HnswIndexOptions, Int8FlatIndexOptions, Int8HnswIndexOptions, L2Norm} | ||
import com.sksamuel.elastic4s.handlers.fields.{DenseVectorFieldBuilderFn, ElasticFieldBuilderFn} | ||
import com.sksamuel.elastic4s.fields.DenseVectorField.{Flat, Hnsw, Int8Flat, Int8Hnsw} | ||
import com.sksamuel.elastic4s.ElasticApi | ||
import com.sksamuel.elastic4s.fields.{Cosine, DenseVectorField, DenseVectorIndexOptions, DotProduct, L2Norm, MaxInnerProduct} | ||
import com.sksamuel.elastic4s.handlers.fields.{DenseVectorFieldBuilderFn} | ||
import org.scalatest.flatspec.AnyFlatSpec | ||
import org.scalatest.matchers.should.Matchers | ||
|
||
class DenseVectorFieldTest extends AnyFlatSpec with Matchers with ElasticApi { | ||
private val denseVectorIndexOptions = DenseVectorIndexOptions(Int8Hnsw, Some(10), Some(100), Some(1.0f)) | ||
|
||
"A DenseVectorField" should "support dims property" in { | ||
val field = DenseVectorField(name = "myfield", dims = 3) | ||
DenseVectorFieldBuilderFn.build(field).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":false,"similarity":"l2_norm"}""" | ||
"""{"type":"dense_vector","dims":3,"index":false}""" | ||
} | ||
|
||
"A DenseVectorField" should "support a hnsw type of kNN algorithm for a index_options if a index property is true" in { | ||
val field = DenseVectorField( | ||
name = "myfield", | ||
dims = 3, | ||
index = true, | ||
similarity = L2Norm, | ||
indexOptions = Some(HnswIndexOptions(m = Some(100), efConstruction = Some(200))) | ||
) | ||
val jsonStringValue = """{"type":"dense_vector","dims":3,"index":true,"similarity":"l2_norm","index_options":{"type":"hnsw","m":100,"ef_construction":200}}""" | ||
ElasticFieldBuilderFn(field).string shouldBe jsonStringValue | ||
ElasticFieldBuilderFn.construct(field.name, JacksonSupport.mapper.readValue[Map[String, Any]](jsonStringValue)) shouldBe (field) | ||
} | ||
|
||
"A DenseVectorField" should "don't support a hnsw type of kNN algorithm for a index_options if a index property is false" in { | ||
val field = DenseVectorField( | ||
name = "myfield", | ||
dims = 3, | ||
similarity = L2Norm, | ||
indexOptions = Some(HnswIndexOptions(m = Some(100), efConstruction = Some(200))) | ||
) | ||
val jsonStringValue = """{"type":"dense_vector","dims":3,"index":false,"similarity":"l2_norm"}""" | ||
ElasticFieldBuilderFn(field).string shouldBe jsonStringValue | ||
ElasticFieldBuilderFn.construct(field.name, JacksonSupport.mapper.readValue[Map[String, Any]](jsonStringValue)) shouldBe (field.copy(indexOptions = None)) | ||
} | ||
|
||
"A DenseVectorField" should "support a int8_hnsw type of kNN algorithm for a index_options if a index property is true" in { | ||
val field = DenseVectorField( | ||
name = "myfield", | ||
dims = 3, | ||
index = true, | ||
similarity = L2Norm, | ||
indexOptions = Some(Int8HnswIndexOptions(m = Some(100), efConstruction = Some(200), confidenceInterval = Some(0.5d))) | ||
) | ||
val jsonStringValue = """{"type":"dense_vector","dims":3,"index":true,"similarity":"l2_norm","index_options":{"type":"int8_hnsw","m":100,"ef_construction":200,"confidence_interval":0.5}}""" | ||
ElasticFieldBuilderFn(field).string shouldBe jsonStringValue | ||
ElasticFieldBuilderFn.construct(field.name, JacksonSupport.mapper.readValue[Map[String, Any]](jsonStringValue)) shouldBe (field) | ||
} | ||
|
||
"A DenseVectorField" should "don't support a int8_hnsw type of kNN algorithm for a index_options if a index property is false" in { | ||
val field = DenseVectorField( | ||
name = "myfield", | ||
dims = 3, | ||
similarity = L2Norm, | ||
indexOptions = Some(Int8HnswIndexOptions(m = Some(100), efConstruction = Some(200), confidenceInterval = Some(0.5d))) | ||
) | ||
val jsonStringValue = """{"type":"dense_vector","dims":3,"index":false,"similarity":"l2_norm"}""" | ||
ElasticFieldBuilderFn(field).string shouldBe jsonStringValue | ||
ElasticFieldBuilderFn.construct(field.name, JacksonSupport.mapper.readValue[Map[String, Any]](jsonStringValue)) shouldBe (field.copy(indexOptions = None)) | ||
it should "support all similarity options" in { | ||
val field = DenseVectorField(name = "myfield", dims = 3, index = true, similarity = L2Norm) | ||
DenseVectorFieldBuilderFn.build(field).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":true,"similarity":"l2_norm"}""" | ||
DenseVectorFieldBuilderFn.build(field.similarity(DotProduct)).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":true,"similarity":"dot_product"}""" | ||
DenseVectorFieldBuilderFn.build(field.similarity(Cosine)).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":true,"similarity":"cosine"}""" | ||
DenseVectorFieldBuilderFn.build(field.similarity(MaxInnerProduct)).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":true,"similarity":"max_inner_product"}""" | ||
} | ||
|
||
"A DenseVectorField" should "support a flat type of kNN algorithm for a index_options if a index property is true" in { | ||
val field = DenseVectorField( | ||
name = "myfield", | ||
dims = 3, | ||
index = true, | ||
similarity = L2Norm, | ||
indexOptions = Some(FlatIndexOptions()) | ||
) | ||
val jsonStringValue = """{"type":"dense_vector","dims":3,"index":true,"similarity":"l2_norm","index_options":{"type":"flat"}}""" | ||
ElasticFieldBuilderFn(field).string shouldBe jsonStringValue | ||
ElasticFieldBuilderFn.construct(field.name, JacksonSupport.mapper.readValue[Map[String, Any]](jsonStringValue)) shouldBe (field) | ||
it should "support elementType property" in { | ||
val field = DenseVectorField(name = "myfield", dims = 3).elementType("byte") | ||
DenseVectorFieldBuilderFn.build(field).string shouldBe | ||
"""{"type":"dense_vector","element_type":"byte","dims":3,"index":false}""" | ||
} | ||
|
||
"A DenseVectorField" should "don't support a flat type of kNN algorithm for a index_options if a index property is false" in { | ||
val field = DenseVectorField( | ||
name = "myfield", | ||
dims = 3, | ||
similarity = L2Norm, | ||
indexOptions = Some(FlatIndexOptions()) | ||
) | ||
val jsonStringValue = """{"type":"dense_vector","dims":3,"index":false,"similarity":"l2_norm"}""" | ||
ElasticFieldBuilderFn(field).string shouldBe jsonStringValue | ||
ElasticFieldBuilderFn.construct(field.name, JacksonSupport.mapper.readValue[Map[String, Any]](jsonStringValue)) shouldBe (field.copy(indexOptions = None)) | ||
it should "not set similarity or indexOptions when index = false" in { | ||
val field = DenseVectorField(name = "myfield", dims = Some(3), index = Some(false), indexOptions = Some(denseVectorIndexOptions)) | ||
DenseVectorFieldBuilderFn.build(field).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":false}""" | ||
} | ||
|
||
"A DenseVectorField" should "support a int8_flat type of kNN algorithm for a index_options if a index property is true" in { | ||
val field = DenseVectorField( | ||
name = "myfield", | ||
dims = 3, | ||
index = true, | ||
similarity = L2Norm, | ||
indexOptions = Some(Int8FlatIndexOptions(confidenceInterval = Some(0.5d))) | ||
) | ||
val jsonStringValue = """{"type":"dense_vector","dims":3,"index":true,"similarity":"l2_norm","index_options":{"type":"int8_flat","confidence_interval":0.5}}""" | ||
ElasticFieldBuilderFn(field).string shouldBe jsonStringValue | ||
ElasticFieldBuilderFn.construct(field.name, JacksonSupport.mapper.readValue[Map[String, Any]](jsonStringValue)) shouldBe (field) | ||
it should "support indexOptions property" in { | ||
val field = DenseVectorField(name = "myfield", dims = Some(3), index = Some(true), indexOptions = Some(denseVectorIndexOptions)) | ||
DenseVectorFieldBuilderFn.build(field).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":true,"index_options":{"type":"int8_hnsw","m":10,"ef_construction":100,"confidence_interval":1.0}}""" | ||
} | ||
|
||
"A DenseVectorField" should "don't support a int8_flat type of kNN algorithm for a index_options if a index property is false" in { | ||
val field = DenseVectorField( | ||
name = "myfield", | ||
dims = 3, | ||
similarity = L2Norm, | ||
indexOptions = Some(Int8FlatIndexOptions(confidenceInterval = Some(0.5d))) | ||
) | ||
val jsonStringValue = """{"type":"dense_vector","dims":3,"index":false,"similarity":"l2_norm"}""" | ||
ElasticFieldBuilderFn(field).string shouldBe jsonStringValue | ||
ElasticFieldBuilderFn.construct(field.name, JacksonSupport.mapper.readValue[Map[String, Any]](jsonStringValue)) shouldBe (field.copy(indexOptions = None)) | ||
it should "support all index options types and only set m, efConstruction and confidenceInterval when applicable" in { | ||
val field = DenseVectorField(name = "myfield", dims = Some(3), index = Some(true), indexOptions = Some(denseVectorIndexOptions)) | ||
DenseVectorFieldBuilderFn.build(field).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":true,"index_options":{"type":"int8_hnsw","m":10,"ef_construction":100,"confidence_interval":1.0}}""" | ||
DenseVectorFieldBuilderFn.build(field.indexOptions(denseVectorIndexOptions.copy(`type` = Hnsw))).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":true,"index_options":{"type":"hnsw","m":10,"ef_construction":100}}""" | ||
DenseVectorFieldBuilderFn.build(field.indexOptions(denseVectorIndexOptions.copy(`type` = Flat))).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":true,"index_options":{"type":"flat"}}""" | ||
DenseVectorFieldBuilderFn.build(field.indexOptions(denseVectorIndexOptions.copy(`type` = Int8Flat))).string shouldBe | ||
"""{"type":"dense_vector","dims":3,"index":true,"index_options":{"type":"int8_flat","confidence_interval":1.0}}""" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 40 additions & 29 deletions
69
...ers/src/main/scala/com/sksamuel/elastic4s/handlers/fields/DenseVectorFieldBuilderFn.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters