🇬🇧United Kingdom @seogow

Account created on 12 October 2014, over 9 years ago
#

Recent comments

🇬🇧United Kingdom seogow

The scope is to conduct a Vector search at indexed embeddedings and provide it as a Search API plugin, so the developer can:

  1. Create a Vector Search Index.
  2. Conduct a search on the index via Views.

If there are limitations as to what Vector Index can do, similarly to Search API Solr module, these should be reflected upon rendered View.

Reasoning: This module's aim is to work out of the box and be plug-and-play replacement for any other Search API index technology. However, there is no limit on implementation of Vector search:

  • It can be combined with keyword search to provide even more accurate results.
  • It can work as pre-selection/ordering tool of entities and then be fed to reranking.
  • ...

But that are advanced implementations, which might (or not) be implemented here, after when 1.0 is out.

I hope the above makes sense.

🇬🇧United Kingdom seogow

Combination of indexes should be IMHO separate module. There is a Drupal 7 module Search API Multi-Index Searches and it calls for Drupal 10 for sure.

However, I believe combining search indexes is out of scope of the AI module?

🇬🇧United Kingdom seogow

I am starting this right now. The idea is to be in line with the rest of the LLM APIs supported by the AI module. Each Embedding API must either support a default, set by the AI module abstraction, or provide its own defaults, which the module gracefully uses if that API is selected.

In the development version of the Search API AI for the AI module, I do not plan to have any GUI settings for chunking. I plan for it to work out of the box as a plug-and-play replacement for the Solr and DB search. For an index, this means that once it is created, it cannot be changed, though re-indexing may be triggered as usual.

I am happy to take more feature requests as the Alpha is out, but I do not want to chase too many birds at the same time.

I hope the above makes sense.

🇬🇧United Kingdom seogow

No further development will be done in this module, it has been deprecated in favour of AI module.

🇬🇧United Kingdom seogow

Ticket has been answered - no further development will be done in this module, it has been deprecated in favour of AI module.

🇬🇧United Kingdom seogow
  1. I have added a support for Huggingface - just enable the module along with the LLM Provider manager and add your key to /admin/config/huggingface/settings.
  2. Now, the module has the ability to automatically generate configuration forms for any LLM Provider. The HuggingFace one is already implemented and when the module is enabled, you can see it at: /admin/config/system/llm-provider-manager-settings.
  3. All the configurations are now managed by Drupal, and are fully editable inline at the call time. The common settings like 'temperature' or 'top_k' are shared between models - see the implementation at /admin/config/llm-provider-chat-example.

Let me know what do you think.

🇬🇧United Kingdom seogow

The module code was updated to be Drupal 11 compatible.

🇬🇧United Kingdom seogow

The issue seems to be fixed in 1.3.2.

OK (1 test, 18 assertions).

🇬🇧United Kingdom seogow

To test, simply enable Drupal LLM Provider for the LM Studio API along with running LM Studio as a server with any Chat LLM.

🇬🇧United Kingdom seogow

I have updated the module. It now allows for inline configuration and its interface is much clearer.

I have decided not to include the entity-based configuration in the 'Provider Manager Service', but rather to create a 'Flexible LLM Provider' later (with Ollama and Mistral as examples). That way the 'Provider Manager Service' stays lightweight and non-opinionated.

Feel free to use it now - if you see nothing wrong with it, I will publish 1.0. And I am of course happy to incorporate any changes which would make it better.

The usage is simple (and shown in detail in the example module 'llm_provider_chat'):

  1. $instance->llmServiceManager = $container->get('llm_provider.manager') - this gives you the service;
  2. $this->llmServiceManager->getModels([Bundles::Chat->name]) - this gives you a list of all the available LLM Chat services in the Manager (without parameter you simply are getting all types of LLM available). The example module provides a method which creates options for Drupal Select from this array.
  3. $this->llmServiceManager->getResponse($provider, $model, $input, $authentication=[], $configuration=[], $normalise_io=TRUE) - here you make the call. As you can see, you can (but do not have to) change any configuration, including credentials.
🇬🇧United Kingdom seogow

Thank you for contributing!

Could you elaborate a bit more? I cannot reproduce the issue. I need at least:

  • Drupal version
  • PHP version
  • Filtered field type
🇬🇧United Kingdom seogow

Oh, I thought you might not love it :) It seems simplistic at the surface, but it really isn't.

Let me show you the dev implementation first (including one plugin for every LLM module which allows these very now) and then we can either move forward (beta), or deprecate this module in favour of some better LLM Service project/module. I do not want mess, I want a go-to solution for everyone.

I do not duplicate Augmentor approach, nor Interpolator approach. Not even Huggingface approach. It is really about offering standard Interface agnostic to backend API. In this case even backend implementation. The good thing about it is, that both Augmentor and Interpolator accept plugins now. And what LLM Provider Service will be good at is automatically providing plugins for everything when any new LLM API is added to it. And even better it will be for modules which would use its service directly.

But as I've said - going to work now and ping you soon, when ready :)

