Instrucciones y estilo de IA editables desde el panel (Configuración Avanzada)
This commit is contained in:
55
server.js
55
server.js
@@ -1596,6 +1596,16 @@ async function registrarMovimiento(serviceId, userId, action, details) {
|
|||||||
// ==========================================
|
// ==========================================
|
||||||
// 🧠 CEREBRO IA (WHATSAPP)
|
// 🧠 CEREBRO IA (WHATSAPP)
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
// 🗣️ Texto por defecto del bloque "Estilo e instrucciones de la empresa" que se ve y se
|
||||||
|
// edita desde el cuadro de "Instrucciones y estilo de la IA" en Configuración Avanzada.
|
||||||
|
// Si la empresa no ha guardado nunca nada en ese cuadro, se usa este texto (que es
|
||||||
|
// exactamente el comportamiento que la IA tenía antes de poder editarse desde el panel).
|
||||||
|
const DEFAULT_REGLAS_NEGOCIO_IA = `Habla de tú, de forma natural, clara, cercana y profesional.
|
||||||
|
Los fines de semana solo se ofrecen citas si es una urgencia.
|
||||||
|
Máximo 2 frases por mensaje: sé claro y directo.
|
||||||
|
No te presentes de nuevo si ya habéis hablado antes.
|
||||||
|
No uses la muletilla "¿En qué más te puedo ayudar?".`;
|
||||||
|
|
||||||
async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||||
try {
|
try {
|
||||||
const userQ = await pool.query(
|
const userQ = await pool.query(
|
||||||
@@ -1607,7 +1617,12 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
|||||||
|
|
||||||
const userData = userQ.rows[0];
|
const userData = userQ.rows[0];
|
||||||
const settings = userData?.wa_settings || {};
|
const settings = userData?.wa_settings || {};
|
||||||
const instruccionesExtra = settings.ai_custom_prompt || "";
|
// 🗣️ Estilo e instrucciones de la empresa: editable desde el panel web
|
||||||
|
// (Configuración Avanzada → cuadro "Instrucciones y estilo de la IA"). Si la
|
||||||
|
// empresa nunca ha guardado nada ahí, usamos el texto por defecto de siempre.
|
||||||
|
const reglasNegocioIA = (settings.ai_custom_prompt && settings.ai_custom_prompt.trim())
|
||||||
|
? settings.ai_custom_prompt.trim()
|
||||||
|
: DEFAULT_REGLAS_NEGOCIO_IA;
|
||||||
const empresaNombre = userData?.full_name || "nuestra empresa";
|
const empresaNombre = userData?.full_name || "nuestra empresa";
|
||||||
|
|
||||||
// 🧾 Condiciones de cobertura por compañía y/o gremio: cada regla puede llevar una
|
// 🧾 Condiciones de cobertura por compañía y/o gremio: cada regla puede llevar una
|
||||||
@@ -1972,11 +1987,11 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
|||||||
if (tieneCitaConfirmada && datosExpediente.cita) {
|
if (tieneCitaConfirmada && datosExpediente.cita) {
|
||||||
const ahora = new Date();
|
const ahora = new Date();
|
||||||
const [y, m, d] = datosExpediente.cita.split('-');
|
const [y, m, d] = datosExpediente.cita.split('-');
|
||||||
// Si no hay hora concreta, solo se considera "pasada" al cambiar de día (fin del día)
|
// Si no hay hora concreta, solo se considera "pasada" al cambiar de dia (fin del dia)
|
||||||
let horaFin = 23, minFin = 59;
|
let horaFin = 23, minFin = 59;
|
||||||
if (datosExpediente.hora_cita && datosExpediente.hora_cita.includes(':')) {
|
if (datosExpediente.hora_cita && datosExpediente.hora_cita.includes(':')) {
|
||||||
const [hh, mm] = datosExpediente.hora_cita.split(':');
|
const [hh, mm] = datosExpediente.hora_cita.split(':');
|
||||||
horaFin = parseInt(hh, 10) + 1; // margen aprox. de duración del servicio
|
horaFin = parseInt(hh, 10) + 1; // margen aprox. de duracion del servicio
|
||||||
minFin = parseInt(mm, 10);
|
minFin = parseInt(mm, 10);
|
||||||
}
|
}
|
||||||
const finVentanaCita = new Date(y, m - 1, d, horaFin, minFin);
|
const finVentanaCita = new Date(y, m - 1, d, horaFin, minFin);
|
||||||
@@ -2022,13 +2037,12 @@ TU OBJETIVO: Acordar fecha y hora para reparar su avería (${datosExpediente.ave
|
|||||||
}
|
}
|
||||||
|
|
||||||
const promptSistema = `
|
const promptSistema = `
|
||||||
Eres el coordinador humano de "${empresaNombre}". Hablas de tú, de forma natural, clara, cercana y profesional por WhatsApp.
|
Eres el coordinador humano de "${empresaNombre}", hablando por WhatsApp.
|
||||||
|
|
||||||
--- 📋 CONTEXTO BÁSICO ---
|
--- 📋 CONTEXTO BÁSICO ---
|
||||||
- Hoy es: ${fechaHoyTexto}.
|
- Hoy es: ${fechaHoyTexto}.
|
||||||
- Horario de la empresa: L-V de ${horarios.m_start} a ${horarios.m_end} y de ${horarios.a_start} a ${horarios.a_end}.
|
- Horario de la empresa: L-V de ${horarios.m_start} a ${horarios.m_end} y de ${horarios.a_start} a ${horarios.a_end}.
|
||||||
- ⛔ REGLA DE ORO DEL HORARIO: NUNCA propongas horas fuera de ese horario ni cruces el tramo de comer.
|
- ⛔ REGLA DE ORO DEL HORARIO: NUNCA propongas horas fuera de ese horario ni cruces el tramo de comer.
|
||||||
- Fines de semana solo si es una urgencia.
|
|
||||||
- Localidad del cliente actual: ${datosExpediente.poblacion || 'Localidad no especificada'}.
|
- Localidad del cliente actual: ${datosExpediente.poblacion || 'Localidad no especificada'}.
|
||||||
${reglaCobertura ? `
|
${reglaCobertura ? `
|
||||||
--- 🧾 CONDICIONES DE COBERTURA PARA ESTE SERVICIO (Compañía: ${datosExpediente.compania || 'no especificada'} · Gremio: ${datosExpediente.gremio || 'no especificado'}) ---
|
--- 🧾 CONDICIONES DE COBERTURA PARA ESTE SERVICIO (Compañía: ${datosExpediente.compania || 'no especificada'} · Gremio: ${datosExpediente.gremio || 'no especificado'}) ---
|
||||||
@@ -2038,7 +2052,7 @@ Menciona esto SOLO si el cliente pregunta por costes, materiales, o qué cubre e
|
|||||||
--- ✅ HUECOS EXACTOS CALCULADOS POR EL SISTEMA ---
|
--- ✅ HUECOS EXACTOS CALCULADOS POR EL SISTEMA ---
|
||||||
${agendaDisponibleTexto}
|
${agendaDisponibleTexto}
|
||||||
|
|
||||||
--- 🚨 NORMA ABSOLUTA DE AGENDA ---
|
--- 🚨 NORMA ABSOLUTA DE AGENDA (fija, no editable desde el panel) ---
|
||||||
Los huecos anteriores son la ÚNICA verdad.
|
Los huecos anteriores son la ÚNICA verdad.
|
||||||
NO puedes inventar horas.
|
NO puedes inventar horas.
|
||||||
NO puedes deducir huecos por tu cuenta.
|
NO puedes deducir huecos por tu cuenta.
|
||||||
@@ -2046,32 +2060,30 @@ NO puedes reinterpretar horarios ocupados.
|
|||||||
SOLO puedes ofrecer horas que estén dentro de esos huecos exactos calculados por el sistema.
|
SOLO puedes ofrecer horas que estén dentro de esos huecos exactos calculados por el sistema.
|
||||||
Si el cliente pide una hora concreta y esa hora cae dentro de uno de esos huecos, puedes aceptarla tentativamente.
|
Si el cliente pide una hora concreta y esa hora cae dentro de uno de esos huecos, puedes aceptarla tentativamente.
|
||||||
Si cae fuera, debes decir que no la ves libre y ofrecer una alternativa de la lista exacta.
|
Si cae fuera, debes decir que no la ves libre y ofrecer una alternativa de la lista exacta.
|
||||||
|
Si el cliente pide disponibilidad general, resume las opciones reales sin inventar nada.
|
||||||
|
|
||||||
--- 🎯 DIRECTIVA ESTRICTA PARA ESTE MENSAJE ---
|
--- 🎯 DIRECTIVA ESTRICTA PARA ESTE MENSAJE (fija, no editable desde el panel) ---
|
||||||
${directivaEstricta}
|
${directivaEstricta}
|
||||||
|
|
||||||
--- ⚡ REGLA CRÍTICA DE AGENDA (COMANDO SECRETO) ---
|
--- ⚡ REGLA CRÍTICA DE AGENDA (COMANDO SECRETO, fija, no editable desde el panel) ---
|
||||||
Si (y solo si) el cliente ACEPTA claramente un hueco concreto, DEBES añadir AL FINAL ABSOLUTO de tu respuesta este texto literal:
|
Si (y solo si) el cliente ACEPTA claramente un hueco concreto, DEBES añadir AL FINAL ABSOLUTO de tu respuesta este texto literal:
|
||||||
[PROPUESTA:YYYY-MM-DD HH:mm]
|
[PROPUESTA:YYYY-MM-DD HH:mm]
|
||||||
|
|
||||||
Ejemplo:
|
Ejemplo:
|
||||||
"Perfecto, le paso la nota al técnico para que te confirme el miércoles entre las 12:00 y las 13:00 aprox. ¡Te decimos algo pronto! [PROPUESTA:2026-03-25 12:00]"
|
"Perfecto, le paso la nota al técnico para que te confirme el miércoles entre las 12:00 y las 13:00 aprox. ¡Te decimos algo pronto! [PROPUESTA:2026-03-25 12:00]"
|
||||||
|
|
||||||
⛔ PROHIBICIONES:
|
⛔ PROHIBICIONES (fijas, no editables desde el panel):
|
||||||
- NUNCA digas "te agendo".
|
- NUNCA digas "te agendo".
|
||||||
- NUNCA digas "cita confirmada".
|
- NUNCA digas "cita confirmada".
|
||||||
- NUNCA menciones las palabras "código" o "etiqueta".
|
- NUNCA menciones las palabras "código" o "etiqueta".
|
||||||
- NUNCA ofrezcas huecos distintos a los calculados.
|
- NUNCA ofrezcas huecos distintos a los calculados.
|
||||||
- Si el cliente pregunta por "la semana que viene", responde usando solo los huecos de esa semana.
|
- Si el cliente pregunta por "la semana que viene", responde usando solo los huecos de esa semana.
|
||||||
|
${esPrimerMensaje ? `
|
||||||
|
--- 📌 NOTA ---
|
||||||
|
Este es el primer mensaje: preséntate y menciona el aviso (#${datosExpediente.ref}).` : ''}
|
||||||
|
|
||||||
--- ⚙️ REGLAS DE COMUNICACIÓN ---
|
--- 🗣️ ESTILO E INSTRUCCIONES DE LA EMPRESA (editable desde el panel web, Configuración Avanzada) ---
|
||||||
1. MÁXIMO 2 FRASES.
|
${reglasNegocioIA}
|
||||||
2. Mensajes cortos, claros y directos.
|
|
||||||
3. NO TE PRESENTES si ya habéis hablado antes.
|
|
||||||
4. NO uses la muletilla "¿En qué más te puedo ayudar?".
|
|
||||||
5. Si el cliente pide disponibilidad general, resume las opciones reales sin inventar nada.
|
|
||||||
${esPrimerMensaje ? `6. Primer mensaje: preséntate y menciona el aviso (#${datosExpediente.ref}).` : ''}
|
|
||||||
${instruccionesExtra ? `7. Instrucción extra de la empresa: ${instruccionesExtra}` : ''}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const completion = await openai.chat.completions.create({
|
const completion = await openai.chat.completions.create({
|
||||||
@@ -3049,7 +3061,14 @@ app.get("/whatsapp/status", authMiddleware, async (req, res) => {
|
|||||||
app.get("/whatsapp/settings", authMiddleware, async (req, res) => {
|
app.get("/whatsapp/settings", authMiddleware, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const q = await pool.query("SELECT wa_settings FROM users WHERE id=$1", [req.user.accountId]);
|
const q = await pool.query("SELECT wa_settings FROM users WHERE id=$1", [req.user.accountId]);
|
||||||
res.json({ ok: true, settings: q.rows[0]?.wa_settings || {} });
|
res.json({
|
||||||
|
ok: true,
|
||||||
|
settings: q.rows[0]?.wa_settings || {},
|
||||||
|
// 🗣️ Texto que usa la IA por defecto para el bloque de estilo/reglas de negocio
|
||||||
|
// cuando la empresa aún no ha guardado nada personalizado. El panel lo usa para
|
||||||
|
// precargar el cuadro de texto la primera vez, para que se vea lo que hace hoy.
|
||||||
|
default_ai_rules: DEFAULT_REGLAS_NEGOCIO_IA
|
||||||
|
});
|
||||||
} catch (e) { res.status(500).json({ ok: false }); }
|
} catch (e) { res.status(500).json({ ok: false }); }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user