@@ -28,8 +28,8 @@ similarity of an embedding generated from some query text with embeddings stored
2828or JSON fields, Redis can retrieve documents that closely match the query in terms
2929of their meaning.
3030
31- In the example below, we use the [ HuggingFace] ( https://huggingface.co/ ) model
32- [ ` all-mpnet-base -v2 ` ] ( https://huggingface.co/sentence-transformers/all-mpnet-base -v2 )
31+ The example below uses the [ HuggingFace] ( https://huggingface.co/ ) model
32+ [ ` all-MiniLM-L6 -v2 ` ] ( https://huggingface.co/sentence-transformers/all-MiniLM-L6 -v2 )
3333to generate the vector embeddings to store and index with Redis Query Engine.
3434The code is first demonstrated for hash documents with a
3535separate section to explain the
@@ -53,21 +53,33 @@ dependencies to your `pom.xml` file:
5353<dependency >
5454 <groupId >redis.clients</groupId >
5555 <artifactId >jedis</artifactId >
56- <version >5.2 .0</version >
56+ <version >6.1 .0</version >
5757</dependency >
5858<dependency >
5959 <groupId >ai.djl.huggingface</groupId >
6060 <artifactId >tokenizers</artifactId >
61- <version >0.24.0</version >
61+ <version >0.33.0</version >
62+ </dependency >
63+ <dependency >
64+ <groupId >ai.djl.pytorch</groupId >
65+ <artifactId >pytorch-model-zoo</artifactId >
66+ <version >0.33.0</version >
67+ </dependency >
68+ <dependency >
69+ <groupId >ai.djl</groupId >
70+ <artifactId >api</artifactId >
71+ <version >0.33.0</version >
6272</dependency >
6373```
6474
6575If you are using [ Gradle] ( https://gradle.org/ ) , add the following
6676dependencies to your ` build.gradle ` file:
6777
6878``` bash
69- implementation ' redis.clients:jedis:5.2.0'
70- implementation ' ai.djl.huggingface:tokenizers:0.24.0'
79+ implementation ' redis.clients:jedis:6.1.0'
80+ implementation ' ai.djl.huggingface:tokenizers:0.33.0'
81+ implementation ' ai.djl.pytorch:pytorch-model-zoo:0.33.0'
82+ implementation ' ai.djl:api:0.33.0'
7183```
7284
7385## Import dependencies
@@ -79,24 +91,25 @@ Import the following classes in your source file:
7991
8092## Define a helper method
8193
82- Our embedding model represents the vectors as an array of ` long ` integer values,
83- but Redis Query Engine expects the vector components to be ` float ` values .
94+ The embedding model represents the vectors as an array of ` float ` values,
95+ which is the format required by Redis Query Engine .
8496Also, when you store vectors in a hash object, you must encode the vector
85- array as a ` byte ` string. To simplify this situation, we declare a helper
86- method ` longsToFloatsByteString() ` that takes the ` long ` array that the
87- embedding model returns, converts it to an array of ` float ` values, and
88- then encodes the ` float ` array as a ` byte ` string:
97+ array as a ` byte ` string. To simplify this situation, you can declare a helper
98+ method ` floatsToByteString() ` that takes the ` float ` array that the
99+ embedding model returns and encodes it as a ` byte ` string:
89100
90101{{< clients-example set="HomeQueryVec" step="helper_method" lang_filter="Java-Sync" >}}
91102{{< /clients-example >}}
92103
93104## Create a tokenizer instance
94105
95- We will use the
96- [ ` all-mpnet-base-v2 ` ] ( https://huggingface.co/sentence-transformers/all-mpnet-base-v2 )
97- tokenizer to generate the embeddings. The vectors that represent the
98- embeddings have 768 components, regardless of the length of the input
99- text.
106+ The next step is to generate the embeddings using the
107+ [ ` all-MiniLM-L6-v2 ` ] ( https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2 )
108+ model. The vectors that represent the
109+ embeddings have 384 components, regardless of the length of the input
110+ text, but note that the input is truncated to 256
111+ tokens (see
112+ [ Word piece tokenization] ( https://huggingface.co/learn/nlp-course/en/chapter6/6 )
100113
101114{{< clients-example set="HomeQueryVec" step="tokenizer" lang_filter="Java-Sync" >}}
102115{{< /clients-example >}}
@@ -111,7 +124,7 @@ the index doesn't already exist, which is why you need the
111124{{< clients-example set="HomeQueryVec" step="connect" lang_filter="Java-Sync" >}}
112125{{< /clients-example >}}
113126
114- Next, we create the index.
127+ Next, create the index.
115128The schema in the example below includes three fields: the text content to index, a
116129[ tag] ({{< relref "/develop/ai/search-and-query/advanced-concepts/tags" >}})
117130field to represent the "genre" of the text, and the embedding vector generated from
@@ -120,10 +133,10 @@ the original text content. The `embedding` field specifies
120133indexing, the
121134[ L2] ({{< relref "/develop/ai/search-and-query/vectors#distance-metrics" >}})
122135vector distance metric, ` Float32 ` values to represent the vector's components,
123- and 768 dimensions, as required by the ` all-mpnet-base -v2 ` embedding model.
136+ and 384 dimensions, as required by the ` all-MiniLM-L6 -v2 ` embedding model.
124137
125138The ` FTCreateParams ` object specifies hash objects for storage and a
126- prefix ` doc: ` that identifies the hash objects we want to index.
139+ prefix ` doc: ` that identifies the hash objects to index.
127140
128141{{< clients-example set="HomeQueryVec" step="create_index" lang_filter="Java-Sync" >}}
129142{{< /clients-example >}}
@@ -134,16 +147,15 @@ You can now supply the data objects, which will be indexed automatically
134147when you add them with [ ` hset() ` ] ({{< relref "/commands/hset" >}}), as long as
135148you use the ` doc: ` prefix specified in the index definition.
136149
137- Use the ` encode ()` method of the ` sentenceTokenizer ` object
150+ Use the ` predict ()` method of the ` Predictor ` object
138151as shown below to create the embedding that represents the ` content ` field.
139- The ` getIds() ` method that follows ` encode() ` obtains the vector
140- of ` long ` values which we then convert to a ` float ` array stored as a ` byte `
141- string using our helper method. Use the ` byte ` string representation when you are
142- indexing hash objects (as we are here), but use an array of ` float ` for
152+ The ` predict() ` method returns a ` float[] ` array which is then converted to a ` byte `
153+ string using the helper method. Use the ` byte ` string representation when you are
154+ indexing hash objects (as we are here), but use the array of ` float ` directly for
143155JSON objects (see [ Differences with JSON objects] ( #differences-with-json-documents )
144- below). Note that when we set the ` embedding ` field, we must use an overload
156+ below). Note that when you set the ` embedding ` field, you must use an overload
145157of ` hset() ` that requires ` byte ` arrays for each of the key, the field name, and
146- the value, which is why we include the ` getBytes() ` calls on the strings.
158+ the value, which is why you must include the ` getBytes() ` calls on the strings.
147159
148160{{< clients-example set="HomeQueryVec" step="add_data" lang_filter="Java-Sync" >}}
149161{{< /clients-example >}}
@@ -153,10 +165,10 @@ the value, which is why we include the `getBytes()` calls on the strings.
153165After you have created the index and added the data, you are ready to run a query.
154166To do this, you must create another embedding vector from your chosen query
155167text. Redis calculates the vector distance between the query vector and each
156- embedding vector in the index as it runs the query. We can request the results to be
168+ embedding vector in the index as it runs the query. You can request the results to be
157169sorted to rank them in order of ascending distance.
158170
159- The code below creates the query embedding using the ` encode ()` method, as with
171+ The code below creates the query embedding using the ` predict ()` method, as with
160172the indexing, and passes it as a parameter when the query executes (see
161173[ Vector search] ({{< relref "/develop/ai/search-and-query/query/vector-search" >}})
162174for more information about using query parameters with embeddings).
@@ -170,19 +182,19 @@ search that sorts the results in order of vector distance from the query vector.
170182Assuming you have added the code from the steps above to your source file,
171183it is now ready to run, but note that it may take a while to complete when
172184you run it for the first time (which happens because the tokenizer must download the
173- ` all-mpnet-base -v2 ` model data before it can
185+ ` all-MiniLM-L6 -v2 ` model data before it can
174186generate the embeddings). When you run the code, it outputs the following result text:
175187
176188```
177189Results:
178- ID: doc:2 , Distance: 1411344 , Content: That is a happy dog
179- ID: doc:1 , Distance: 9301635 , Content: That is a very happy person
180- ID: doc:3, Distance: 67178800 , Content: Today is a sunny day
190+ ID: doc:1 , Distance: 0.114169836044 , Content: That is a very happy person
191+ ID: doc:2 , Distance: 0.610845506191 , Content: That is a happy dog
192+ ID: doc:3, Distance: 1.48624765873 , Content: Today is a sunny day
181193```
182194
183195Note that the results are ordered according to the value of the ` distance `
184196field, with the lowest distance indicating the greatest similarity to the query.
185- For this model , the text * "That is a happy dog "*
197+ As expected , the text * "That is a very happy person "*
186198is the result judged to be most similar in meaning to the query text
187199* "That is a happy person"* .
188200
@@ -202,12 +214,8 @@ the one created previously for hashes:
202214{{< /clients-example >}}
203215
204216An important difference with JSON indexing is that the vectors are
205- specified using arrays of ` float ` instead of binary strings. This requires
206- a modified version of the ` longsToFloatsByteString() ` method
207- used previously:
208-
209- {{< clients-example set="HomeQueryVec" step="json_helper_method" lang_filter="Java-Sync" >}}
210- {{< /clients-example >}}
217+ specified using arrays of ` float ` instead of binary strings, so you don't need
218+ a helper method to convert the array to a binary string.
211219
212220Use [ ` jsonSet() ` ] ({{< relref "/commands/json.set" >}}) to add the data
213221instead of [ ` hset() ` ] ({{< relref "/commands/hset" >}}). Use instances
@@ -221,7 +229,7 @@ The query is almost identical to the one for the hash documents. This
221229demonstrates how the right choice of aliases for the JSON paths can
222230save you having to write complex queries. An important thing to notice
223231is that the vector parameter for the query is still specified as a
224- binary string (using the ` longsToFloatsByteString ()` method), even though
232+ binary string (created using the ` floatsToByteString ()` method), even though
225233the data for the ` embedding ` field of the JSON was specified as an array.
226234
227235{{< clients-example set="HomeQueryVec" step="json_query" lang_filter="Java-Sync" >}}
@@ -232,9 +240,9 @@ query is the same as for hash:
232240
233241```
234242Results:
235- ID: jdoc:2 , Distance: 1411344 , Content: That is a happy dog
236- ID: jdoc:1 , Distance: 9301635 , Content: That is a very happy person
237- ID: jdoc:3, Distance: 67178800 , Content: Today is a sunny day
243+ ID: jdoc:1 , Distance: 0.114169836044 , Content: That is a very happy person
244+ ID: jdoc:2 , Distance: 0.610845506191 , Content: That is a happy dog
245+ ID: jdoc:3, Distance: 1.48624765873 , Content: Today is a sunny day
238246```
239247
240248## Learn more
0 commit comments