UNPKG

@oliverlessa/gemini-agent-lib

Version:

Uma biblioteca NodeJS para criar agentes de IA com Gemini LLM

100 lines (89 loc) 4.02 kB
const { PredictionServiceClient } = require('@google-cloud/aiplatform').v1; const { helpers } = require('@google-cloud/aiplatform'); // Helper para converter valores JS para protos /** * Classe para gerar embeddings usando a API Vertex AI. */ class VertexAIEmbeddingFunction { /** * Construtor da classe. * @param {Object} config - Configuração para a API Vertex AI. * @param {string} config.projectId - O ID do seu projeto Google Cloud. * @param {string} config.location - A localização da API (ex: 'us-central1'). * @param {string} config.modelId - O ID do modelo de embedding a ser usado (ex: 'textembedding-gecko@003'). * @param {string} [config.apiEndpoint] - (Opcional) O endpoint da API, se diferente do padrão. * @param {Object} [config.clientOptions] - (Opcional) Opções adicionais para o cliente gRPC. */ constructor({ projectId, location, modelId, apiEndpoint, clientOptions }) { if (!projectId || !location || !modelId) { throw new Error("projectId, location, e modelId são obrigatórios na configuração do VertexAIEmbeddingFunction."); } this.projectId = projectId; this.location = location; this.modelId = modelId; this.apiEndpoint = apiEndpoint || `${location}-aiplatform.googleapis.com`; this.client = new PredictionServiceClient({ apiEndpoint: this.apiEndpoint, ...clientOptions, }); this.endpoint = `projects/${this.projectId}/locations/${this.location}/publishers/google/models/${this.modelId}`; } /** * Gera embeddings para um array de textos (documentos). * @param {string[]} texts - Um array de strings para gerar embeddings. * @returns {Promise<number[][]>} Uma promessa que resolve com um array de embeddings (arrays de números). */ async embedDocuments(texts) { if (!Array.isArray(texts) || texts.length === 0) { return []; } // A API pode ter limites no número de instâncias por chamada, // pode ser necessário dividir em lotes (batches) se 'texts' for muito grande. // Para simplificação inicial, vamos assumir que cabe em uma chamada. const instances = texts.map(text => helpers.toValue({ content: text })); const parameters = helpers.toValue({ // Parâmetros específicos do modelo, se houver (ex: task_type) // autoTruncate: false // Exemplo }); const request = { endpoint: this.endpoint, instances: instances, parameters: parameters, }; try { const [response] = await this.client.predict(request); if (!response.predictions || response.predictions.length !== texts.length) { throw new Error('Resposta inválida da API de embeddings do Vertex AI.'); } // Extrai os embeddings da resposta const embeddings = response.predictions.map(predictionProto => { const prediction = helpers.fromValue(predictionProto); if (!prediction.embeddings || !prediction.embeddings.values) { console.error("Predição sem embeddings:", prediction); throw new Error('Formato inesperado na resposta de embeddings.'); } return prediction.embeddings.values; }); return embeddings; } catch (error) { console.error("Erro ao gerar embeddings de documentos no Vertex AI:", error); throw new Error(`Falha ao gerar embeddings de documentos: ${error.message}`); } } /** * Gera embedding para um único texto (consulta). * @param {string} text - O texto da consulta. * @returns {Promise<number[]>} Uma promessa que resolve com o embedding (array de números). */ async embedQuery(text) { if (!text) { throw new Error("Texto da consulta não pode ser vazio."); } // Reutiliza embedDocuments para uma única consulta const embeddings = await this.embedDocuments([text]); if (embeddings.length !== 1) { throw new Error("Falha ao gerar embedding para a consulta."); } return embeddings[0]; } } module.exports = VertexAIEmbeddingFunction;