@@ -12,24 +12,59 @@ function cosineSimilarity(a: Float32Array, b: Float32Array): number {
1212 return dot / ( Math . sqrt ( normA ) * Math . sqrt ( normB ) ) ;
1313}
1414
15- // Get embedding from Azure OpenAI
15+ // Get embedding — auto-detect provider
1616async function getEmbedding ( text : string , config : LLMConfig ) : Promise < Float32Array > {
17- const { default : OpenAI } = await import ( "openai" ) ;
17+ const input = text . slice ( 0 , 8000 ) ;
1818
19- // Azure OpenAI embedding endpoint
20- const client = new OpenAI ( {
21- apiKey : config . api_key ,
22- baseURL : `${ config . endpoint } /openai/deployments/text-embedding-3-small` ,
23- defaultQuery : { "api-version" : "2024-06-01" } ,
24- defaultHeaders : { "api-key" : config . api_key } ,
19+ if ( config . provider === "gemini" ) {
20+ return await geminiEmbedding ( input , config ) ;
21+ } else if ( config . provider === "azure-openai" ) {
22+ return await azureEmbedding ( input , config ) ;
23+ } else if ( config . provider === "openai" ) {
24+ return await openaiEmbedding ( input , config ) ;
25+ }
26+ throw new Error ( `Embedding not supported for provider: ${ config . provider } ` ) ;
27+ }
28+
29+ // Gemini Embedding API (free)
30+ async function geminiEmbedding ( text : string , config : LLMConfig ) : Promise < Float32Array > {
31+ const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-001:embedContent` ;
32+ const resp = await fetch ( url , {
33+ method : "POST" ,
34+ headers : { "Content-Type" : "application/json" , "x-goog-api-key" : config . api_key } ,
35+ body : JSON . stringify ( {
36+ model : "models/gemini-embedding-001" ,
37+ content : { parts : [ { text } ] }
38+ } )
2539 } ) ;
40+ if ( ! resp . ok ) throw new Error ( `Gemini embedding error (${ resp . status } )` ) ;
41+ const data = await resp . json ( ) as { embedding : { values : number [ ] } } ;
42+ return new Float32Array ( data . embedding . values ) ;
43+ }
2644
27- const response = await client . embeddings . create ( {
28- model : "text-embedding-3-small" ,
29- input : text . slice ( 0 , 8000 ) , // Limit input length
45+ // Azure OpenAI Embedding
46+ async function azureEmbedding ( text : string , config : LLMConfig ) : Promise < Float32Array > {
47+ const url = `${ config . endpoint } /openai/deployments/text-embedding-3-small/embeddings?api-version=2024-06-01` ;
48+ const resp = await fetch ( url , {
49+ method : "POST" ,
50+ headers : { "Content-Type" : "application/json" , "api-key" : config . api_key } ,
51+ body : JSON . stringify ( { input : text , model : "text-embedding-3-small" } )
3052 } ) ;
53+ if ( ! resp . ok ) throw new Error ( `Azure embedding error (${ resp . status } )` ) ;
54+ const data = await resp . json ( ) as { data : Array < { embedding : number [ ] } > } ;
55+ return new Float32Array ( data . data [ 0 ] . embedding ) ;
56+ }
3157
32- return new Float32Array ( response . data [ 0 ] . embedding ) ;
58+ // OpenAI Embedding
59+ async function openaiEmbedding ( text : string , config : LLMConfig ) : Promise < Float32Array > {
60+ const resp = await fetch ( "https://api.openai.com/v1/embeddings" , {
61+ method : "POST" ,
62+ headers : { "Content-Type" : "application/json" , "Authorization" : `Bearer ${ config . api_key } ` } ,
63+ body : JSON . stringify ( { input : text , model : "text-embedding-3-small" } )
64+ } ) ;
65+ if ( ! resp . ok ) throw new Error ( `OpenAI embedding error (${ resp . status } )` ) ;
66+ const data = await resp . json ( ) as { data : Array < { embedding : number [ ] } > } ;
67+ return new Float32Array ( data . data [ 0 ] . embedding ) ;
3368}
3469
3570// Generate embeddings for all pages that don't have one
0 commit comments