v3.0: Add multi-provider Bedrock models, newborn milestones, Converse API

- Bedrock: Add 14 non-vendor model models (Amazon Nova, Meta Llama 4, DeepSeek R1/V3,
  Mistral Large 3, Cohere Command R+, AI21 Jamba) with verified AWS model IDs
- Bedrock: Implement Converse API for non-Anthropic models (unified cross-model API),
  keep native Messages API for vendor model models (best performance)
- Milestones: Add Newborn / 1 month developmental milestones (Gross Motor, Fine Motor,
  Language, Social/Emotional, Cognitive) — previously started at 2 months
- Bump version to 3.0.0, docker-compose tag to v3.0
This commit is contained in:
Daniel 2026-03-23 22:13:19 +01:00
parent eb8c86f70e
commit d2ed08cd46
6 changed files with 144 additions and 32 deletions

View file

@ -1,6 +1,6 @@
services:
pediatric-scribe:
image: danielonyejesi/pediatric-ai-scribe-v3:v2.7
image: danielonyejesi/pediatric-ai-scribe-v3:v3.0
ports:
- "3552:3000"
env_file:

View file

@ -1,6 +1,6 @@
{
"name": "pediatric-ai-scribe",
"version": "2.9.0",
"version": "3.0.0",
"description": "AI-powered pediatric clinical documentation platform",
"main": "server.js",
"scripts": {

View file

@ -1002,6 +1002,7 @@
<label>Age Group</label>
<select id="ms-age-group">
<option value="">-- Select --</option>
<option value="Newborn / 1 month">Newborn / 1 Month</option>
<option value="2 months">2 Months</option>
<option value="4 months">4 Months</option>
<option value="6 months">6 Months</option>

View file

@ -6,6 +6,37 @@
var MILESTONES_DATA = {
"Newborn / 1 month": {
"Gross Motor": [
"Moves arms and legs equally",
"Lifts head briefly when on tummy (prone)",
"Strong flexion posture (arms and legs tucked)",
"Turns head side to side when lying on back"
],
"Fine Motor": [
"Hands mostly fisted",
"Strong grasp reflex when palm is touched",
"Brings hands near face"
],
"Language": [
"Cries to express needs",
"Startles or quiets to sounds",
"Makes brief throaty sounds"
],
"Social/Emotional": [
"Recognizes caregiver voice",
"Briefly fixates on faces at close range (8-12 inches)",
"Calms when held or hears familiar voice",
"Shows brief alert periods"
],
"Cognitive": [
"Focuses on faces briefly",
"Follows objects briefly to midline",
"Prefers black and white or high-contrast patterns",
"Responds to loud sounds (Moro reflex)"
]
},
"2 months": {
"Gross Motor": [
"Lifts head when prone (45 degrees)",

View file

@ -148,15 +148,15 @@ async function callAzure(messages, model, temperature, maxTokens) {
// ============================================================
// CALL AWS BEDROCK
// Anthropic models use InvokeModel (Messages API)
// All other models use Converse API (unified cross-model API)
// ============================================================
async function callBedrock(messages, model, temperature, maxTokens) {
if (!bedrockClient) throw new Error('AWS Bedrock not configured');
var BedrockModule = require('@aws-sdk/client-bedrock-runtime');
var InvokeModelCommand = BedrockModule.InvokeModelCommand;
// Map friendly model ID to Bedrock model ID
var modelId = getBedrockModelId(model);
var isAnthropic = modelId.startsWith('anthropic.');
// Separate system message from chat messages
var systemMsg = '';
@ -169,35 +169,77 @@ async function callBedrock(messages, model, temperature, maxTokens) {
}
});
// Build request body (Anthropic Messages API format for Bedrock)
var body = {
anthropic_version: 'bedrock-2023-05-31',
max_tokens: maxTokens,
temperature: temperature,
messages: chatMessages
};
if (systemMsg) body.system = systemMsg;
if (isAnthropic) {
// Anthropic Messages API format (native, best performance)
var InvokeModelCommand = BedrockModule.InvokeModelCommand;
var body = {
anthropic_version: 'bedrock-2023-05-31',
max_tokens: maxTokens,
temperature: temperature,
messages: chatMessages
};
if (systemMsg) body.system = systemMsg;
var command = new InvokeModelCommand({
modelId: modelId,
contentType: 'application/json',
accept: 'application/json',
body: JSON.stringify(body)
});
var command = new InvokeModelCommand({
modelId: modelId,
contentType: 'application/json',
accept: 'application/json',
body: JSON.stringify(body)
});
var response = await bedrockClient.send(command);
var responseBody = JSON.parse(new TextDecoder().decode(response.body));
var response = await bedrockClient.send(command);
var responseBody = JSON.parse(new TextDecoder().decode(response.body));
return {
success: true,
content: responseBody.content[0].text,
model: modelId,
provider: 'bedrock',
usage: {
prompt_tokens: responseBody.usage ? responseBody.usage.input_tokens : 0,
completion_tokens: responseBody.usage ? responseBody.usage.output_tokens : 0
return {
success: true,
content: responseBody.content[0].text,
model: modelId,
provider: 'bedrock',
usage: {
prompt_tokens: responseBody.usage ? responseBody.usage.input_tokens : 0,
completion_tokens: responseBody.usage ? responseBody.usage.output_tokens : 0
}
};
} else {
// Converse API — unified API for all non-Anthropic Bedrock models
var ConverseCommand = BedrockModule.ConverseCommand;
var converseMessages = chatMessages.map(function(m) {
return { role: m.role, content: [{ text: m.content }] };
});
var converseParams = {
modelId: modelId,
messages: converseMessages,
inferenceConfig: {
maxTokens: maxTokens,
temperature: temperature
}
};
if (systemMsg) {
converseParams.system = [{ text: systemMsg }];
}
};
var converseResponse = await bedrockClient.send(new ConverseCommand(converseParams));
var outputText = '';
if (converseResponse.output && converseResponse.output.message && converseResponse.output.message.content) {
converseResponse.output.message.content.forEach(function(block) {
if (block.text) outputText += block.text;
});
}
return {
success: true,
content: outputText,
model: modelId,
provider: 'bedrock',
usage: {
prompt_tokens: converseResponse.usage ? converseResponse.usage.inputTokens : 0,
completion_tokens: converseResponse.usage ? converseResponse.usage.outputTokens : 0
}
};
}
}
// ============================================================

View file

@ -27,7 +27,7 @@ var OPENROUTER_MODELS = [
];
var BEDROCK_MODELS = [
// vendor model models only — verified IDs from AWS docs (models-supported.html)
// ── Anthropic vendor model — verified IDs from AWS docs (models-supported.html) ──
{ id: 'anthropic/vendor-model-opus-4-6', name: 'vendor model Opus 4.6', cost: '~$0.075', tag: 'BEST NUANCE', category: 'premium',
bedrockId: 'anthropic.agent-config-opus-4-6-v1' },
{ id: 'anthropic/vendor-model-opus-4-5', name: 'vendor model Opus 4.5', cost: '~$0.075', tag: 'OPUS', category: 'premium',
@ -41,7 +41,45 @@ var BEDROCK_MODELS = [
{ id: 'anthropic/vendor-model-haiku-4-5', name: 'vendor model Haiku 4.5', cost: '~$0.003', tag: 'FAST', category: 'smart',
bedrockId: 'anthropic.agent-config-haiku-4-5-20251001-v1:0' },
{ id: 'anthropic/vendor-model-3.5-haiku', name: 'vendor model 3.5 Haiku', cost: '~$0.002', tag: 'VALUE', category: 'smart',
bedrockId: 'anthropic.agent-config-3-5-haiku-20241022-v1:0' }
bedrockId: 'anthropic.agent-config-3-5-haiku-20241022-v1:0' },
// ── Amazon Nova ──
{ id: 'amazon/nova-pro', name: 'Amazon Nova Pro', cost: '~$0.008', tag: 'SMART', category: 'smart',
bedrockId: 'amazon.nova-pro-v1:0' },
{ id: 'amazon/nova-lite', name: 'Amazon Nova Lite', cost: '~$0.001', tag: 'FAST', category: 'fast',
bedrockId: 'amazon.nova-lite-v1:0' },
{ id: 'amazon/nova-micro', name: 'Amazon Nova Micro', cost: '~$0.0004', tag: 'CHEAPEST', category: 'fast',
bedrockId: 'amazon.nova-micro-v1:0' },
{ id: 'amazon/nova-premier', name: 'Amazon Nova Premier', cost: '~$0.04', tag: 'BEST AMAZON', category: 'premium',
bedrockId: 'amazon.nova-premier-v1:0' },
// ── Meta Llama ──
{ id: 'meta/llama-4-maverick', name: 'Llama 4 Maverick', cost: '~$0.005', tag: 'NEW', category: 'smart',
bedrockId: 'meta.llama4-maverick-17b-instruct-v1:0' },
{ id: 'meta/llama-4-scout', name: 'Llama 4 Scout', cost: '~$0.004', tag: 'NEW', category: 'smart',
bedrockId: 'meta.llama4-scout-17b-instruct-v1:0' },
{ id: 'meta/llama-3.3-70b', name: 'Llama 3.3 70B', cost: '~$0.003', tag: 'GOOD', category: 'smart',
bedrockId: 'meta.llama3-3-70b-instruct-v1:0' },
// ── DeepSeek ──
{ id: 'deepseek/r1', name: 'DeepSeek R1', cost: '~$0.005', tag: 'REASONING', category: 'smart',
bedrockId: 'deepseek.r1-v1:0' },
{ id: 'deepseek/v3', name: 'DeepSeek V3', cost: '~$0.001', tag: 'CHEAP', category: 'fast',
bedrockId: 'deepseek.v3-v1:0' },
// ── Mistral AI ──
{ id: 'mistral/large-3', name: 'Mistral Large 3 (675B)', cost: '~$0.008', tag: 'PREMIUM', category: 'premium',
bedrockId: 'mistral.mistral-large-3-675b-instruct' },
{ id: 'mistral/mistral-large-2407', name: 'Mistral Large (24.07)', cost: '~$0.006', tag: 'GOOD', category: 'smart',
bedrockId: 'mistral.mistral-large-2407-v1:0' },
// ── Cohere ──
{ id: 'cohere/command-r-plus', name: 'Command R+', cost: '~$0.005', tag: 'GOOD', category: 'smart',
bedrockId: 'cohere.command-r-plus-v1:0' },
// ── AI21 Labs ──
{ id: 'ai21/jamba-1.5-large', name: 'Jamba 1.5 Large', cost: '~$0.005', tag: 'GOOD', category: 'smart',
bedrockId: 'ai21.jamba-1-5-large-v1:0' }
];
var AZURE_MODELS = [