Een hart voor de Drupal Community

Bij make it fly geloven we sterk in Drupal en Open Source software in het algemeen. We maken dagelijks gebruik van vele open source componenten en de vele Drupal modules die beschikbaar zijn. We dragen actief ons steentje bij aan de community door zelf patches, modules en documentatie te voorzien, daarnaast zijn enkele teamleden ook actief in de Drupal User Group vzw.

Een overzicht van onze bijdragen aan de Drupal community vind je terug op onze Drupal.org pagina. Naast het actief meerwerken aan de Drupal community, zetten we ook andere ontwikkelaars op weg door vragen te beantwoorden op Drupal Answers.

  1. Site Settings Extended

    Randal

    This module provides some different layouts/functionality to the excellent Site Settings module.

    Mainly, a complete overhaul of the layout is added.

    There are two options:

    • Single form
    • Core config pages

    Single form

    The single form layout adds all options in vertical tabs, this can however become quite a big form and is usually only recommended for smaller collections of settings.

    Core config pages

    The core config pages layout uses a page with links like a core config overview page. You can add more information by setting up the "menu_description" view mode, this will be rendered as the description (useful for "multiple" items, for example social links: "facebook", "instagram", ... labels could be rendered as the description). Then you can choose to either open settings in modals or open them in new pages.

    When opening settings forms in modals, you should definitely make use of the patch in the issue linked below, otherwise media library modals will wreck functionality. #2741877: Nested modals don't work

  2. Abstract token usage support

    Sven Decabooter

    Added related issues in AI module, that need to be fixed first, before both token usage for both regular chat and streamed chat can be captured.

  3. Add support for streaming chat token usage

    Sven Decabooter

    Problem/Motivation

    See #3524435: Add token usage to streamed chat. Token usage capturing for streamed chat is being worked on in the AI module. Allow this module to fetch that data for the usage limits.

  4. Add token usage to streamed chat

    Sven Decabooter

    Seems like the failure of PostStreamingResponseEvent not being triggered, is a separate issue. See #3526936: PostStreamingResponseEvent never gets triggered.

    The code in this MR can probably be already reviewed, but will not be functional until this other issue is fixed first.

  5. PostStreamingResponseEvent never gets triggered

    Sven Decabooter

    Problem/Motivation

    This problem came up when working on #3524435: Add token usage to streamed chat.

    The method \Drupal\ai\OperationType\Chat\StreamedChatMessageIterator::triggerEvent() never gets called within the AI module, so the event never gets triggered.

    Perhaps this could be added within each AI provider implementation, but it would be best if the base class could take of this.

    Feedback by Marcus Johansson on Slack regarding this:

    hmm, that is a big bug - this is a little bit of added layers because we didn't set the architecture correct from the start. I will look into if we can run it via the base class when iteration is finished, otherwise we will have to add this task on the providers until 2.0.0

    Steps to reproduce

    - Enable AI CKEditor integration module + AI Provider OpenAI - Add AI button to CKEditor - Enable "Fix spelling" for example - Select a text in CKEditor that needs spelling fixes. - The action gets performed, but the debugger never enters the method `\Drupal\ai\OperationType\Chat\StreamedChatMessageIterator::triggerEvent`

    Proposed resolution

    Feedback by Marcus Johansson:

    __destruct magic method would most likely work to trigger it

  6. Update to config split 2.x for patching capability

    Sven Decabooter

    Thanks for the merge. I guess we can now create followup tickets, so different local sites can request to merge in their own config_split.config_split.la_[LOCAL_SITE].yml and appropriate config/la_[LOCAL_SITE] config split folder.

  7. Add token usage to streamed chat

    Sven Decabooter

    Thanks for the added logic sarvjeetsingh. I am unable to make this work on my local installation though, as mentioned above.

    Test scenario: - Enable AI CKEditor integration module + AI Provider OpenAI - Add AI button to CKEditor - Enable "Fix spelling" for example - Select a text in CKEditor that needs spelling fixes. - The action gets performed, but my debugger never enters the method `\Drupal\ai\OperationType\Chat\StreamedChatMessageIterator::triggerEvent`

  8. Subscribe to AI ProviderDisabledEvent

    Sven Decabooter

    Problem/Motivation

    Subscribe to the ProviderDisabledEvent event provided by AI module. If a provider gets disabled, remove its usage data from the state & clear its config.

  9. Improve config validation

    Sven Decabooter

    Problem/Motivation

    E.g. check if the provider keys provided in `providers` config array are valid AI provider plugin IDs, add explicit config schema definition for each item within the `providers` array, etc...

  10. Improve settings form

    Sven Decabooter

    Problem/Motivation

    Settings form does not use ConfigFormBase or any of the helper logic to manage settings. Fix that.

  11. Abstract token usage support

    Sven Decabooter

    Adding some logic to the MR, in an attempt to also provide support for token usage, in case of streamed responses. This needs https://www.drupal.org/project/ai/issues/3524435 to be fixed first.

  12. Add token usage to streamed chat

    Sven Decabooter

    I have created a MR to start implementing this functionality.

    MR currently contains logic for the first action point:

    Add so that you can collect tokens in the StreamedChatMessage, but do not add it to the interface (no breaking changes).

    This allows this to be used in the ai_provider_openai module for example:

    class OpenAiChatMessageIterator extends StreamedChatMessageIterator {
    
      /**
       * {@inheritdoc}
       */
      public function getIterator(): \Generator {
        foreach ($this->iterator->getIterator() as $data) {
          $metadata = $data->usage ? $data->usage->toArray() : [];
          $streamedChatMessage = new StreamedChatMessage(
            $data->choices[0]->delta->role ?? '',
            $data->choices[0]->delta->content ?? '',
            $metadata
          );
          if (!empty($metadata)) {
            $streamedChatMessage->setInputTokenUsage($metadata['prompt_tokens']);
            $streamedChatMessage->setOutputTokenUsage($metadata['completion_tokens']);
            $streamedChatMessage->setTotalTokenUsage($metadata['total_tokens']);
            $streamedChatMessage->setCachedTokenUsage($metadata['prompt_tokens_details']['cached_tokens']);
            $streamedChatMessage->setReasoningTokenUsage($metadata['completion_tokens_details']['reasoning_tokens']);
          }
          yield $streamedChatMessage;
        }
      }
    
    }
    

    I am a bit stuck on the second and third action point:

    Add so we can collect it in the PostStreamingResponseEvent

    Add so we inject it into the PostStreamingResponseEvent

    I've been looking through the code in the AI module, but can't find where the PostStreamingResponseEvent gets triggered. Well, it gets triggered in \Drupal\ai\OperationType\Chat\StreamedChatMessageIterator::triggerEvent(), but I cannot find where that method is called. Is that supposed to be called by the OpenAI provider for example (because it doesn't currently)? I'm a bit confused as to what the exact code flow should look like...

  13. Only works for nodes, other entity types aren't supported.

    Randal

    I had to open a new branch because the existing one (1.x) created issues for me locally, due to it having the same name as the main module's git branch.

    This attempts to make the functionality as 'global' as possible, by retrieving most stuff dynamically. Please take a look and feel free to test it.

    There is an edge case where this could "not work", which is when the route parameter in `entity.[entity_type].canonical` is not the same as the entity type machine name... But I can't think of a single instance where that would be the case.

  14. Only works for nodes, other entity types aren't supported.

    Randal

    I think this issue is definitely an important one, but the scope still seems too small. I wonder why it should be limited to nodes and taxonomy terms at all, all content entities should be valid here.

    I'll see if I can cough up a solution for that.

Sven Decabooter - Drupal Developer

"Onze teamleden bouwen zelf ook mee aan ons geliefde Drupal, en daar zijn we trots op"

Sven Decabooter
Drupal developer

Betrouwbare technologie, naadloze prestaties. Dat zijn onze Drupal-oplossingen.