// server.js — Backend para FinAI usando Groq // En Replit: agrega GROQ_API_KEY en la pestaña "Secrets" (candado en el sidebar) // Instala primero: npm install express groq-sdk const express = require('express'); const Groq = require('groq-sdk'); const app = express(); app.use(express.json()); app.use(express.static('public')); // sirve tu frontend (React build o HTML) const groq = new Groq({ apiKey: process.env.GROQ_API_KEY }); const systemInstruction = `Eres un asistente de finanzas personales. Analiza la petición del usuario y responde SIEMPRE con un JSON válido con esta estructura exacta: { "accion": "registrar_gasto" | "eliminar_ultimo" | "resumen" | "conversar", "mensaje": "respuesta amigable en español para mostrar en el chat", "parametros": { "cantidad": number, "categoria": string, "descripcion": string } } Reglas para elegir "accion": - "registrar_gasto": si el usuario menciona que gastó dinero. Extrae cantidad (número), categoria (ej. Comida, Transporte, Ocio, Servicios, Vivienda, Otros) y descripcion. - "eliminar_ultimo": si el usuario pide deshacer, borrar o eliminar el último gasto. - "resumen": si el usuario pide ver cómo van sus gastos, estadísticas o su estado de cuenta. - "conversar": para saludos, preguntas generales, o si no encaja en las anteriores. En este caso omite "parametros" o déjalo vacío. Responde siempre en español, con tono amable, y NUNCA agregues texto fuera del JSON.`; app.post('/api/chat', async (req, res) => { const { mensaje } = req.body; if (!mensaje || typeof mensaje !== 'string') { return res.status(400).json({ error: 'Falta el campo "mensaje" en el body' }); } if (!process.env.GROQ_API_KEY) { return res.status(500).json({ error: 'GROQ_API_KEY no configurada en el servidor' }); } try { const completion = await groq.chat.completions.create({ model: "llama-3.3-70b-versatile", messages: [ { role: "system", content: systemInstruction }, { role: "user", content: mensaje } ], response_format: { type: "json_object" }, temperature: 0.3 }); const rawText = completion.choices?.[0]?.message?.content; if (!rawText) { return res.status(502).json({ accion: 'conversar', mensaje: 'No recibí una respuesta válida. ¿Puedes reformular tu mensaje?' }); } const parsed = JSON.parse(rawText); return res.json(parsed); } catch (error) { console.error('Error al llamar a Groq:', error); return res.status(500).json({ accion: 'conversar', mensaje: 'Ocurrió un error inesperado procesando tu solicitud. Intenta de nuevo.' }); } }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`FinAI backend (Groq) corriendo en puerto ${PORT}`));