fix(assistant): add FormattedMessage markdown parser and handle '¿Que puedo preguntar?' with comprehensive guide
This commit is contained in:
@@ -23,7 +23,14 @@ export async function POST(req: NextRequest) {
|
||||
console.error('Error parsing chat body:', e);
|
||||
}
|
||||
|
||||
const query = userMessage.toLowerCase().trim();
|
||||
// Normalizar consulta eliminando tildes, signos de interrogación y puntuación
|
||||
const normQuery = userMessage
|
||||
.toLowerCase()
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/[¿?¡!.,;:_()]/g, ' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
|
||||
// 2. Obtener tenant_id dinámico del usuario autenticado
|
||||
let tenantId = '0b3c5fc0-6901-4caf-b26a-b6a0201d8541';
|
||||
@@ -51,39 +58,64 @@ export async function POST(req: NextRequest) {
|
||||
return NextResponse.json([{ text }]);
|
||||
};
|
||||
|
||||
// 3. Intención: Saludos y Presentación
|
||||
if (
|
||||
query === '' ||
|
||||
query === 'hola' ||
|
||||
query === 'buenas' ||
|
||||
query === 'buenos dias' ||
|
||||
query === 'buenas tardes' ||
|
||||
query === 'hey' ||
|
||||
query.includes('que puedes hacer') ||
|
||||
query.includes('quien eres') ||
|
||||
query.includes('ayuda')
|
||||
) {
|
||||
// 3. Intención: Saludos, Capacidades y "¿Qué puedo preguntar?"
|
||||
const isHelpQuery =
|
||||
normQuery === '' ||
|
||||
normQuery === 'hola' ||
|
||||
normQuery === 'buenas' ||
|
||||
normQuery === 'buenos dias' ||
|
||||
normQuery === 'buenas tardes' ||
|
||||
normQuery === 'hey' ||
|
||||
normQuery.includes('que puedo preguntar') ||
|
||||
normQuery.includes('que te puedo preguntar') ||
|
||||
normQuery.includes('que preguntar') ||
|
||||
normQuery.includes('que sabes') ||
|
||||
normQuery.includes('que puedes hacer') ||
|
||||
normQuery.includes('quien eres') ||
|
||||
normQuery.includes('ayuda') ||
|
||||
normQuery.includes('ejemplos') ||
|
||||
normQuery.includes('comandos') ||
|
||||
normQuery.includes('opciones') ||
|
||||
normQuery.includes('como funciona el asistente') ||
|
||||
normQuery.includes('instrucciones');
|
||||
|
||||
if (isHelpQuery) {
|
||||
return reply(
|
||||
`👋 **¡Hola! Soy el Asistente Financiero y de Crecimiento de 4Ventures** para **${companyName}**.\n\n` +
|
||||
`Estoy conectado directamente a tu base de datos analítica y ejecuto cálculos matemáticos deterministas (temperatura 0.0, sin alucinaciones):\n\n` +
|
||||
`💡 **¿Qué puedes consultarme?**\n` +
|
||||
`1. **Simulaciones presupuestarias:** *«¿Qué pasa si invierto 1.500 € en Meta?»* o *«Simular 2.000 € en Google»*.\n` +
|
||||
`2. **Cumplimiento de Objetivos:** *«¿Cómo vamos con los objetivos de este mes?»*.\n` +
|
||||
`3. **Embudo y Conversión:** *«Muéstrame el embudo comercial y tasa de cierre»*.\n` +
|
||||
`4. **Métricas de CAC y ROAS:** *«¿Cuál es el CAC y ROAS de los últimos 30 días?»*.\n` +
|
||||
`5. **Ranking de Anuncios:** *«¿Cuáles son las mejores campañas activas?»*.\n` +
|
||||
`6. **Biblioteca de Activos:** *«Busca copys de Meta Ads o informes de auditoría»*.\n\n` +
|
||||
`¿Qué métrica o escenario te gustaría analizar hoy?`
|
||||
`👋 **¡Hola! Soy tu Asistente Financiero & de Crecimiento de 4Ventures** para **${companyName}**.\n\n` +
|
||||
`Estoy conectado directamente a tu base de datos analítica y ejecuto cálculos matemáticos deterministas (temperatura 0.0, sin alucinaciones). Aquí tienes todo lo que puedes preguntarme:\n\n` +
|
||||
`1. **🔮 Simulaciones de Inversión ("¿Qué pasa si...?"):**\n` +
|
||||
` - *«¿Qué pasa si invierto 1.000 € en Meta?»*\n` +
|
||||
` - *«Simular 2.500 € en Google Ads»*\n` +
|
||||
` - *«Proyección con 5.000 € de presupuesto»*\n` +
|
||||
` *(Calcula retornos p10 conservador, p50 esperado y p90 optimista según tu histórico real).* \n\n` +
|
||||
`2. **🎯 Objetivos y Cumplimiento Mensual:**\n` +
|
||||
` - *«¿Cómo van los objetivos de este mes?»*\n` +
|
||||
` - *«¿Cuánto llevamos facturado vs la meta?»*\n` +
|
||||
` - *«Progreso de captación de leads»*\n\n` +
|
||||
`3. **🔄 Embudo Comercial y Conversión:**\n` +
|
||||
` - *«Muéstrame el embudo comercial»*\n` +
|
||||
` - *«¿Cuál es nuestra tasa de cierre lead a venta?»*\n` +
|
||||
` - *«Ticket medio de los clientes ganados»*\n\n` +
|
||||
`4. **📊 Métricas CAC y ROAS por Canal:**\n` +
|
||||
` - *«¿Cuál es el CAC y ROAS de los últimos 30 días?»*\n` +
|
||||
` - *«Rendimiento por canal publicitario»*\n\n` +
|
||||
`5. **🏆 Ranking de Campañas:**\n` +
|
||||
` - *«¿Cuáles son las mejores campañas activas?»*\n` +
|
||||
` - *«¿Dónde estamos invirtiendo más?»*\n\n` +
|
||||
`6. **📖 Metodología y Glosario 4Ventures:**\n` +
|
||||
` - *«¿Qué diferencia hay entre CAC de cohorte y CAC de caja?»*\n` +
|
||||
` - *«¿Cómo funciona la atribución universal a 90 días?»*\n\n` +
|
||||
`💡 *Puedes hacer clic en cualquiera de los botones rápidos de abajo o escribir directamente tu consulta.*`
|
||||
);
|
||||
}
|
||||
|
||||
// 4. Intención: Simulación Determinista "¿Qué pasa si...?"
|
||||
if (
|
||||
query.includes('simul') ||
|
||||
query.includes('invierto') ||
|
||||
query.includes('pasa si') ||
|
||||
query.includes('proyec') ||
|
||||
query.includes('presupuesto')
|
||||
normQuery.includes('simul') ||
|
||||
normQuery.includes('invierto') ||
|
||||
normQuery.includes('pasa si') ||
|
||||
normQuery.includes('proyec') ||
|
||||
normQuery.includes('presupuesto')
|
||||
) {
|
||||
try {
|
||||
const matchNumber = query.match(/(\d+[\d\.,]*)/);
|
||||
@@ -93,10 +125,10 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
|
||||
let channel: string | null = null;
|
||||
if (query.includes('meta') || query.includes('facebook') || query.includes('instagram')) channel = 'meta';
|
||||
else if (query.includes('google')) channel = 'google';
|
||||
else if (query.includes('tiktok')) channel = 'tiktok';
|
||||
else if (query.includes('linkedin')) channel = 'linkedin';
|
||||
if (normQuery.includes('meta') || normQuery.includes('facebook') || normQuery.includes('instagram')) channel = 'meta';
|
||||
else if (normQuery.includes('google')) channel = 'google';
|
||||
else if (normQuery.includes('tiktok')) channel = 'tiktok';
|
||||
else if (normQuery.includes('linkedin')) channel = 'linkedin';
|
||||
|
||||
const res = await fetch(`${supabaseUrl}/rest/v1/rpc/simulate_budget`, {
|
||||
method: 'POST',
|
||||
@@ -137,11 +169,11 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
// 5. Intención: Objetivos vs Real / Estrategia
|
||||
if (
|
||||
query.includes('objetivo') ||
|
||||
query.includes('meta') ||
|
||||
query.includes('factura') ||
|
||||
query.includes('target') ||
|
||||
query.includes('cumplimiento')
|
||||
normQuery.includes('objetivo') ||
|
||||
normQuery.includes('meta') ||
|
||||
normQuery.includes('factura') ||
|
||||
normQuery.includes('target') ||
|
||||
normQuery.includes('cumplimiento')
|
||||
) {
|
||||
try {
|
||||
const now = new Date();
|
||||
@@ -176,12 +208,12 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
// 6. Intención: Embudo / Funnel / Conversión
|
||||
if (
|
||||
query.includes('funnel') ||
|
||||
query.includes('embudo') ||
|
||||
query.includes('tasa') ||
|
||||
query.includes('ticket') ||
|
||||
query.includes('conversion') ||
|
||||
query.includes('cierre')
|
||||
normQuery.includes('funnel') ||
|
||||
normQuery.includes('embudo') ||
|
||||
normQuery.includes('tasa') ||
|
||||
normQuery.includes('ticket') ||
|
||||
normQuery.includes('conversion') ||
|
||||
normQuery.includes('cierre')
|
||||
) {
|
||||
try {
|
||||
const res = await fetch(`${supabaseUrl}/rest/v1/rpc/lead_funnel`, {
|
||||
@@ -213,11 +245,11 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
// 7. Intención: Ranking de Campañas / Anuncios
|
||||
if (
|
||||
query.includes('campa') ||
|
||||
query.includes('anuncio') ||
|
||||
query.includes('ranking') ||
|
||||
query.includes('mejor') ||
|
||||
query.includes('ads')
|
||||
normQuery.includes('campa') ||
|
||||
normQuery.includes('anuncio') ||
|
||||
normQuery.includes('ranking') ||
|
||||
normQuery.includes('mejor') ||
|
||||
normQuery.includes('ads')
|
||||
) {
|
||||
try {
|
||||
const res = await fetch(`${supabaseUrl}/rest/v1/rpc/rank_campaigns`, {
|
||||
@@ -245,12 +277,12 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
// 8. Intención: RAG Documental Híbrido (Biblioteca de Activos)
|
||||
if (
|
||||
query.includes('document') ||
|
||||
query.includes('copy') ||
|
||||
query.includes('informe') ||
|
||||
query.includes('brief') ||
|
||||
query.includes('activo') ||
|
||||
query.includes('creativo')
|
||||
normQuery.includes('document') ||
|
||||
normQuery.includes('copy') ||
|
||||
normQuery.includes('informe') ||
|
||||
normQuery.includes('brief') ||
|
||||
normQuery.includes('activo') ||
|
||||
normQuery.includes('creativo')
|
||||
) {
|
||||
try {
|
||||
const res = await fetch(`${supabaseUrl}/rest/v1/rpc/match_documents`, {
|
||||
@@ -290,12 +322,12 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
// 9. Intención: Metodología y Glosario 4Ventures
|
||||
if (
|
||||
query.includes('que es cac') ||
|
||||
query.includes('cohorte') ||
|
||||
query.includes('caja') ||
|
||||
query.includes('atribucion') ||
|
||||
query.includes('90 dias') ||
|
||||
query.includes('metodologia')
|
||||
normQuery.includes('que es cac') ||
|
||||
normQuery.includes('cohorte') ||
|
||||
normQuery.includes('caja') ||
|
||||
normQuery.includes('atribucion') ||
|
||||
normQuery.includes('90 dias') ||
|
||||
normQuery.includes('metodologia')
|
||||
) {
|
||||
return reply(
|
||||
`📖 **Metodología Oficial de Crecimiento — 4Ventures:**\n\n` +
|
||||
|
||||
Reference in New Issue
Block a user