Problem/Motivation
responseToArray() fails with uninitialized properties: The responseToArray() method calls getter methods on the Partitech\PhpMistral\Clients\Response object without checking if
properties are initialized. For example, $response->getPages() throws an error when the $pages property is not set (which is the case for non-document chat responses).
Steps to reproduce
Running
$provider = \Drupal::service("ai.provider")->createInstance("mistral");
$input = new ChatInput([new ChatMessage("user", "Hello")]);
$output = $provider->chat($input, "mistral-small-latest");
results in
[error] Error: Typed property Partitech\PhpMistral\Clients\Response::$pages must not be accessed before initialization in Partitech\PhpMistral\Clients\Response->getPages()
(line 528 of /app/vendor/partitech/php-mistral/src/Clients/Response.php) #0 /app/web/modules/contrib/ai_provider_mistral/src/Plugin/AiProvider/MistralProvider.php(469):
Partitech\PhpMistral\Clients\Response->getPages()
#1 /app/web/modules/contrib/ai_provider_mistral/src/Plugin/AiProvider/MistralProvider.php(366): Drupal\ai_provider_mistral\Plugin\AiProvider\MistralProvider->responseToArray()
#2 [internal function]: Drupal\ai_provider_mistral\Plugin\AiProvider\MistralProvider->chat()
#3 /app/web/modules/contrib/ai/src/Plugin/ProviderProxy.php(269): ReflectionMethod->invokeArgs()
#4 /app/web/modules/contrib/ai/src/Plugin/ProviderProxy.php(133): Drupal\ai\Plugin\ProviderProxy->wrapperCall()
#5 /app/vendor/drush/drush/src/Commands/core/PhpCommands.php(33) : eval()'d code(9): Drupal\ai\Plugin\ProviderProxy->__call()
#6 /app/vendor/drush/drush/src/Commands/core/PhpCommands.php(33): eval()
#7 [internal function]: Drush\Commands\core\PhpCommands->evaluate()
#8 /app/vendor/consolidation/annotated-command/src/CommandProcessor.php(276): call_user_func_array()
Proposed resolution
Wrap $response->getPages() call in try-catch for \Error to handle uninitialized property.
Comments
Comment #3
petar_basic commentedWrapped the potentially uninitialized property accessors (getModel(), getCreated(), getPages()) in try-catch blocks that catch \Error exceptions.
Properties that are initialized will be included in the output array; uninitialized properties are silently skipped.
Comment #4
fagoCatching exceptions and silently throwing them away is a bad practice and usually creates other issues later on, when important-to see errors are not propagageted any more.
Besides that, I wonder why the above got snippet throws this exception? the code snippet seems right, so why is the property un-initialized? are we using the API somehow wrongly? To me, it looks like we are missing the underlying root-cause? Please elaborate.
Comment #5
petar_basic commentedThe Response class from php-mistral has properties without default values. The pages property is only set for OCR/document responses - it's never initialized for regular chats, therefore the above snippet causes the error when the responseToArray tries to call $response->getPages();
For the 'created' property - according to the mistral docs, the OCR response doesn't have it, so in that case it would be not initalized and throw an error.
So basically, the Response class handles multiple response formats from mistral API - but it doesn't seem to handle the optional fields properly.
We can fix this upstream - e.g. set default values
But because it is breaking the chats here now, I would still go with the current impl (and maybe remove once upstream is updated)
Also a possibility is to detect what kind of response we are handling and then access only relevant properties, but then it would need to be maintained in case anything changes upstream/in the mistral API.
What do you think?
Comment #7
fagothanks. I agree, we should add a short-gap fix here. So I went with your MR and just made it a little more bullet-proof by rethrowing the exception if it's not having the excepted error + merged.
Still, the real fix to add the missing initialization is trivial and should be added upstream. Let's create a quick upstream PR please!
So setting to needs work for that.
Comment #8
petar_basic commentedCreated an upstream issue and PR to fix the root cause:
- Issue: https://github.com/partITech/php-mistral/issues/80
- PR: https://github.com/partITech/php-mistral/pull/81
The fix adds default values to the uninitialized properties.
Comment #9
fagowow, the maintain was quick! :-)
let's require https://github.com/partITech/php-mistral/releases/tag/v0.1.26 and remove our hack
Comment #11
petar_basic commentedComment #12
petar_basic commentedBumped partitech/php-mistral from ^0.1.25 to ^0.1.26 and removed the workaround.
Comment #13
fagothx, merged.