agenticaichat 1.0.0 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -26
- package/bin/cli.js +301 -84
- package/dist/core/ChatbotEngine.d.ts +9 -1
- package/dist/core/ChatbotEngine.js +52 -19
- package/dist/core/EngineFactory.d.ts +45 -0
- package/dist/core/EngineFactory.js +126 -0
- package/dist/core/NLToSQLConverter.d.ts +6 -15
- package/dist/core/NLToSQLConverter.js +9 -114
- package/dist/engines/base/DatabaseEngine.d.ts +46 -0
- package/dist/engines/base/DatabaseEngine.js +42 -0
- package/dist/engines/nosql/MongoEngine.d.ts +13 -0
- package/dist/engines/nosql/MongoEngine.js +194 -0
- package/dist/engines/nosql/NoSqlEngine.d.ts +20 -0
- package/dist/engines/nosql/NoSqlEngine.js +29 -0
- package/dist/engines/sql/SqlEngine.d.ts +19 -0
- package/dist/engines/sql/SqlEngine.js +52 -0
- package/dist/engines/sql/dialects/MySQLDialect.d.ts +12 -0
- package/dist/engines/sql/dialects/MySQLDialect.js +109 -0
- package/dist/engines/sql/dialects/PostgresDialect.d.ts +11 -0
- package/dist/engines/sql/dialects/PostgresDialect.js +109 -0
- package/dist/engines/sql/dialects/SQLiteDialect.d.ts +10 -0
- package/dist/engines/sql/dialects/SQLiteDialect.js +101 -0
- package/dist/index.d.ts +17 -4
- package/dist/index.js +44 -8
- package/dist/llm/LLMFactory.d.ts +25 -0
- package/dist/llm/LLMFactory.js +137 -0
- package/dist/llm/providers/ClaudeProvider.d.ts +13 -0
- package/dist/llm/providers/ClaudeProvider.js +132 -0
- package/dist/llm/providers/DeepInfraProvider.d.ts +14 -0
- package/dist/llm/providers/DeepInfraProvider.js +144 -0
- package/dist/llm/providers/GeminiProvider.d.ts +13 -0
- package/dist/llm/providers/GeminiProvider.js +105 -0
- package/dist/llm/providers/GrokProvider.d.ts +14 -0
- package/dist/llm/providers/GrokProvider.js +144 -0
- package/dist/llm/providers/GroqProvider.d.ts +0 -0
- package/dist/llm/providers/GroqProvider.js +148 -0
- package/dist/llm/providers/OpenAIProvider.d.ts +13 -0
- package/dist/llm/providers/OpenAIProvider.js +136 -0
- package/dist/llm/providers/TogetherAIProvider.d.ts +14 -0
- package/dist/llm/providers/TogetherAIProvider.js +144 -0
- package/dist/llm/types.d.ts +34 -0
- package/dist/llm/types.js +2 -0
- package/dist/types/index.d.ts +23 -3
- package/dist/widget/ChatbotWidget.d.ts +1 -1
- package/dist/widget/ChatbotWidget.js +406 -125
- package/package.json +24 -5
- package/scripts/postinstall.js +126 -0
- package/templates/api-route.template.ts +24 -14
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GeminiProvider = void 0;
|
|
4
|
+
const generative_ai_1 = require("@google/generative-ai");
|
|
5
|
+
const logger_1 = require("../../utils/logger");
|
|
6
|
+
class GeminiProvider {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.configured = false;
|
|
9
|
+
if (!config.apiKey) {
|
|
10
|
+
logger_1.logger.error('Gemini API key is required');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
this.client = new generative_ai_1.GoogleGenerativeAI(config.apiKey);
|
|
14
|
+
this.model = config.model || 'gemini-1.5-pro';
|
|
15
|
+
this.configured = true;
|
|
16
|
+
logger_1.logger.info(`Gemini Provider initialized with model: ${this.model}`);
|
|
17
|
+
}
|
|
18
|
+
isConfigured() {
|
|
19
|
+
return this.configured;
|
|
20
|
+
}
|
|
21
|
+
async generateSQL(userQuery, schema) {
|
|
22
|
+
if (!this.configured) {
|
|
23
|
+
throw new Error('Gemini Provider not configured');
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
logger_1.logger.info('Generating SQL with Gemini...');
|
|
27
|
+
const model = this.client.getGenerativeModel({ model: this.model });
|
|
28
|
+
const schemaDescription = this.formatSchema(schema);
|
|
29
|
+
const prompt = this.buildSQLPrompt(userQuery, schemaDescription);
|
|
30
|
+
const result = await model.generateContent(prompt);
|
|
31
|
+
const response = await result.response;
|
|
32
|
+
const sqlQuery = response.text().trim();
|
|
33
|
+
// Remove markdown code blocks
|
|
34
|
+
const cleanedSQL = sqlQuery
|
|
35
|
+
.replace(/```sql\n?/g, '')
|
|
36
|
+
.replace(/```\n?/g, '')
|
|
37
|
+
.trim();
|
|
38
|
+
logger_1.logger.debug_log('Generated SQL:', cleanedSQL);
|
|
39
|
+
return cleanedSQL;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
logger_1.logger.error('Gemini SQL generation failed', error);
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async generateHumanResponse(userQuery, queryResult) {
|
|
47
|
+
if (!this.configured) {
|
|
48
|
+
throw new Error('Gemini Provider not configured');
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
logger_1.logger.info('Generating human response with Gemini...');
|
|
52
|
+
const model = this.client.getGenerativeModel({ model: this.model });
|
|
53
|
+
const prompt = `
|
|
54
|
+
User asked: "${userQuery}"
|
|
55
|
+
|
|
56
|
+
Database returned this result:
|
|
57
|
+
${JSON.stringify(queryResult, null, 2)}
|
|
58
|
+
|
|
59
|
+
Please provide a clear, conversational answer in Hindi/English mix (Hinglish) that explains this data to a business owner. Be specific with numbers.
|
|
60
|
+
`;
|
|
61
|
+
const result = await model.generateContent(prompt);
|
|
62
|
+
const response = await result.response;
|
|
63
|
+
const answer = response.text().trim() || 'Sorry, I could not generate a response.';
|
|
64
|
+
logger_1.logger.debug_log('Generated response:', answer);
|
|
65
|
+
return answer;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
logger_1.logger.error('Gemini response generation failed', error);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
buildSQLPrompt(userQuery, schemaDescription) {
|
|
73
|
+
return `
|
|
74
|
+
You are a SQL expert. Generate a SQL query based on the user's question.
|
|
75
|
+
|
|
76
|
+
Database Schema:
|
|
77
|
+
${schemaDescription}
|
|
78
|
+
|
|
79
|
+
User Question: "${userQuery}"
|
|
80
|
+
|
|
81
|
+
Rules:
|
|
82
|
+
1. Return ONLY the SQL query, nothing else
|
|
83
|
+
2. Use correct table and column names from the schema
|
|
84
|
+
3. Add WHERE clauses for date filtering when needed
|
|
85
|
+
4. Use SUM, COUNT, AVG for aggregations
|
|
86
|
+
5. Handle both singular and plural forms
|
|
87
|
+
6. Use CURRENT_DATE for time-based queries
|
|
88
|
+
7. Make sure the query is syntactically correct
|
|
89
|
+
|
|
90
|
+
SQL Query:
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
93
|
+
formatSchema(schema) {
|
|
94
|
+
let description = '';
|
|
95
|
+
for (const table of schema.tables) {
|
|
96
|
+
description += `\nTable: ${table.name}\n`;
|
|
97
|
+
description += 'Columns:\n';
|
|
98
|
+
for (const column of table.columns) {
|
|
99
|
+
description += ` - ${column.name} (${column.type})${column.nullable ? ' [nullable]' : ''}\n`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return description;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.GeminiProvider = GeminiProvider;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ILLMProvider, GrokProviderConfig } from '../types';
|
|
2
|
+
import { DatabaseSchema } from '../../types';
|
|
3
|
+
export declare class GrokProvider implements ILLMProvider {
|
|
4
|
+
private apiKey;
|
|
5
|
+
private model;
|
|
6
|
+
private configured;
|
|
7
|
+
private baseURL;
|
|
8
|
+
constructor(config: GrokProviderConfig);
|
|
9
|
+
isConfigured(): boolean;
|
|
10
|
+
generateSQL(userQuery: string, schema: DatabaseSchema): Promise<string>;
|
|
11
|
+
generateHumanResponse(userQuery: string, queryResult: any): Promise<string>;
|
|
12
|
+
private buildSQLPrompt;
|
|
13
|
+
private formatSchema;
|
|
14
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GrokProvider = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const logger_1 = require("../../utils/logger");
|
|
9
|
+
class GrokProvider {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.configured = false;
|
|
12
|
+
this.baseURL = 'https://api.x.ai/v1';
|
|
13
|
+
if (!config.apiKey) {
|
|
14
|
+
logger_1.logger.error('Grok API key is required');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
this.apiKey = config.apiKey;
|
|
18
|
+
this.model = config.model || 'grok-beta';
|
|
19
|
+
this.configured = true;
|
|
20
|
+
logger_1.logger.info(`Grok Provider initialized with model: ${this.model}`);
|
|
21
|
+
}
|
|
22
|
+
isConfigured() {
|
|
23
|
+
return this.configured;
|
|
24
|
+
}
|
|
25
|
+
async generateSQL(userQuery, schema) {
|
|
26
|
+
if (!this.configured) {
|
|
27
|
+
throw new Error('Grok Provider not configured');
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
logger_1.logger.info('Generating SQL with Grok...');
|
|
31
|
+
const schemaDescription = this.formatSchema(schema);
|
|
32
|
+
const prompt = this.buildSQLPrompt(userQuery, schemaDescription);
|
|
33
|
+
const response = await axios_1.default.post(`${this.baseURL}/chat/completions`, {
|
|
34
|
+
model: this.model,
|
|
35
|
+
messages: [
|
|
36
|
+
{
|
|
37
|
+
role: 'system',
|
|
38
|
+
content: 'You are an expert SQL query generator. Generate ONLY valid SQL queries without any explanation or markdown.'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
role: 'user',
|
|
42
|
+
content: prompt
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
temperature: 0.2,
|
|
46
|
+
max_tokens: 500
|
|
47
|
+
}, {
|
|
48
|
+
headers: {
|
|
49
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
50
|
+
'Content-Type': 'application/json'
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const sqlQuery = response.data.choices[0]?.message?.content?.trim() || '';
|
|
54
|
+
// Remove markdown code blocks
|
|
55
|
+
const cleanedSQL = sqlQuery
|
|
56
|
+
.replace(/```sql\n?/g, '')
|
|
57
|
+
.replace(/```\n?/g, '')
|
|
58
|
+
.trim();
|
|
59
|
+
logger_1.logger.debug_log('Generated SQL:', cleanedSQL);
|
|
60
|
+
return cleanedSQL;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
logger_1.logger.error('Grok SQL generation failed', error);
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async generateHumanResponse(userQuery, queryResult) {
|
|
68
|
+
if (!this.configured) {
|
|
69
|
+
throw new Error('Grok Provider not configured');
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
logger_1.logger.info('Generating human response with Grok...');
|
|
73
|
+
const prompt = `
|
|
74
|
+
User asked: "${userQuery}"
|
|
75
|
+
|
|
76
|
+
Database returned this result:
|
|
77
|
+
${JSON.stringify(queryResult, null, 2)}
|
|
78
|
+
|
|
79
|
+
Please provide a clear, conversational answer in Hindi/English mix (Hinglish) that explains this data to a business owner. Be specific with numbers.
|
|
80
|
+
`;
|
|
81
|
+
const response = await axios_1.default.post(`${this.baseURL}/chat/completions`, {
|
|
82
|
+
model: this.model,
|
|
83
|
+
messages: [
|
|
84
|
+
{
|
|
85
|
+
role: 'system',
|
|
86
|
+
content: 'You are a helpful business analytics assistant. Explain data clearly in Hinglish (Hindi-English mix).'
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
role: 'user',
|
|
90
|
+
content: prompt
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
temperature: 0.7,
|
|
94
|
+
max_tokens: 300
|
|
95
|
+
}, {
|
|
96
|
+
headers: {
|
|
97
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
98
|
+
'Content-Type': 'application/json'
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
const answer = response.data.choices[0]?.message?.content?.trim() ||
|
|
102
|
+
'Sorry, I could not generate a response.';
|
|
103
|
+
logger_1.logger.debug_log('Generated response:', answer);
|
|
104
|
+
return answer;
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
logger_1.logger.error('Grok response generation failed', error);
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
buildSQLPrompt(userQuery, schemaDescription) {
|
|
112
|
+
return `
|
|
113
|
+
You are a SQL expert. Generate a SQL query based on the user's question.
|
|
114
|
+
|
|
115
|
+
Database Schema:
|
|
116
|
+
${schemaDescription}
|
|
117
|
+
|
|
118
|
+
User Question: "${userQuery}"
|
|
119
|
+
|
|
120
|
+
Rules:
|
|
121
|
+
1. Return ONLY the SQL query, nothing else
|
|
122
|
+
2. Use correct table and column names from the schema
|
|
123
|
+
3. Add WHERE clauses for date filtering when needed
|
|
124
|
+
4. Use SUM, COUNT, AVG for aggregations
|
|
125
|
+
5. Handle both singular and plural forms
|
|
126
|
+
6. Use CURRENT_DATE for time-based queries
|
|
127
|
+
7. Make sure the query is syntactically correct
|
|
128
|
+
|
|
129
|
+
SQL Query:
|
|
130
|
+
`;
|
|
131
|
+
}
|
|
132
|
+
formatSchema(schema) {
|
|
133
|
+
let description = '';
|
|
134
|
+
for (const table of schema.tables) {
|
|
135
|
+
description += `\nTable: ${table.name}\n`;
|
|
136
|
+
description += 'Columns:\n';
|
|
137
|
+
for (const column of table.columns) {
|
|
138
|
+
description += ` - ${column.name} (${column.type})${column.nullable ? ' [nullable]' : ''}\n`;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return description;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
exports.GrokProvider = GrokProvider;
|
|
File without changes
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// import axios from 'axios';
|
|
3
|
+
// import { ILLMProvider, GroqProviderConfig } from '../types';
|
|
4
|
+
// import { DatabaseSchema } from '../../types';
|
|
5
|
+
// import { logger } from '../../utils/logger';
|
|
6
|
+
// export class GroqProvider implements ILLMProvider {
|
|
7
|
+
// private apiKey: string;
|
|
8
|
+
// private model: string;
|
|
9
|
+
// private configured: boolean = false;
|
|
10
|
+
// private baseURL: string = 'https://api.groq.com/openai/v1';
|
|
11
|
+
// constructor(config: GroqProviderConfig) {
|
|
12
|
+
// if (!config.apiKey) {
|
|
13
|
+
// logger.error('Groq API key is required');
|
|
14
|
+
// return;
|
|
15
|
+
// }
|
|
16
|
+
// this.apiKey = config.apiKey;
|
|
17
|
+
// this.model = config.model || 'llama3-70b-8192';
|
|
18
|
+
// this.configured = true;
|
|
19
|
+
// logger.info(`Groq Provider initialized with model: ${this.model}`);
|
|
20
|
+
// }
|
|
21
|
+
// isConfigured(): boolean {
|
|
22
|
+
// return this.configured;
|
|
23
|
+
// }
|
|
24
|
+
// async generateSQL(
|
|
25
|
+
// userQuery: string,
|
|
26
|
+
// schema: DatabaseSchema
|
|
27
|
+
// ): Promise<string> {
|
|
28
|
+
// if (!this.configured) {
|
|
29
|
+
// throw new Error('Groq Provider not configured');
|
|
30
|
+
// }
|
|
31
|
+
// try {
|
|
32
|
+
// logger.info('Generating SQL with Groq...');
|
|
33
|
+
// const schemaDescription = this.formatSchema(schema);
|
|
34
|
+
// const prompt = this.buildSQLPrompt(userQuery, schemaDescription);
|
|
35
|
+
// const response = await axios.post(
|
|
36
|
+
// `${this.baseURL}/chat/completions`,
|
|
37
|
+
// {
|
|
38
|
+
// model: this.model,
|
|
39
|
+
// messages: [
|
|
40
|
+
// {
|
|
41
|
+
// role: 'system',
|
|
42
|
+
// content: 'You are an expert SQL query generator. Generate ONLY valid SQL queries without any explanation or markdown.'
|
|
43
|
+
// },
|
|
44
|
+
// {
|
|
45
|
+
// role: 'user',
|
|
46
|
+
// content: prompt
|
|
47
|
+
// }
|
|
48
|
+
// ],
|
|
49
|
+
// temperature: 0.2,
|
|
50
|
+
// max_tokens: 500
|
|
51
|
+
// },
|
|
52
|
+
// {
|
|
53
|
+
// headers: {
|
|
54
|
+
// 'Authorization': `Bearer ${this.apiKey}`,
|
|
55
|
+
// 'Content-Type': 'application/json'
|
|
56
|
+
// }
|
|
57
|
+
// }
|
|
58
|
+
// );
|
|
59
|
+
// const sqlQuery = response.data.choices[0]?.message?.content?.trim() || '';
|
|
60
|
+
// // Remove markdown code blocks
|
|
61
|
+
// const cleanedSQL = sqlQuery
|
|
62
|
+
// .replace(/```sql\n?/g, '')
|
|
63
|
+
// .replace(/```\n?/g, '')
|
|
64
|
+
// .trim();
|
|
65
|
+
// logger.debug_log('Generated SQL:', cleanedSQL);
|
|
66
|
+
// return cleanedSQL;
|
|
67
|
+
// } catch (error) {
|
|
68
|
+
// logger.error('Groq SQL generation failed', error as Error);
|
|
69
|
+
// throw error;
|
|
70
|
+
// }
|
|
71
|
+
// }
|
|
72
|
+
// async generateHumanResponse(
|
|
73
|
+
// userQuery: string,
|
|
74
|
+
// queryResult: any
|
|
75
|
+
// ): Promise<string> {
|
|
76
|
+
// if (!this.configured) {
|
|
77
|
+
// throw new Error('Groq Provider not configured');
|
|
78
|
+
// }
|
|
79
|
+
// try {
|
|
80
|
+
// logger.info('Generating human response with Groq...');
|
|
81
|
+
// const prompt = `
|
|
82
|
+
// User asked: "${userQuery}"
|
|
83
|
+
// Database returned this result:
|
|
84
|
+
// ${JSON.stringify(queryResult, null, 2)}
|
|
85
|
+
// Please provide a clear, conversational answer in Hindi/English mix (Hinglish) that explains this data to a business owner. Be specific with numbers.
|
|
86
|
+
// `;
|
|
87
|
+
// const response = await axios.post(
|
|
88
|
+
// `${this.baseURL}/chat/completions`,
|
|
89
|
+
// {
|
|
90
|
+
// model: this.model,
|
|
91
|
+
// messages: [
|
|
92
|
+
// {
|
|
93
|
+
// role: 'system',
|
|
94
|
+
// content: 'You are a helpful business analytics assistant. Explain data clearly in Hinglish (Hindi-English mix).'
|
|
95
|
+
// },
|
|
96
|
+
// {
|
|
97
|
+
// role: 'user',
|
|
98
|
+
// content: prompt
|
|
99
|
+
// }
|
|
100
|
+
// ],
|
|
101
|
+
// temperature: 0.7,
|
|
102
|
+
// max_tokens: 300
|
|
103
|
+
// },
|
|
104
|
+
// {
|
|
105
|
+
// headers: {
|
|
106
|
+
// 'Authorization': `Bearer ${this.apiKey}`,
|
|
107
|
+
// 'Content-Type': 'application/json'
|
|
108
|
+
// }
|
|
109
|
+
// }
|
|
110
|
+
// );
|
|
111
|
+
// const answer = response.data.choices[0]?.message?.content?.trim() ||
|
|
112
|
+
// 'Sorry, I could not generate a response.';
|
|
113
|
+
// logger.debug_log('Generated response:', answer);
|
|
114
|
+
// return answer;
|
|
115
|
+
// } catch (error) {
|
|
116
|
+
// logger.error('Groq response generation failed', error as Error);
|
|
117
|
+
// throw error;
|
|
118
|
+
// }
|
|
119
|
+
// }
|
|
120
|
+
// private buildSQLPrompt(userQuery: string, schemaDescription: string): string {
|
|
121
|
+
// return `
|
|
122
|
+
// You are a SQL expert. Generate a SQL query based on the user's question.
|
|
123
|
+
// Database Schema:
|
|
124
|
+
// ${schemaDescription}
|
|
125
|
+
// User Question: "${userQuery}"
|
|
126
|
+
// Rules:
|
|
127
|
+
// 1. Return ONLY the SQL query, nothing else
|
|
128
|
+
// 2. Use correct table and column names from the schema
|
|
129
|
+
// 3. Add WHERE clauses for date filtering when needed
|
|
130
|
+
// 4. Use SUM, COUNT, AVG for aggregations
|
|
131
|
+
// 5. Handle both singular and plural forms
|
|
132
|
+
// 6. Use CURRENT_DATE for time-based queries
|
|
133
|
+
// 7. Make sure the query is syntactically correct
|
|
134
|
+
// SQL Query:
|
|
135
|
+
// `;
|
|
136
|
+
// }
|
|
137
|
+
// private formatSchema(schema: DatabaseSchema): string {
|
|
138
|
+
// let description = '';
|
|
139
|
+
// for (const table of schema.tables) {
|
|
140
|
+
// description += `\nTable: ${table.name}\n`;
|
|
141
|
+
// description += 'Columns:\n';
|
|
142
|
+
// for (const column of table.columns) {
|
|
143
|
+
// description += ` - ${column.name} (${column.type})${column.nullable ? ' [nullable]' : ''}\n`;
|
|
144
|
+
// }
|
|
145
|
+
// }
|
|
146
|
+
// return description;
|
|
147
|
+
// }
|
|
148
|
+
// }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ILLMProvider, OpenAIProviderConfig } from '../types';
|
|
2
|
+
import { DatabaseSchema } from '../../types';
|
|
3
|
+
export declare class OpenAIProvider implements ILLMProvider {
|
|
4
|
+
private client;
|
|
5
|
+
private model;
|
|
6
|
+
private configured;
|
|
7
|
+
constructor(config: OpenAIProviderConfig);
|
|
8
|
+
isConfigured(): boolean;
|
|
9
|
+
generateSQL(userQuery: string, schema: DatabaseSchema): Promise<string>;
|
|
10
|
+
generateHumanResponse(userQuery: string, queryResult: any): Promise<string>;
|
|
11
|
+
private buildSQLPrompt;
|
|
12
|
+
private formatSchema;
|
|
13
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.OpenAIProvider = void 0;
|
|
7
|
+
const openai_1 = __importDefault(require("openai"));
|
|
8
|
+
const logger_1 = require("../../utils/logger");
|
|
9
|
+
class OpenAIProvider {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.configured = false;
|
|
12
|
+
if (!config.apiKey) {
|
|
13
|
+
logger_1.logger.error('OpenAI API key is required');
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
this.client = new openai_1.default({
|
|
17
|
+
apiKey: config.apiKey,
|
|
18
|
+
organization: config.organization
|
|
19
|
+
});
|
|
20
|
+
this.model = config.model || 'gpt-3.5-turbo';
|
|
21
|
+
this.configured = true;
|
|
22
|
+
logger_1.logger.info(`OpenAI Provider initialized with model: ${this.model}`);
|
|
23
|
+
}
|
|
24
|
+
isConfigured() {
|
|
25
|
+
return this.configured;
|
|
26
|
+
}
|
|
27
|
+
async generateSQL(userQuery, schema) {
|
|
28
|
+
if (!this.configured) {
|
|
29
|
+
throw new Error('OpenAI Provider not configured');
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
logger_1.logger.info('Generating SQL with OpenAI...');
|
|
33
|
+
const schemaDescription = this.formatSchema(schema);
|
|
34
|
+
const prompt = this.buildSQLPrompt(userQuery, schemaDescription);
|
|
35
|
+
const response = await this.client.chat.completions.create({
|
|
36
|
+
model: this.model,
|
|
37
|
+
messages: [
|
|
38
|
+
{
|
|
39
|
+
role: 'system',
|
|
40
|
+
content: 'You are an expert SQL query generator. Generate ONLY valid SQL queries without any explanation or markdown.'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
role: 'user',
|
|
44
|
+
content: prompt
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
temperature: 0.2,
|
|
48
|
+
max_tokens: 500
|
|
49
|
+
});
|
|
50
|
+
const sqlQuery = response.choices[0]?.message?.content?.trim() || '';
|
|
51
|
+
// Remove markdown code blocks if present
|
|
52
|
+
const cleanedSQL = sqlQuery
|
|
53
|
+
.replace(/```sql\n?/g, '')
|
|
54
|
+
.replace(/```\n?/g, '')
|
|
55
|
+
.trim();
|
|
56
|
+
logger_1.logger.debug_log('Generated SQL:', cleanedSQL);
|
|
57
|
+
return cleanedSQL;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
logger_1.logger.error('OpenAI SQL generation failed', error);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async generateHumanResponse(userQuery, queryResult) {
|
|
65
|
+
if (!this.configured) {
|
|
66
|
+
throw new Error('OpenAI Provider not configured');
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
logger_1.logger.info('Generating human response with OpenAI...');
|
|
70
|
+
const prompt = `
|
|
71
|
+
User asked: "${userQuery}"
|
|
72
|
+
|
|
73
|
+
Database returned this result:
|
|
74
|
+
${JSON.stringify(queryResult, null, 2)}
|
|
75
|
+
|
|
76
|
+
Please provide a clear, conversational answer in Hindi/English mix (Hinglish) that explains this data to a business owner. Be specific with numbers.
|
|
77
|
+
`;
|
|
78
|
+
const response = await this.client.chat.completions.create({
|
|
79
|
+
model: this.model,
|
|
80
|
+
messages: [
|
|
81
|
+
{
|
|
82
|
+
role: 'system',
|
|
83
|
+
content: 'You are a helpful business analytics assistant. Explain data clearly in Hinglish (Hindi-English mix).'
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
role: 'user',
|
|
87
|
+
content: prompt
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
temperature: 0.7,
|
|
91
|
+
max_tokens: 300
|
|
92
|
+
});
|
|
93
|
+
const answer = response.choices[0]?.message?.content?.trim() ||
|
|
94
|
+
'Sorry, I could not generate a response.';
|
|
95
|
+
logger_1.logger.debug_log('Generated response:', answer);
|
|
96
|
+
return answer;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
logger_1.logger.error('OpenAI response generation failed', error);
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
buildSQLPrompt(userQuery, schemaDescription) {
|
|
104
|
+
return `
|
|
105
|
+
You are a SQL expert. Generate a SQL query based on the user's question.
|
|
106
|
+
|
|
107
|
+
Database Schema:
|
|
108
|
+
${schemaDescription}
|
|
109
|
+
|
|
110
|
+
User Question: "${userQuery}"
|
|
111
|
+
|
|
112
|
+
Rules:
|
|
113
|
+
1. Return ONLY the SQL query, nothing else
|
|
114
|
+
2. Use correct table and column names from the schema
|
|
115
|
+
3. Add WHERE clauses for date filtering when needed
|
|
116
|
+
4. Use SUM, COUNT, AVG for aggregations
|
|
117
|
+
5. Handle both singular and plural forms (sales/sale, orders/order)
|
|
118
|
+
6. Use CURRENT_DATE, CURRENT_MONTH for time-based queries
|
|
119
|
+
7. Make sure the query is syntactically correct
|
|
120
|
+
|
|
121
|
+
SQL Query:
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
formatSchema(schema) {
|
|
125
|
+
let description = '';
|
|
126
|
+
for (const table of schema.tables) {
|
|
127
|
+
description += `\nTable: ${table.name}\n`;
|
|
128
|
+
description += 'Columns:\n';
|
|
129
|
+
for (const column of table.columns) {
|
|
130
|
+
description += ` - ${column.name} (${column.type})${column.nullable ? ' [nullable]' : ''}\n`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return description;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.OpenAIProvider = OpenAIProvider;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ILLMProvider, TogetherAIProviderConfig } from '../types';
|
|
2
|
+
import { DatabaseSchema } from '../../types';
|
|
3
|
+
export declare class TogetherAIProvider implements ILLMProvider {
|
|
4
|
+
private apiKey;
|
|
5
|
+
private model;
|
|
6
|
+
private configured;
|
|
7
|
+
private baseURL;
|
|
8
|
+
constructor(config: TogetherAIProviderConfig);
|
|
9
|
+
isConfigured(): boolean;
|
|
10
|
+
generateSQL(userQuery: string, schema: DatabaseSchema): Promise<string>;
|
|
11
|
+
generateHumanResponse(userQuery: string, queryResult: any): Promise<string>;
|
|
12
|
+
private buildSQLPrompt;
|
|
13
|
+
private formatSchema;
|
|
14
|
+
}
|