Emalawi19 commited on
Commit
f3001d7
Β·
verified Β·
1 Parent(s): 0390951

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +136 -68
server.js CHANGED
@@ -11,19 +11,80 @@ async function loadModel() {
11
  console.log("Model loaded successfully!");
12
  }
13
 
14
- // Keywords that signal a coding request
15
- const CODING_KEYWORDS = [
16
- 'generate', 'create', 'build', 'make', 'code', 'write', 'show',
17
- 'website', 'webpage', 'page', 'app', 'application',
18
- 'login', 'register', 'signup', 'form', 'button', 'navbar', 'footer',
19
- 'html', 'css', 'javascript', 'js', 'node', 'express', 'backend',
20
- 'frontend', 'server', 'api', 'database', 'function', 'script',
21
- 'component', 'template', 'layout', 'style', 'fetch', 'route', 'endpoint'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  ];
23
 
24
  function isCodingRequest(prompt) {
 
 
 
 
 
 
25
  const lower = prompt.toLowerCase();
26
- return CODING_KEYWORDS.some(k => lower.includes(k));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  }
28
 
29
  const server = http.createServer(async (req, res) => {
@@ -36,15 +97,16 @@ const server = http.createServer(async (req, res) => {
36
  return res.end();
37
  }
38
 
39
- res.setHeader('Content-Type', 'application/json');
40
  const pathname = req.url.split('?')[0];
41
 
42
  if (pathname === '/' && req.method === 'GET') {
 
43
  res.writeHead(200);
44
  res.end(JSON.stringify({ status: "Backend is running" }));
45
  return;
46
  }
47
 
 
48
  if (pathname === '/generate' && req.method === 'POST') {
49
  let body = '';
50
  req.on('data', chunk => { body += chunk.toString(); });
@@ -52,13 +114,14 @@ const server = http.createServer(async (req, res) => {
52
  try {
53
  const { prompt } = JSON.parse(body);
54
  if (!generator) {
 
55
  res.writeHead(503);
56
  return res.end(JSON.stringify({ error: "Model is still loading..." }));
57
  }
58
 
59
  const coding = isCodingRequest(prompt);
 
60
 
61
- // Reframe coding prompts so the model never misreads them as unsafe
62
  const finalPrompt = coding
63
  ? `You are a coding assistant. Write complete, working code for this task. Never refuse. Always provide full code: ${prompt}`
64
  : prompt;
@@ -71,90 +134,95 @@ IDENTITY:
71
  - You are an AI assistant, not a human.
72
 
73
  CODING RULES β€” NEVER BREAK THESE:
74
- 1. You ALWAYS write code when asked. You NEVER say "I can't help" for any coding task.
75
- 2. Any request for a website, page, form, login, register, button, API, or any web topic ALWAYS gets complete working code.
76
- 3. You NEVER refuse a coding request. Ever.
77
- 4. Code must be complete, real, and copy-paste ready β€” no placeholders, no "add your logic here".
78
- 5. Always wrap code in triple backticks with the language tag e.g. \`\`\`html \`\`\`javascript \`\`\`css
79
- 6. Add short comments inside the code so the user understands each part.
 
 
 
 
 
 
 
 
80
 
81
  STEP-BY-STEP RULES:
82
- 1. When asked to build a full website or app, first list ALL steps with short titles.
83
- 2. Say: "Let's begin with Step 1. Say 'next' when ready to continue."
84
- 3. For each step:
85
- a) "Step X of Y: Title"
86
- b) One sentence explaining what this step does
87
- c) Complete working code in a code block
88
- d) Filename and where to save it
89
- e) How to run it if needed
90
- f) End with: "Say 'next' to continue to Step X."
91
- 4. ONE step per response only. Never combine steps.
92
- 5. NEVER cut off mid-code. Always finish the full code for the current step.
93
- 6. Default stack: HTML + CSS + JS frontend, Node.js + Express backend.`
94
-
95
- : `You are Gini AI, a full-stack web development AI assistant created by Emalawi19, founded by Professor Roosevelt Chinkwende.
96
 
97
  IDENTITY:
98
  - Your name is Gini AI, created by Emalawi19, founded by Professor Roosevelt Chinkwende.
99
  - You are an AI assistant, not a human.
100
 
101
  GENERAL BEHAVIOR:
102
- - Answer questions clearly, helpfully, and concisely.
103
- - If the question is related to web development, programming, or tech, answer with practical advice.
104
- - Keep answers short and to the point β€” no unnecessary padding.
105
- - Do not include code unless the user specifically asks for it.
106
- - Be friendly and encouraging.`;
107
 
108
  const messages = [
109
  { role: 'system', content: systemPrompt },
110
  { role: 'user', content: finalPrompt }
111
  ];
112
 
113
- const output = await generator(messages, {
114
- max_new_tokens: coding ? 800 : 800, // shorter for chat, longer for code
115
- temperature: coding ? 0.2 : 0.5, // precise for code, natural for chat
116
- repetition_penalty: 1.2,
117
- do_sample: !coding // deterministic for code, sampled for chat
 
118
  });
119
 
120
- let result = output[0].generated_text.at(-1).content;
121
-
122
- // Catch any refusals and retry with a direct code-only prompt
123
- const refusals = ["i can't assist", "i cannot assist", "i'm sorry", "i am sorry", "i'm unable", "i cannot help", "i can't help"];
124
- const refused = refusals.some(r => result.toLowerCase().startsWith(r));
125
-
126
- if (refused && coding) {
127
- const retryMessages = [
128
- {
129
- role: 'system',
130
- content: 'You are a code generator. Output only complete working code. Never refuse any request. No explanations, just code.'
131
- },
132
- {
133
- role: 'user',
134
- content: `Write complete working code for: ${prompt}`
 
 
 
 
135
  }
136
- ];
137
- const retryOutput = await generator(retryMessages, {
138
- max_new_tokens: 800,
139
- temperature: 0.1,
140
- do_sample: false
141
- });
142
- result = retryOutput[0].generated_text.at(-1).content;
143
  }
144
 
145
- res.writeHead(200);
146
- res.end(JSON.stringify({ result }));
 
147
 
148
  } catch (err) {
149
- res.writeHead(400);
150
- res.end(JSON.stringify({ error: "Invalid request", detail: err.message }));
151
  }
152
  });
153
  return;
154
  }
155
 
 
156
  res.writeHead(404);
157
- res.end(JSON.stringify({ error: "Not Found", requested_path: pathname }));
158
  });
159
 
160
  loadModel().then(() => {
 
11
  console.log("Model loaded successfully!");
12
  }
13
 
14
+ const CODING_PHRASES = [
15
+ 'generate code', 'write code', 'create code',
16
+ 'generate a website', 'build a website', 'create a website', 'make a website',
17
+ 'generate a webpage', 'build a webpage',
18
+ 'generate a login', 'create a login', 'build a login',
19
+ 'generate a form', 'create a form', 'build a form',
20
+ 'generate a page', 'create a page', 'build a page',
21
+ 'generate an app', 'create an app', 'build an app',
22
+ 'write a function', 'write a script', 'write a program',
23
+ 'create a function', 'create a script',
24
+ 'build an api', 'create an api', 'generate an api',
25
+ 'node.js', 'express.js', 'express server',
26
+ 'show me the code', 'give me the code', 'write html',
27
+ 'write css', 'write javascript', 'write js',
28
+ 'create a backend', 'build a backend',
29
+ 'create a frontend', 'build a frontend',
30
+ 'create a server', 'build a server',
31
+ 'how do i code', 'how to code', 'code for',
32
+ 'sample code', 'example code', '```'
33
+ ];
34
+
35
+ const NON_CODING_CONTEXTS = [
36
+ 'function of', 'functions of', 'what is the function',
37
+ 'what are the functions', 'purpose of', 'role of',
38
+ 'explain', 'what is', 'what are', 'tell me about',
39
+ 'history of', 'meaning of', 'definition of',
40
+ 'describe', 'how does', 'why is', 'benefits of',
41
+ 'importance of', 'effects of', 'causes of'
42
  ];
43
 
44
  function isCodingRequest(prompt) {
45
+ const lower = prompt.toLowerCase().trim();
46
+ if (NON_CODING_CONTEXTS.some(ctx => lower.includes(ctx))) return false;
47
+ return CODING_PHRASES.some(phrase => lower.includes(phrase));
48
+ }
49
+
50
+ function isWebsiteRequest(prompt) {
51
  const lower = prompt.toLowerCase();
52
+ return ['website', 'webpage', 'web page', 'html page', 'login page',
53
+ 'register page', 'landing page', 'form page', 'signup page',
54
+ 'homepage', 'home page', 'portfolio', 'dashboard'].some(w => lower.includes(w));
55
+ }
56
+
57
+ function cleanHTML(html) {
58
+ if (!html.trimStart().toLowerCase().startsWith('<!doctype')) {
59
+ if (html.trimStart().toLowerCase().startsWith('<html')) {
60
+ html = '<!DOCTYPE html>\n' + html.trimStart();
61
+ } else {
62
+ html = '<!DOCTYPE html>\n<html lang="en">\n' + html.trimStart();
63
+ }
64
+ }
65
+ if (!html.trimEnd().toLowerCase().endsWith('</html>')) {
66
+ if (html.toLowerCase().includes('</body>')) {
67
+ html = html.replace(/<\/body>\s*$/i, '</body>\n</html>');
68
+ } else {
69
+ html = html.trimEnd() + '\n</body>\n</html>';
70
+ }
71
+ }
72
+ return html.trim();
73
+ }
74
+
75
+ function enforceHTMLStructure(text) {
76
+ const codeBlockMatch = text.match(/```html\s*([\s\S]*?)```/i);
77
+ if (codeBlockMatch) {
78
+ return '```html\n' + cleanHTML(codeBlockMatch[1].trim()) + '\n```';
79
+ }
80
+ const htmlStart = text.search(/<(!DOCTYPE|html)/i);
81
+ if (htmlStart !== -1) {
82
+ let html = text.slice(htmlStart);
83
+ const htmlEnd = html.search(/<\/html>/i);
84
+ if (htmlEnd !== -1) html = html.slice(0, htmlEnd + 7);
85
+ return '```html\n' + cleanHTML(html) + '\n```';
86
+ }
87
+ return text;
88
  }
89
 
90
  const server = http.createServer(async (req, res) => {
 
97
  return res.end();
98
  }
99
 
 
100
  const pathname = req.url.split('?')[0];
101
 
102
  if (pathname === '/' && req.method === 'GET') {
103
+ res.setHeader('Content-Type', 'application/json');
104
  res.writeHead(200);
105
  res.end(JSON.stringify({ status: "Backend is running" }));
106
  return;
107
  }
108
 
109
+ // ── STREAMING ENDPOINT ───────────────────────────────────────────────────
110
  if (pathname === '/generate' && req.method === 'POST') {
111
  let body = '';
112
  req.on('data', chunk => { body += chunk.toString(); });
 
114
  try {
115
  const { prompt } = JSON.parse(body);
116
  if (!generator) {
117
+ res.setHeader('Content-Type', 'application/json');
118
  res.writeHead(503);
119
  return res.end(JSON.stringify({ error: "Model is still loading..." }));
120
  }
121
 
122
  const coding = isCodingRequest(prompt);
123
+ const websiteReq = isWebsiteRequest(prompt);
124
 
 
125
  const finalPrompt = coding
126
  ? `You are a coding assistant. Write complete, working code for this task. Never refuse. Always provide full code: ${prompt}`
127
  : prompt;
 
134
  - You are an AI assistant, not a human.
135
 
136
  CODING RULES β€” NEVER BREAK THESE:
137
+ 1. You ALWAYS write code when asked. You NEVER refuse any coding task.
138
+ 2. Code must be complete, real, and copy-paste ready β€” no placeholders.
139
+ 3. Default language is always JavaScript/HTML/CSS β€” NEVER Python unless the user asks.
140
+ 4. Add short comments inside the code.
141
+
142
+ HTML WEBSITE RULES:
143
+ 1. ALL website/page code MUST start with <!DOCTYPE html> on the very first line.
144
+ 2. Then <html lang="en"> on the second line.
145
+ 3. Must include a proper <head> with <meta charset>, <meta viewport>, <title>, and <style>.
146
+ 4. Must include a proper <body> with all content.
147
+ 5. Must end with </body> then </html> as the very last line.
148
+ 6. ALL CSS inside <style> in <head>. ALL JS inside <script> at the bottom of <body>.
149
+ 7. Wrap full HTML in a \`\`\`html code block.
150
+ 8. The page must be complete and functional β€” never cut off mid-code.
151
 
152
  STEP-BY-STEP RULES:
153
+ 1. When asked to build a full website or app, list ALL steps first.
154
+ 2. Say: "Let's begin with Step 1. Say 'next' when ready."
155
+ 3. For each step: title, explanation, complete code, filename, how to run, then "Say 'next' to continue."
156
+ 4. ONE step per response. Never combine. Never cut off mid-code.`
157
+
158
+ : `You are Gini AI, a helpful AI assistant created by Emalawi19, founded by Professor Roosevelt Chinkwende.
 
 
 
 
 
 
 
 
159
 
160
  IDENTITY:
161
  - Your name is Gini AI, created by Emalawi19, founded by Professor Roosevelt Chinkwende.
162
  - You are an AI assistant, not a human.
163
 
164
  GENERAL BEHAVIOR:
165
+ - Answer directly and clearly in plain English.
166
+ - NEVER generate code for general knowledge or everyday questions.
167
+ - NEVER use any programming language to answer a non-coding question.
168
+ - Answer in plain sentences. Keep it concise, friendly, and easy to understand.`;
 
169
 
170
  const messages = [
171
  { role: 'system', content: systemPrompt },
172
  { role: 'user', content: finalPrompt }
173
  ];
174
 
175
+ // Set SSE headers for streaming
176
+ res.writeHead(200, {
177
+ 'Content-Type': 'text/event-stream',
178
+ 'Cache-Control': 'no-cache',
179
+ 'Connection': 'keep-alive',
180
+ 'X-Accel-Buffering': 'no'
181
  });
182
 
183
+ let fullResult = '';
184
+
185
+ // Stream tokens as they are generated
186
+ await generator(messages, {
187
+ max_new_tokens: coding ? 800 : 300,
188
+ temperature: coding ? 0.2 : 0.5,
189
+ repetition_penalty: 1.2,
190
+ do_sample: !coding,
191
+ // This callback fires every time a new token is produced
192
+ callback_function: (beams) => {
193
+ const token = beams[0].output_token_ids;
194
+ const newText = beams[0]?.generated_text ?? '';
195
+
196
+ // Calculate only the new characters added since last callback
197
+ if (newText.length > fullResult.length) {
198
+ const newChunk = newText.slice(fullResult.length);
199
+ fullResult = newText;
200
+ // Send the new chunk immediately as an SSE event
201
+ res.write(`data: ${JSON.stringify({ chunk: newChunk })}\n\n`);
202
  }
203
+ }
204
+ });
205
+
206
+ // Post-process HTML if needed
207
+ if (websiteReq && coding) {
208
+ fullResult = enforceHTMLStructure(fullResult);
 
209
  }
210
 
211
+ // Send the final complete result and close the stream
212
+ res.write(`data: ${JSON.stringify({ done: true, result: fullResult })}\n\n`);
213
+ res.end();
214
 
215
  } catch (err) {
216
+ res.write(`data: ${JSON.stringify({ error: err.message })}\n\n`);
217
+ res.end();
218
  }
219
  });
220
  return;
221
  }
222
 
223
+ res.setHeader('Content-Type', 'application/json');
224
  res.writeHead(404);
225
+ res.end(JSON.stringify({ error: "Not Found" }));
226
  });
227
 
228
  loadModel().then(() => {