Skip to content

Commit 280cb2d

Browse files
Merge pull request #18 from priyansh-narang2308/feat/ai-chat-bot-integration
[WOC] feat: Add AI-powered Chat bot Assistant with Doc Context #5
2 parents e18a631 + f87e8ab commit 280cb2d

File tree

10 files changed

+1783
-274
lines changed

10 files changed

+1783
-274
lines changed

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
INCLUDE_DOCS_CONTEXT=false
3+
VITE_ENABLE_CHAT=true
4+
GOOGLE_GENERATIVE_AI_API_KEY=""

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules/
22
.vitepress/cache
3-
.vitepress/dist
3+
.vitepress/dist
4+
.env

.vitepress/config.mjs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
import { defineConfig } from "vitepress";
2+
import path from "path";
3+
import fs from "fs";
4+
import { google } from "@ai-sdk/google";
5+
import { streamText } from "ai";
6+
import dotenv from "dotenv";
7+
import { globSync } from "glob";
8+
9+
dotenv.config();
210

311
export default defineConfig({
412
base: "/user_docs/",
@@ -179,4 +187,113 @@ export default defineConfig({
179187
message: "Released under the GPL 3.0 License as of 2025.",
180188
},
181189
},
190+
vite: {
191+
resolve: {
192+
alias: {
193+
"zod/v3": "zod",
194+
"zod/v4": "zod",
195+
},
196+
},
197+
plugins: [
198+
{
199+
name: "handle-chat-api",
200+
configureServer(server) {
201+
server.middlewares.use(async (req, res, next) => {
202+
if (req.url === "/api/chat" && req.method === "POST") {
203+
let body = "";
204+
req.on("data", (chunk) => {
205+
body += chunk.toString();
206+
});
207+
req.on("end", async () => {
208+
try {
209+
const { messages } = JSON.parse(body);
210+
211+
if (
212+
!process.env
213+
.GOOGLE_GENERATIVE_AI_API_KEY
214+
) {
215+
throw new Error(
216+
"Missing GOOGLE_GENERATIVE_AI_API_KEY in .env file",
217+
);
218+
}
219+
220+
let docsContext = "";
221+
let systemPrompt = "";
222+
223+
const includeDocs = process.env.INCLUDE_DOCS_CONTEXT === "true";
224+
225+
if (includeDocs) {
226+
const docsPath = path.resolve(process.cwd());
227+
const mdFiles = globSync("**/*.md", {
228+
cwd: docsPath,
229+
ignore: ["node_modules/**"]
230+
});
231+
232+
for (const file of mdFiles) {
233+
const fullPath = path.join(docsPath, file);
234+
const content = fs.readFileSync(fullPath, "utf-8");
235+
docsContext += `\n--- FILE: ${file} ---\n${content}\n`;
236+
}
237+
238+
systemPrompt = `You are the EvOC AI Assistant. Your PRIMARY goal is to provide accurate information based EXCLUSIVELY on the project's documentation provided below.
239+
240+
DOCUMENTATION CONTEXT:
241+
${docsContext}
242+
243+
INSTRUCTIONS:
244+
1. Strict Grounding: Use ONLY the documentation provided above. If the answer is not in the documentation, state that you don't have that information.
245+
2. Identity: EvOC is a GUI-based framework for Evolutionary Algorithms using Python/DEAP.
246+
3. Markdown: Use rich markdown (headers, bold, lists, code blocks).
247+
4. Professionalism: Be helpful, concise, and professional.`;
248+
249+
250+
} else {
251+
// less token prompt
252+
systemPrompt = `You are the EvOC AI Assistant, a specialized technical guide for the Evolve On Click (EvOC) framework. Your PRIMARY goal is to provide accurate information based on the project's documentation.
253+
254+
IDENTITY:
255+
EvOC (Evolutionary Algorithms On Click) is a user-friendly framework for designing, executing, and analyzing Evolutionary Algorithms (EA) without writing code. It uses Python and the **DEAP library** under the hood.
256+
257+
INSTRUCTIONS:
258+
1. Guidance: Answer questions about EvOC's features, algorithms (GA, GP, PSO, DE), and usage.
259+
2. Markdown: Use rich markdown (headers, bold, lists).
260+
3. Professionalism: Be helpful, concise, and professional.
261+
4. Note: Full documentation context is currently disabled. Answer based on general knowledge of the framework.`;
262+
}
263+
264+
const result = await streamText({
265+
model: google("gemini-flash-latest"),
266+
system: systemPrompt,
267+
messages,
268+
});
269+
270+
res.setHeader(
271+
"Content-Type",
272+
"text/plain; charset=utf-8",
273+
);
274+
res.setHeader("x-vercel-ai-data-stream", "v1");
275+
276+
for await (const textPart of result.textStream) {
277+
res.write(`0:${JSON.stringify(textPart)}\n`);
278+
}
279+
res.end();
280+
} catch (error) {
281+
console.error("--- Chat API ERROR ---");
282+
console.error(error);
283+
res.statusCode = 500;
284+
res.end(
285+
JSON.stringify({
286+
error: error.message,
287+
}),
288+
);
289+
}
290+
});
291+
} else {
292+
next();
293+
}
294+
});
295+
},
296+
},
297+
],
298+
},
182299
});

0 commit comments

Comments
 (0)