@@ -0,0 +1,89 @@
|
|||||||
|
const clickhouse = require('../database/clickhouse');
|
||||||
|
|
||||||
|
const fetchHistory = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { responseId } = req.body;
|
||||||
|
|
||||||
|
const rows = await clickhouse.query({
|
||||||
|
query: `
|
||||||
|
SELECT response_json
|
||||||
|
FROM userdetails.chat_history
|
||||||
|
WHERE response_id = {responseId:UInt64}
|
||||||
|
LIMIT 1
|
||||||
|
`,
|
||||||
|
query_params: {
|
||||||
|
responseId: Number(responseId)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await rows.json();
|
||||||
|
|
||||||
|
if (!result.data.length) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "History not found"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = JSON.parse(
|
||||||
|
result.data[0].response_json
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
data: response
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchUserHistory = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userId = req.user?.client_id || null;
|
||||||
|
|
||||||
|
const rows = await clickhouse.query({
|
||||||
|
query: `
|
||||||
|
SELECT
|
||||||
|
response_id,
|
||||||
|
prompt,
|
||||||
|
created_at
|
||||||
|
FROM userdetails.chat_history
|
||||||
|
WHERE user_id = {userId:UInt64}
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
`,
|
||||||
|
query_params: {
|
||||||
|
userId: Number(userId)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await rows.json();
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
totalRecords: result.data.length,
|
||||||
|
data: result.data
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
fetchHistory,
|
||||||
|
fetchUserHistory
|
||||||
|
};
|
||||||
@@ -2,6 +2,7 @@ const axios = require('axios');
|
|||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
const { OpenAI } = require('openai');
|
const { OpenAI } = require('openai');
|
||||||
const yaml = require('js-yaml');
|
const yaml = require('js-yaml');
|
||||||
|
const clickhouse = require('../database/clickhouse');
|
||||||
|
|
||||||
const azureEndpoint = "https://cpmindiayoda-resource.services.ai.azure.com";
|
const azureEndpoint = "https://cpmindiayoda-resource.services.ai.azure.com";
|
||||||
const deploymentName = "gpt-4o-mini";
|
const deploymentName = "gpt-4o-mini";
|
||||||
@@ -231,6 +232,7 @@ const fetchWrenData = async (prompt) => {
|
|||||||
{ threadId: createThread.id, data: { question: prompt, sql: wrenSql } }
|
{ threadId: createThread.id, data: { question: prompt, sql: wrenSql } }
|
||||||
);
|
);
|
||||||
console.log("Response ID =>", createThreadResponse.id);
|
console.log("Response ID =>", createThreadResponse.id);
|
||||||
|
const responseId = createThreadResponse.id;
|
||||||
|
|
||||||
// Step 5: Preview data
|
// Step 5: Preview data
|
||||||
const { previewData } = await gql("PreviewData",
|
const { previewData } = await gql("PreviewData",
|
||||||
@@ -247,6 +249,8 @@ const fetchWrenData = async (prompt) => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
console.log(`Done — ${rows.length} rows`);
|
console.log(`Done — ${rows.length} rows`);
|
||||||
console.table(rows);
|
console.table(rows);
|
||||||
|
|
||||||
@@ -258,6 +262,7 @@ const fetchWrenData = async (prompt) => {
|
|||||||
totalRows: rows.length,
|
totalRows: rows.length,
|
||||||
columns,
|
columns,
|
||||||
data: rows,
|
data: rows,
|
||||||
|
responseId
|
||||||
};
|
};
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -272,7 +277,6 @@ const fetchWrenData = async (prompt) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const generateVegaJson = async (queryResult) => {
|
const generateVegaJson = async (queryResult) => {
|
||||||
try {
|
try {
|
||||||
const systemPrompt = `You are a data visualization expert. I will provide a user's question and a JSON array of data. Your task is to generate a strictly valid Vega-Lite JSON specification to visualize this data. The data array will be provided to the Vega spec internally. Map the JSON keys to the correct x, y, and color axes. Choose the best chart type (bar,pai,line, arc) based on the question.`;
|
const systemPrompt = `You are a data visualization expert. I will provide a user's question and a JSON array of data. Your task is to generate a strictly valid Vega-Lite JSON specification to visualize this data. The data array will be provided to the Vega spec internally. Map the JSON keys to the correct x, y, and color axes. Choose the best chart type (bar,pai,line, arc) based on the question.`;
|
||||||
@@ -317,6 +321,8 @@ const ask = async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const { prompt } = req.body;
|
const { prompt } = req.body;
|
||||||
|
|
||||||
|
const userId = req.user?.client_id || null;
|
||||||
|
|
||||||
if (!prompt?.trim()) {
|
if (!prompt?.trim()) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
success: false,
|
success: false,
|
||||||
@@ -334,12 +340,32 @@ const ask = async (req, res) => {
|
|||||||
chart: result.prompt,
|
chart: result.prompt,
|
||||||
sql: result.sql
|
sql: result.sql
|
||||||
});
|
});
|
||||||
// console.log("Ask Result =>",vegaSpec);
|
|
||||||
return res.json({
|
const finalResponse = {
|
||||||
...result,
|
...result,
|
||||||
vegaSpec
|
vegaSpec
|
||||||
|
};
|
||||||
|
|
||||||
|
await clickhouse.insert({
|
||||||
|
table: "userdetails.chat_history",
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
user_id: userId,
|
||||||
|
response_id: result.responseId,
|
||||||
|
prompt: prompt,
|
||||||
|
response_json: JSON.stringify(finalResponse)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
format: "JSONEachRow"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return res.json(finalResponse);
|
||||||
|
|
||||||
|
// return res.json({
|
||||||
|
// ...result,
|
||||||
|
// vegaSpec
|
||||||
|
// });
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
@@ -381,11 +407,194 @@ const getSuggestedQuestions = async () => {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const suggestions = async (req, res) => {
|
const suggestions = async (req, res) => {
|
||||||
const questions = await getSuggestedQuestions();
|
const questions = await getSuggestedQuestions();
|
||||||
res.json({ success: true, questions });
|
res.json({ success: true, questions });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
const getThreadDetails = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { threadId } = req.body;
|
||||||
|
|
||||||
|
if (!threadId) {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: "threadId is required",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = `
|
||||||
|
query Thread($threadId: Int!) {
|
||||||
|
thread(threadId: $threadId) {
|
||||||
|
id
|
||||||
|
responses {
|
||||||
|
id
|
||||||
|
threadId
|
||||||
|
question
|
||||||
|
sql
|
||||||
|
|
||||||
|
answerDetail {
|
||||||
|
queryId
|
||||||
|
status
|
||||||
|
content
|
||||||
|
numRowsUsedInLLM
|
||||||
|
error {
|
||||||
|
code
|
||||||
|
shortMessage
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chartDetail {
|
||||||
|
queryId
|
||||||
|
status
|
||||||
|
description
|
||||||
|
chartType
|
||||||
|
chartSchema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const { thread } = await gql(
|
||||||
|
"Thread",
|
||||||
|
query,
|
||||||
|
{
|
||||||
|
threadId: Number(threadId),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!thread) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "Thread not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const latestResponse =
|
||||||
|
thread.responses?.[thread.responses.length - 1] || null;
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
threadId: thread.id,
|
||||||
|
totalResponses: thread.responses.length,
|
||||||
|
|
||||||
|
latestResponse: latestResponse
|
||||||
|
? {
|
||||||
|
responseId: latestResponse.id,
|
||||||
|
question: latestResponse.question,
|
||||||
|
sql: latestResponse.sql,
|
||||||
|
status: latestResponse.answerDetail?.status,
|
||||||
|
queryId: latestResponse.answerDetail?.queryId,
|
||||||
|
content: latestResponse.answerDetail?.content,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
|
||||||
|
responses: thread.responses.map(r => ({
|
||||||
|
responseId: r.id,
|
||||||
|
question: r.question,
|
||||||
|
status: r.answerDetail?.status,
|
||||||
|
queryId: r.answerDetail?.queryId,
|
||||||
|
content: r.answerDetail?.content,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: err.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getResponseDetails = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { responseId } = req.body;
|
||||||
|
|
||||||
|
if (!responseId) {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: "responseId is required",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = `
|
||||||
|
query ThreadResponse($responseId: Int!) {
|
||||||
|
threadResponse(responseId: $responseId) {
|
||||||
|
id
|
||||||
|
threadId
|
||||||
|
question
|
||||||
|
sql
|
||||||
|
|
||||||
|
answerDetail {
|
||||||
|
queryId
|
||||||
|
status
|
||||||
|
content
|
||||||
|
numRowsUsedInLLM
|
||||||
|
error {
|
||||||
|
code
|
||||||
|
shortMessage
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chartDetail {
|
||||||
|
queryId
|
||||||
|
status
|
||||||
|
description
|
||||||
|
chartType
|
||||||
|
chartSchema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const { threadResponse } = await gql(
|
||||||
|
"ThreadResponse",
|
||||||
|
query,
|
||||||
|
{
|
||||||
|
responseId: Number(responseId),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!threadResponse) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "Response not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
responseId: threadResponse.id,
|
||||||
|
threadId: threadResponse.threadId,
|
||||||
|
question: threadResponse.question,
|
||||||
|
sql: threadResponse.sql,
|
||||||
|
|
||||||
|
status: threadResponse.answerDetail?.status,
|
||||||
|
queryId: threadResponse.answerDetail?.queryId,
|
||||||
|
content: threadResponse.answerDetail?.content,
|
||||||
|
|
||||||
|
chartDetail: threadResponse.chartDetail || null,
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: err.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { ask, suggestions, getThreadDetails, getResponseDetails };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = { ask, suggestions };
|
|
||||||
|
|||||||
+12
-2
@@ -3,10 +3,20 @@ const router = express.Router();
|
|||||||
const loginUser = require('../controller/loginUser.js');
|
const loginUser = require('../controller/loginUser.js');
|
||||||
const authMiddleware = require('../middleware/authMiddleware.js');
|
const authMiddleware = require('../middleware/authMiddleware.js');
|
||||||
const handleOrchestration = require('../controller/handleOrchestration.js');
|
const handleOrchestration = require('../controller/handleOrchestration.js');
|
||||||
|
const fetchHistory = require('../controller/fetchhistory.js');
|
||||||
|
|
||||||
|
//*****************************loginUser****************************************************
|
||||||
router.post('/loginUser', loginUser.loginUser);
|
router.post('/loginUser', loginUser.loginUser);
|
||||||
// router.post('/handleOrchestration', authMiddleware, handleOrchestration.handleOrchestration);
|
|
||||||
router.post('/ask', handleOrchestration.ask);
|
//**********************************handleOrchestration******************************************** */
|
||||||
|
router.post('/ask',authMiddleware, handleOrchestration.ask);
|
||||||
router.get('/suggestions', handleOrchestration.suggestions);
|
router.get('/suggestions', handleOrchestration.suggestions);
|
||||||
|
router.get('/getThreadDetails', handleOrchestration.getThreadDetails);
|
||||||
|
router.get('/getResponseDetails', handleOrchestration.getResponseDetails);
|
||||||
|
|
||||||
|
|
||||||
|
//***********************************fetchHistory****************************************************
|
||||||
|
router.get('/fetchHistory', authMiddleware, fetchHistory.fetchHistory);
|
||||||
|
router.get('/fetchUserHistory', authMiddleware, fetchHistory.fetchUserHistory);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
Reference in New Issue
Block a user