diff --git a/server.js b/server.js index 516c44d..6d08d32 100644 --- a/server.js +++ b/server.js @@ -2968,53 +2968,8 @@ app.post('/api/chat', requireAuth, async (req, res) => { let detectedText = null; let usingGroqForDetection = false; - // 1) Tentar MiniMax M3 como primário - if (process.env.MINIMAX_API_KEY) { - try { - console.log('[Smart Router] Detectando intenção via MiniMax M3...'); - const r = await callMinimax({ - messages: [{ role: 'user', content: promptText }], - system: systemDetector, - temperature: 0.0, - max_tokens: 20 - }); - detectedText = r.text; - } catch (err) { - console.error('[Smart Router] Falha na detecção via MiniMax, tentando OpenRouter...', err.message); - } - } - - // 2) Fallback: OpenRouter - if (!detectedText && process.env.OPENROUTER_API_KEY) { - try { - console.log('[Smart Router] Detectando intenção via OpenRouter...'); - const detectResponse = await fetch('https://openrouter.ai/api/v1/chat/completions', { - method: 'POST', - headers: { - 'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`, - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - model: process.env.OPENROUTER_MODEL || 'openai/gpt-4.1-nano', - messages: [ - { role: 'system', content: systemDetector }, - { role: 'user', content: promptText } - ], - max_tokens: 20, - temperature: 0.0 - }) - }); - if (detectResponse.ok) { - const detectData = await detectResponse.json(); - detectedText = detectData.choices?.[0]?.message?.content?.toUpperCase() || null; - } - } catch (err) { - console.error('[Smart Router] Falha de detecção na OpenRouter, tentando Groq...', err.message); - } - } - - // 3) Fallback final: Groq - if (!detectedText && process.env.GROQ_API_KEY) { + // 1) Tentar Groq como primário (ultrarrápido para classificação) + if (process.env.GROQ_API_KEY) { console.log('[Smart Router] Detectando intenção via Groq (llama-3.1-8b-instant)...'); try { const detectResponse = await fetch('https://api.groq.com/openai/v1/chat/completions', { @@ -3039,7 +2994,52 @@ app.post('/api/chat', requireAuth, async (req, res) => { usingGroqForDetection = !!detectedText; } } catch (groqErr) { - console.error('[Smart Router] Falha de detecção na API da Groq:', groqErr.message); + console.error('[Smart Router] Falha de detecção na API da Groq, tentando MiniMax...', groqErr.message); + } + } + + // 2) Fallback: MiniMax M3 + if (!detectedText && process.env.MINIMAX_API_KEY) { + try { + console.log('[Smart Router] Detectando intenção via MiniMax M3...'); + const r = await callMinimax({ + messages: [{ role: 'user', content: promptText }], + system: systemDetector, + temperature: 0.0, + max_tokens: 20 + }); + detectedText = r.text; + } catch (err) { + console.error('[Smart Router] Falha na detecção via MiniMax, tentando OpenRouter...', err.message); + } + } + + // 3) Fallback final: OpenRouter + if (!detectedText && process.env.OPENROUTER_API_KEY) { + try { + console.log('[Smart Router] Detectando intenção via OpenRouter...'); + const detectResponse = await fetch('https://openrouter.ai/api/v1/chat/completions', { + method: 'POST', + headers: { + 'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + model: process.env.OPENROUTER_MODEL || 'openai/gpt-4.1-nano', + messages: [ + { role: 'system', content: systemDetector }, + { role: 'user', content: promptText } + ], + max_tokens: 20, + temperature: 0.0 + }) + }); + if (detectResponse.ok) { + const detectData = await detectResponse.json(); + detectedText = detectData.choices?.[0]?.message?.content?.toUpperCase() || null; + } + } catch (err) { + console.error('[Smart Router] Falha de detecção final na OpenRouter:', err.message); } } @@ -3445,54 +3445,37 @@ app.post('/api/chat', requireAuth, async (req, res) => { let chatResponse; let providerUsed = 'MiniMax-M3'; - // 1) Tentar MiniMax M3 (NÃO-STREAMING para o M3 porque o M3 devolve thinking blocks - // que não seguem o protocolo SSE do OpenAI; a UI consome o JSON final e faz o streaming - // via o endpoint /v1/chat/completions que vamos montar localmente). - let useMinimaxNonStream = false; + // 1) Tentar MiniMax M3 (Streaming OpenAI-compatível) para velocidade instantânea + let useMinimaxStream = false; try { - console.log('[Smart Router] Chamando MiniMax M3 (não-streaming, JSON final)...'); - const minmBase = (process.env.MINIMAX_API_BASE || 'https://api.minimax.io/v1').replace(/\/v1\/?$/, ''); - const minmResp = await fetch(`${minmBase}/anthropic/v1/messages`, { - method: 'POST', - headers: { - 'X-Api-Key': process.env.MINIMAX_API_KEY, - 'Content-Type': 'application/json', - 'anthropic-version': '2023-06-01' - }, - body: JSON.stringify({ - model: process.env.MINIMAX_MODEL || 'MiniMax-M3', - max_tokens: 4096, - temperature, - system: enrichedMessages[0].content, - messages: enrichedMessages.slice(1) - }) - }); - if (minmResp.ok) { - const data = await minmResp.json(); - const text = (data.content || []).filter(b => b.type === 'text').map(b => b.text).join('').trim(); - if (text) { - // "Transformar" resposta JSON em um objeto compatível com o resto do fluxo: - // devolvemos um Response falso com stream SSE - const sseBody = - `data: ${JSON.stringify({ choices: [{ delta: { content: text } }] })}\n\n` + - `data: [DONE]\n\n`; - chatResponse = new Response(sseBody, { - status: 200, - headers: { 'Content-Type': 'text/event-stream' } - }); - useMinimaxNonStream = true; + if (process.env.MINIMAX_API_KEY) { + console.log('[Smart Router] Chamando MiniMax M3 (streaming OpenAI-compat)...'); + const minmBase = (process.env.MINIMAX_API_BASE || 'https://api.minimax.io/v1').replace(/\/v1\/?$/, ''); + chatResponse = await fetch(`${minmBase}/v1/chat/completions`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${process.env.MINIMAX_API_KEY}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + model: process.env.MINIMAX_MODEL || 'MiniMax-M3', + messages: enrichedMessages, + stream: true, + temperature + }) + }); + if (chatResponse.ok) { + useMinimaxStream = true; } else { - console.warn('[Smart Router] M3 respondeu OK mas sem texto; caindo no OpenRouter.'); + console.warn('[Smart Router] M3 streaming status', chatResponse.status, '- caindo no OpenRouter.'); } - } else { - console.warn('[Smart Router] M3 status', minmResp.status, '- caindo no OpenRouter.'); } } catch (e) { - console.error('Erro na conexão com MiniMax M3, tentando OpenRouter...', e.message); + console.error('Erro na conexão streaming com MiniMax M3, tentando OpenRouter...', e.message); } // 2) Fallback: OpenRouter (streaming SSE, igual ao original) - if ((!chatResponse || !chatResponse.ok) && !useMinimaxNonStream && process.env.OPENROUTER_API_KEY) { + if ((!chatResponse || !chatResponse.ok) && !useMinimaxStream && process.env.OPENROUTER_API_KEY) { console.log('[Smart Router] Usando OpenRouter como fallback de streaming de texto...'); providerUsed = 'OpenRouter'; try {