fix: an empty model reply is logged with its finish reason, and a pool batch that gets one is retried once
Two batches in five came back as a 200 with an empty message — nothing in the gateway log, nothing in ours. callLiteLLM now says when that happens (finish reason, completion tokens, whether the tokens went into reasoning), and the starter-question build tries such a batch once more instead of writing the category off. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
This commit is contained in:
parent
a528986a2d
commit
d517a3fdf6
2 changed files with 21 additions and 4 deletions
|
|
@ -366,14 +366,24 @@ async function callLiteLLM(messages, model, temperature, maxTokens, generation)
|
|||
max_tokens: maxTokens
|
||||
}, generation || {}), generation));
|
||||
|
||||
var choice = completion.choices[0];
|
||||
// An empty reply with a 200 is the one failure nothing else reports: the
|
||||
// gateway is happy, the caller gets '' and a JSON task keeps nothing. Say
|
||||
// what the model said about it — the finish reason and whether the tokens
|
||||
// went into reasoning instead of the answer.
|
||||
if (!choice.message.content && !choice.message.tool_calls) {
|
||||
var reasoningChars = String(choice.message.reasoning_content || choice.message.reasoning || '').length;
|
||||
console.warn('[ai] empty reply from ' + model + ': finish_reason=' + (choice.finish_reason || '?') +
|
||||
' completion_tokens=' + (completion.usage && completion.usage.completion_tokens) + ' reasoning_chars=' + reasoningChars);
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
content: completion.choices[0].message.content,
|
||||
...(completion.choices[0].message.tool_calls ? { toolCalls: completion.choices[0].message.tool_calls } : {}),
|
||||
content: choice.message.content,
|
||||
...(choice.message.tool_calls ? { toolCalls: choice.message.tool_calls } : {}),
|
||||
model: model,
|
||||
provider: 'litellm',
|
||||
usage: completion.usage || null,
|
||||
finishReason: completion.choices[0].finish_reason || null
|
||||
finishReason: choice.finish_reason || null
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -360,7 +360,14 @@ function createClinicalPromptPool(opts) {
|
|||
});
|
||||
var parsed = parseJsonObject(String(ai.content || ''));
|
||||
var offered = Array.isArray(parsed.questions) ? parsed.questions.length : 0;
|
||||
if (!offered) console.warn('[clinical-assistant] prompt pool ' + item.category + ' batch ' + (i + 1) + ': nothing parseable in ' + String(ai.content || '').length + ' chars');
|
||||
if (!offered) {
|
||||
// The model answers a JSON task with an empty message now and then —
|
||||
// two batches in five came back with nothing. One more try with the
|
||||
// same snippets is cheap and usually enough.
|
||||
console.warn('[clinical-assistant] prompt pool ' + item.category + ' batch ' + (i + 1) + ': nothing parseable in ' + String(ai.content || '').length + ' chars (finish ' + (ai.finishReason || '?') + '); retrying once');
|
||||
i--; batches++; if (batches > 12) break;
|
||||
continue;
|
||||
}
|
||||
else if (parsed.truncated) console.warn('[clinical-assistant] prompt pool ' + item.category + ' batch ' + (i + 1) + ': reply was cut off; ' + offered + ' questions salvaged');
|
||||
categoryExamples = normalizeGeneratedExamples(categoryExamples.concat(parsed.questions || []), item).slice(0, item.quota);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue