⚡ Auto-deploy: Otimização da latência de chat (detecção rápida com Groq e streaming nativo com MiniMax M3)
This commit is contained in:
@@ -2968,53 +2968,8 @@ app.post('/api/chat', requireAuth, async (req, res) => {
|
|||||||
let detectedText = null;
|
let detectedText = null;
|
||||||
let usingGroqForDetection = false;
|
let usingGroqForDetection = false;
|
||||||
|
|
||||||
// 1) Tentar MiniMax M3 como primário
|
// 1) Tentar Groq como primário (ultrarrápido para classificação)
|
||||||
if (process.env.MINIMAX_API_KEY) {
|
if (process.env.GROQ_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) {
|
|
||||||
console.log('[Smart Router] Detectando intenção via Groq (llama-3.1-8b-instant)...');
|
console.log('[Smart Router] Detectando intenção via Groq (llama-3.1-8b-instant)...');
|
||||||
try {
|
try {
|
||||||
const detectResponse = await fetch('https://api.groq.com/openai/v1/chat/completions', {
|
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;
|
usingGroqForDetection = !!detectedText;
|
||||||
}
|
}
|
||||||
} catch (groqErr) {
|
} 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 chatResponse;
|
||||||
let providerUsed = 'MiniMax-M3';
|
let providerUsed = 'MiniMax-M3';
|
||||||
|
|
||||||
// 1) Tentar MiniMax M3 (NÃO-STREAMING para o M3 porque o M3 devolve thinking blocks
|
// 1) Tentar MiniMax M3 (Streaming OpenAI-compatível) para velocidade instantânea
|
||||||
// que não seguem o protocolo SSE do OpenAI; a UI consome o JSON final e faz o streaming
|
let useMinimaxStream = false;
|
||||||
// via o endpoint /v1/chat/completions que vamos montar localmente).
|
|
||||||
let useMinimaxNonStream = false;
|
|
||||||
try {
|
try {
|
||||||
console.log('[Smart Router] Chamando MiniMax M3 (não-streaming, JSON final)...');
|
if (process.env.MINIMAX_API_KEY) {
|
||||||
const minmBase = (process.env.MINIMAX_API_BASE || 'https://api.minimax.io/v1').replace(/\/v1\/?$/, '');
|
console.log('[Smart Router] Chamando MiniMax M3 (streaming OpenAI-compat)...');
|
||||||
const minmResp = await fetch(`${minmBase}/anthropic/v1/messages`, {
|
const minmBase = (process.env.MINIMAX_API_BASE || 'https://api.minimax.io/v1').replace(/\/v1\/?$/, '');
|
||||||
method: 'POST',
|
chatResponse = await fetch(`${minmBase}/v1/chat/completions`, {
|
||||||
headers: {
|
method: 'POST',
|
||||||
'X-Api-Key': process.env.MINIMAX_API_KEY,
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Authorization': `Bearer ${process.env.MINIMAX_API_KEY}`,
|
||||||
'anthropic-version': '2023-06-01'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
model: process.env.MINIMAX_MODEL || 'MiniMax-M3',
|
model: process.env.MINIMAX_MODEL || 'MiniMax-M3',
|
||||||
max_tokens: 4096,
|
messages: enrichedMessages,
|
||||||
temperature,
|
stream: true,
|
||||||
system: enrichedMessages[0].content,
|
temperature
|
||||||
messages: enrichedMessages.slice(1)
|
})
|
||||||
})
|
});
|
||||||
});
|
if (chatResponse.ok) {
|
||||||
if (minmResp.ok) {
|
useMinimaxStream = true;
|
||||||
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;
|
|
||||||
} else {
|
} 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) {
|
} 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)
|
// 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...');
|
console.log('[Smart Router] Usando OpenRouter como fallback de streaming de texto...');
|
||||||
providerUsed = 'OpenRouter';
|
providerUsed = 'OpenRouter';
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user