UNPKG

@rexdug7005/nvidia-llama4

Version:

Integración de NVIDIA Llama4 con LangChain.js

138 lines (134 loc) 4.67 kB
'use strict'; var embeddings = require('@langchain/core/embeddings'); var axios = require('axios'); /** * Implementación de Embeddings de NVIDIA para LangChain */ class NvidiaEmbeddings extends embeddings.Embeddings { constructor(fields) { super(fields); Object.defineProperty(this, "apiKey", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "baseUrl", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "modelName", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "inputType", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "encodingFormat", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "truncate", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "maxRetries", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "defaultOptions", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.apiKey = fields.apiKey; this.baseUrl = fields.baseUrl || "https://integrate.api.nvidia.com/v1/embeddings"; this.modelName = fields.model || "nvidia/nv-embedcode-7b-v1"; this.inputType = fields.inputType || "query"; this.encodingFormat = fields.encodingFormat || "float"; this.truncate = fields.truncate || "NONE"; this.maxRetries = fields.maxRetries ?? 3; // Extraer las opciones que no son parte de la configuración principal const keysToExclude = [ "apiKey", "baseUrl", "model", "inputType", "encodingFormat", "truncate", "maxRetries", ]; // Creamos un objeto con todas las propiedades que no son de configuración principal this.defaultOptions = Object.fromEntries(Object.entries(fields).filter(([key]) => !keysToExclude.includes(key))); } /** * Método para realizar la llamada a la API con reintentos */ async embeddingWithRetry(text) { const texts = Array.isArray(text) ? text : [text]; // Preparar payload para la API const payload = { model: this.modelName, input: texts, input_type: this.inputType, encoding_format: this.encodingFormat, truncate: this.truncate, ...this.defaultOptions, }; // Opciones para la petición const requestOptions = { headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}`, }, }; // Implementación de backoff exponencial para reintentos let error = ""; for (let i = 0; i < this.maxRetries; i += 1) { try { const response = await axios.post(this.baseUrl, payload, requestOptions); return response.data.data.map((item) => item.embedding); } catch (err) { error = String(err); // Esperar antes de reintentar (backoff exponencial) const waitTime = 2 ** i * 1000 + Math.random() * 100; // eslint-disable-next-line no-await-in-loop await new Promise((resolve) => { setTimeout(resolve, waitTime); }); } } // Si llegamos aquí, todos los reintentos fallaron throw new Error(`Error al generar embeddings después de ${this.maxRetries} intentos: ${error}`); } /** * Generar embedding para un solo texto */ async embedQuery(text) { const embeddings = await this.embeddingWithRetry(text); return embeddings[0]; } /** * Generar embeddings para múltiples textos */ async embedDocuments(documents) { return this.embeddingWithRetry(documents); } } exports.NvidiaEmbeddings = NvidiaEmbeddings;