109 lines
3.7 KiB
JavaScript

const express = require('express');
const multer = require('multer');
const cors = require('cors');
const fs = require('fs');
const path = require('path');
const OpenAI = require('openai');
require('dotenv').config();
const app = express();
const port = 3001;
// Configurações de Segurança e JSON
app.use(cors());
app.use(express.json());
// Configuração da OpenAI
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// Configuração do Multer (Upload de arquivos temporários)
const upload = multer({ dest: 'uploads/' });
// Rota Principal: Recebe áudio e devolve JSON
app.post('/api/transcrever-relatorio', upload.single('audio'), async (req, res) => {
if (!req.file) {
return res.status(400).json({ error: 'Nenhum arquivo de áudio enviado.' });
}
// --- CORREÇÃO DO FORMATO DE ARQUIVO ---
const originalExt = path.extname(req.file.originalname);
const audioPath = req.file.path + originalExt;
// Renomeia o arquivo físico na pasta uploads
fs.renameSync(req.file.path, audioPath);
// ---------------------------------------
try {
console.log(`1. Processando arquivo: ${audioPath}`);
// PASSO 1: Whisper (Áudio -> Texto)
const transcription = await openai.audio.transcriptions.create({
file: fs.createReadStream(audioPath),
model: "whisper-1",
language: "pt",
});
const textoTranscrevido = transcription.text;
console.log("Texto Transcrito:", textoTranscrevido);
console.log("2. Enviando para GPT-4 extrair dados...");
// PASSO 2: GPT-4o (Texto -> JSON Estruturado)
const completion = await openai.chat.completions.create({
model: "gpt-4o",
response_format: { type: "json_object" },
messages: [
{
role: "system",
content: `
Você é um assistente médico especialista em estruturar laudos.
Sua tarefa é ler a transcrição de um ditado médico e extrair as informações para um JSON.
Os campos obrigatórios do JSON são:
- "paciente": O Nome completo do paciente mencionado. Se não houver, retorne string vazia "".
- "exam": Nome do exame realizado.
- "diagnostico": O texto completo referente aos achados/diagnóstico. (Não repita o nome do paciente aqui, foque na doença).
- "conclusao": O texto da conclusão ou impressão diagnóstica.
Se o médico não mencionar algum campo, deixe como string vazia "".
Não invente informações.
`
},
{
role: "user",
content: `Aqui está a transcrição do áudio: \n\n ${textoTranscrevido}`
}
]
});
// Parse do resultado da IA para Objeto JS
const dadosEstruturados = JSON.parse(completion.choices[0].message.content);
console.log("Dados Prontos:", dadosEstruturados);
// Devolve para o React
res.json(dadosEstruturados);
} catch (error) {
console.error("Erro no processamento:", error);
if (error.code === 'insufficient_quota') {
return res.status(429).json({ error: 'Erro: Saldo insuficiente na API da OpenAI. Verifique o Billing.' });
}
res.status(500).json({ error: 'Erro ao processar o áudio na IA.' });
} finally {
// PASSO 3: Limpeza
if (fs.existsSync(audioPath)) {
fs.unlinkSync(audioPath);
}
}
});
app.listen(port, () => {
console.log(`🚀 Backend rodando em http://localhost:${port}`);
});