Vector set embeddings
Index and query embeddings with Redis vector sets
Vector set is a new data type that is currently in preview and may be subject to change.
A Redis vector set lets you store a set of unique keys, each with its own associated vector. You can then retrieve keys from the set according to the similarity between their stored vectors and a query vector that you specify.
You can use vector sets to store any type of numeric vector but they are
particularly optimized to work with text embedding vectors (see
Redis for AI to learn more about text
embeddings). The example below shows how to generate vector embeddings and then
store and retrieve them using a vector set with Lettuce
.
Initialize
If you are using Maven, add the following
dependencies to your pom.xml
file
(note that you need Lettuce
v6.8.0 or later to use vector sets):
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.8.0.RELEASE</version>
</dependency>
<dependency>
<groupId>ai.djl.huggingface</groupId>
<artifactId>tokenizers</artifactId>
<version>0.33.0</version>
</dependency>
<dependency>
<groupId>ai.djl.pytorch</groupId>
<artifactId>pytorch-model-zoo</artifactId>
<version>0.33.0</version>
</dependency>
<dependency>
<groupId>ai.djl</groupId>
<artifactId>api</artifactId>
<version>0.33.0</version>
</dependency>
If you are using Gradle, add the following
dependencies to your build.gradle
file:
compileOnly 'io.lettuce:lettuce-core:6.8.0.RELEASE'
compileOnly 'ai.djl.huggingface:tokenizers:0.33.0'
compileOnly 'ai.djl.pytorch:pytorch-model-zoo:0.33.0'
compileOnly 'ai.djl:api:0.33.0'
In a new Java file, import the required classes:
package io.redis.examples.async;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
// Standard library classes for data manipulation and
// asynchronous programming.
import java.util.*;
import java.util.concurrent.CompletableFuture;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
CompletableFuture<?>[] vaddFutures = new CompletableFuture[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = asyncCommands.vadd("famousPeople", person.name, personArgs, embedding)
.thenApply(result -> {
System.out.println(result); // >>> true
return result;
}).toCompletableFuture();
}
CompletableFuture.allOf(vaddFutures).join();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> basicQuery = asyncCommands.vsim("famousPeople", actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
return result;
}).toCompletableFuture();
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
CompletableFuture<List<String>> limitedQuery = asyncCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> entertainerQuery = asyncCommands.vsim("famousPeople", entertainerEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
return result;
}).toCompletableFuture();
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> scienceQuery = asyncCommands.vsim("famousPeople", scienceEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
CompletableFuture<List<String>> filteredQuery = asyncCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
return result;
}).toCompletableFuture();
CompletableFuture.allOf(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).join();
} finally {
redisClient.shutdown();
}
}
}
package io.redis.examples.reactive;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
// Standard library classes for data manipulation and
// reactive programming.
import java.util.*;
import reactor.core.publisher.Mono;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();
Mono<?>[] vaddFutures = new Mono[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = reactiveCommands.vadd("famousPeople", person.name, personArgs, embedding)
.doOnNext(result -> {
System.out.println(result); // >>> true
});
}
Mono.when(vaddFutures).block();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> basicQuery = reactiveCommands.vsim("famousPeople", actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
});
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
Mono<java.util.List<String>> limitedQuery = reactiveCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
});
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> entertainerQuery = reactiveCommands.vsim("famousPeople", entertainerEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
});
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> scienceQuery = reactiveCommands.vsim("famousPeople", scienceEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
});
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
Mono<java.util.List<String>> filteredQuery = reactiveCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
});
Mono.when(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).block();
}
}
}
The imports include the classes required to generate embeddings from text.
This example uses an instance of the Predictor
class with the
all-MiniLM-L6-v2
model for the embeddings. This model generates vectors with 384 dimensions, regardless
of the length of the input text, but note that the input is truncated to 256
tokens (see
Word piece tokenization
at the Hugging Face docs to learn more about the way tokens
are related to the original text).
package io.redis.examples.async;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
// Standard library classes for data manipulation and
// asynchronous programming.
import java.util.*;
import java.util.concurrent.CompletableFuture;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
CompletableFuture<?>[] vaddFutures = new CompletableFuture[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = asyncCommands.vadd("famousPeople", person.name, personArgs, embedding)
.thenApply(result -> {
System.out.println(result); // >>> true
return result;
}).toCompletableFuture();
}
CompletableFuture.allOf(vaddFutures).join();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> basicQuery = asyncCommands.vsim("famousPeople", actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
return result;
}).toCompletableFuture();
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
CompletableFuture<List<String>> limitedQuery = asyncCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> entertainerQuery = asyncCommands.vsim("famousPeople", entertainerEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
return result;
}).toCompletableFuture();
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> scienceQuery = asyncCommands.vsim("famousPeople", scienceEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
CompletableFuture<List<String>> filteredQuery = asyncCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
return result;
}).toCompletableFuture();
CompletableFuture.allOf(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).join();
} finally {
redisClient.shutdown();
}
}
}
package io.redis.examples.reactive;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
// Standard library classes for data manipulation and
// reactive programming.
import java.util.*;
import reactor.core.publisher.Mono;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();
Mono<?>[] vaddFutures = new Mono[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = reactiveCommands.vadd("famousPeople", person.name, personArgs, embedding)
.doOnNext(result -> {
System.out.println(result); // >>> true
});
}
Mono.when(vaddFutures).block();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> basicQuery = reactiveCommands.vsim("famousPeople", actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
});
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
Mono<java.util.List<String>> limitedQuery = reactiveCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
});
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> entertainerQuery = reactiveCommands.vsim("famousPeople", entertainerEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
});
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> scienceQuery = reactiveCommands.vsim("famousPeople", scienceEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
});
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
Mono<java.util.List<String>> filteredQuery = reactiveCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
});
Mono.when(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).block();
}
}
}
Create the data
The example data is contained in a List<Person>
object with some brief
descriptions of famous people.
package io.redis.examples.async;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
// Standard library classes for data manipulation and
// asynchronous programming.
import java.util.*;
import java.util.concurrent.CompletableFuture;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
CompletableFuture<?>[] vaddFutures = new CompletableFuture[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = asyncCommands.vadd("famousPeople", person.name, personArgs, embedding)
.thenApply(result -> {
System.out.println(result); // >>> true
return result;
}).toCompletableFuture();
}
CompletableFuture.allOf(vaddFutures).join();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> basicQuery = asyncCommands.vsim("famousPeople", actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
return result;
}).toCompletableFuture();
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
CompletableFuture<List<String>> limitedQuery = asyncCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> entertainerQuery = asyncCommands.vsim("famousPeople", entertainerEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
return result;
}).toCompletableFuture();
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> scienceQuery = asyncCommands.vsim("famousPeople", scienceEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
CompletableFuture<List<String>> filteredQuery = asyncCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
return result;
}).toCompletableFuture();
CompletableFuture.allOf(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).join();
} finally {
redisClient.shutdown();
}
}
}
package io.redis.examples.reactive;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
// Standard library classes for data manipulation and
// reactive programming.
import java.util.*;
import reactor.core.publisher.Mono;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();
Mono<?>[] vaddFutures = new Mono[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = reactiveCommands.vadd("famousPeople", person.name, personArgs, embedding)
.doOnNext(result -> {
System.out.println(result); // >>> true
});
}
Mono.when(vaddFutures).block();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> basicQuery = reactiveCommands.vsim("famousPeople", actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
});
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
Mono<java.util.List<String>> limitedQuery = reactiveCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
});
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> entertainerQuery = reactiveCommands.vsim("famousPeople", entertainerEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
});
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> scienceQuery = reactiveCommands.vsim("famousPeople", scienceEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
});
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
Mono<java.util.List<String>> filteredQuery = reactiveCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
});
Mono.when(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).block();
}
}
}
Add the data to a vector set
The next step is to connect to Redis and add the data to a new vector set.
The predictor.predict()
method that generates the embeddings returns a float[]
array.
The vadd()
method that adds the embeddings to the vector set accepts a Double[]
array,
so it is useful to define a helper method to perform the conversion:
package io.redis.examples.async;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
// Standard library classes for data manipulation and
// asynchronous programming.
import java.util.*;
import java.util.concurrent.CompletableFuture;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
CompletableFuture<?>[] vaddFutures = new CompletableFuture[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = asyncCommands.vadd("famousPeople", person.name, personArgs, embedding)
.thenApply(result -> {
System.out.println(result); // >>> true
return result;
}).toCompletableFuture();
}
CompletableFuture.allOf(vaddFutures).join();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> basicQuery = asyncCommands.vsim("famousPeople", actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
return result;
}).toCompletableFuture();
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
CompletableFuture<List<String>> limitedQuery = asyncCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> entertainerQuery = asyncCommands.vsim("famousPeople", entertainerEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
return result;
}).toCompletableFuture();
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> scienceQuery = asyncCommands.vsim("famousPeople", scienceEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
CompletableFuture<List<String>> filteredQuery = asyncCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
return result;
}).toCompletableFuture();
CompletableFuture.allOf(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).join();
} finally {
redisClient.shutdown();
}
}
}
package io.redis.examples.reactive;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
// Standard library classes for data manipulation and
// reactive programming.
import java.util.*;
import reactor.core.publisher.Mono;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();
Mono<?>[] vaddFutures = new Mono[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = reactiveCommands.vadd("famousPeople", person.name, personArgs, embedding)
.doOnNext(result -> {
System.out.println(result); // >>> true
});
}
Mono.when(vaddFutures).block();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> basicQuery = reactiveCommands.vsim("famousPeople", actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
});
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
Mono<java.util.List<String>> limitedQuery = reactiveCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
});
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> entertainerQuery = reactiveCommands.vsim("famousPeople", entertainerEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
});
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> scienceQuery = reactiveCommands.vsim("famousPeople", scienceEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
});
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
Mono<java.util.List<String>> filteredQuery = reactiveCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
});
Mono.when(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).block();
}
}
}
The code below connects to Redis, then iterates through all the items in the people
list,
generates embeddings for each person's description, and then
adds the appropriate elements to a vector set called famousPeople
.
Note that the predict()
call is in a try
/catch
block because it can throw
exceptions if it can't download the embedding model (you should add code to handle
the exceptions for production).
The call to vadd()
also adds the born
and died
values from the
original people
list as attribute data. You can access this during a query
or by using the vgetattr()
method.
package io.redis.examples.async;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
// Standard library classes for data manipulation and
// asynchronous programming.
import java.util.*;
import java.util.concurrent.CompletableFuture;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
CompletableFuture<?>[] vaddFutures = new CompletableFuture[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = asyncCommands.vadd("famousPeople", person.name, personArgs, embedding)
.thenApply(result -> {
System.out.println(result); // >>> true
return result;
}).toCompletableFuture();
}
CompletableFuture.allOf(vaddFutures).join();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> basicQuery = asyncCommands.vsim("famousPeople", actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
return result;
}).toCompletableFuture();
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
CompletableFuture<List<String>> limitedQuery = asyncCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> entertainerQuery = asyncCommands.vsim("famousPeople", entertainerEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
return result;
}).toCompletableFuture();
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> scienceQuery = asyncCommands.vsim("famousPeople", scienceEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
CompletableFuture<List<String>> filteredQuery = asyncCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
return result;
}).toCompletableFuture();
CompletableFuture.allOf(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).join();
} finally {
redisClient.shutdown();
}
}
}
package io.redis.examples.reactive;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
// Standard library classes for data manipulation and
// reactive programming.
import java.util.*;
import reactor.core.publisher.Mono;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();
Mono<?>[] vaddFutures = new Mono[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = reactiveCommands.vadd("famousPeople", person.name, personArgs, embedding)
.doOnNext(result -> {
System.out.println(result); // >>> true
});
}
Mono.when(vaddFutures).block();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> basicQuery = reactiveCommands.vsim("famousPeople", actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
});
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
Mono<java.util.List<String>> limitedQuery = reactiveCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
});
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> entertainerQuery = reactiveCommands.vsim("famousPeople", entertainerEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
});
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> scienceQuery = reactiveCommands.vsim("famousPeople", scienceEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
});
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
Mono<java.util.List<String>> filteredQuery = reactiveCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
});
Mono.when(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).block();
}
}
}
Query the vector set
You can now query the data in the set. The basic approach is to use the
predict()
method to generate another embedding vector for the query text.
(This is the same method used to add the elements to the set.) Then, pass
the query vector to vsim()
to return elements
of the set, ranked in order of similarity to the query.
Start with a simple query for "actors":
package io.redis.examples.async;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
// Standard library classes for data manipulation and
// asynchronous programming.
import java.util.*;
import java.util.concurrent.CompletableFuture;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
CompletableFuture<?>[] vaddFutures = new CompletableFuture[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = asyncCommands.vadd("famousPeople", person.name, personArgs, embedding)
.thenApply(result -> {
System.out.println(result); // >>> true
return result;
}).toCompletableFuture();
}
CompletableFuture.allOf(vaddFutures).join();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> basicQuery = asyncCommands.vsim("famousPeople", actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
return result;
}).toCompletableFuture();
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
CompletableFuture<List<String>> limitedQuery = asyncCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> entertainerQuery = asyncCommands.vsim("famousPeople", entertainerEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
return result;
}).toCompletableFuture();
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> scienceQuery = asyncCommands.vsim("famousPeople", scienceEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
CompletableFuture<List<String>> filteredQuery = asyncCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
return result;
}).toCompletableFuture();
CompletableFuture.allOf(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).join();
} finally {
redisClient.shutdown();
}
}
}
package io.redis.examples.reactive;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
// Standard library classes for data manipulation and
// reactive programming.
import java.util.*;
import reactor.core.publisher.Mono;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();
Mono<?>[] vaddFutures = new Mono[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = reactiveCommands.vadd("famousPeople", person.name, personArgs, embedding)
.doOnNext(result -> {
System.out.println(result); // >>> true
});
}
Mono.when(vaddFutures).block();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> basicQuery = reactiveCommands.vsim("famousPeople", actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
});
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
Mono<java.util.List<String>> limitedQuery = reactiveCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
});
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> entertainerQuery = reactiveCommands.vsim("famousPeople", entertainerEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
});
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> scienceQuery = reactiveCommands.vsim("famousPeople", scienceEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
});
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
Mono<java.util.List<String>> filteredQuery = reactiveCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
});
Mono.when(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).block();
}
}
}
This returns the following list of elements (formatted slightly for clarity):
['Masako Natsume', 'Chaim Topol', 'Linus Pauling',
'Marie Fredriksson', 'Maryam Mirzakhani', 'Marie Curie',
'Freddie Mercury', 'Paul Erdos']
The first two people in the list are the two actors, as expected, but none of the
people from Linus Pauling onward was especially well-known for acting (and there certainly
isn't any information about that in the short description text).
As it stands, the search attempts to rank all the elements in the set, based
on the information contained in the embedding model.
You can use the count
parameter of vsim()
to limit the list of elements
to just the most relevant few items:
package io.redis.examples.async;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
// Standard library classes for data manipulation and
// asynchronous programming.
import java.util.*;
import java.util.concurrent.CompletableFuture;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
CompletableFuture<?>[] vaddFutures = new CompletableFuture[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = asyncCommands.vadd("famousPeople", person.name, personArgs, embedding)
.thenApply(result -> {
System.out.println(result); // >>> true
return result;
}).toCompletableFuture();
}
CompletableFuture.allOf(vaddFutures).join();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> basicQuery = asyncCommands.vsim("famousPeople", actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
return result;
}).toCompletableFuture();
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
CompletableFuture<List<String>> limitedQuery = asyncCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> entertainerQuery = asyncCommands.vsim("famousPeople", entertainerEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
return result;
}).toCompletableFuture();
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> scienceQuery = asyncCommands.vsim("famousPeople", scienceEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
CompletableFuture<List<String>> filteredQuery = asyncCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
return result;
}).toCompletableFuture();
CompletableFuture.allOf(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).join();
} finally {
redisClient.shutdown();
}
}
}
package io.redis.examples.reactive;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
// Standard library classes for data manipulation and
// reactive programming.
import java.util.*;
import reactor.core.publisher.Mono;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();
Mono<?>[] vaddFutures = new Mono[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = reactiveCommands.vadd("famousPeople", person.name, personArgs, embedding)
.doOnNext(result -> {
System.out.println(result); // >>> true
});
}
Mono.when(vaddFutures).block();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> basicQuery = reactiveCommands.vsim("famousPeople", actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
});
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
Mono<java.util.List<String>> limitedQuery = reactiveCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
});
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> entertainerQuery = reactiveCommands.vsim("famousPeople", entertainerEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
});
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> scienceQuery = reactiveCommands.vsim("famousPeople", scienceEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
});
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
Mono<java.util.List<String>> filteredQuery = reactiveCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
});
Mono.when(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).block();
}
}
}
The reason for using text embeddings rather than simple text search is that the embeddings represent semantic information. This allows a query to find elements with a similar meaning even if the text is different. For example, the word "entertainer" doesn't appear in any of the descriptions, but if you use it as a query, the actors and musicians are ranked highest in the results list:
package io.redis.examples.async;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
// Standard library classes for data manipulation and
// asynchronous programming.
import java.util.*;
import java.util.concurrent.CompletableFuture;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
CompletableFuture<?>[] vaddFutures = new CompletableFuture[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = asyncCommands.vadd("famousPeople", person.name, personArgs, embedding)
.thenApply(result -> {
System.out.println(result); // >>> true
return result;
}).toCompletableFuture();
}
CompletableFuture.allOf(vaddFutures).join();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> basicQuery = asyncCommands.vsim("famousPeople", actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
return result;
}).toCompletableFuture();
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
CompletableFuture<List<String>> limitedQuery = asyncCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> entertainerQuery = asyncCommands.vsim("famousPeople", entertainerEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
return result;
}).toCompletableFuture();
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> scienceQuery = asyncCommands.vsim("famousPeople", scienceEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
CompletableFuture<List<String>> filteredQuery = asyncCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
return result;
}).toCompletableFuture();
CompletableFuture.allOf(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).join();
} finally {
redisClient.shutdown();
}
}
}
package io.redis.examples.reactive;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
// Standard library classes for data manipulation and
// reactive programming.
import java.util.*;
import reactor.core.publisher.Mono;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();
Mono<?>[] vaddFutures = new Mono[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = reactiveCommands.vadd("famousPeople", person.name, personArgs, embedding)
.doOnNext(result -> {
System.out.println(result); // >>> true
});
}
Mono.when(vaddFutures).block();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> basicQuery = reactiveCommands.vsim("famousPeople", actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
});
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
Mono<java.util.List<String>> limitedQuery = reactiveCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
});
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> entertainerQuery = reactiveCommands.vsim("famousPeople", entertainerEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
});
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> scienceQuery = reactiveCommands.vsim("famousPeople", scienceEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
});
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
Mono<java.util.List<String>> filteredQuery = reactiveCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
});
Mono.when(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).block();
}
}
}
Similarly, if you use "science" as a query, you get the following results:
['Marie Curie', 'Linus Pauling', 'Maryam Mirzakhani',
'Paul Erdos', 'Marie Fredriksson', 'Freddie Mercury', 'Masako Natsume',
'Chaim Topol']
The scientists are ranked highest, followed by the mathematicians. This ranking seems reasonable given the connection between mathematics and science.
You can also use
filter expressions
with vsim()
to restrict the search further. For example,
repeat the "science" query, but this time limit the results to people
who died before the year 2000:
package io.redis.examples.async;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
// Standard library classes for data manipulation and
// asynchronous programming.
import java.util.*;
import java.util.concurrent.CompletableFuture;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
CompletableFuture<?>[] vaddFutures = new CompletableFuture[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = asyncCommands.vadd("famousPeople", person.name, personArgs, embedding)
.thenApply(result -> {
System.out.println(result); // >>> true
return result;
}).toCompletableFuture();
}
CompletableFuture.allOf(vaddFutures).join();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> basicQuery = asyncCommands.vsim("famousPeople", actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
return result;
}).toCompletableFuture();
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
CompletableFuture<List<String>> limitedQuery = asyncCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> entertainerQuery = asyncCommands.vsim("famousPeople", entertainerEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
return result;
}).toCompletableFuture();
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
CompletableFuture<List<String>> scienceQuery = asyncCommands.vsim("famousPeople", scienceEmbedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
return result;
}).toCompletableFuture();
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
CompletableFuture<List<String>> filteredQuery = asyncCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.thenApply(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
return result;
}).toCompletableFuture();
CompletableFuture.allOf(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).join();
} finally {
redisClient.shutdown();
}
}
}
package io.redis.examples.reactive;
// Lettuce client and query engine classes.
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
// Standard library classes for data manipulation and
// reactive programming.
import java.util.*;
import reactor.core.publisher.Mono;
// DJL classes for model loading and inference.
import ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.Criteria;
import ai.djl.training.util.ProgressBar;
public class HomeVecSetsExample {
public static Double[] convertFloatsToDoubles(float[] input) {
if (input == null) {
return null;
}
Double[] output = new Double[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = Double.valueOf(input[i]);
}
return output;
}
public void run() {
Predictor<String, float[]> predictor = null;
try {
Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)
.optModelUrls("djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2")
.optEngine("PyTorch").optTranslatorFactory(new TextEmbeddingTranslatorFactory())
.optProgress(new ProgressBar()).build();
predictor = criteria.loadModel().newPredictor();
} catch (Exception e) {
// ...
}
final class Person {
final String name;
final int born;
final int died;
final String description;
Person(String name, int born, int died, String description) {
this.name = name; this.born = born; this.died = died; this.description = description;
}
}
List<Person> people = Arrays.asList(
new Person(
"Marie Curie",
1867, 1934,
"Polish-French chemist and physicist. The only person ever to win" +
" two Nobel prizes for two different sciences."
),
new Person(
"Linus Pauling",
1901, 1994,
"American chemist and peace activist. One of only two people to" +
" win two Nobel prizes in different fields (chemistry and peace)."
),
new Person(
"Freddie Mercury",
1946, 1991,
"British musician, best known as the lead singer of the rock band Queen."
),
new Person(
"Marie Fredriksson",
1958, 2019,
"Swedish multi-instrumentalist, mainly known as the lead singer and" +
" keyboardist of the band Roxette."
),
new Person(
"Paul Erdos",
1913, 1996,
"Hungarian mathematician, known for his eccentric personality almost" +
" as much as his contributions to many different fields of mathematics."
),
new Person(
"Maryam Mirzakhani",
1977, 2017,
"Iranian mathematician. The first woman ever to win the Fields medal" +
" for her contributions to mathematics."
),
new Person(
"Masako Natsume",
1957, 1985,
"Japanese actress. She was very famous in Japan but was primarily" +
" known elsewhere in the world for her portrayal of Tripitaka in the" +
" TV series Monkey."
),
new Person(
"Chaim Topol",
1935, 2023,
"Israeli actor and singer, usually credited simply as 'Topol'. He was" +
" best known for his many appearances as Tevye in the musical Fiddler" +
" on the Roof."
)
);
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();
Mono<?>[] vaddFutures = new Mono[people.size()];
for (int i = 0; i < people.size(); i++) {
Person person = people.get(i);
Double[] embedding = null;
try {
embedding = convertFloatsToDoubles(predictor.predict(person.description));
} catch (Exception e) {
// ...
}
VAddArgs personArgs = VAddArgs.Builder.attributes(String.format("{\"born\": %d, \"died\": %d}", person.born, person.died));
vaddFutures[i] = reactiveCommands.vadd("famousPeople", person.name, personArgs, embedding)
.doOnNext(result -> {
System.out.println(result); // >>> true
});
}
Mono.when(vaddFutures).block();
Double[] actorsEmbedding = null;
try {
actorsEmbedding = convertFloatsToDoubles(predictor.predict("actors"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> basicQuery = reactiveCommands.vsim("famousPeople", actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol, Linus Pauling, Marie Fredriksson, Maryam Mirzakhani, Marie Curie, Freddie Mercury, Paul Erdos]
});
VSimArgs limitArgs = VSimArgs.Builder.count(2L);
Mono<java.util.List<String>> limitedQuery = reactiveCommands.vsim("famousPeople", limitArgs, actorsEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Masako Natsume, Chaim Topol]
});
Double[] entertainerEmbedding = null;
try {
entertainerEmbedding = convertFloatsToDoubles(predictor.predict("entertainers"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> entertainerQuery = reactiveCommands.vsim("famousPeople", entertainerEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Freddie Mercury, Chaim Topol, Linus Pauling, Marie Fredriksson, Masako Natsume, Paul Erdos, Maryam Mirzakhani, Marie Curie]
});
Double[] scienceEmbedding = null;
try {
scienceEmbedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
Mono<java.util.List<String>> scienceQuery = reactiveCommands.vsim("famousPeople", scienceEmbedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Maryam Mirzakhani, Paul Erdos, Marie Fredriksson, Freddie Mercury, Masako Natsume, Chaim Topol]
});
Double[] science2000Embedding = null;
try {
science2000Embedding = convertFloatsToDoubles(predictor.predict("science"));
} catch (Exception e) {
// ...
}
VSimArgs filterArgs = VSimArgs.Builder.filter(".died < 2000");
Mono<java.util.List<String>> filteredQuery = reactiveCommands.vsim("famousPeople", filterArgs, science2000Embedding)
.collectList().doOnNext(result -> {
System.out.println(result);
// >>> [Marie Curie, Linus Pauling, Paul Erdos, Freddie Mercury, Masako Natsume]
});
Mono.when(basicQuery, limitedQuery, entertainerQuery, scienceQuery, filteredQuery).block();
}
}
}
Note that the boolean filter expression is applied to items in the list before the vector distance calculation is performed. Items that don't pass the filter test are removed from the results completely, rather than just reduced in rank. This can help to improve the performance of the search because there is no need to calculate the vector distance for elements that have already been filtered out of the search.
More information
See the vector sets docs for more information and code examples. See the Redis for AI section for more details about text embeddings and other AI techniques you can use with Redis.
You may also be interested in vector search. This is a feature of the Redis query engine that lets you retrieve JSON and hash documents based on vector data stored in their fields.