Debate_Engine / server /index.js
Shokat's picture
Upload 10 files
fc851c4 verified
Raw
History Blame Contribute Delete
7.16 kB
const express = require('express');
const path = require('path');
const cors = require('cors');
const { MODELS, callGroq, callGeminiDebater, callArchitect } = require('./api');
const app = express();
const PORT = process.env.PORT || 3000;
app.use(cors());
app.use(express.json());
app.use(express.static(path.join(__dirname, '../public')));
// Debate Endpoint
app.post('/api/debate', async (req, res) => {
const { topic } = req.body;
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const sendEvent = (type, data) => {
res.write(`event: ${type}\ndata: ${JSON.stringify(data)}\n\n`);
};
sendEvent('status', { message: 'Debate Initiated', topic });
let transcript = "";
// ROUND 1
sendEvent('status', { message: 'Round 1: Opening Arguments...' });
let round1Responses = {};
for (const model of MODELS) {
sendEvent('model_start', { round: 1, model });
let content = "";
let finalSystemPrompt = `You are a critical thinker and expert advisor taking part in a debate. Give your best, concise opening argument on this topic. Don't be cliché, be brave, direct, and specific. Keep to ~150 words.`;
if (model.includes('gemini')) {
content = await callGeminiDebater(model, finalSystemPrompt, `Topic: ${topic}`);
} else {
if (model.includes('qwen')) {
finalSystemPrompt += "\n\nIMPORTANT: Output ONLY valid JSON in the format {\"argument\": \"your final polished response without any thinking\"}.";
}
content = await callGroq(model, finalSystemPrompt, `Topic: ${topic}`);
if (model.includes('qwen')) {
try {
const jsonMatch = content.match(/\{[\s\S]*\}/);
if (jsonMatch) content = JSON.parse(jsonMatch[0]).argument;
} catch(e) {}
}
}
round1Responses[model] = content;
sendEvent('model_end', { round: 1, model, content });
// small 1s delay to respect free tier rate limit
await new Promise(resolve => setTimeout(resolve, 1000));
}
transcript += "\n--- ROUND 1: OPENING ARGUMENTS ---\n";
for(let m of MODELS) { transcript += `${m}:\n${round1Responses[m]}\n\n`; }
// ROUND 2
sendEvent('status', { message: 'Round 2: Rebuttals...' });
let round2Responses = {};
for (const model of MODELS) {
sendEvent('model_start', { round: 2, model });
let otherArguments = "";
for (const [m, r] of Object.entries(round1Responses)) {
if (m !== model) {
otherArguments += `${m} argued: "${r}"\n\n`;
}
}
let content = "";
let finalSystemPrompt = `You are a critical debater. Review the opening arguments of the other AI models. Point out flaws, logical fallacies, or forcefully expand on weak points in their arguments. Be aggressive but intellectual. Keep it under ~150 words.`;
const userPrompt = `Topic: ${topic}\n\nHere is what the others said:\n${otherArguments}\n\nDeliver your rebuttal.`;
if (model.includes('gemini')) {
content = await callGeminiDebater(model, finalSystemPrompt, userPrompt);
} else {
if (model.includes('qwen')) {
finalSystemPrompt += "\n\nIMPORTANT: Output ONLY valid JSON in the format {\"argument\": \"your final polished rebuttal without any thinking\"}.";
}
content = await callGroq(model, finalSystemPrompt, userPrompt);
if (model.includes('qwen')) {
try {
const jsonMatch = content.match(/\{[\s\S]*\}/);
if (jsonMatch) content = JSON.parse(jsonMatch[0]).argument;
} catch(e) {}
}
}
round2Responses[model] = content;
sendEvent('model_end', { round: 2, model, content });
await new Promise(resolve => setTimeout(resolve, 1000));
}
transcript += "\n--- ROUND 2: REBUTTALS ---\n";
for(let m of MODELS) { transcript += `${m}:\n${round2Responses[m]}\n\n`; }
// ROUND 3
sendEvent('status', { message: 'Round 3: Final Responses & Defense...' });
let round3Responses = {};
for (const model of MODELS) {
sendEvent('model_start', { round: 3, model });
let otherRebuttals = "";
for (const [m, r] of Object.entries(round2Responses)) {
if (m !== model) {
otherRebuttals += `${m} critiqued: "${r}"\n\n`;
}
}
let content = "";
let finalSystemPrompt = `This is your final defense. Acknowledge valid critiques but firmly defend your core premise based on the other models' rebuttals to the group. Give your concluding stance. Max 150 words.`;
const userPrompt = `Topic: ${topic}\n\nHere are the critiques from others in the last round:\n${otherRebuttals}\n\nDeliver your final defense and conclusion.`;
if (model.includes('gemini')) {
content = await callGeminiDebater(model, finalSystemPrompt, userPrompt);
} else {
if (model.includes('qwen')) {
finalSystemPrompt += "\n\nIMPORTANT: Output ONLY valid JSON in the format {\"argument\": \"your final polished defense without any thinking\"}.";
}
content = await callGroq(model, finalSystemPrompt, userPrompt);
if (model.includes('qwen')) {
try {
const jsonMatch = content.match(/\{[\s\S]*\}/);
if (jsonMatch) content = JSON.parse(jsonMatch[0]).argument;
} catch(e) {}
}
}
round3Responses[model] = content;
sendEvent('model_end', { round: 3, model, content });
await new Promise(resolve => setTimeout(resolve, 1000));
}
transcript += "\n--- ROUND 3: FINAL DEFENSE ---\n";
for(let m of MODELS) { transcript += `${m}:\n${round3Responses[m]}\n\n`; }
// FINAL VERDICT
sendEvent('status', { message: 'Synthesizing Final Verdict via Gemma 4...' });
sendEvent('model_start', { round: 'Final', model: 'Gemma 4 (Architect)' });
const geminiSystemPrompt = `You are the Lead Architect and final judge of this debate. Review the transcript of the 3-round debate across the multiple models.
Your goal:
1. Synthesize the most compelling arguments.
2. Call out specific models if they had a brilliant insight or if they hallucinated/made a weak/false point.
3. Deliver the unvarnished, brutal truth final verdict on the topic. Be decisive. Do not sit on the fence.
Format your output beautifully in Markdown.`;
const geminiVerdict = await callArchitect(geminiSystemPrompt, transcript);
sendEvent('model_end', { round: 'Final', model: 'Gemma 4 (Architect)', content: geminiVerdict });
// End Stream
sendEvent('done', { message: 'Debate Concluded' });
res.end();
});
app.listen(PORT, () => {
console.log(`AI Debate Engine running on http://localhost:${PORT}`);
});