@@ -41,18 +41,32 @@ const courseData = [
4141
4242class GeminiEmbeddings {
4343 constructor ( ) {
44- this . model = new GoogleGenerativeAIEmbeddings ( {
44+ this . primary = new GoogleGenerativeAIEmbeddings ( {
4545 apiKey : process . env . GEMINI_API_KEY ,
46- modelName : "gemini-embedding-002" ,
46+ modelName : "gemini-embedding-001" ,
47+ } ) ;
48+ this . fallback = new GoogleGenerativeAIEmbeddings ( {
49+ apiKey : process . env . GEMINI_API_KEY ,
50+ modelName : "gemini-embedding-2" ,
4751 } ) ;
4852 }
4953
5054 async embedDocuments ( documents ) {
51- return this . model . embedDocuments ( documents ) ;
55+ try {
56+ return await this . primary . embedDocuments ( documents ) ;
57+ } catch ( err ) {
58+ console . warn ( `[VectorStore] Primary embedding failed, trying fallback:` , err . message ) ;
59+ return await this . fallback . embedDocuments ( documents ) ;
60+ }
5261 }
5362
5463 async embedQuery ( document ) {
55- return this . model . embedQuery ( document ) ;
64+ try {
65+ return await this . primary . embedQuery ( document ) ;
66+ } catch ( err ) {
67+ console . warn ( `[VectorStore] Primary embedding failed, trying fallback:` , err . message ) ;
68+ return await this . fallback . embedQuery ( document ) ;
69+ }
5670 }
5771}
5872
@@ -213,54 +227,19 @@ async function getVectorStore(namespace = '') {
213227
214228 if ( totalVectors === 0 && process . env . FORCE_RESEED !== 'true' ) {
215229 console . log ( `[VectorStore] Namespace '${ namespace || 'default' } ' is empty — seeding course data...` ) ;
216- // Embed with retry for Gemini rate limits
217- let vectors ;
218- const maxEmbedRetries = 3 ;
219- for ( let attempt = 1 ; attempt <= maxEmbedRetries ; attempt ++ ) {
220- try {
221- vectors = await embeddings . embedDocuments ( courseData ) ;
222- break ;
223- } catch ( embedErr ) {
224- const isRetryable = embedErr . message && (
225- embedErr . message . includes ( "429" ) ||
226- embedErr . message . includes ( "RESOURCE_EXHAUSTED" ) ||
227- embedErr . message . includes ( "quota" ) ||
228- embedErr . message . includes ( "503" )
229- ) ;
230- if ( isRetryable && attempt < maxEmbedRetries ) {
231- const waitTime = attempt === 1 ? 5000 : 15000 ;
232- console . warn ( `[VectorStore] ⚠️ Embed rate limited (attempt ${ attempt } ). Retrying in ${ waitTime / 1000 } s...` ) ;
233- await new Promise ( res => setTimeout ( res , waitTime ) ) ;
234- } else {
235- console . error ( `[VectorStore] ❌ Embed failed after ${ attempt } attempts:` , embedErr . message ) ;
236- throw embedErr ;
237- }
238- }
239- }
240-
230+ const vectors = await embeddings . embedDocuments ( courseData ) ;
241231 const records = courseData . map ( ( text , i ) => ( {
242232 id : `course-${ i } ` ,
243233 values : vectors [ i ] ,
244234 metadata : { text, source : 'course-data' , chunk : i } ,
245235 } ) ) ;
246236
247- // Upsert with retry
237+ // Upsert directly into the given namespace
248238 const targetIndex = namespace ? pineconeIndex . namespace ( namespace ) : pineconeIndex ;
239+
249240 const batchSize = 100 ;
250241 for ( let i = 0 ; i < records . length ; i += batchSize ) {
251- let upserted = false ;
252- for ( let attempt = 1 ; attempt <= 3 ; attempt ++ ) {
253- try {
254- await targetIndex . upsert ( { records : records . slice ( i , i + batchSize ) } ) ;
255- upserted = true ;
256- break ;
257- } catch ( upsertErr ) {
258- const waitTime = attempt === 1 ? 3000 : 10000 ;
259- console . warn ( `[VectorStore] ⚠️ Upsert batch ${ i } failed (attempt ${ attempt } ). Retrying in ${ waitTime / 1000 } s...` ) ;
260- await new Promise ( res => setTimeout ( res , waitTime ) ) ;
261- if ( attempt === 3 ) throw upsertErr ;
262- }
263- }
242+ await targetIndex . upsert ( { records : records . slice ( i , i + batchSize ) } ) ;
264243 }
265244 console . log ( `[VectorStore] Seeded ${ courseData . length } vectors into Pinecone namespace: '${ namespace || 'default' } '.` ) ;
266245 } else {
0 commit comments