mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-14 20:55:15 +02:00
68 lines
1.9 KiB
Python
68 lines
1.9 KiB
Python
"""Parsing a model's reply into a structured shape.
|
|
|
|
Agent LLMs wrap JSON in prose and markdown fences. ``invoke_json`` exists so
|
|
every generation node tolerates that the same way. The LLM is an external
|
|
boundary, so it is faked with a canned reply; the behavior under test is the
|
|
parsing, not the model.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
from pydantic import BaseModel
|
|
|
|
from app.podcasts.generation.structured import StructuredOutputError, invoke_json
|
|
|
|
pytestmark = pytest.mark.unit
|
|
|
|
|
|
class _Shape(BaseModel):
|
|
name: str
|
|
count: int
|
|
|
|
|
|
class _CannedLLM:
|
|
"""A TTS-free stand-in for the chat model: replies with one fixed string."""
|
|
|
|
def __init__(self, reply: str) -> None:
|
|
self._reply = reply
|
|
|
|
async def ainvoke(self, _messages):
|
|
return SimpleReply(self._reply)
|
|
|
|
|
|
class SimpleReply:
|
|
def __init__(self, content: str) -> None:
|
|
self.content = content
|
|
|
|
|
|
async def _parse(reply: str) -> _Shape:
|
|
return await invoke_json(_CannedLLM(reply), [], _Shape)
|
|
|
|
|
|
async def test_parses_a_clean_json_reply():
|
|
shape = await _parse('{"name": "alpha", "count": 3}')
|
|
assert shape == _Shape(name="alpha", count=3)
|
|
|
|
|
|
async def test_parses_json_wrapped_in_a_markdown_fence():
|
|
reply = '```json\n{"name": "beta", "count": 7}\n```'
|
|
shape = await _parse(reply)
|
|
assert shape == _Shape(name="beta", count=7)
|
|
|
|
|
|
async def test_extracts_json_embedded_in_prose():
|
|
"""Reasoning models prepend/append chatter around the object."""
|
|
reply = 'Sure, here you go: {"name": "gamma", "count": 1} — hope that helps!'
|
|
shape = await _parse(reply)
|
|
assert shape == _Shape(name="gamma", count=1)
|
|
|
|
|
|
async def test_raises_when_there_is_no_json_object():
|
|
with pytest.raises(StructuredOutputError):
|
|
await _parse("I could not produce that.")
|
|
|
|
|
|
async def test_raises_when_the_json_does_not_match_the_shape():
|
|
with pytest.raises(StructuredOutputError):
|
|
await _parse('{"name": "delta"}')
|