Spaces:
Sleeping
Sleeping
File size: 7,163 Bytes
fc851c4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | 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}`);
});
|