StructuredBot and AsyncStructuredBot — EARS
Parent LLD: ./LLD.md
Model and initialization
-
[x] CORE-STRUCT-001: Where the model name contains
ollama_chat,StructuredBot.__init__shall not requireresponse_formatandresponse_schemain supported OpenAI params. -
[x] CORE-STRUCT-002: For other models, where
response_formatwithresponse_schemais not supported,StructuredBot.__init__shall raiseValueErrorwith guidance to use a compatible model. -
[x] CORE-STRUCT-003:
StructuredBotshall callSimpleBot.__init__withjson_mode=Trueand the suppliedmodel_nameandstream_target.
Structured message composition
- [x] CORE-STRUCT-010:
compose_structured_first_attempt_messagesshall returnfull_messagesequal to[system_prompt]plusto_basemessage(user_messages)with no memory retrieval.
Validation loop
-
[x] CORE-STRUCT-020:
StructuredBot.__call__shall attempt up tonum_attemptscompletions; on each attempt it shall parse assistant content as JSON and validate withpydantic_model.model_validate. -
[x] CORE-STRUCT-021: On
ValidationErrorbefore the last attempt, the system shall extend the conversation with the prior assistant message and theHumanMessagefromget_validation_error_message. -
[x] CORE-STRUCT-022: On the last attempt, if validation fails and
allow_failed_validationis true and a parsed dict exists, the system shall returnpydantic_model.model_construct(**last_codeblock); otherwise it shall re-raise the validation error.
AsyncStructuredBot
- [x] CORE-STRUCT-030:
AsyncStructuredBot.__call__shall execute the synchronousStructuredBot.__call__viaasyncio.to_threadwith the samenum_attemptsandverbosearguments.
Verification
| ID | Tests / code |
|---|---|
| CORE-STRUCT-001–003 | tests/bot/test_structuredbot.py (model support / init) |
| CORE-STRUCT-010 | tests/bot/test_structuredbot.py (compose_structured_first_attempt_messages) |
| CORE-STRUCT-020–022 | tests/bot/test_structuredbot.py (validation loop, allow_failed_validation) |
| CORE-STRUCT-030 | llamabot/bot/structuredbot.py (AsyncStructuredBot.__call__ → asyncio.to_thread); no dedicated pytest for __call__ yet |