Correção do upload de áudio, integração com OpenAI e ajuste de campos no frontend

This commit is contained in:
RafaelMTA13 2025-12-03 22:53:50 -03:00
parent bc7a2ed7d8
commit 78f125c279
5 changed files with 35 additions and 26 deletions

2
.env
View File

@ -1,2 +1,2 @@
OPENAI_API_KEY=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
OPENAI_API_KEY=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
PORT=5000

View File

@ -1 +1 @@
OPENAI_API_KEY=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
OPENAI_API_KEY=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

View File

@ -3,11 +3,11 @@ const multer = require('multer');
const cors = require('cors');
const fs = require('fs');
const path = require('path');
const OpenAI = require('openai/index.js');
const OpenAI = require('openai');
require('dotenv').config();
const app = express();
const port = 3001; // O backend rodará na porta 3001
const port = 3001;
// Configurações de Segurança e JSON
app.use(cors());
@ -28,16 +28,22 @@ app.post('/api/transcrever-relatorio', upload.single('audio'), async (req, res)
return res.status(400).json({ error: 'Nenhum arquivo de áudio enviado.' });
}
const audioPath = req.file.path;
// --- 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. Recebendo áudio e iniciando transcrição...");
console.log(`1. Processando arquivo: ${audioPath}`);
// PASSO 1: Whisper (Áudio -> Texto)
const transcription = await openai.audio.transcriptions.create({
file: fs.createReadStream(audioPath),
file: fs.createReadStream(audioPath),
model: "whisper-1",
language: "pt", // Força português para melhorar precisão médica
language: "pt",
});
const textoTranscrevido = transcription.text;
@ -48,7 +54,7 @@ app.post('/api/transcrever-relatorio', upload.single('audio'), async (req, res)
// PASSO 2: GPT-4o (Texto -> JSON Estruturado)
const completion = await openai.chat.completions.create({
model: "gpt-4o",
response_format: { type: "json_object" }, // Garante que volta JSON válido
response_format: { type: "json_object" },
messages: [
{
role: "system",
@ -57,8 +63,9 @@ app.post('/api/transcrever-relatorio', upload.single('audio'), async (req, res)
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. Melhore a pontuação e corrija termos médicos se necessário.
- "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 "".
@ -82,16 +89,21 @@ app.post('/api/transcrever-relatorio', upload.single('audio'), async (req, res)
} catch (error) {
console.error("Erro no processamento:", error);
res.status(500).json({ error: 'Erro ao processar o áudio.' });
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 (Apagar o áudio da pasta uploads para não encher o servidor)
// PASSO 3: Limpeza
if (fs.existsSync(audioPath)) {
fs.unlinkSync(audioPath);
}
}
});
// Iniciar Servidor
app.listen(port, () => {
console.log(`🚀 Backend rodando em http://localhost:${port}`);
});

View File

@ -1,11 +1,11 @@
import React, { useState, useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom'; // <--- 1. ADICIONADO useLocation
import { useNavigate, useLocation } from 'react-router-dom';
import html2pdf from 'html2pdf.js';
import './styleMedico/NovoRelatorioAudio.css';
const NovoRelatorioAudio = () => {
const navigate = useNavigate();
const location = useLocation(); // <--- 2. Inicializa o hook para ler os dados enviados
const location = useLocation();
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState({
@ -14,33 +14,26 @@ const NovoRelatorioAudio = () => {
exam: '',
diagnostico: '',
conclusao: '',
medico_nome: 'Dr._______________________________' // Ajuste conforme necessário
medico_nome: 'Dr._______________________________'
});
// --- 3. NOVO BLOCO: Receber dados da Videochamada ---
// --- Receber dados da Videochamada (Se houver) ---
useEffect(() => {
// Verifica se a navegação trouxe dados no "state"
if (location.state && location.state.aiResult) {
console.log("Dados recebidos da Videochamada:", location.state);
const { aiResult, paciente } = location.state;
// Atualiza o formulário com o que a IA gerou
setFormData(prev => ({
...prev,
// Se tiver paciente vindo da chamada, usa ele. Se não, mantém vazio.
paciente_nome: paciente?.name || prev.paciente_nome,
// Dados da IA
exam: aiResult.exam || 'Consulta Telemedicina',
diagnostico: aiResult.diagnostico || '',
conclusao: aiResult.conclusao || ''
}));
}
}, [location]); // Executa assim que a página carrega
// --- FIM DO BLOCO NOVO ---
}, [location]);
// --- LÓGICA DO UPLOAD DE ÁUDIO ---
const handleAudioUpload = async (e) => {
const file = e.target.files[0];
if (!file) return;
@ -59,8 +52,10 @@ const NovoRelatorioAudio = () => {
const result = await response.json();
// ATUALIZAÇÃO AQUI: Mapeando todos os campos retornados pela IA
setFormData(prev => ({
...prev,
paciente_nome: result.paciente || prev.paciente_nome, // Pega o nome do paciente
exam: result.exam || prev.exam,
diagnostico: result.diagnostico || prev.diagnostico,
conclusao: result.conclusao || prev.conclusao

View File

@ -7,6 +7,7 @@ import LaudoManager from "../../pages/LaudoManager";
import ConsultaCadastroManager from "../../PagesPaciente/ConsultaCadastroManager";
import ConsultasPaciente from "../../PagesPaciente/ConsultasPaciente";
import ConsultaEditPage from "../../PagesPaciente/ConsultaEditPage";
import BotaoVideoPaciente from "../../components/BotaoVideoPaciente";
function PerfilPaciente({ onLogout }) {
const [dadosConsulta, setConsulta] = useState({})
@ -25,6 +26,7 @@ const [dadosConsulta, setConsulta] = useState({})
<Route path="*" element={<h2>Página não encontrada</h2>} />
</Routes>
</div>
<BotaoVideoPaciente />
</div>
);
}