Skip to content

Commit 60db1c0

Browse files
authored
AI: Extending follow-up (#2587)
* AI: Review follow-up * Applied review suggestions
1 parent 278ae4a commit 60db1c0

File tree

5 files changed

+27
-22
lines changed

5 files changed

+27
-22
lines changed

code_samples/ai_actions/config/services.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ services:
2525

2626
App\Command\AddMissingAltTextCommand:
2727
arguments:
28-
$projectDir: '%kernel.project_dir%'
28+
$binaryDataHandler: '@Ibexa\Core\IO\IOBinarydataHandler\SiteAccessDependentBinaryDataHandler'
2929

3030
App\AI\Handler\LLaVATextToTextActionHandler:
3131
tags:

code_samples/ai_actions/src/Command/ActionConfigurationCreateCommand.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7676
$this->actionConfigurationService->createActionConfiguration($actionConfigurationCreateStruct);
7777

7878
$action = new RefineTextAction(new Text([
79-
<<<TEXT
80-
Proteins differ from one another primarily in their sequence of amino acids, which is dictated by the nucleotide sequence of their genes,
81-
and which usually results in protein folding into a specific 3D structure that determines its activity.
79+
<<<TEXT
80+
Proteins differ from one another primarily in their sequence of amino acids, which is dictated by the nucleotide sequence of their genes,
81+
and which usually results in protein folding into a specific 3D structure that determines its activity.
8282
TEXT
8383
]));
8484
$actionConfiguration = $this->actionConfigurationService->getActionConfiguration('rewrite_casual');

code_samples/ai_actions/src/Command/AddMissingAltTextCommand.php

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Operator;
2222
use Ibexa\Contracts\Core\Repository\Values\Filter\Filter;
2323
use Ibexa\Core\FieldType\Image\Value;
24+
use Ibexa\Core\IO\IOBinarydataHandler;
2425
use Symfony\Component\Console\Command\Command;
2526
use Symfony\Component\Console\Input\InputArgument;
2627
use Symfony\Component\Console\Input\InputInterface;
@@ -42,23 +43,23 @@ final class AddMissingAltTextCommand extends Command
4243

4344
private ActionServiceInterface $actionService;
4445

45-
private string $projectDir;
46+
private IOBinarydataHandler $binaryDataHandler;
4647

4748
public function __construct(
4849
ContentService $contentService,
4950
PermissionResolver $permissionResolver,
5051
UserService $userService,
5152
FieldTypeService $fieldTypeService,
5253
ActionServiceInterface $actionService,
53-
string $projectDir
54+
IOBinarydataHandler $binaryDataHandler
5455
) {
5556
parent::__construct();
5657
$this->contentService = $contentService;
5758
$this->permissionResolver = $permissionResolver;
5859
$this->userService = $userService;
5960
$this->fieldTypeService = $fieldTypeService;
6061
$this->actionService = $actionService;
61-
$this->projectDir = $projectDir;
62+
$this->binaryDataHandler = $binaryDataHandler;
6263
}
6364

6465
protected function configure(): void
@@ -75,11 +76,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7576

7677
/** @var \Ibexa\Contracts\Core\Repository\Values\Content\Content $content */
7778
foreach ($modifiedImages as $content) {
78-
/** @var ?Value $value */
79+
/** @var \Ibexa\Core\FieldType\Image\Value $value */
7980
$value = $content->getFieldValue(self::IMAGE_FIELD_IDENTIFIER);
8081

8182
if ($value === null || !$this->shouldGenerateAltText($value)) {
82-
$output->writeln(sprintf('Image %s has the image field empty or the alternative text is already specified. Skipping.', $content->getName()));
83+
$output->writeln(sprintf('Image %s has the image field empty, the file cannot be accessed, or the alternative text is already specified. Skipping.', $content->getName()));
8384
continue;
8485
}
8586

@@ -124,12 +125,10 @@ private function getSuggestedAltText(string $imageEncodedInBase64, string $langu
124125
return $output->getText();
125126
}
126127

127-
private function convertImageToBase64(?string $uri): string
128+
private function convertImageToBase64(string $uri): string
128129
{
129-
$file = file_get_contents($this->projectDir . \DIRECTORY_SEPARATOR . 'public' . \DIRECTORY_SEPARATOR . $uri);
130-
if ($file === false) {
131-
throw new \RuntimeException('Cannot read file');
132-
}
130+
$id = $this->binaryDataHandler->getIdFromUri($uri);
131+
$file = $this->binaryDataHandler->getContents($id);
133132

134133
return 'data:image/jpeg;base64,' . base64_encode($file);
135134
}
@@ -145,10 +144,12 @@ private function getModifiedImages(): ContentList
145144
return $this->contentService->find($filter);
146145
}
147146

147+
/** @phpstan-assert-if-true string $value->uri */
148148
private function shouldGenerateAltText(Value $value): bool
149149
{
150150
return $this->fieldTypeService->getFieldType('ezimage')->isEmptyValue($value) === false &&
151-
$value->isAlternativeTextEmpty();
151+
$value->isAlternativeTextEmpty() &&
152+
$value->uri !== null;
152153
}
153154

154155
private function setUser(string $userLogin): void

docs/ai_actions/extend_ai_actions.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ month_change: false
55

66
# Extend AI Actions
77

8-
By extending AI Actions, you can make regular content management and editing tasks more appealing and less demanding.
8+
By extending [AI Actions](ai_actions_guide.md), you can make regular content management and editing tasks more appealing and less demanding.
99
You can start by integrating additional AI services to the existing action types or develop custom ones that impact completely new areas of application.
1010
For example, you can create a handler that connects to a translation model and use it to translate your website on-the-fly, or generate illustrations based on a body of an article.
1111

@@ -14,7 +14,7 @@ For example, you can create a handler that connects to a translation model and u
1414
You can execute AI Actions by using the [ActionServiceInterface](../api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionServiceInterface.html) service, as in the following example:
1515

1616
``` php
17-
[[= include_file('code_samples/ai_actions/src/Command/AddMissingAltTextCommand.php', 101, 120) =]]
17+
[[= include_file('code_samples/ai_actions/src/Command/AddMissingAltTextCommand.php', 102, 121) =]]
1818
```
1919

2020
The `GenerateAltTextAction` is a built-in action that implements the [ActionInterface](../api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionInterface.html), takes an [Image](../api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-Action-DataType-Image.html) as an input, and generates the alternative text in the response.
@@ -43,7 +43,7 @@ You can influence the execution of an Action with two events:
4343
Below you can find the full example of a Symfony Command, together with a matching service definition.
4444
The command finds the images modified in the last 24 hours, and adds the alternative text to them if it's missing.
4545

46-
``` php hl_lines="87 100-125"
46+
``` php hl_lines="88 101-126"
4747
[[= include_file('code_samples/ai_actions/src/Command/AddMissingAltTextCommand.php') =]]
4848
```
4949

@@ -114,7 +114,7 @@ Create a class implementing the [ActionHandlerInterface](../api/php_api/php_api_
114114

115115
See the code sample below, together with a matching service definition:
116116

117-
``` php hl_lines="21 29-31 34-69 71-74"
117+
``` php hl_lines="21 29-32 34-69 71-74"
118118
[[= include_file('code_samples/ai_actions/src/AI/Handler/LLaVaTextToTextActionHandler.php') =]]
119119
```
120120

@@ -146,10 +146,14 @@ The created Form Type adds the `system_prompt` field to the Form.
146146
Use the `Ibexa\Bundle\ConnectorAi\Form\FormMapper\ActionConfiguration\ActionHandlerOptionsFormMapper` class together with the `ibexa.connector_ai.action_configuration.form_mapper.options` service tag to make it part of the Action Handler options form.
147147
Pass the Action Handler identifier (`LLaVATextToText`) as the type when tagging the service.
148148

149-
The Action Handler and Action Type options are rendered in the back office using the built-in Twig option formatter.
149+
The Action Handler and Action Type options are rendered in the back office using the built-in Twig options formatter.
150+
151+
![Custom Action Handler options rendered using the default Twig options formatter](img/action_handler_options.png "Custom Action Handler options rendered using the default Twig options formatter")
152+
153+
150154
You can create your own formatting by creating a class implementing the [OptionsFormatterInterface](../api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-OptionsFormatterInterface.html) interface and aliasing it to `Ibexa\Contracts\ConnectorAi\ActionConfiguration\OptionsFormatterInterface`.
151155

152-
The following service definition switches the options rendering to the other built-in option formatter, displaying the options as JSON.
156+
The following service definition switches the options rendering to the other built-in options formatter, displaying the options as JSON.
153157

154158
``` yaml
155159
[[= include_file('code_samples/ai_actions/config/services.yaml', 64, 66) =]]
@@ -192,7 +196,7 @@ See the built-in Action Types like Generate Alt Text or Refine Text for an examp
192196

193197
### Create custom Data classes
194198

195-
The `TranscribeAudio` Action Type requires adding two data classes that exists in its definition:
199+
The `TranscribeAudio` Action Type requires adding two data classes that exist in its definition:
196200

197201
- an `Audio` class, implementing the [DataType interface](../api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-DataType.html), to store the input data for the Action
198202

189 KB
Loading

0 commit comments

Comments
 (0)