From c966be7ed4476a284c4bf369348b636d85fb7d7a Mon Sep 17 00:00:00 2001 From: admtracksteel Date: Tue, 2 Jun 2026 15:02:10 +0000 Subject: [PATCH] Corrige a inclusao de obs gerais e aumenta limites de tokens das IAs para evitar cortes --- scratch/test_gen.js | 188 ++++++++++++++++++++++++++++++++++++++++++++ server.js | 7 +- 2 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 scratch/test_gen.js diff --git a/scratch/test_gen.js b/scratch/test_gen.js new file mode 100644 index 0000000..ae33e04 --- /dev/null +++ b/scratch/test_gen.js @@ -0,0 +1,188 @@ +const { Pool } = require('pg'); +require('dotenv').config(); + +const dbPool = new Pool({ + connectionString: process.env.DATABASE_URL +}); + +function readAgentConfig() { + try { + const fs = require('fs'); + const path = require('path'); + const CONFIG_FILE_PATH = path.join(__dirname, '../agent_config.json'); + if (fs.existsSync(CONFIG_FILE_PATH)) { + return JSON.parse(fs.readFileSync(CONFIG_FILE_PATH, 'utf8')); + } + } catch (err) { + console.error('Erro ao ler agent_config.json:', err); + } + return {}; +} + +async function test() { + try { + const crianca = 'Maria'; + const modeloId = 2; // O ID de Avaliação Semestral Individual + + // 1. Buscar o modelo/template + const templateRes = await dbPool.query("SELECT * FROM escola.modelos WHERE id = $1;", [modeloId]); + const template = templateRes.rows[0]; + console.log('Template:', template.nome); + + // 2. Buscar as observações + let sql = ` + SELECT date, time, report, criancas, tags + FROM escola.observacoes + WHERE 1=1 + `; + const params = []; + let pCount = 1; + + sql += ` AND ( + (jsonb_typeof(criancas) = 'array' AND EXISTS ( + SELECT 1 FROM jsonb_array_elements_text(criancas) AS c + WHERE LOWER(c) LIKE $${pCount} + )) + OR jsonb_typeof(criancas) = 'null' + OR criancas IS NULL + )`; + params.push(`%${crianca.toLowerCase()}%`); + pCount++; + + sql += ` ORDER BY date ASC`; + const dbRes = await dbPool.query(sql, params); + const observations = dbRes.rows; + console.log('Quantidade de observações:', observations.length); + + // 3. Montar prompt + const combinedObsText = observations.map((o, idx) => { + const dateText = o.date ? `Data: ${o.date}` : ''; + const tagsText = o.tags ? `Tags: ${Array.isArray(o.tags) ? o.tags.join(', ') : o.tags}` : ''; + return `[Observação #${idx + 1} ${dateText} ${tagsText}]\n${o.report}`; + }).join('\n\n---\n\n'); + + const agentConfig = readAgentConfig(); + const agentName = agentConfig.agentName || "Kemily"; + + const targetStudentInfo = `\nATENÇÃO CRÍTICA: A criança que está sendo avaliada e para quem você deve gerar o relatório individual é especificamente: "${crianca}". Todas as observações, avanços, preferências e conclusões descritas na PARTE 2 (Desenvolvimento Individual) devem referir-se exclusivamente a ${crianca}. Nunca confunda ${crianca} com outros colegas eventualmente citados nas observações (como Joãozinho, Vanderlei, etc.), e não atribua as ações deles a ela.\n`; + + const systemPrompt = `Você é a ${agentName}, uma assistente pedagógica e especialista em educação infantil. +Seu objetivo é analisar o histórico de observações de uma criança e redigir um relatório pedagógico consolidado e profissional sobre o desenvolvimento individual desta criança. +${targetStudentInfo} + +Você DEVE estruturar o relatório seguindo exatamente as seções e diretrizes fornecidas no modelo de relatório selecionado. + +MODELO DE RELATÓRIO: "${template.nome}" +FINALIDADE: "${template.finalidade || 'Não informada'}" +PERIODICIDADE: "${template.periodicidade || 'Não informada'}" + +ESTRUTURA/DIRETRIZES DO MODELO: +""" +${template.estrutura} +""" + +HISTÓRICO DE OBSERVAÇÕES REGISTRADAS: +""" +${combinedObsText} +""" + +Orientações adicionais: +- Redija o relatório em português brasileiro formal e adequado para pedagogia. +- Preencha cada seção da estrutura de forma rica e detalhada, baseando-se estritamente nos fatos reais descritos nas observações. +- Não invente acontecimentos que não estejam descritos nas observações, mas faça as conexões pedagógicas pertinentes de acordo com as evidências apresentadas. +- Retorne apenas o relatório em formato Markdown estruturado.`; + + let generatedReport = ''; + + // Tenta OpenRouter + try { + console.log('Chamando OpenRouter...'); + const response = 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: 'user', content: systemPrompt }], + temperature: 0.5, + max_tokens: 6000 + }) + }); + if (response.ok) { + const data = await response.json(); + generatedReport = data.choices?.[0]?.message?.content || ''; + console.log('OpenRouter OK! Comprimento:', generatedReport.length); + } else { + console.warn('Falha no OpenRouter status:', response.status, await response.text()); + } + } catch (err) { + console.error('Erro no OpenRouter:', err.message); + } + + // Fallback para Google Gemini + if (!generatedReport && process.env.GOOGLE_AI_API_KEY) { + try { + console.log('Fallback para Google Gemini...'); + const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${process.env.GOOGLE_AI_MODEL || 'gemini-2.5-flash'}:generateContent?key=${process.env.GOOGLE_AI_API_KEY}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + contents: [{ parts: [{ text: systemPrompt }] }], + generationConfig: { temperature: 0.5, maxOutputTokens: 8192 } + }) + }); + if (response.ok) { + const data = await response.json(); + generatedReport = data.candidates?.[0]?.content?.parts?.[0]?.text || ''; + console.log('Google Gemini OK! Comprimento:', generatedReport.length); + } else { + console.warn('Falha no Google Gemini status:', response.status, await response.text()); + } + } catch (err) { + console.error('Erro no Google Gemini:', err.message); + } + } + + // Fallback para Groq + if (!generatedReport && process.env.GROQ_API_KEY) { + try { + console.log('Fallback para Groq...'); + const response = 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: [{ role: 'user', content: systemPrompt }], + temperature: 0.5, + max_tokens: 6000 + }) + }); + if (response.ok) { + const data = await response.json(); + generatedReport = data.choices?.[0]?.message?.content || ''; + console.log('Groq OK! Comprimento:', generatedReport.length); + } else { + console.warn('Falha no Groq status:', response.status, await response.text()); + } + } catch (err) { + console.error('Erro no Groq:', err.message); + } + } + + console.log('=== REPORT GENERATED ==='); + console.log(generatedReport); + console.log('========================'); + + } catch (err) { + console.error(err); + } finally { + await dbPool.end(); + } +} + +test(); diff --git a/server.js b/server.js index 022188b..09a9809 100644 --- a/server.js +++ b/server.js @@ -913,6 +913,7 @@ app.post('/api/modelos/gerar-relatorio', requireAuth, async (req, res) => { SELECT 1 FROM jsonb_array_elements_text(criancas) AS c WHERE LOWER(c) LIKE $${pCount} )) + OR jsonb_typeof(criancas) = 'null' OR criancas IS NULL )`; params.push(`%${crianca.toLowerCase()}%`); @@ -1017,7 +1018,7 @@ Orientações adicionais: model: process.env.OPENROUTER_MODEL || 'openai/gpt-4.1-nano', messages: [{ role: 'user', content: systemPrompt }], temperature: 0.5, - max_tokens: 2500 + max_tokens: 6000 }) }); if (response.ok) { @@ -1039,7 +1040,7 @@ Orientações adicionais: headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: systemPrompt }] }], - generationConfig: { temperature: 0.5, maxOutputTokens: 2500 } + generationConfig: { temperature: 0.5, maxOutputTokens: 8192 } }) }); if (response.ok) { @@ -1065,7 +1066,7 @@ Orientações adicionais: model: process.env.GROQ_MODEL || 'llama-3.3-70b-versatile', messages: [{ role: 'user', content: systemPrompt }], temperature: 0.5, - max_tokens: 2500 + max_tokens: 6000 }) }); if (response.ok) {