🇬🇧United Kingdom seogow

I am not thinking about configuration entities, but real entities.

In fact, I shall employ this https://www.drupal.org/project/eck .

🇬🇧United Kingdom seogow

I will introduce an API Configuration Entity.

The plan is to walk away from any hardcoded API implementations completely, allowing user to define API specification using Entity API. It sill will be possible to write a module with Entity configuration to have instant API definition (e.g. manually or via configuration import), but it will not be necessary. The LLM Provider Service will itself provide default API Configuration Entity bundles and Entity instances for the most common APIs.

The powers are:

  1. You, as a service subscriber, can use the service provided by this module with just ID of any API Configuration Entity available to you, which has bundle functionality compatible with your module requirements. It will just work out of the box.
  2. You are completely free to create new API Configuration Entity or clone any existing API Configuration Entity available to you. All you need to make a successful call to API is to provide ID of the new entity you want to use.
  3. As Drupal provides all the tools for entities out of the box, you can:
    1. Use Views to organise and show API Configuration Entities.
    2. Use API Configuration Entities as resource of any select list.
    3. Perform CRUD operations on API Configuration Entities (according to your permissions).

That way we allow users to use any available LLM API, even the ones which nobody hardcoded, via simply creating an API Configuration Entity with correct bundle, which would be defined by its functionality and compulsory API message input type(s) and API response types:

  1. Chat bundle: text | text
  2. Image generation bundle: text | binary data
  3. Image description bundle: binary data | text
  4. Embedding bundle: text | text
  5. Tokenizer bundle: text | text
  6. ...

The beauty of this architecture is, that if you want to provide any form/field sanitisation (e.g. input text length, input name, description etc.) in your frontend, you can always load API Configuration Entity (by ID, name, again Drupal has it all) and obtain the information from the actual object.

🇬🇧United Kingdom seogow

I believe your suggestion about field storage is just the thing we need. I am going to update the code with working example on how it can work.

🇬🇧United Kingdom seogow

I believe the 'LLM Provider Service' module needs to provide just an interface, say a class to extend, for each LLM functionality, from chat to video generation.

Huggingface still duplicates code (tokens/credentials storage).

I envisage the workflow as follows:

  • LLM Provider module (e.g. Drupal LLM Provider for the LM Studio API ) extends the functionality specific LLMProvider class(es) provided by 'LLM Provider Service module', consisting of API compulsory settings (access means like credentials, token or URL etc.), functional compulsory settings (e.g. text input, binary image data etc.) and optional functional settings (everything else, along with default values and descriptions).
  • Any frontend which consumes the client via LLM Provider obtains this information from a Drupal service call, according to a selected model (above) and fills it in order to use the service. Exception is thrown if some compulsory information is missing or empty.

So to answer your question, IMHO having model configuration inline would be the best approach. The 'LLM Provider Service' module should not care if you use a wrapper entity or any other means of data management at the client side, but I like the usage of the Key module for credentials/keys because that way you can share these between models (e.g. different models in the OpenAI Stack).

The reasoning for the above is that at the end of the day we want to enable users to use different credentials on the same site (say a user with the role 'OpenAI consumer' can use their own credentials to access the service via enabled frontend and store these via Key), and that is only possible with an inline approach.

I hope the above makes sense.

🇬🇧United Kingdom seogow

I work on the Big Three (Mistral, Anthropic and OpenAI) now. When that is done (I hope April 2024), I will provide patches for already existing most interesting/useful 3rd party modules (hopefully at the same time).

🇬🇧United Kingdom seogow

I hope I will have time to investigate AI Interpolator more next week.

But I agree with the plan - I shall write Providers for all the big LLMs and let know maintainers of the biggest Drupal AI ecosystems that here is available interface which can serve them all. Let's see what happens.

🇬🇧United Kingdom seogow

After reviewing other modules, I've concluded that the decision to deprecate the AI models library was justified. Consolidating every possible API call implementation into a single module would have been impractical.

However, I see great alignment between this module and your vision of having numerous modules integrate AI APIs. Its design specifically accommodates various implementations, even allowing for competition among implementations of the same API, while providing a unified interface for AI backend/frontend modules. This approach ensures that these modules remain functional regardless of the API used. I suggest we start with the OpenAi Specification as our foundation.

I am open to sharing this module's maintenance responsibilities, allowing for the addition and enhancement of the service interface as new integrations necessitate changes or new functionalities.

I believe the best way forward would be to open this module to the authors of OpenAI / ChatGPT Integration and AI Interpolator , enabling them to provide a fully implemented OpenAI Provider and incorporate the abstraction into their modules. This would then unleash the power of all their submodules to everyone. I would be happy to provide Mistral and Anthropic Providers, so out of the box, we would have a wide range of functionality supported by three powerful LLMs.

🇬🇧United Kingdom seogow

Thank you, this has been implemented.

🇬🇧United Kingdom seogow

Re-rolled the patch, included library dependency, minified JS and added mapping.

Tested against 5.1.

🇬🇧United Kingdom seogow

