Imp.Adapter.XML (Imp v0.16.0)

Copy Markdown View Source

XML adapter with DSPy's field dialect and current output-completion contract.

One XML-only dialect end to end: the system message renders the interaction structure as <field>\n{field}\n</field> blocks (no [[ ## ]] markers and no completed sentinel), user turns wrap every input value in its field tag, demo/history assistant turns wrap every output value in its field tag, and the main request ends with DSPy's exact output requirement sentence ("Respond with the corresponding output fields wrapped in XML tags ...").

Parse fills declared output defaults and omitted nullable fields, then returns an Imp.AdapterParseError of kind :missing_fields if any required output remains absent. Typed objects, arrays, mappings, and unions use recursive XML. Saxy parses completed responses; declarations, doctypes, and custom entities are rejected before parsing.

A reply with none of the requested output tags (prose, a JSON object, Chat marker sections) is an Imp.AdapterParseError of kind :missing_fields naming every output, even when every output is optional or has a default, so the caller's fallback or retry runs instead of a prediction made only of defaults. A signature that names an output in metadata[:text_field] is read as Imp.Adapter.Chat reads it: prose is that field, trimmed, a blank reply is a step that said nothing, and the other outputs take their defaults. A reply with an output's tag, a [[ ## field ## ]] line, or a JSON object with an output's key is not prose: it is parsed by tags, and with no requested tag it is a parse error that the JSON fallback reads. A reply with some requested tags and not others is read as Chat reads a partial reply: absent outputs take their defaults or nil when optional, and a required one that is still absent is reported missing.

Rendering is byte-verified against real DSPy 3.2.1 by the golden-trace differential (test/fixtures/golden_trace/cases.json, xml_* cases).