@peopl-health/nexus 5.67.0-dev.11929 → 5.67.0-dev.11930
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -475,14 +475,17 @@ class AnthropicProvider extends BaseLLMProvider {
|
|
|
475
475
|
// Split placement: the inline copy carries recency on single-round turns, the hoisted developer
|
|
476
476
|
// turn persists once tool results are appended after it on multi-round turns.
|
|
477
477
|
_buildInput({ additionalInstructions, ...rest }) {
|
|
478
|
-
const
|
|
479
|
-
const pinned = { role: 'developer', content: `${RISK_HEADLINE_MARKER}\n${RISK_HEADLINE_DISCLAIMER}` };
|
|
480
|
-
const ordered = [...input.filter(i => !i[TAIL_PLACEMENT]), pinned, ...input.filter(i => i[TAIL_PLACEMENT])];
|
|
478
|
+
const ordered = this._orderRuntimeMessages(super._buildInput({ additionalInstructions, ...rest }));
|
|
481
479
|
if (!additionalInstructions) return ordered;
|
|
482
480
|
const { content } = this._operatorInstructionTurn(additionalInstructions);
|
|
483
481
|
return [...ordered, { role: 'user', content: `${OPERATOR_TURN_PREFIX} ${content}`, type: 'message' }];
|
|
484
482
|
}
|
|
485
483
|
|
|
484
|
+
_orderRuntimeMessages(input) {
|
|
485
|
+
const pinned = { role: 'developer', content: `${RISK_HEADLINE_MARKER}\n${RISK_HEADLINE_DISCLAIMER}` };
|
|
486
|
+
return [...input.filter(i => !i[TAIL_PLACEMENT]), pinned, ...input.filter(i => i[TAIL_PLACEMENT])];
|
|
487
|
+
}
|
|
488
|
+
|
|
486
489
|
_mapModelConfig(modelConfig) {
|
|
487
490
|
const mapped = { ...(modelConfig || {}) };
|
|
488
491
|
if (mapped.max_tokens == null && mapped.max_output_tokens != null) mapped.max_tokens = mapped.max_output_tokens;
|
|
@@ -783,6 +783,11 @@ class BaseLLMProvider {
|
|
|
783
783
|
};
|
|
784
784
|
}
|
|
785
785
|
|
|
786
|
+
// Providers that pin runtime messages around the tail-placed block override this.
|
|
787
|
+
_orderRuntimeMessages(input) {
|
|
788
|
+
return input;
|
|
789
|
+
}
|
|
790
|
+
|
|
786
791
|
_sanitizeInput(input) {
|
|
787
792
|
const isMessage = (item) => !item.type || item.type === 'message';
|
|
788
793
|
const items = (input || []).filter(item => isMessage(item) ? this._hasTextContent(item.content) : true);
|
|
@@ -38,6 +38,11 @@ class GatewayProvider extends BaseLLMProvider {
|
|
|
38
38
|
return this._sub(vendor)._buildInput(config);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
_orderRuntimeMessages(input, modelConfig = null) {
|
|
42
|
+
const { vendor } = this._route(modelConfig?.model);
|
|
43
|
+
return this._sub(vendor)._orderRuntimeMessages(input);
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
_route(model) {
|
|
42
47
|
if (!model) return { vendor: 'openai', model: undefined };
|
|
43
48
|
const slash = model.indexOf('/');
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { safeParse, isPlainObject } = require('../../utils/jsonUtils');
|
|
2
2
|
const { logger } = require('../../utils/logger');
|
|
3
3
|
const { sanitizeInlineText } = require('../../utils/sanitizerUtils');
|
|
4
|
+
const { withTimeout } = require('../../utils/timeoutUtils');
|
|
4
5
|
const { composePrompt } = require('./promptComposerService');
|
|
5
6
|
|
|
6
7
|
const NUTRITION_GUIDE_PROMPT_ID = 'nutrition_plan_guide';
|
|
@@ -60,15 +61,14 @@ function readGuide() {
|
|
|
60
61
|
// The guide only adds to the plan, so a slow read must not hold the patient's turn,
|
|
61
62
|
// and a read that never settles must not hold every later turn either.
|
|
62
63
|
async function loadNutritionGuide() {
|
|
63
|
-
let timer;
|
|
64
64
|
const read = readGuide();
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
try {
|
|
66
|
+
return await withTimeout(read, GUIDE_TIMEOUT_MS, 'nutrition guide read');
|
|
67
|
+
} catch {
|
|
68
|
+
if (guideRead === read) guideRead = null;
|
|
69
|
+
logger.warn('[nutritionPlanService] nutrition guide read timed out; using the last one read', { timeoutMs: GUIDE_TIMEOUT_MS });
|
|
70
|
+
return lastGuide;
|
|
71
|
+
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
async function resolveNutritionPlan(section, { now = new Date() } = {}) {
|
package/lib/eval/EvalProvider.js
CHANGED
|
@@ -225,17 +225,21 @@ class EvalProvider {
|
|
|
225
225
|
const clinicalMessage = typeof this.provider._buildClinicalMessage === 'function'
|
|
226
226
|
? this.provider._buildClinicalMessage(promptVariables, interpolatedVariables)
|
|
227
227
|
: [];
|
|
228
|
-
const input = this.provider._sanitizeInput([...memoryMessage, ...clinicalMessage, ...convertedMessages]);
|
|
229
228
|
const isContextOnly = this.mode === 'context-only';
|
|
230
229
|
|
|
231
230
|
const shouldUsePromptRegistry = !presetId && this.provider.supportsPromptRegistry && !!assistantId;
|
|
231
|
+
const modelConfig = shouldUsePromptRegistry ? {} : this._modelConfig(presetModelConfig);
|
|
232
|
+
const input = this.provider._orderRuntimeMessages(
|
|
233
|
+
this.provider._sanitizeInput([...memoryMessage, ...clinicalMessage, ...convertedMessages]),
|
|
234
|
+
modelConfig,
|
|
235
|
+
);
|
|
232
236
|
|
|
233
237
|
return {
|
|
234
238
|
instructions: devContent || '',
|
|
235
239
|
input,
|
|
236
240
|
toolSchemas: isContextOnly ? [] : toolSchemas,
|
|
237
241
|
toolChoice: isContextOnly ? 'none' : this.toolChoice,
|
|
238
|
-
modelConfig
|
|
242
|
+
modelConfig,
|
|
239
243
|
assistant: isContextOnly ? null : assistant,
|
|
240
244
|
phiProcessor: this.phiProcessor,
|
|
241
245
|
promptVariables,
|