fix: parse_turn falls back gracefully + classify logs flapping classifiers
The turn endpoint was 500ing in multi-bot scenes whenever the classifier provider hiccuped on parse_turn — particularly visible after a guest was added and bots started exchanging turns. The traceback was 'classify failed for schema ParsedTurn with no default' because parse_turn was the only classify caller without a default. Two changes: - chat/services/turn_parse.py: parse_turn now passes a default that wraps the whole prose as one 'dialogue' segment. The narrative still fires on the prose; we lose finer-grained segment kinds (action vs dialogue vs ooc) on this turn, but the request returns cleanly. Updated the existing test that pinned the old RuntimeError contract. - chat/llm/classify.py: when retries are exhausted, log a WARNING with the schema name, last error type, and a snippet of the last raw text the model returned. Surfaces flapping classifiers in the uvicorn log for diagnosis without taking down the request. Suite: 471 passed in 11.7s.
This commit is contained in:
@@ -73,11 +73,25 @@ async def test_parse_turn_empty_prose_short_circuits_without_classifier_call():
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_parse_turn_raises_when_classifier_fails_twice():
|
||||
async def test_parse_turn_falls_back_to_whole_prose_when_classifier_fails():
|
||||
"""A flapping classifier (3 invalid responses) no longer 500s the
|
||||
request. ``parse_turn`` returns the original prose as a single
|
||||
``dialogue`` segment so the turn flow can keep moving — the
|
||||
narrative will still fire on the prose, just without finer-grained
|
||||
segment classification.
|
||||
|
||||
The old contract was ``RuntimeError`` (no default), but in
|
||||
production that took down the whole turn endpoint with a 500 the
|
||||
moment any classifier provider hiccuped — particularly painful in
|
||||
multi-bot scenes where every user turn pays the parse_turn cost.
|
||||
"""
|
||||
mock = MockLLMClient(canned=["nope", "still nope", "nope3"])
|
||||
with pytest.raises(RuntimeError):
|
||||
await parse_turn(
|
||||
mock,
|
||||
model="m",
|
||||
prose='*shrugs* "whatever"',
|
||||
)
|
||||
result = await parse_turn(
|
||||
mock,
|
||||
model="m",
|
||||
prose='*shrugs* "whatever"',
|
||||
)
|
||||
assert len(result.segments) == 1
|
||||
assert result.segments[0].kind == "dialogue"
|
||||
assert result.segments[0].text == '*shrugs* "whatever"'
|
||||
assert result.intent == "narrative"
|
||||
|
||||
Reference in New Issue
Block a user