Overview
The Clinical Insights API uses GPT-4 to analyze SOAP notes and generate clinical decision support insights including risk assessments, diagnostic suggestions, and treatment recommendations.
Generate Clinical Insights
Analyze SOAP notes and generate clinical insights.
Endpoint
POST /api/ai/clinical-insights
Request
curl -X POST http://localhost:3000/api/ai/clinical-insights \
-H "Content-Type: application/json" \
-d '{
"soap": {
"subjective": "10 year old Labrador with lethargy and polyuria/polydipsia for 2 weeks",
"objective": "BCS 4/9, dehydrated, pale mucous membranes",
"assessment": "Rule out diabetes, kidney disease, Cushings",
"plan": "Complete bloodwork, urinalysis, start IV fluids"
},
"patientName": "Buddy",
"species": "dog",
"breed": "Labrador Retriever"
}'
Request Parameters
SOAP note content with subjective, objective, assessment, and plan fields
Patient name for personalized insights
Patient species (dog, cat, etc.)
Patient breed for breed-specific insights
Response
{
"insights": [
{
"type": "risk",
"priority": "high",
"title": "Diabetic Ketoacidosis Risk",
"description": "The combination of polyuria/polydipsia, lethargy, and dehydration in a senior dog suggests diabetes mellitus. Immediate blood glucose and ketone testing recommended to rule out DKA, which requires emergency treatment.",
"confidence": 0.85
},
{
"type": "diagnosis",
"priority": "high",
"title": "Chronic Kidney Disease Likely",
"description": "PU/PD with dehydration and pale mucous membranes in a 10-year-old Labrador is highly suggestive of CKD. Recommend full renal panel including creatinine, BUN, phosphorus, and urine specific gravity. SDMA testing may detect early kidney disease.",
"confidence": 0.78
},
{
"type": "suggestion",
"priority": "medium",
"title": "Blood Pressure Monitoring",
"description": "Given the differential diagnoses (DM, CKD, Cushing's), systemic hypertension is common. Recommend blood pressure measurement as hypertension can cause secondary organ damage.",
"confidence": 0.72
},
{
"type": "suggestion",
"priority": "medium",
"title": "Retinal Examination",
"description": "Both diabetes and hypertension (secondary to CKD) can cause retinal changes. Ophthalmoscopic exam recommended to check for hemorrhages or detachment.",
"confidence": 0.65
},
{
"type": "suggestion",
"priority": "low",
"title": "Consider ACTH Stimulation Test",
"description": "While less likely than DM or CKD, Cushing's disease should remain on the differential list for PU/PD in an older dog. Consider ACTH stimulation or low-dose dexamethasone suppression test if initial workup is inconclusive.",
"confidence": 0.55
}
]
}
Insight Object Structure
Insight type: risk, diagnosis, suggestion
Priority level: high, medium, low
Detailed explanation and recommendations
AI confidence score (0.0 - 1.0)
Insight Types
Risk Insights
Identify potential medical risks:
{
"type": "risk",
"priority": "high",
"title": "Gastric Dilatation-Volvulus Risk",
"description": "Large breed dog with acute onset bloating and non-productive retching. GDV is life-threatening and requires immediate radiographic confirmation and surgical intervention if positive.",
"confidence": 0.92
}
Diagnostic Insights
Suggest likely diagnoses:
{
"type": "diagnosis",
"priority": "high",
"title": "Feline Hyperthyroidism",
"description": "Senior cat presenting with weight loss despite increased appetite, plus tachycardia on exam. These are classic signs of hyperthyroidism. Recommend total T4 measurement.",
"confidence": 0.88
}
Treatment Suggestions
Recommend additional diagnostics or treatments:
{
"type": "suggestion",
"priority": "medium",
"title": "Pain Management",
"description": "Patient showing signs of orthopedic pain (reluctance to jump, stiff gait). Consider multimodal pain management including NSAIDs and joint supplements.",
"confidence": 0.75
}
Managing Insights
Accept or Reject Insights
interface ClinicalInsight {
id: string;
type: 'risk' | 'diagnosis' | 'suggestion';
priority: 'high' | 'medium' | 'low';
title: string;
description: string;
confidence: number;
status: 'pending' | 'accepted' | 'rejected';
}
// Accept an insight
const acceptInsight = (insightId: string) => {
setInsights(prev => prev.map(insight =>
insight.id === insightId
? { ...insight, status: 'accepted' }
: insight
));
// Add to SOAP plan
const insight = insights.find(i => i.id === insightId);
if (insight) {
appendToPlan(`- ${insight.description}`);
}
};
// Reject an insight
const rejectInsight = (insightId: string) => {
setInsights(prev => prev.map(insight =>
insight.id === insightId
? { ...insight, status: 'rejected' }
: insight
));
};
Display Insights in UI
const InsightCard = ({ insight }: { insight: ClinicalInsight }) => {
const priorityColor = {
high: 'border-red-500 bg-red-50',
medium: 'border-amber-500 bg-amber-50',
low: 'border-green-500 bg-green-50'
}[insight.priority];
const typeIcon = {
risk: <AlertTriangle />,
diagnosis: <FileText />,
suggestion: <Lightbulb />
}[insight.type];
return (
<div className={`border-l-4 p-4 rounded-lg ${priorityColor}`}>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
{typeIcon}
<h4 className="font-medium">{insight.title}</h4>
</div>
<Badge>{Math.round(insight.confidence * 100)}%</Badge>
</div>
<p className="text-sm mt-2">{insight.description}</p>
{insight.status === 'pending' && (
<div className="flex gap-2 mt-3">
<Button onClick={() => acceptInsight(insight.id)}>
<ThumbsUp /> Accept
</Button>
<Button variant="outline" onClick={() => rejectInsight(insight.id)}>
<ThumbsDown /> Dismiss
</Button>
</div>
)}
</div>
);
};
Integration with Medical Records
import { supabase } from '@/lib/supabase';
// Generate insights for a medical record
const generateInsightsForRecord = async (recordId: string) => {
// Fetch record
const { data: record } = await supabase
.from('medical_records')
.select('*')
.eq('id', recordId)
.single();
if (!record) return;
// Generate insights
const response = await fetch('/api/ai/clinical-insights', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
soap: {
subjective: record.soap_subjective,
objective: record.soap_objective,
assessment: record.soap_assessment,
plan: record.soap_plan
},
patientName: record.pet_name,
species: record.species,
breed: record.breed
})
});
const { insights } = await response.json();
// Store insights with record
await supabase
.from('medical_records')
.update({
insights: insights
})
.eq('id', recordId);
return insights;
};
Confidence Thresholds
Filter insights by confidence level:
const getHighConfidenceInsights = (insights: ClinicalInsight[]) => {
return insights.filter(i => i.confidence >= 0.75);
};
const prioritizeInsights = (insights: ClinicalInsight[]) => {
return insights.sort((a, b) => {
// Sort by priority first, then confidence
const priorityOrder = { high: 0, medium: 1, low: 2 };
if (priorityOrder[a.priority] !== priorityOrder[b.priority]) {
return priorityOrder[a.priority] - priorityOrder[b.priority];
}
return b.confidence - a.confidence;
});
};
Rate Limits
- Clinical Insights: 10 requests per minute
- Maximum SOAP length: 8000 characters
Best Practices
Clinical insights are AI-generated suggestions for decision support only. Always apply clinical judgment and verify recommendations.
- Review all insights - Don’t auto-accept; use as a second opinion
- Consider confidence scores - Higher confidence (>0.8) is more reliable
- Prioritize by urgency - Address high-priority insights first
- Document decisions - Note which insights were accepted/rejected
- Update regularly - Re-generate insights if SOAP notes are significantly updated