fetchhistory changes
Deploy Node App / deploy (push) Successful in 10s

This commit is contained in:
Gitea
2026-06-03 11:17:02 +05:30
parent 03a8b87936
commit fe5a10d1fc
3 changed files with 315 additions and 7 deletions
+89
View File
@@ -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
};
+214 -5
View File
@@ -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
View File
@@ -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;