feat: turn input parser via classifier
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from chat.llm.mock import MockLLMClient
|
||||
from chat.services.turn_parse import (
|
||||
ParsedTurn,
|
||||
TurnSegment,
|
||||
parse_turn,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_parse_turn_three_segment_happy_path():
|
||||
canned = json.dumps(
|
||||
{
|
||||
"segments": [
|
||||
{"kind": "action", "text": "walks over"},
|
||||
{"kind": "dialogue", "text": "Hey."},
|
||||
{"kind": "ooc", "text": "player note"},
|
||||
]
|
||||
}
|
||||
)
|
||||
mock = MockLLMClient(canned=[canned])
|
||||
result = await parse_turn(
|
||||
mock,
|
||||
model="m",
|
||||
prose='*walks over* "Hey." ((player note))',
|
||||
)
|
||||
assert isinstance(result, ParsedTurn)
|
||||
assert len(result.segments) == 3
|
||||
kinds = [s.kind for s in result.segments]
|
||||
assert kinds == ["action", "dialogue", "ooc"]
|
||||
texts = [s.text for s in result.segments]
|
||||
assert texts == ["walks over", "Hey.", "player note"]
|
||||
assert all(isinstance(s, TurnSegment) for s in result.segments)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_parse_turn_pure_dialogue_single_segment():
|
||||
canned = json.dumps(
|
||||
{
|
||||
"segments": [
|
||||
{"kind": "dialogue", "text": "Hello there"},
|
||||
]
|
||||
}
|
||||
)
|
||||
mock = MockLLMClient(canned=[canned])
|
||||
result = await parse_turn(
|
||||
mock,
|
||||
model="m",
|
||||
prose='"Hello there"',
|
||||
)
|
||||
assert isinstance(result, ParsedTurn)
|
||||
assert len(result.segments) == 1
|
||||
assert result.segments[0].kind == "dialogue"
|
||||
assert result.segments[0].text == "Hello there"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_parse_turn_empty_prose_short_circuits_without_classifier_call():
|
||||
# No canned responses provided — if classify() is invoked it will raise
|
||||
# IndexError on the empty list. The short-circuit must prevent that.
|
||||
mock = MockLLMClient(canned=[])
|
||||
result = await parse_turn(mock, model="m", prose="")
|
||||
assert isinstance(result, ParsedTurn)
|
||||
assert result.segments == []
|
||||
|
||||
# Whitespace-only prose must also short-circuit.
|
||||
result_ws = await parse_turn(mock, model="m", prose=" \n\t ")
|
||||
assert isinstance(result_ws, ParsedTurn)
|
||||
assert result_ws.segments == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_parse_turn_raises_when_classifier_fails_twice():
|
||||
mock = MockLLMClient(canned=["nope", "still nope"])
|
||||
with pytest.raises(RuntimeError):
|
||||
await parse_turn(
|
||||
mock,
|
||||
model="m",
|
||||
prose='*shrugs* "whatever"',
|
||||
)
|
||||
Reference in New Issue
Block a user