From 5ea359264b3f1c75c54e92eadbe84c96f26ca43a Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Tue, 11 Aug 2026 17:58:40 +0200 Subject: [PATCH] feat(vectorizer): add support for multi2vec-twelvelabs module --- .../v1/api/collections/VectorConfig.java | 45 +++- .../Multi2VecTwelveLabsVectorizer.java | 202 ++++++++++++++++++ .../client6/v1/internal/json/JSONTest.java | 24 +++ 3 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/vectorizers/Multi2VecTwelveLabsVectorizer.java diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/VectorConfig.java b/src/main/java/io/weaviate/client6/v1/api/collections/VectorConfig.java index 44eb595f6..4fa6ae6d0 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/VectorConfig.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/VectorConfig.java @@ -25,6 +25,7 @@ import io.weaviate.client6.v1.api.collections.vectorizers.Multi2VecGoogleVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Multi2VecJinaAiVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Multi2VecNvidiaVectorizer; +import io.weaviate.client6.v1.api.collections.vectorizers.Multi2VecTwelveLabsVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Multi2VecVoyageAiVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Ref2VecCentroidVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.SelfProvidedVectorizer; @@ -33,10 +34,10 @@ import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecAzureOpenAiVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecCohereVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecDatabricksVectorizer; +import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecDigitalOceanVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecGoogleVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecHuggingFaceVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecJinaAiVectorizer; -import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecDigitalOceanVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecMistralVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecModel2VecVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecMorphVectorizer; @@ -78,6 +79,7 @@ public enum Kind implements JsonEnum { MULTI2VEC_GOOGLE("multi2vec-google"), MULTI2VEC_COHERE("multi2vec-cohere"), MULTI2VEC_JINAAI("multi2vec-jinaai"), + MULTI2VEC_TWELVELABS("multi2vec-twelvelabs"), MULTI2VEC_NVIDIA("multi2vec-nvidia"), MULTI2VEC_VOYAGEAI("multi2vec-voyageai"), TEXT2MULTIVEC_JINAAI("text2multivec-jinaai"), @@ -530,6 +532,36 @@ public static Map.Entry multi2vecJinaAi() { return multi2vecJinaAi(VectorIndex.DEFAULT_VECTOR_NAME); } + /** + * Create a vector index with an {@code multi2vec-twelvelabs} vectorizer. + * + * @param fn Lambda expression for optional parameters. + */ + public static Map.Entry multi2vecTwelveLabs( + Function> fn) { + return multi2vecTwelveLabs(VectorIndex.DEFAULT_VECTOR_NAME, fn); + } + + /** + * Create a named vector index with an {@code multi2vec-twelvelabs} vectorizer. + * + * @param vectorName Vector name. + */ + public static Map.Entry multi2vecTwelveLabs(String vectorName) { + return Map.entry(vectorName, Multi2VecTwelveLabsVectorizer.of()); + } + + /** + * Create a named vector index with an {@code multi2vec-twelvelabs} vectorizer. + * + * @param vectorName Vector name. + * @param fn Lambda expression for optional parameters. + */ + public static Map.Entry multi2vecTwelveLabs(String vectorName, + Function> fn) { + return Map.entry(vectorName, Multi2VecTwelveLabsVectorizer.of(fn)); + } + /** * Create a vector index with an {@code multi2vec-jinaai} vectorizer. * @@ -1475,6 +1507,16 @@ default public Multi2VecGoogleVectorizer asMulti2VecGoogle() { return _as(VectorConfig.Kind.MULTI2VEC_GOOGLE); } + /** Is this an instance of {@link Multi2VecTwelveLabsVectorizer}? */ + default public boolean isMulti2VecTwelveLabs() { + return _is(VectorConfig.Kind.MULTI2VEC_TWELVELABS); + } + + /** Convert this instance to {@link Multi2VecTwelveLabsVectorizer}. */ + default public Multi2VecTwelveLabsVectorizer asMulti2VecTwelveLabs() { + return _as(VectorConfig.Kind.MULTI2VEC_TWELVELABS); + } + /** Is this an instance of {@link Multi2VecJinaAiVectorizer}? */ default public boolean isMulti2VecJinaAi() { return _is(VectorConfig.Kind.MULTI2VEC_JINAAI); @@ -1733,6 +1775,7 @@ private final void init(Gson gson) { addAdapter(gson, VectorConfig.Kind.MULTI2VEC_GOOGLE, Multi2VecGoogleVectorizer.class); addAdapter(gson, VectorConfig.Kind.MULTI2VEC_COHERE, Multi2VecCohereVectorizer.class); addAdapter(gson, VectorConfig.Kind.MULTI2VEC_JINAAI, Multi2VecJinaAiVectorizer.class); + addAdapter(gson, VectorConfig.Kind.MULTI2VEC_TWELVELABS, Multi2VecTwelveLabsVectorizer.class); addAdapter(gson, VectorConfig.Kind.MULTI2VEC_NVIDIA, Multi2VecNvidiaVectorizer.class); addAdapter(gson, VectorConfig.Kind.MULTI2VEC_VOYAGEAI, Multi2VecVoyageAiVectorizer.class); addAdapter(gson, VectorConfig.Kind.TEXT2MULTIVEC_JINAAI, Text2MultiVecJinaAiVectorizer.class); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/vectorizers/Multi2VecTwelveLabsVectorizer.java b/src/main/java/io/weaviate/client6/v1/api/collections/vectorizers/Multi2VecTwelveLabsVectorizer.java new file mode 100644 index 000000000..e0e88f0b3 --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/vectorizers/Multi2VecTwelveLabsVectorizer.java @@ -0,0 +1,202 @@ +package io.weaviate.client6.v1.api.collections.vectorizers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +import com.google.gson.annotations.SerializedName; + +import io.weaviate.client6.v1.api.collections.Quantization; +import io.weaviate.client6.v1.api.collections.VectorConfig; +import io.weaviate.client6.v1.api.collections.VectorIndex; +import io.weaviate.client6.v1.internal.ObjectBuilder; + +public record Multi2VecTwelveLabsVectorizer( + /** Base URL of the embedding service. */ + @SerializedName("baseURL") String baseUrl, + /** Inference model to use. */ + @SerializedName("model") String model, + /** BLOB properties included in the embedding. */ + @SerializedName("imageFields") List imageFields, + /** TEXT properties included in the embedding. */ + @SerializedName("textFields") List textFields, + /** Weights of the included properties. */ + @SerializedName("weights") Weights weights, + /** Vector index configuration. */ + VectorIndex vectorIndex, + /** Vector quantization method. */ + Quantization quantization) implements VectorConfig { + + private static record Weights( + /** + * Weights of the BLOB properties. Values appear in the same order as the + * corresponding property names in {@code imageFields}. + */ + @SerializedName("imageWeights") List imageWeights, + /** + * Weights of the TEXT properties. Values appear in the same order as the + * corresponding property names in {@code textFields}. + */ + @SerializedName("textWeights") List textWeights) { + } + + @Override + public VectorConfig.Kind _kind() { + return VectorConfig.Kind.MULTI2VEC_TWELVELABS; + } + + @Override + public Object _self() { + return this; + } + + public static final String MARENGO30 = "marengo3.0"; + + public static Multi2VecTwelveLabsVectorizer of() { + return of(ObjectBuilder.identity()); + } + + public static Multi2VecTwelveLabsVectorizer of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + public Multi2VecTwelveLabsVectorizer( + String baseUrl, + String model, + List imageFields, + List textFields, + Weights weights, + VectorIndex vectorIndex, + Quantization quantization) { + this.baseUrl = baseUrl; + this.model = model; + this.imageFields = imageFields; + this.textFields = textFields; + this.weights = weights; + this.vectorIndex = vectorIndex; + this.quantization = quantization; + } + + public Multi2VecTwelveLabsVectorizer(Builder builder) { + this( + builder.baseUrl, + builder.model, + builder.imageFields, + builder.textFields, + builder.getWeights(), + builder.vectorIndex, + builder.quantization); + } + + public static class Builder implements ObjectBuilder { + private VectorIndex vectorIndex = VectorIndex.DEFAULT_VECTOR_INDEX; + private Quantization quantization; + + private List imageFields; + private List imageWeights; + private List textFields; + private List textWeights; + + private String baseUrl; + private String model; + + /** Set base URL of the embedding service. */ + public Builder baseUrl(String baseUrl) { + this.baseUrl = baseUrl; + return this; + } + + public Builder model(String model) { + this.model = model; + return this; + } + + /** Add BLOB properties to include in the embedding. */ + public Builder imageFields(List fields) { + this.imageFields = fields; + return this; + } + + /** Add BLOB properties to include in the embedding. */ + public Builder imageFields(String... fields) { + return imageFields(Arrays.asList(fields)); + } + + /** + * Add BLOB property to include in the embedding. + * + * @param field Property name. + * @param weight Custom weight between 0.0 and 1.0. + */ + public Builder imageField(String field, float weight) { + if (this.imageFields == null) { + this.imageFields = new ArrayList<>(); + } + if (this.imageWeights == null) { + this.imageWeights = new ArrayList<>(); + } + this.imageFields.add(field); + this.imageWeights.add(weight); + return this; + } + + /** Add TEXT properties to include in the embedding. */ + public Builder textFields(List fields) { + this.textFields = fields; + return this; + } + + /** Add TEXT properties to include in the embedding. */ + public Builder textFields(String... fields) { + return textFields(Arrays.asList(fields)); + } + + /** + * Add TEXT property to include in the embedding. + * + * @param field Property name. + * @param weight Custom weight between 0.0 and 1.0. + */ + public Builder textField(String field, float weight) { + if (this.textFields == null) { + this.textFields = new ArrayList<>(); + } + if (this.textWeights == null) { + this.textWeights = new ArrayList<>(); + } + this.textFields.add(field); + this.textWeights.add(weight); + return this; + } + + protected Weights getWeights() { + if (this.textWeights != null || this.imageWeights != null) { + return new Weights(this.imageWeights, this.textWeights); + } + return null; + } + + /** + * Override default vector index configuration. + * + * HNSW + * is the default vector index. + */ + public Builder vectorIndex(VectorIndex vectorIndex) { + this.vectorIndex = vectorIndex; + return this; + } + + public Builder quantization(Quantization quantization) { + this.quantization = quantization; + return this; + } + + @Override + public Multi2VecTwelveLabsVectorizer build() { + return new Multi2VecTwelveLabsVectorizer(this); + } + } +} diff --git a/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java b/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java index 560ce8269..e7c0d6203 100644 --- a/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java +++ b/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java @@ -47,6 +47,7 @@ import io.weaviate.client6.v1.api.collections.vectorizers.Multi2VecGoogleVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Multi2VecJinaAiVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Multi2VecNvidiaVectorizer; +import io.weaviate.client6.v1.api.collections.vectorizers.Multi2VecTwelveLabsVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Multi2VecVoyageAiVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.SelfProvidedVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecAwsVectorizer; @@ -974,6 +975,29 @@ public static Object[][] testCases() { } """, }, + { + VectorConfig.class, + Multi2VecTwelveLabsVectorizer.of( + v -> v + .baseUrl("example.com") + .model(Multi2VecTwelveLabsVectorizer.MARENGO30) + .imageFields("a", "b") + .textFields("c")), + """ + { + "vectorIndexType": "hnsw", + "vectorIndexConfig": {}, + "vectorizer": { + "multi2vec-twelvelabs": { + "baseURL": "example.com", + "model": "marengo3.0", + "imageFields": ["a", "b"], + "textFields": ["c"] + } + } + } + """, + }, { VectorConfig.class, Multi2VecJinaAiVectorizer.of(v -> v.imageFields("a", "b").textFields("c")),