Move the input of structured output to an object.

Created on 8 September 2025, 26 days ago

--- AI TRACKER METADATA ---
Update Summary: Changes to make it easier to input structured output.
Check-in Date: MM/DD/YYYY (US format) [When we should see progress/get an update]
Due Date: MM/DD/YYYY (US format) [When the issue should be fully completed]
Blocked by: [#XXXXXX] (New issues on new lines)
Additional Collaborators: @username1, @username2
AI Tracker found here: https://www.drupalstarforge.ai/
--- END METADATA ---

Problem/Motivation

The current solution for adding a structured output, is based on an OpenAI array and needs to be manipulated by any processor that might need another structure. OpenAI for instance has name, description on top of a json schema.

These two things are important for guidance, but are in theory optional. They also have no usage for certain other providers.

If we instead create a DTO or a class that can take the name, description, strict and json schema as methods, this will allow for a more structured input on top of keeping the array as optional. Similar to how the input works for the actual provider input, where it takes raw or object. We could then add validation for the json schema later.

So the method for now would be something like the following.

  public function setChatStructuredJsonSchema(array|StructuredOutputSchema $schema): void {
    if ($schema instranceof StructuredOutputSchema) {
       $schema = $schema->toArray();
    }
    $this->setDebugDataValue('chat_structured_json_schema', $schema);
    $this->chatStructuredJsonSchema = $schema;
  }

Then for 2.0.x, we can remove free array and also look into how you can add any class, similar to how Symfony is doing it, see: https://github.com/symfony/ai/blob/a40908dfdc2a0bf96e1a84b6d6437c6a2d6a2...

Proposed resolution

  • Create an interface called StructuredOutputSchemaInterface, that has name, description, strict and json schema.
  • Create an class for it, for now just getters and setters and toArray (and maybe fromArray)
  • For now, just make an array when its set in the ChatInput.
  • If the json_schema is missing, it should throw an error.
  • If the name is missing, it should set something generic like "json_schema".
  • Strict should be set to false.
  • If strict is set in the object, we should set chatStrictSchema with it, for BC.
  • Add a deprecation notice that setChatStrictSchema and getChatStrictSchema will be removed for 2.0 and should be set on the setChatStructuredJsonSchema input instead.
๐Ÿ“Œ Task
Status

Active

Version

1.2

Component

AI Core module

Created by

๐Ÿ‡ฉ๐Ÿ‡ชGermany marcus_johansson

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @marcus_johansson
  • ๐Ÿ‡ฆ๐Ÿ‡บAustralia kim.pepper ๐Ÿ„โ€โ™‚๏ธ๐Ÿ‡ฆ๐Ÿ‡บSydney, Australia

    In this issue, I showed how you can create a value object and validate it using Symfony Validator. It's a pretty clean solution IMO. ๐Ÿ“Œ Create an 'embedding' object that can be validated Active

  • ๐Ÿ‡ฆ๐Ÿ‡บAustralia kim.pepper ๐Ÿ„โ€โ™‚๏ธ๐Ÿ‡ฆ๐Ÿ‡บSydney, Australia

    Some example code:

    Create a plain old value object with some constraint attributes:

    use Symfony\Component\Validator\Constraints as Assert;
    
    class Embedding {
    
      public function __construct(
        #[Assert\Regex(
          pattern: '/^[A-Za-z0-9_-]+:[A-Za-z0-9_-]+$/',
          message: 'Id should be in the format "prefix:suffix"',
        )]
        readonly public string $id,
        #[Assert\NotBlank(message: 'Values should not be empty')]
        public array $values,
        #[Assert\NotBlank(message: 'Metadata should not be empty')]
        protected array $metadata,
      ) {}
    

    Create a Symfony validator that looks for the attributes:

    $validator = \Symfony\Component\Validator\Validation::createValidatorBuilder()
            ->enableAttributeMapping()
            ->getValidator();
    

    Validate the object:

    $embedding = new Embedding(
          'model1:embedding1',
          [0.1, 0.2, 0.3],
          ['source' => 'test']
        );
    
    /** @var \Symfony\Component\Validator\ConstraintViolationListInterface $violations */
    $violations = $validator->validate($embedding);
    
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany marcus_johansson

    I think we can add symfony validation, on the inputs. The major issue is that there is no way to assert a json-schema asfaik? The question is if we should also add that validation here, if we are doing validation?

    The provider usually responds with a human readable error message that gets logged, but it would be nice to be consistent.

    It would add an external library, but going forward structured outputs will play a big role in ECA, Agent outputs and most likely Automators.

  • Pipeline finished with Failed
    23 days ago
    Total: 194s
    #596151
  • Pipeline finished with Failed
    16 days ago
    #602441
  • Pipeline finished with Success
    16 days ago
    #602449
  • Pipeline finished with Success
    11 days ago
    Total: 178s
    #606627
Production build 0.71.5 2024