saksh-wallet
Version:
A Node.js library for managing user wallets, including functionalities for crediting, debiting, and converting currencies, as well as retrieving balances and transaction reports.
163 lines (138 loc) • 6.53 kB
JavaScript
const EventEmitter = require('events');
const mongoose = require('mongoose');
const Transaction = require('./models/Transaction');
const WalletUser = require('./models/WalletUser');
const RecurringPayment = require('./models/RecurringPayment');
const { Configuration, OpenAIApi } = require('openai');
class SakshAIReporting extends EventEmitter {
constructor(userModel = WalletUser, transactionModel = Transaction) {
super();
this.User = userModel;
this.Transaction = transactionModel;
}
/**
* Set the Gemini AI key and initialize OpenAI configuration.
* @param {String} gemini_ai_key - The API key for Gemini AI.
* @param {String} aimodel - The AI model to use.
* @param {Number} max_tokens - The maximum number of tokens for the AI response.
*/
async sakshGeminiAIKey(gemini_ai_key, aimodel, max_tokens) {
const configuration = new Configuration({
gemini_ai_key
});
this.aimodel = aimodel;
this.max_tokens = max_tokens;
this.openai = new OpenAIApi(configuration);
this.emit('aiKeySet', { gemini_ai_key, aimodel, max_tokens });
}
/**
* Generate a summary for the given transactions using OpenAI.
* @param {Array} transactions - List of transactions to summarize.
* @returns {String} - The generated summary.
*/
async sakshGenerateReportSummary(transactions) {
const transactionDetails = transactions.map(tx => {
return `On ${tx.date.toDateString()}, ${tx.type} of ${tx.amount} ${tx.currency} for ${tx.description}.`;
}).join(' ');
const prompt = `Generate a summary for the following transactions: ${transactionDetails}`;
const response = await this.openai.createCompletion({
model: this.aimodel,
prompt: prompt,
max_tokens: this.max_tokens,
});
const summary = response.data.choices[0].text.trim();
this.emit('reportSummaryGenerated', { transactions, summary });
return summary;
}
/**
* Handle user query by generating and executing a MongoDB query.
* @param {String} query - The user's query.
* @returns {Object} - The query result and summary.
*/
async sakshHandleUserQuery(query) {
const prompt = `You are an AI assistant. The user asked: "${query}". Based on the user's query, generate a MongoDB query to fetch the relevant data from the database.`;
const response = await this.openai.createCompletion({
model: this.aimodel,
prompt: prompt,
max_tokens: this.max_tokens,
});
const mongoQuery = response.data.choices[0].text.trim();
// Execute the generated MongoDB query
let result;
try {
result = await eval(mongoQuery); // Be cautious with eval
} catch (error) {
this.emit('queryExecutionFailed', { query, error });
throw new Error('Failed to execute MongoDB query: ' + error.message);
}
// Generate a summary of the results
const summary = await this.sakshGenerateReportSummary(result);
// Emit an event with the results and summary
this.emit('userQueryHandled', { query, mongoQuery, result, summary });
// Return the results and summary in JSON format
return {
query: query,
mongoQuery: mongoQuery,
result: result,
summary: summary
};
}
/**
* Generate a report based on the given prompt and user ID.
* @param {String} prompt - The user's prompt.
* @param {String} userId - The ID of the user.
* @returns {String} - The generated report.
*/
async sakshGenerateReport(prompt, userId) {
let data;
try {
const aggregationPipeline = [];
aggregationPipeline.push({ $match: { userId } });
if (prompt.includes('balance')) {
// No additional filtering needed for balance
} else if (prompt.includes('transaction')) {
// Add filtering for specific transactions (optional)
} else if (prompt.includes('monthly transaction') || prompt.includes('daily transaction')) {
const dateMatch = prompt.match(/\d+/g);
if (!dateMatch) {
throw new Error('Invalid prompt format for date-based reports.');
}
let startDate, endDate;
if (prompt.includes('monthly')) {
startDate = new Date(dateMatch[0], dateMatch[1] - 1, 1);
endDate = new Date(dateMatch[0], dateMatch[1], 0, 23, 59, 59, 999);
} else { // Daily
startDate = new Date(dateMatch[0]);
startDate.setHours(0, 0, 0, 0);
endDate = new Date(dateMatch[0]);
endDate.setHours(23, 59, 59, 999);
}
aggregationPipeline.push({ $match: { date: { $gte: startDate, $lte: endDate } } });
} else if (prompt.includes('budget')) {
// Add filtering for specific categories (optional)
} else {
return 'Invalid prompt. Please specify "balance", "transaction", "monthly transaction", "daily transaction", or "budget".';
}
data = await this.User.aggregate(aggregationPipeline);
} catch (error) {
console.error('Error fetching data:', error);
this.emit('dataFetchFailed', { prompt, userId, error });
return 'Failed to generate report.';
}
const formattedData = JSON.stringify(data);
try {
const response = await this.openai.createCompletion({
model: this.aimodel,
prompt: `Generate a comprehensive report based on the following data:\n${formattedData}`,
});
const report = response.data.choices[0].text;
this.emit('reportGenerated', { prompt, userId, report });
return report;
} catch (error) {
console.error('Error generating report:', error);
this.emit('reportGenerationFailed', { prompt, userId, error });
return 'Failed to generate report.';
}
}
}
module.exports = SakshAIReporting;