pediatric-ai-scribe-v3/test/clinical-generation-options.test.js
Daniel b683356458
Some checks failed
Forgejo Docker Build / Root app tests (push) Successful in 52s
Forgejo Docker Build / Build Docker image (push) Successful in 6s
Forgejo Docker Build / End-to-end (browser) (push) Failing after 7s
feat: DeepSeek is asked without thinking unless the caller asks for it
The switch was opt-in, and the callers that said nothing were the ones that
paid for it: a 16,000-token deck reasoned its whole budget away and wrote
nothing (reasoning_chars=51573), the four 2,000-token reviews of that deck did
the same, and a 16,000-token revision reasoned for a minute and a half before
writing a word — which is past the point a browser waits for a request. Every
clinical route (encounters, notes, chart review, the visits, take-home, and
the rest) passes no reasoning option at all, so all of them were in that
position.

Silence now means off for DeepSeek, in one place rather than in fifteen, and
an explicit effort still means what it says: a task that wants reasoning asks
for it. The retry after a reasoning-starved reply no longer asks for 'low'
either — on DeepSeek that means thinking on, which is how a starved call came
back starved with four times the budget. It adds room instead.

Other providers are untouched, the Groq Qwen profile included.
2026-09-16 04:11:35 +02:00

73 lines
4.3 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const { assistantGenerationOptions } = require('../src/utils/clinicalAnswer');
const { resolveGenerationOptions, addReasoningOptions } = require('../src/utils/generationOptions');
test('clinical assistant profile requests low reasoning without exposing it', () => {
assert.deepEqual(assistantGenerationOptions({ temperature: 0, maxTokens: 80 }), {
reasoningEffort: 'low',
reasoningFormat: 'hidden',
temperature: 0,
maxTokens: 80
});
});
test('generation defaults preserve an explicit zero temperature', () => {
assert.equal(resolveGenerationOptions({ temperature: 0 }).temperature, 0);
assert.equal(resolveGenerationOptions({}).temperature, 0.3);
});
test('reasoning fields are sent only to the confirmed Groq Qwen model', () => {
const profile = { reasoningEffort: 'low', reasoningFormat: 'hidden' };
assert.deepEqual(addReasoningOptions({ model: 'openai-gpt-4.1' }, profile), { model: 'openai-gpt-4.1' });
assert.deepEqual(addReasoningOptions({ model: 'groq-qwen3.8-27b' }, profile), {
model: 'groq-qwen3.8-27b', reasoning_effort: 'low', reasoning_format: 'hidden'
});
});
test('DeepSeek thinks unless told not to: only an effort of none sends the switch, as DeepSeek spells it', () => {
assert.deepEqual(addReasoningOptions({ model: 'ds-deepseek-v4.1-flash' }, { reasoningEffort: 'none', reasoningFormat: 'hidden' }),
{ model: 'ds-deepseek-v4.1-flash', thinking: { type: 'disabled' } });
assert.deepEqual(addReasoningOptions({ model: 'openrouter-deepseek-v4.1-flash' }, { reasoningEffort: 'low', reasoningFormat: 'hidden' }),
{ model: 'openrouter-deepseek-v4.1-flash' }, 'the historical low profile leaves the provider default alone');
assert.deepEqual(addReasoningOptions({ model: 'ds-deepseek-r1' }, { reasoningEffort: 'none' }),
{ model: 'ds-deepseek-r1', thinking: { type: 'disabled' } });
});
test('saying nothing now means no thinking on DeepSeek, and an explicit effort still overrides it', () => {
// The switch was opt-in, and the callers that did not opt in were the ones
// that paid for it: a deck reasoned its whole 16,000-token budget away and
// wrote nothing, and so did the reviews and the revision after it. Every
// clinical route passes no reasoning option at all, which is what this is for.
assert.deepEqual(addReasoningOptions({ model: 'ds-deepseek-v4.1-flash' }, {}),
{ model: 'ds-deepseek-v4.1-flash', thinking: { type: 'disabled' } });
assert.deepEqual(addReasoningOptions({ model: 'openrouter-deepseek-v4.1-flash' }, {}),
{ model: 'openrouter-deepseek-v4.1-flash', thinking: { type: 'disabled' } });
assert.deepEqual(addReasoningOptions({ model: 'ds-deepseek-r1' }, { reasoningEffort: 'high' }),
{ model: 'ds-deepseek-r1' }, 'a task that wants reasoning still gets it');
// And nothing changes for models this rule was never about.
assert.deepEqual(addReasoningOptions({ model: 'openai-gpt-4.1' }, {}), { model: 'openai-gpt-4.1' });
assert.deepEqual(addReasoningOptions({ model: 'groq-qwen3.8-27b' }, {}), { model: 'groq-qwen3.8-27b' });
});
test('the starvation retry adds room, and does not turn thinking back on', () => {
// It used to retry with reasoningEffort 'low', which on DeepSeek is thinking
// on: the retry of a call that had just reasoned its budget away asked it to
// reason again with four times the budget. More room is the fix.
const src = fs.readFileSync(path.join(__dirname, '..', 'src/utils/ai.js'), 'utf8');
const retry = src.slice(src.indexOf('var starved ='), src.indexOf('var starved =') + 700);
assert.match(retry, /reasoningRetried: true/);
assert.doesNotMatch(retry, /reasoningEffort/, 'the retry must not ask for thinking');
assert.match(retry, /reasoning consumed the budget; retrying/);
});
test('the assistant profile takes its effort from the environment, and only a known value', () => {
const { assistantReasoningEffort } = require('../src/utils/clinicalAnswer');
assert.equal(assistantReasoningEffort({}), 'low');
assert.equal(assistantReasoningEffort({ CLINICAL_ASSISTANT_REASONING_EFFORT: 'none' }), 'none');
assert.equal(assistantReasoningEffort({ CLINICAL_ASSISTANT_REASONING_EFFORT: 'NONE ' }), 'none');
assert.equal(assistantReasoningEffort({ CLINICAL_ASSISTANT_REASONING_EFFORT: 'maximum' }), 'low');
});