From 6a498bfddb1187148462d9d176dc160be3a90b0a Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 18:45:22 +0800 Subject: [PATCH 1/8] Update env to include llm api key --- .env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.example b/.env.example index 84102d4..4696c76 100644 --- a/.env.example +++ b/.env.example @@ -4,3 +4,4 @@ DATABASE_PORT=5432 DATABASE_NAME=your_database_name DATABASE_USER=your_database_user DATABASE_PASSWORD=your_database_password +LLM_API_KEY=your_llm_api_key From 7463f10f812255fa26b63b26c3fc9b1240b43551 Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 19:46:10 +0800 Subject: [PATCH 2/8] Add endpoint for chatbot --- package-lock.json | 132 +++++++++++++++++++++++++++++++++++++ package.json | 1 + routes/chatbot.js | 162 ++++++++++++++++++++++++++++++++++++++++++++++ server.js | 2 + 4 files changed, 297 insertions(+) create mode 100644 routes/chatbot.js diff --git a/package-lock.json b/package-lock.json index b3c8582..2361cb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "axios": "^1.10.0", "bcrypt": "^6.0.0", "cookie-parser": "^1.4.7", "dotenv": "^16.5.0", @@ -1228,6 +1229,23 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -1651,6 +1669,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1823,6 +1853,15 @@ "node": ">=0.10.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1960,6 +1999,21 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2162,6 +2216,63 @@ "node": ">=8" } }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2364,6 +2475,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -4061,6 +4187,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", diff --git a/package.json b/package.json index 6018c52..22764fd 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "jest": "^29.7.0" }, "dependencies": { + "axios": "^1.10.0", "bcrypt": "^6.0.0", "cookie-parser": "^1.4.7", "dotenv": "^16.5.0", diff --git a/routes/chatbot.js b/routes/chatbot.js new file mode 100644 index 0000000..06a7a63 --- /dev/null +++ b/routes/chatbot.js @@ -0,0 +1,162 @@ +const express = require("express"); +const pool = require("../database/db"); +const router = express.Router(); + +function getAuthUser(req) { + const { auth } = req.cookies; + if (!auth) return null; + try { + return JSON.parse(auth); + } catch { + return null; + } +} + +const axios = require("axios"); +const GROQ_API_KEY = process.env.LLM_API_KEY; + +async function callLLM(context) { + const systemPrompt = ` + You are a technical course assistant for an online platform. + Use the course/module/skills context provided to answer user questions using your expertise, + as if you are an instructor on that module. Do not mention that you lack material access. + Do not mention "Since we are in this particular course", just answer the question directly. + Answer the question as if you are directly talking to the student. + If unsure, give your best expert guess based on course/module metadata and tags. Keep your answers concise and focused on the question. + If the question is not related to the course/module, politely redirect them to the appropriate support + `; + + const messages = [ + { role: "system", content: systemPrompt }, + { role: "user", content: JSON.stringify(context, null, 2) }, + { role: "user", content: context.question }, + ]; + + const resp = await axios.post( + "https://api.groq.com/openai/v1/chat/completions", + { + model: "llama3-70b-8192", + messages, + temperature: 0.3, + max_tokens: 512, + }, + { + headers: { + Authorization: `Bearer ${GROQ_API_KEY}`, + "Content-Type": "application/json", + }, + } + ); + + return resp.data.choices[0].message.content; +} + +router.post("/ask", async (req, res) => { + const user = getAuthUser(req); + if (!user || !user.isLoggedIn) { + return res.status(401).json({ message: "Not logged in" }); + } + + const { courseId, moduleId, question } = req.body; + if (!courseId || !moduleId) { + return res + .status(400) + .json({ message: "Course and module IDs are required" }); + } + if (!question || question.trim() === "") { + return res.status(400).json({ message: "Question is required" }); + } + + const client = await pool.connect(); + const courseRes = await client.query( + `SELECT name, description + FROM courses + WHERE id = $1`, + [courseId] + ); + const course = courseRes.rows[0]; + const moduleRes = await client.query( + `SELECT title, description + FROM modules + WHERE id = $1`, + [moduleId] + ); + const module = moduleRes.rows[0]; + + const courseSkillsRes = await client.query( + `SELECT s.id, s.name, s.description + FROM module_skills ms + JOIN skills s ON s.id = ms.skill_id + WHERE ms.module_id = $1`, + [moduleId] + ); + const courseSkills = + courseSkillsRes.rows.map((skill) => ({ + id: skill.id, + name: skill.name, + description: skill.description, + })) || []; + const channelRes = await client.query( + `SELECT c.id, c.name, c.description + FROM course_channels cc + JOIN channels c ON c.id = cc.channel_id + WHERE cc.course_id = $1`, + [courseId] + ); + const channel = channelRes.rows[0] || { + id: null, + name: "No channel", + description: "", + }; + + const levelRes = await client.query( + `SELECT l.id, l.name, l.description, l.sort_order + FROM course_channels cc + JOIN levels l ON l.id = cc.level_id + WHERE cc.course_id = $1`, + [courseId] + ); + const level = levelRes.rows[0] || { + id: null, + name: "No level", + description: "", + sort_order: 0, + }; + + await client.release(); + + try { + const context = { + course_name: course.name, + course_description: course.description, + module_name: module.title, + module_description: module.description, + channel: { + id: channel.id, + name: channel.name, + description: channel.description, + }, + level: { + id: level.id, + name: level.name, + description: level.description, + sort_order: level.sort_order, + }, + skill_tags: courseSkills.map((s) => ({ + id: s.id, + name: s.name, + description: s.description, + })), + question: question, + }; + + const answer = await callLLM(context); + + return res.json({ success: true, answer }); + } catch (err) { + console.error("Error processing question:", err); + return res.status(500).json({ message: "Server error" }); + } +}); + +module.exports = router; diff --git a/server.js b/server.js index 8dd8b42..d253229 100644 --- a/server.js +++ b/server.js @@ -10,6 +10,7 @@ const roadmapRoutes = require("./routes/roadmaps"); const materialRoutes = require("./routes/materials"); const activityRoutes = require("./routes/activity"); const dashboardRoutes = require("./routes/dashboard"); +const chatbotRoutes = require("./routes/chatbot"); const pool = require("./database/db"); const app = express(); const PORT = process.env.PORT || 4000; @@ -54,6 +55,7 @@ app.use("/api/roadmaps", roadmapRoutes); app.use("/api/materials", materialRoutes); app.use("/api/activity", activityRoutes); app.use("/api/dashboard", dashboardRoutes); +app.use("/api/chatbot", chatbotRoutes); app.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); From dad8e0264d86e4f5275122c012bd7cc1b510a354 Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 20:01:32 +0800 Subject: [PATCH 3/8] Add chat logs table --- database/schema.sql | 10 +++++ routes/chatbot.js | 100 +++++++++++++++++++++++++------------------- 2 files changed, 66 insertions(+), 44 deletions(-) diff --git a/database/schema.sql b/database/schema.sql index cd3b4b8..e4116e9 100644 --- a/database/schema.sql +++ b/database/schema.sql @@ -332,6 +332,16 @@ CREATE TABLE activity_logs ( display_metadata JSONB NOT NULL DEFAULT '{}' ); +CREATE TABLE chat_logs ( + id SERIAL PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + organisation_id INTEGER REFERENCES organisations(id) ON DELETE SET NULL, + course_id INTEGER REFERENCES courses(id) ON DELETE SET NULL, + module_id INTEGER REFERENCES modules(id) ON DELETE SET NULL, + question TEXT NOT NULL, + answer TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now() +); COMMIT; \ No newline at end of file diff --git a/routes/chatbot.js b/routes/chatbot.js index 06a7a63..afd1c3e 100644 --- a/routes/chatbot.js +++ b/routes/chatbot.js @@ -57,6 +57,12 @@ router.post("/ask", async (req, res) => { return res.status(401).json({ message: "Not logged in" }); } + const userId = user.userId; + const organisationId = user.organisation?.id; + if (!organisationId) { + return res.status(403).json({ message: "Forbidden" }); + } + const { courseId, moduleId, question } = req.body; if (!courseId || !moduleId) { return res @@ -67,65 +73,63 @@ router.post("/ask", async (req, res) => { return res.status(400).json({ message: "Question is required" }); } - const client = await pool.connect(); - const courseRes = await client.query( - `SELECT name, description + try { + const client = await pool.connect(); + const courseRes = await client.query( + `SELECT name, description FROM courses WHERE id = $1`, - [courseId] - ); - const course = courseRes.rows[0]; - const moduleRes = await client.query( - `SELECT title, description + [courseId] + ); + const course = courseRes.rows[0]; + const moduleRes = await client.query( + `SELECT title, description FROM modules WHERE id = $1`, - [moduleId] - ); - const module = moduleRes.rows[0]; + [moduleId] + ); + const module = moduleRes.rows[0]; - const courseSkillsRes = await client.query( - `SELECT s.id, s.name, s.description + const courseSkillsRes = await client.query( + `SELECT s.id, s.name, s.description FROM module_skills ms JOIN skills s ON s.id = ms.skill_id WHERE ms.module_id = $1`, - [moduleId] - ); - const courseSkills = - courseSkillsRes.rows.map((skill) => ({ - id: skill.id, - name: skill.name, - description: skill.description, - })) || []; - const channelRes = await client.query( - `SELECT c.id, c.name, c.description + [moduleId] + ); + const courseSkills = + courseSkillsRes.rows.map((skill) => ({ + id: skill.id, + name: skill.name, + description: skill.description, + })) || []; + const channelRes = await client.query( + `SELECT c.id, c.name, c.description FROM course_channels cc JOIN channels c ON c.id = cc.channel_id WHERE cc.course_id = $1`, - [courseId] - ); - const channel = channelRes.rows[0] || { - id: null, - name: "No channel", - description: "", - }; - - const levelRes = await client.query( - `SELECT l.id, l.name, l.description, l.sort_order + [courseId] + ); + const channel = channelRes.rows[0] || { + id: null, + name: "No channel", + description: "", + }; + + const levelRes = await client.query( + `SELECT l.id, l.name, l.description, l.sort_order FROM course_channels cc JOIN levels l ON l.id = cc.level_id WHERE cc.course_id = $1`, - [courseId] - ); - const level = levelRes.rows[0] || { - id: null, - name: "No level", - description: "", - sort_order: 0, - }; - - await client.release(); + [courseId] + ); + const level = levelRes.rows[0] || { + id: null, + name: "No level", + description: "", + sort_order: 0, + }; - try { const context = { course_name: course.name, course_description: course.description, @@ -152,6 +156,14 @@ router.post("/ask", async (req, res) => { const answer = await callLLM(context); + await client.query( + `INSERT INTO chat_logs (user_id, organisation_id, course_id, module_id, question, answer) + VALUES ($1, $2, $3, $4, $5, $6)`, + [userId, organisationId, courseId, moduleId, question, answer] + ); + + await client.release(); + return res.json({ success: true, answer }); } catch (err) { console.error("Error processing question:", err); From 29afc6dbcab09b5e5cdaebcb0b2b6e194e30a503 Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 20:11:11 +0800 Subject: [PATCH 4/8] Add endpoint to show chat history --- routes/chatbot.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/routes/chatbot.js b/routes/chatbot.js index afd1c3e..23754ea 100644 --- a/routes/chatbot.js +++ b/routes/chatbot.js @@ -171,4 +171,39 @@ router.post("/ask", async (req, res) => { } }); +router.get("/logs", async (req, res) => { + const { auth } = req.cookies; + if (!auth) return res.status(401).json({ message: "Not authenticated" }); + let user; + try { + user = JSON.parse(auth); + } catch { + return res.status(400).json({ message: "Invalid session" }); + } + if (!user.isLoggedIn) { + return res.status(401).json({ message: "Not logged in" }); + } + + const userId = user.userId; + const organisationId = user.organisation?.id; + if (!organisationId) { + return res.status(403).json({ message: "Forbidden" }); + } + try { + const client = await pool.connect(); + const logs = await client.query( + `SELECT question, answer + FROM chat_logs + WHERE user_id = $1 AND organisation_id = $2 + ORDER BY created_at DESC`, + [userId, organisationId] + ); + await client.release(); + return res.json({ success: true, logs: logs.rows }); + } catch (err) { + console.error(err); + return res.status(500).json({ message: "Server error" }); + } +}); + module.exports = router; From 55513afae3ce001eb03710d9cb593637b80656e4 Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 20:15:09 +0800 Subject: [PATCH 5/8] Add logs as per course id andmodule id --- routes/chatbot.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/routes/chatbot.js b/routes/chatbot.js index 23754ea..94eb88b 100644 --- a/routes/chatbot.js +++ b/routes/chatbot.js @@ -171,7 +171,7 @@ router.post("/ask", async (req, res) => { } }); -router.get("/logs", async (req, res) => { +router.post("/logs", async (req, res) => { const { auth } = req.cookies; if (!auth) return res.status(401).json({ message: "Not authenticated" }); let user; @@ -189,14 +189,22 @@ router.get("/logs", async (req, res) => { if (!organisationId) { return res.status(403).json({ message: "Forbidden" }); } + + const { courseId, moduleId } = req.body; + if (!courseId || !moduleId) { + return res + .status(400) + .json({ message: "Course and module IDs are required" }); + } try { const client = await pool.connect(); const logs = await client.query( `SELECT question, answer FROM chat_logs WHERE user_id = $1 AND organisation_id = $2 + AND course_id = $3 AND module_id = $4 ORDER BY created_at DESC`, - [userId, organisationId] + [userId, organisationId, courseId, moduleId] ); await client.release(); return res.json({ success: true, logs: logs.rows }); From e61560d2e98b421750670ae0e886fa96a12da196 Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 20:30:42 +0800 Subject: [PATCH 6/8] Add endpoint to show all chat history --- routes/chatbot.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/routes/chatbot.js b/routes/chatbot.js index 94eb88b..f9004ff 100644 --- a/routes/chatbot.js +++ b/routes/chatbot.js @@ -214,4 +214,34 @@ router.post("/logs", async (req, res) => { } }); +router.get("/history", async (req, res) => { + const user = getAuthUser(req); + if (!user || !user.isLoggedIn) { + return res.status(401).json({ message: "Not logged in" }); + } + + const userId = user.userId; + const organisationId = user.organisation?.id; + if (!organisationId) { + return res.status(403).json({ message: "Forbidden" }); + } + + try { + const client = await pool.connect(); + const logs = await client.query( + `SELECT cl.id, c.name, m.title, cl.question, cl.answer, cl.created_at + FROM chat_logs cl, courses c, modules m + WHERE cl.course_id = c.id and cl.module_id = m.id AND + cl.user_id = $1 AND cl.organisation_id = $2 + ORDER BY created_at DESC`, + [userId, organisationId] + ); + await client.release(); + return res.json({ success: true, logs: logs.rows }); + } catch (err) { + console.error(err); + return res.status(500).json({ message: "Server error" }); + } +}); + module.exports = router; From c73dd94068c87d1c228d42e149fd8164dc99c898 Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 20:37:26 +0800 Subject: [PATCH 7/8] Update endpoint to include course and module ids --- routes/chatbot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/chatbot.js b/routes/chatbot.js index f9004ff..06557bc 100644 --- a/routes/chatbot.js +++ b/routes/chatbot.js @@ -229,7 +229,7 @@ router.get("/history", async (req, res) => { try { const client = await pool.connect(); const logs = await client.query( - `SELECT cl.id, c.name, m.title, cl.question, cl.answer, cl.created_at + `SELECT cl.id, c.id as course_id, c.name, m.id as module_id, m.title, cl.question, cl.answer, cl.created_at FROM chat_logs cl, courses c, modules m WHERE cl.course_id = c.id and cl.module_id = m.id AND cl.user_id = $1 AND cl.organisation_id = $2 From b625d7e58e1867f0c8ef288a6c28ecd35bb19cab Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 21:27:20 +0800 Subject: [PATCH 8/8] Update prompt --- routes/chatbot.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/routes/chatbot.js b/routes/chatbot.js index 06557bc..b21d7a8 100644 --- a/routes/chatbot.js +++ b/routes/chatbot.js @@ -23,7 +23,8 @@ async function callLLM(context) { Do not mention "Since we are in this particular course", just answer the question directly. Answer the question as if you are directly talking to the student. If unsure, give your best expert guess based on course/module metadata and tags. Keep your answers concise and focused on the question. - If the question is not related to the course/module, politely redirect them to the appropriate support + If the question is not related to the course/module, politely redirect them to the appropriate support. Do not answer anything unrelated to the + course material at all. `; const messages = [