@catch (and @fallenturtle) I was thinking about usage of replace, but there are downsides to both approaches:

  • If another module or theme in your Drupal project genuinely needs fakeobjects, it won't get installed because Composer thinks it's already provided.
  • You'll need to manually manage the version in the provides section if the unnecessary dependency's version changes in the original module's composer.json before the patch is applied.

Thus, since we all agree patch works, I would still suggest to wait for merge or go patchless.

🇬🇧United Kingdom seogow

@fallenturtle that is correct.

Until this dependency is removed as dependency from the composer.json in the footnotes module, it will be required in composer.lock. The workflow is as follows:

  1. Footnotes are installed including their dependencies (fakeobjects).
  2. Patch is applied, removing dependencies from .info (works) and from composer.json (only after they were recorded in central composer.lock).

AFAIK you have two options:

  1. Use patchless approach; or
  2. Live with the unused modules in code source until the patch is incorporated into the module.

I hope the above explains the issue :)

🇬🇧United Kingdom seogow

This version is becoming obsolete.

🇬🇧United Kingdom seogow

Module is compatible with Drupal 10.

🇬🇧United Kingdom seogow

The patch is compatible and accepted. Tested on vanilla Drupal 10.0.

🇬🇧United Kingdom seogow

@reszli, I agree that employing an exact match is always better. I'll make sure to update the code accordingly when implementing a functional test.

@apaderno, I sincerely appreciate all your insightful comments. They have been tremendously helpful.

@vishal.kadam, once again, thank you for your valuable input.

🇬🇧United Kingdom seogow

@msn5158, I apologize for any confusion earlier. You can indeed achieve your requirement using Views Contextual Filters. However, this particular question might be better suited for Drupal Answers. That platform would not only provide you with a more appropriate response but also allow others to benefit from the discussion.

I will be closing this request as it is considered out of scope for the current module. The focus here is to filter the View output to display rows that are associated with the values on the last delta of the selected field, whereas your concern relates to values on any delta of a multi-value field.

🇬🇧United Kingdom seogow

If I understand the requirement correctly, you can accomplish this by using the core Views delta filter with the "is less than or equal to" operator, in conjunction with the Token Views Filter module. Would this solution meet your requirements?

🇬🇧United Kingdom seogow

@vishal.kadam, thank you, highly appreciated!

@apaderno,

See detailed answer below, but thank you for the security catch! Normally I would not deploy again until you are completely happy with the code, but since there was a security issue, I have done that immediately.

Query bugfix:

/**
   * {@inheritdoc}
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Exception
   */
  public function query() {
    // If filtering is disabled, do nothing.
    if (!$this->value) {
      return;
    }

    $this->ensureMyTable();
    $database = \Drupal::database();
    $field = $database->escapeField("$this->tableAlias.delta");
    $query_base_table = $this->relationship ?: $this->view->storage->get('base_table');
    $entity_type = $this->entityTypeManager->getDefinition($this->getEntityType());
    $keys = $entity_type->getKeys();
    $data = Views::viewsData()->get($this->table);
    $join_info = $data['table']['join'][$query_base_table];

    $join_info_table = $database->escapeTable($join_info['table']);
    $join_info_field = $database->escapeField($join_info['field']);
    $query_base_table_id = $database->escapeField($query_base_table . '.' . $keys['id']);

    $query = "(($field IS NULL) OR ($field IN (SELECT MAX($field) FROM $this->tableAlias WHERE $join_info_table.$join_info_field = $query_base_table_id)))";
    $this->query->addWhereExpression($this->options['group'], $query);
  }

Additional Documentation fixes deployed:

Class:

/**
 * Filter to handle last delta value.
 *
 * @ingroup views_filter_handlers
 *
 * @ViewsFilter("vfld")
 *
 * @package Drupal\vfld\Plugin\views\filter
 */

constructor:

/**
   * Constructs a new instance of LastDeltaFilter.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   Entity Type Manager Service.
   */

I do not see any issues with declaration of values I have done. The same approach to change the property value is used in Drupal Core by authors of the Views module themselves:

see: namespace Drupal\views\Plugin\views\filter;

However, I am happy, if you want me to (let me know), follow the classic software engineering practices by:

/**
   * Constructs a new LastDeltaFilter.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   Entity Type Manager Service.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
    $this->alwaysMultiple = TRUE;
    $this->alwaysRequired = TRUE;
  }

Thank you for your feedback!

🇬🇧United Kingdom seogow

@vishal.kadam - You are right, I have fixed the vfld.info.yml file. I have also fixed the line lengths in the README.md. You can check my other contribution e.g. there: https://www.drupal.org/project/mail_safety/issues/3267796 🐛 No mail with symfony_mailer Needs work .

@apaderno - I do not see any issue with that variable per se - this is a Boolean filter and its value is either Set (filter) or Not set (do not filter), hence I force it not to be optional ("Not set" equals to that and it is far less confusing). However, my PHP Documentation should follow the inheritance. Fixed that.

Thank you both very much for your time and effort!

Production build 0.69.0 2024