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.
73 lines
4.3 KiB
JavaScript
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');
|
|
});
|