feat: fase 3 - integração de observações com chat da IA

- Nova API GET /api/observacoes/buscar (filtros: crianca, mes, tags)
- Nova API GET /api/observacoes/resumo (compila relatório pedagógico via GPT)
- Resumo pedagógico estruturado: perfil, aspectos sociais/cognitivos/motores,
  pontos de atenção, pontos fortes, sugestões para planejamento
- System prompt atualizado: IA reconhece comandos como 'observações da Maria',
  'resumo pedagógico do João' e 调用a API para buscar/compilar registros
This commit is contained in:
2026-05-27 16:04:28 +00:00
parent 0b35055e23
commit e97e88d8a7
+179
View File
@@ -383,6 +383,157 @@ app.get('/api/observacoes/:yearMonth/:filename', requireAuth, (req, res) => {
res.sendFile(filePath);
});
// Rota: GET /api/observacoes/buscar — busca observações por criança e/ou período
// Query: ?crianca=Nome&mes=YYYY-MM&tags=social,cognitivo&limit=20
app.get('/api/observacoes/buscar', requireAuth, (req, res) => {
const { crianca, mes, tags, limit = 20 } = req.query;
const idx = readObsIndex();
let results = idx.observations || [];
// Filtra por criança
if (crianca) {
const searchName = crianca.toLowerCase();
results = results.filter(o =>
o.criancas && o.criancas.some(c => c.toLowerCase().includes(searchName))
);
}
// Filtra por mês
if (mes) {
results = results.filter(o => o.date && o.date.startsWith(mes));
}
// Filtra por tags
if (tags) {
const tagList = tags.split(',').map(t => t.trim());
results = results.filter(o =>
o.tags && tagList.some(t => o.tags.includes(t))
);
}
// Limita resultados
results = results.slice(0, parseInt(limit));
// Carrega conteúdo completo de cada resultado
const enriched = results.map(o => {
const filePath = path.join(OBSERVACOES_DIR, o.date?.slice(0, 7), o.filename);
let fullContent = '';
if (fs.existsSync(filePath)) {
fullContent = fs.readFileSync(filePath, 'utf8');
}
return { ...o, fullContent };
});
res.json({ observations: enriched, total: idx.observations?.length || 0 });
});
// Rota: GET /api/observacoes/resumo — compila observações em resumo para documentos
// Query: ?crianca=Nome&mes=YYYY-MM
// Retorna resumo estruturado que a IA pode usar em HTPC/planejamentos
app.get('/api/observacoes/resumo', requireAuth, async (req, res) => {
const { crianca, mes } = req.query;
if (!crianca) return res.status(400).json({ error: 'Nome da criança é obrigatório' });
// Busca observações
const idx = readObsIndex();
let results = idx.observations || [];
const searchName = crianca.toLowerCase();
results = results.filter(o =>
o.criancas && o.criancas.some(c => c.toLowerCase().includes(searchName))
);
if (mes) results = results.filter(o => o.date?.startsWith(mes));
if (results.length === 0) {
return res.json({ resumo: null, total: 0, message: `Nenhuma observação encontrada para "${crianca}"${mes ? ` em ${mes}` : ''}.` });
}
// Carrega conteúdo completo
const observations = results.slice(0, 15).map(o => {
const filePath = path.join(OBSERVACOES_DIR, o.date?.slice(0, 7), o.filename);
let fullContent = '';
if (fs.existsSync(filePath)) {
fullContent = fs.readFileSync(filePath, 'utf8');
}
return { ...o, fullContent };
});
// Compila textos
const texts = observations.map(o => o.fullContent.replace(/^---[\s\S]*?---\n/, '')).filter(Boolean);
const combined = texts.join('\n\n---\n\n');
// Pede para IA compilar resumo pedagógico
const compilePrompt = `Você é a Kemily, assistente pedagógica. Compilar um RESUMO PEDAGÓGICO consolidado a partir de várias observações de uma criança.
CRIANÇA: ${crianca}
NÚMERO DE OBSERVAÇÕES: ${observations.length}
${mes ? `PERÍODO: ${mes}` : ''}
COLEÇÃO DE OBSERVAÇÕES:
"""
${combined.slice(0, 4000)}
"""
GERE UM RESUMO ESTRUTURADO COM:
## Perfil da Criança
[Padrões de comportamento, habilidades, desenvolvimento observado]
## Aspectos Sociais e Emocionais
[Interações com outras crianças, gestão emocional, socialização]
## Aspectos Cognitivos e de Aprendizagem
[Curiosidade, resolução de problemas, atenção, concentração]
## Aspectos Motores e de Linguagem
[Desenvolvimento motor, linguagem oral, comunicação]
## Pontos de Atenção
[Dificuldades, necessidades de suporte, áreas a desenvolver]
## Pontos Fortes
[Conquistas, habilidades desarrolladas, aspectos positivos]
## Sugestões para Planejamento
[Recomendações para próximos passos, atividades sugeridas, seguimento]
-use linguagem formal-pedagógica
-Máximo 300 palavras
-Sea objetivo e baseado nas evidências das observações`;
try {
const compileRes = 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: compilePrompt }],
temperature: 0.4,
max_tokens: 800
})
});
const compileData = await compileRes.json();
const resumoText = compileData.choices?.[0]?.message?.content || '';
res.json({
crianca,
mes: mes || 'todos',
total: observations.length,
datas: observations.map(o => o.date).filter(Boolean),
resumo: resumoText,
observations: observations.map(o => ({
date: o.date, time: o.time, tags: o.tags, turma: o.turma, preview: o.preview
}))
});
} catch (err) {
console.error('Erro ao compilar resumo:', err);
res.status(500).json({ error: 'Erro ao gerar resumo pedagógico' });
}
});
// Rota POST para upload de imagem em base64
app.post('/api/upload-avatar', requireAuth, (req, res) => {
const { avatarType, base64Data } = req.body;
@@ -688,6 +839,34 @@ ESCRITA DA CRIANÇA:
- Hipótese de escrita silábico-alfabética
- Hipótese de escrita alfabética
═══════════════════════════════════════════════════
SISTEMA DE OBSERVAÇÕES POR VOZ — Como acessar registros
═══════════════════════════════════════════════════
A Camila possui um sistema de OBSERVAÇÕES POR VOZ onde grava registros sobre crianças durante o dia. Esses registros são salvos e ficam disponíveis para consulta.
QUANDO A CAMILA PEDIR "observações da [nome da criança]", "resumo da [criança]", "ler observações da [nome]" ou similar:
→ Use a API: GET /api/observacoes/resumo?crianca=[nome]&mes=YYYY-MM
→ O sistema retorna um RESUMO PEDAGÓGICO compilado de todas as observações daquela criança no período
→ Use esse resumo para ajudar a elaborar HTPCs, relatórios, planejamentos
EXEMPLOS DE COMANDO:
- "mostre as observações da Maria deste mês"
- "resumo pedagógico da Ana"
- "ler observações do João"
- "compilar observações da Sofia em maio"
AO RECEBER O RESUMO:
- Analise o conteúdo returned
- Use para fundamentar documentos que a Camila pedir
- Se não houver observações, diga: "Não encontrei observações registradas para [criança] neste período. Posso ajudar de outra forma?"
- Integre o resumo de forma natural no documento que estiver criando
LIMITES:
- Máximo 15 observações por consulta
- Resumos são compactados para caber no contexto
- Se a Camila pedir mais detalhes, pode mostrar a lista de observações individuais
═══════════════════════════════════════════════════
REGRAS DE ATUAÇÃO
═══════════════════════════════════════════════════