189 lines
7.0 KiB
JavaScript
189 lines
7.0 KiB
JavaScript
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();
|