feat: implementado fallback automatico do Groq para classificacao e chat de texto
This commit is contained in:
@@ -5,3 +5,5 @@ OPENROUTER_MODEL=openai/gpt-4.1-nano
|
||||
SESSION_SECRET=camila-secret-key-321123
|
||||
MINIMAX_API_KEY=sk-cp-iWzSsdzjVy0tT5dnvv_sGrAlv3Nw7kkrZ8hPK0KjbNeSRQxIY1O6AhkQAq_yrYV1XPJY1TH6ZQeOlJZd-Zi_elkJhef9PcTSzn2m9bcKIxezarM19BREcVM
|
||||
MINIMAX_API_BASE=https://api.minimax.io/v1
|
||||
GROQ_API_KEY=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
|
||||
GROQ_MODEL=llama-3.3-70b-versatile
|
||||
|
||||
@@ -274,7 +274,11 @@ app.post('/api/chat', requireAuth, async (req, res) => {
|
||||
try {
|
||||
const systemDetector = "Você é um classificador de intenções de prompt. Classifique a última mensagem do usuário em uma destas quatro categorias exatas: 'TEXT' (para conversas normais, perguntas, redação de relatórios, planejamentos, textos pedagógicos, respostas gerais), 'IMAGE' (se o usuário estiver pedindo explicitamente para gerar, desenhar, criar ou ilustrar uma imagem, figura, ilustração ou foto), 'AUDIO' (se o usuário estiver pedindo explicitamente para gerar uma música, melodia, trilha sonora, cantiga ou som), ou 'VIDEO' (se o usuário estiver pedindo explicitamente para gerar ou criar um vídeo ou animação). Responda APENAS com a palavra da categoria em letras maiúsculas: TEXT, IMAGE, AUDIO, VIDEO.";
|
||||
|
||||
const detectResponse = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
||||
let detectResponse;
|
||||
let usingGroqForDetection = false;
|
||||
|
||||
try {
|
||||
detectResponse = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`,
|
||||
@@ -290,8 +294,37 @@ app.post('/api/chat', requireAuth, async (req, res) => {
|
||||
temperature: 0.0
|
||||
})
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('[Smart Router] Falha de conexão com OpenRouter para detecção, tentando Groq...', err.message);
|
||||
}
|
||||
|
||||
if (detectResponse.ok) {
|
||||
// Se OpenRouter falhou ou retornou erro (ex: status != 200), tenta o Groq como fallback
|
||||
if ((!detectResponse || !detectResponse.ok) && process.env.GROQ_API_KEY) {
|
||||
console.log('[Smart Router] Usando Groq (llama-3.1-8b-instant) para classificar intenção...');
|
||||
try {
|
||||
detectResponse = await fetch('https://api.groq.com/openai/v1/chat/completions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.GROQ_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'llama-3.1-8b-instant',
|
||||
messages: [
|
||||
{ role: 'system', content: systemDetector },
|
||||
{ role: 'user', content: promptText }
|
||||
],
|
||||
max_tokens: 20,
|
||||
temperature: 0.0
|
||||
})
|
||||
});
|
||||
usingGroqForDetection = detectResponse.ok;
|
||||
} catch (groqErr) {
|
||||
console.error('[Smart Router] Falha de detecção na API da Groq:', groqErr.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (detectResponse && detectResponse.ok) {
|
||||
const detectData = await detectResponse.json();
|
||||
const detectedText = detectData.choices?.[0]?.message?.content?.toUpperCase() || 'TEXT';
|
||||
console.log(`[Smart Router] Resposta crua do detector: "${detectedText}"`);
|
||||
@@ -615,13 +648,16 @@ app.post('/api/chat', requireAuth, async (req, res) => {
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// FLUXO PADRÃO DE TEXTO (OpenRouter com SSE streaming original)
|
||||
// FLUXO PADRÃO DE TEXTO (OpenRouter com SSE streaming original, com fallback Groq)
|
||||
// ==========================================================================
|
||||
const enrichedMessages = [KEMILY_SYSTEM_PROMPT, ...messages];
|
||||
|
||||
try {
|
||||
const openrouterUrl = 'https://openrouter.ai/api/v1/chat/completions';
|
||||
const response = await fetch(openrouterUrl, {
|
||||
let chatResponse;
|
||||
let providerUsed = 'OpenRouter';
|
||||
|
||||
try {
|
||||
chatResponse = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`,
|
||||
@@ -635,11 +671,36 @@ app.post('/api/chat', requireAuth, async (req, res) => {
|
||||
stream: true
|
||||
})
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Erro na conexão com OpenRouter, tentando Groq...', e.message);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error('Erro na API do OpenRouter:', errorText);
|
||||
return res.status(response.status).json({ error: 'Erro ao processar requisição na API do OpenRouter' });
|
||||
// Se o OpenRouter falhar ou retornar erro (ex: status != 200), caímos no fallback do Groq
|
||||
if ((!chatResponse || !chatResponse.ok) && process.env.GROQ_API_KEY) {
|
||||
console.log('[Smart Router] Usando Groq (llama-3.3-70b-versatile) como fallback de streaming de texto...');
|
||||
providerUsed = 'Groq';
|
||||
try {
|
||||
chatResponse = await fetch('https://api.groq.com/openai/v1/chat/completions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.GROQ_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: process.env.GROQ_MODEL || 'llama-3.3-70b-versatile',
|
||||
messages: enrichedMessages,
|
||||
stream: true
|
||||
})
|
||||
});
|
||||
} catch (groqErr) {
|
||||
console.error('[Smart Router] Erro crítico: Falha no fallback do Groq também:', groqErr.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (!chatResponse || !chatResponse.ok) {
|
||||
const errorText = chatResponse ? await chatResponse.text() : 'Sem conexão com os servidores de IA';
|
||||
console.error(`Erro na API de IA (${providerUsed}):`, errorText);
|
||||
return res.status(500).json({ error: `Erro ao processar requisição na API de IA (${providerUsed})` });
|
||||
}
|
||||
|
||||
// Configurar headers para Server-Sent Events (SSE)
|
||||
@@ -647,7 +708,7 @@ app.post('/api/chat', requireAuth, async (req, res) => {
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const reader = chatResponse.body.getReader();
|
||||
const decoder = new TextDecoder('utf-8');
|
||||
let buffer = '';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user