@@ -176,6 +176,97 @@ describe("OpenAICompatibleEmbedder", () => {
176176 } )
177177 } )
178178
179+ /**
180+ * Test base64 conversion logic
181+ */
182+ describe ( "base64 conversion" , ( ) => {
183+ it ( "should convert base64 encoded embeddings to float arrays" , async ( ) => {
184+ const testTexts = [ "Hello world" ]
185+
186+ // Create a Float32Array with test values that can be exactly represented in Float32
187+ const testEmbedding = new Float32Array ( [ 0.25 , 0.5 , 0.75 , 1.0 ] )
188+
189+ // Convert to base64 string (simulating what OpenAI API returns)
190+ const buffer = Buffer . from ( testEmbedding . buffer )
191+ const base64String = buffer . toString ( "base64" )
192+
193+ const mockResponse = {
194+ data : [ { embedding : base64String } ] , // Base64 string instead of array
195+ usage : { prompt_tokens : 10 , total_tokens : 15 } ,
196+ }
197+ mockEmbeddingsCreate . mockResolvedValue ( mockResponse )
198+
199+ const result = await embedder . createEmbeddings ( testTexts )
200+
201+ expect ( mockEmbeddingsCreate ) . toHaveBeenCalledWith ( {
202+ input : testTexts ,
203+ model : testModelId ,
204+ encoding_format : "base64" ,
205+ } )
206+
207+ // Verify the base64 string was converted back to the original float array
208+ expect ( result ) . toEqual ( {
209+ embeddings : [ [ 0.25 , 0.5 , 0.75 , 1.0 ] ] ,
210+ usage : { promptTokens : 10 , totalTokens : 15 } ,
211+ } )
212+ } )
213+
214+ it ( "should handle multiple base64 encoded embeddings" , async ( ) => {
215+ const testTexts = [ "Hello world" , "Goodbye world" ]
216+
217+ // Create test embeddings with values that can be exactly represented in Float32
218+ const embedding1 = new Float32Array ( [ 0.25 , 0.5 , 0.75 ] )
219+ const embedding2 = new Float32Array ( [ 1.0 , 1.25 , 1.5 ] )
220+
221+ // Convert to base64 strings
222+ const base64String1 = Buffer . from ( embedding1 . buffer ) . toString ( "base64" )
223+ const base64String2 = Buffer . from ( embedding2 . buffer ) . toString ( "base64" )
224+
225+ const mockResponse = {
226+ data : [ { embedding : base64String1 } , { embedding : base64String2 } ] ,
227+ usage : { prompt_tokens : 20 , total_tokens : 30 } ,
228+ }
229+ mockEmbeddingsCreate . mockResolvedValue ( mockResponse )
230+
231+ const result = await embedder . createEmbeddings ( testTexts )
232+
233+ expect ( result ) . toEqual ( {
234+ embeddings : [
235+ [ 0.25 , 0.5 , 0.75 ] ,
236+ [ 1.0 , 1.25 , 1.5 ] ,
237+ ] ,
238+ usage : { promptTokens : 20 , totalTokens : 30 } ,
239+ } )
240+ } )
241+
242+ it ( "should handle mixed base64 and array embeddings" , async ( ) => {
243+ const testTexts = [ "Hello world" , "Goodbye world" ]
244+
245+ // Create one base64 embedding and one regular array (edge case)
246+ const embedding1 = new Float32Array ( [ 0.25 , 0.5 , 0.75 ] )
247+ const base64String1 = Buffer . from ( embedding1 . buffer ) . toString ( "base64" )
248+
249+ const mockResponse = {
250+ data : [
251+ { embedding : base64String1 } , // Base64 string
252+ { embedding : [ 1.0 , 1.25 , 1.5 ] } , // Regular array
253+ ] ,
254+ usage : { prompt_tokens : 20 , total_tokens : 30 } ,
255+ }
256+ mockEmbeddingsCreate . mockResolvedValue ( mockResponse )
257+
258+ const result = await embedder . createEmbeddings ( testTexts )
259+
260+ expect ( result ) . toEqual ( {
261+ embeddings : [
262+ [ 0.25 , 0.5 , 0.75 ] ,
263+ [ 1.0 , 1.25 , 1.5 ] ,
264+ ] ,
265+ usage : { promptTokens : 20 , totalTokens : 30 } ,
266+ } )
267+ } )
268+ } )
269+
179270 /**
180271 * Test batching logic when texts exceed token limits
181272 */
@@ -252,11 +343,15 @@ describe("OpenAICompatibleEmbedder", () => {
252343 const testTexts = [ "Hello world" ]
253344 const rateLimitError = { status : 429 , message : "Rate limit exceeded" }
254345
346+ // Create base64 encoded embedding for successful response
347+ const testEmbedding = new Float32Array ( [ 0.25 , 0.5 , 0.75 ] )
348+ const base64String = Buffer . from ( testEmbedding . buffer ) . toString ( "base64" )
349+
255350 mockEmbeddingsCreate
256351 . mockRejectedValueOnce ( rateLimitError )
257352 . mockRejectedValueOnce ( rateLimitError )
258353 . mockResolvedValueOnce ( {
259- data : [ { embedding : [ 0.1 , 0.2 , 0.3 ] } ] ,
354+ data : [ { embedding : base64String } ] ,
260355 usage : { prompt_tokens : 10 , total_tokens : 15 } ,
261356 } )
262357
@@ -271,7 +366,7 @@ describe("OpenAICompatibleEmbedder", () => {
271366 expect ( mockEmbeddingsCreate ) . toHaveBeenCalledTimes ( 3 )
272367 expect ( console . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( "Rate limit hit, retrying in" ) )
273368 expect ( result ) . toEqual ( {
274- embeddings : [ [ 0.1 , 0.2 , 0.3 ] ] ,
369+ embeddings : [ [ 0.25 , 0.5 , 0.75 ] ] ,
275370 usage : { promptTokens : 10 , totalTokens : 15 } ,
276371 } )
277372 } )
0 commit comments