Features: - Live encounter recording → HPI (outpatient/inpatient) - Voice dictation → HPI / SOAP note - Hospital course generator (prose/day-by-day/organ system/psych) - Chart review / precharting (outpatient/subspecialty/ED) - SOAP note generator (full/subjective only) - Developmental milestones (AAP/Nelson) with narrative + 3-sentence summary - AI refine & shorten for all outputs - Ask AI what's missing (clarification) - Authentication (email/password, email verification, 2FA) - Nextcloud integration with auto date folders - PWA support (installable on phone) - 18+ AI models via OpenRouter - HIPAA compliance guidance - Docker support
62 lines
2.2 KiB
JavaScript
62 lines
2.2 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const { callAI } = require('../utils/ai');
|
|
const PROMPTS = require('../utils/prompts');
|
|
|
|
// Generate chart review
|
|
router.post('/generate-chart-review', async (req, res) => {
|
|
try {
|
|
const {
|
|
type, // 'outpatient' | 'subspecialty' | 'ed'
|
|
patientAge, patientGender, pmh,
|
|
visits, // Array of { date, type, content }
|
|
subspecialty, // Array of { date, specialistName, specialty, content }
|
|
edVisits, // Array of { date, content, labs }
|
|
labs, // Array of { date, values }
|
|
model,
|
|
additionalInstructions
|
|
} = req.body;
|
|
|
|
let prompt;
|
|
let clinicalData = `Patient: ${patientAge || 'Unknown'}, ${patientGender || 'Unknown'}`;
|
|
if (pmh) clinicalData += `\nPMH: ${pmh}`;
|
|
|
|
if (type === 'ed' || (edVisits && edVisits.length > 0)) {
|
|
prompt = PROMPTS.chartReviewED;
|
|
(edVisits || []).forEach(v => {
|
|
clinicalData += `\n\n=== ED VISIT (${v.date}) ===\n${v.content}`;
|
|
if (v.labs) clinicalData += `\nLabs: ${v.labs}`;
|
|
});
|
|
} else if (type === 'subspecialty' || (subspecialty && subspecialty.length > 0)) {
|
|
prompt = PROMPTS.chartReviewSubspecialty;
|
|
(subspecialty || []).forEach(s => {
|
|
clinicalData += `\n\n=== ${(s.specialty || 'Subspecialty').toUpperCase()} — ${s.specialistName || 'Unknown'} (${s.date}) ===\n${s.content}`;
|
|
});
|
|
} else {
|
|
prompt = PROMPTS.chartReviewOutpatient;
|
|
(visits || []).forEach(v => {
|
|
clinicalData += `\n\n=== ${(v.type || 'Visit').toUpperCase()} (${v.date}) ===\n${v.content}`;
|
|
});
|
|
}
|
|
|
|
if (labs && labs.length > 0) {
|
|
clinicalData += '\n\n=== LABS ===';
|
|
labs.forEach(l => { clinicalData += `\n${l.date}: ${l.values}`; });
|
|
}
|
|
|
|
if (additionalInstructions) {
|
|
prompt += `\n\nADDITIONAL INSTRUCTIONS:\n${additionalInstructions}`;
|
|
}
|
|
|
|
const result = await callAI([
|
|
{ role: 'system', content: prompt },
|
|
{ role: 'user', content: clinicalData }
|
|
], { model, maxTokens: 4000 });
|
|
|
|
res.json({ success: true, review: result.content, model: result.model });
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|