Give reasoning models room; skip the advisor's self-contradictory ask
DeepSeek is a reasoning model — its chain-of-thought counts against the completion budget. The 1024 max_tokens default let it burn the whole budget "thinking" and get cut off (finish_reason: length) with an empty content, which read as a parse failure. Raise DEFAULT_MAX_TOKENS to 4096 so it can finish reasoning AND emit the JSON. Also return a clear error on empty responses. The spiral was triggered by a contradictory prompt: the fight was already "deadly" yet the advisor still asked the model to "add creatures to reach Deadly." Skip the LLM when the target tier isn't actually harder than the current one and let the deterministic path ease the over-tuned fight instead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -108,6 +108,11 @@ export function useEncounterAdvisor(campaign: Campaign, encounter: Encounter) {
|
||||
const existing: ReinforceMonster[] = monsterCombatants.map((c) => ({ name: c.name, cr: c.cr, level: c.level }));
|
||||
const current = computeBudget(campaign.system, partyLevels, existing.map((m) => ({ cr: m.cr, level: m.level }))).difficulty;
|
||||
const target = nextTarget(campaign.system, current);
|
||||
// When the fight is already at (or above) the hardest tier, "add creatures to
|
||||
// reach <target>" is a contradiction — it makes reasoning models spiral and burn
|
||||
// their whole token budget. Only ask the AI when the target is genuinely harder;
|
||||
// otherwise fall through to the deterministic path (which eases an over-tuned fight).
|
||||
const targetIsHarder = (ORDINAL[target.toLowerCase()] ?? 99) > (ORDINAL[current.toLowerCase()] ?? -1);
|
||||
|
||||
// Candidates the AI may choose from: the creatures already in the fight
|
||||
// (so it can say "add another goblin") plus level-appropriate bestiary picks.
|
||||
@@ -125,7 +130,7 @@ export function useEncounterAdvisor(campaign: Campaign, encounter: Encounter) {
|
||||
const candidates = [...existingCands, ...poolCands];
|
||||
if (candidates.length === 0) { setMessage('No suitable creatures found for this party.'); setState('error'); return; }
|
||||
|
||||
if (canUseLlm) {
|
||||
if (canUseLlm && targetIsHarder) {
|
||||
const prompt = buildBalancePrompt(ctx, { difficulty: current, targetDifficulty: target, candidates });
|
||||
const res = await complete<BalanceSuggestion>(getLlmConfig(), { system: prompt.system, user: prompt.user, schema: balanceSuggestionSchema });
|
||||
if (res.ok && 'data' in res) {
|
||||
|
||||
Reference in New Issue
Block a user