Skip to content

feat(formats): implement Express and Elemental InferenceFormats #1982

Open
gspencergoog wants to merge 21 commits into
mainfrom
unified-inference-formats-strategies
Open

feat(formats): implement Express and Elemental InferenceFormats #1982
gspencergoog wants to merge 21 commits into
mainfrom
unified-inference-formats-strategies

Conversation

@gspencergoog

@gspencergoog gspencergoog commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Refactors the structured inference SDK API and evaluation harness in Python to unify the handling of different inference formats (standard JSON transport, experimental Express DSL, and experimental Elemental HTML). It does this by restructuring the formats as polymorphic implementations of the InferenceFormat interface and using these abstractions to consolidate system prompt generation and response parsing logic.

Changes

  • SDK Package & Interface Unification:
    • Restructured experimental Express and Elemental formats under agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/.
    • Defined polymorphic methods on the base InferenceFormat class (decompile, transform_examples, format_description, catalog_description) and implemented them across TransportFormat, ElementalFormat, and ExpressFormat.
    • Updated prompt generators (ExpressPromptGenerator, ElementalPromptGenerator) to align with the new structure.
  • Evaluation Solvers Consolidation:
    • Replaced the separate format-specific solvers (direct.py, express.py, elemental.py) under eval/a2ui_eval/strategies/ with a unified format.py solver.
    • The format solver dynamically loads the correct format implementation (TransportFormat, ExpressFormat, or ElementalFormat) based on config, allowing polymorphic prompt formatting and output compilation/validation.
  • Robustness & General Fixes:
    • Fixed case-insensitive action property resolution in ElementalCompiler when multiple action properties are present.
    • Ensured prompt generator helper/catalog/decompiler are initialized in catalog_description when called prior to generate().
    • Moved regular expression compilation in ElementalParser to the module level for efficiency.
    • Cleaned up redundant imports and optimized invariant dataset metadata accesses in eval/ to fail fast.
  • Tests & Conformance:
    • Renamed the conformance suite schema_manager.yaml to inference_format.yaml.
    • Updated all Python SDK test suites and conformance tests to reflect the new layout and verified all 621 tests pass.

Impact & Risks

  • This is a breaking refactoring for internal SDK layout, but encapsulates formatting details cleanly behind the unified InferenceFormat API and preserves external integration endpoints.

Testing

Verify the changes by running all SDK and evaluation unit tests:

uv run pytest

gemini-code-assist[bot]

This comment was marked as resolved.

@gspencergoog gspencergoog force-pushed the unified-inference-formats-strategies branch 3 times, most recently from 6238957 to 82bd501 Compare July 10, 2026 16:56
@gspencergoog gspencergoog force-pushed the unified-inference-formats-foundation branch from 89a547a to 1134c08 Compare July 10, 2026 16:59
@gspencergoog gspencergoog force-pushed the unified-inference-formats-strategies branch 10 times, most recently from 5266cef to 77a52dd Compare July 13, 2026 21:12
@gspencergoog gspencergoog force-pushed the unified-inference-formats-foundation branch from dd30576 to 914f571 Compare July 13, 2026 21:44
@gspencergoog gspencergoog force-pushed the unified-inference-formats-strategies branch 2 times, most recently from c0e7429 to 33fc7c2 Compare July 13, 2026 21:49
@gspencergoog gspencergoog force-pushed the unified-inference-formats-strategies branch from e910b3c to 090a859 Compare July 15, 2026 21:43
…r API

style(express): remove dead empty TYPE_CHECKING block in express prompt_generator.py

feat(sdk): remove remaining A2UI_EXPRESS_ENABLED environment variable references

feat(sdk): support complete flag on has_format_content for Express and Elemental

feat(sdk): implement has_format_content for Express and Elemental parsers

refactor(sdk): rename prompts directory to prompt (singular)

refactor(sdk): hide Express and Elemental prompt generators from package exports

refactor(sdk): expose prompt_generator on Express/Elemental formats and move to prompts/generator.py

Refactor the Express and Elemental inference strategies to the new configuration.
@gspencergoog gspencergoog force-pushed the unified-inference-formats-strategies branch from 0bbda91 to d495ff0 Compare July 15, 2026 21:52
@gspencergoog gspencergoog changed the title feat(formats): implement Express and Elemental inference format strategies feat(formats): implement Express and Elemental InferenceFormats Jul 15, 2026
gemini-code-assist[bot]

This comment was marked as resolved.

…plate duplication

- Promotes decompile, transform_examples, format_description, and catalog_description as abstract methods on the InferenceFormat base class.
- Standardizes parameter signatures for format_description and catalog_description across Express, Elemental, and Transport formats.
- Removes duplicated prompt templates and translation/compilation logic from ExpressPromptGenerator and ElementalPromptGenerator, delegating directly to the format classes.
- Standardizes backwards-compatible prompt generator helpers to fallback to default format instances if initialized with raw catalog models.
- Resolves all Python SDK unit tests and Kotlin conformance tests.
@gspencergoog gspencergoog force-pushed the unified-inference-formats-strategies branch from c7fd39d to 1cc6a6e Compare July 15, 2026 23:05
gemini-code-assist[bot]

This comment was marked as resolved.

@gspencergoog gspencergoog requested a review from nan-yu July 15, 2026 23:50
…e prompt rules

- Remove deprecated parse_elemental_response and parse_express_response wrapper functions.
- Update all integration and compiler tests to instantiate and call ElementalParser and ExpressParser directly.
- Move format-specific rules (constants) and transform_examples helper methods into ElementalPromptGenerator and ExpressPromptGenerator.
- Remove format_description from InferenceFormat base class and subclasses.
- Retain catalog_description on the strategy classes (ElementalFormat, ExpressFormat, TransportFormat) as requested.
… error retry context

- Create custom A2uiCompilationError exception carrying error message, line, column, raw content, and partial results.
- Add is_final field to ResponsePart and document all fields.
- Refactor ExpressParser and ElementalParser to be stateless by tracking block truncation metadata on ResponsePart objects.
- Propagate is_final metadata through compile method signatures to prevent stateful tracking on parser instances.
- Wrap compiler exceptions in A2uiCompilationError and attach the preceding parsed parts.
- Fix greedy tag parsing in ElementalParser's block detection.
- Add comprehensive integration tests for ElementalParser.
…states

- Create a shared generic state-machine BlockLexer utilizing a LexerState Enum to scan LLM responses.
- Correctly handle string literals (including triple quotes), backslash escapes, and code comments to prevent premature tag detection when "</a2ui>" appears inside them.
- Support open tag matching with attributes (e.g. `<a2ui id="main">`).
- Handle global Markdown backticks wrapper cleaning globally inside BlockLexer for all inference formats.
- Refactor ExpressParser and ElementalParser to use BlockLexer for unwrapping.
- Add comprehensive unit tests validating BlockLexer.
…ag attributes loss

- Implement preserve_enclosing_tags option in BlockLexer and configure it in ElementalParser to prevent losing <a2ui> start tag attributes (like id / surfaceId).
- Remove circular state mutation/double-dispatch of helper/decompiler on prompt_gen in format.catalog_description.
- Override __str__ on A2uiCompilationError to output formatted error locations (line, column) and help messages.
- Modernize type annotations using Python 3.10 built-in generics and PEP 604 pipe unions.
- Reformat modified files with pyink.
…compiler sentinel wrapping

- Refactor A2UI Elemental root component tag from <a2ui> to <body>.
- Unify sentinel wrapping under <a2ui>...</a2ui> across all formats (Express and Elemental).
- Update ExpressDecompiler and ElementalDecompiler to return raw unwrapped DSL/HTML strings inside decompile().
- Delegate sentinel wrapping strictly to wrap_decompiled_blocks() inside decompiler classes.
- Update BlockLexer to behave as a clean tag-stripping tokenizer.
- Auto-append trailing </body> in ElementalParser if compiles a truncated/unclosed creation block.
…o PromptGenerator

- Remove catalog_description from InferenceFormat base interface and all format subclasses.
- Add catalog_description directly to PromptGenerator subclasses (Express, Elemental, Transport).
- Update prompt generator internal callers to call catalog_description locally.
- Move format catalog description unit tests into prompt generator tests, and update target references.
- Declare and annotate local/instance variables in BlockLexer and TransportPromptGenerator.
- Refactor _clean_markdown to always return a string, updating related test assertions.
- Resolve Liskov substitution violation in A2uiTemplateManager.generate_system_prompt.
- Implement stub properties for abstract InferenceFormat methods inside A2uiTemplateManager.
- Typecast TypedDict dictionary queries inside TransportFormat catalog resolution.
…actoring

- Update mock model output payload in test_a2ui_elemental_solvers to use <body> root tag inside <a2ui> sentinels, reflecting A2UI Elemental refactoring contract.
gemini-code-assist[bot]

This comment was marked as resolved.

- Make experiments parameter conditional on version == "1.0" in eval format strategy resolver.
- Support resolving surface ID from both a2ui and body tags in completion solver regex.
- Auto-close unclosed a2ui tags during streaming compilation in ElementalParser.
- Ensure prompt generator delegates example decompilation using its pruned catalog decompiler if available.
- Call _ensure_catalog before instantiating prompt generator in ExpressFormat property.
- Fix prefix check for action properties in ElementalDecompiler to look for "on-".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants