diff --git a/CHANGELOG.md b/CHANGELOG.md index 1093ebd..996447e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. - Add brand new option to generate **product variants**. Configure what property group to use, and AI will automatically generate all variants, if appropriate for the product. - Add 2 files in the cache directory for the generated prompt and response of product generation requests. +- Add new product image styles. Open the plugin configuration an select what styles to use for the product images. ### Changed diff --git a/src/Command/ProductGenerateCommand.php b/src/Command/ProductGenerateCommand.php index 9086bcd..3909c1f 100644 --- a/src/Command/ProductGenerateCommand.php +++ b/src/Command/ProductGenerateCommand.php @@ -7,6 +7,7 @@ use AIDemoData\Service\Generator\ProductGenerator; use AIDemoData\Service\Generator\ProductGeneratorInterface; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -121,27 +122,43 @@ protected function execute(InputInterface $input, OutputInterface $output): int # ----------------------------------------------------------------------------------------------------------------------- + $rows = []; + if ($category === '') { - $this->io->note('No category given. Products will be generated without a category.'); + $rows[] = ['Category', '-']; } else { - $this->io->note('Products will be generated for category: ' . $category); + $rows[] = ['Category', $category]; } if ($salesChannel === '') { - $this->io->note('No sales channel given. Products will be added the first found storefront sales channel.'); + $rows[] = ['Sales Channel', '-']; } else { - $this->io->note('Products will be added to sales channel: ' . $salesChannel); + $rows[] = ['Sales Channel', $salesChannel]; } + $rows[] = ['Description Length', $descriptionLength . ' characters']; + if ($withImages) { - $this->io->note('Images will be generated for the products: ' . $imgSize . 'px'); + $rows[] = ['Generate Images', 'Yes']; } else { - $this->io->note('Images will not be generated for the products.'); + $rows[] = ['Generate Images', 'No']; } + $imageStyles = $this->configService->getProductImageStyles(); + $rows[] = ['Image Styles', implode(', ', $imageStyles)]; + + $rows[] = ['Image Size', $imgSize]; + - $this->io->note('Product description length: ' . $descriptionLength . ' characters'); + $table = new Table($output); + $table->setStyle('default'); + $table->setHeaders(['Configuration', 'Value']); + $table->setRows($rows); + $table->render(); + + $this->io->writeln(''); + $this->io->writeln(''); # ----------------------------------------------------------------------------------------------------------------------- @@ -151,15 +168,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int # ----------------------------------------------------------------------------------------------------------------------- - $this->io->writeln('Starting product generation...'); - $this->productGenerator->generate( $keyWords, $count, $category, $salesChannel, $descriptionLength, - $this->configService->getProductVariantPropertyGroupId() + $this->configService->getProductVariantPropertyGroupId(), + $imageStyles ); if ($this->errorCount <= 0) { @@ -193,8 +209,6 @@ public function onProductGenerating(string $number, string $name, int $count, in */ public function onProductGenerated(string $number, string $name, int $count, int $maxCount): void { - $this->io->writeln('Product generated'); - $this->generatedCount++; } diff --git a/src/Resources/config/config.xml b/src/Resources/config/config.xml index 60518d8..41e606c 100644 --- a/src/Resources/config/config.xml +++ b/src/Resources/config/config.xml @@ -37,6 +37,35 @@ If enabled product images will be automatically generated if no CLI argument is provided. + + productImageStyles + + Select what styles you want to use for the images. These will be picked by random. + isolated + + + + + + + + + productImageSize @@ -73,12 +102,12 @@ 1024x1024 diff --git a/src/Service/Config/ConfigService.php b/src/Service/Config/ConfigService.php index 11dba7d..fb531ec 100644 --- a/src/Service/Config/ConfigService.php +++ b/src/Service/Config/ConfigService.php @@ -37,6 +37,11 @@ class ConfigService */ private $productVariantPropertyGroup; + /** + * @var string[] + */ + private $productImageStyles; + /** * @param SystemConfigService $configService @@ -53,6 +58,10 @@ public function __construct(SystemConfigService $configService) $this->productDescriptionLength = $configService->getInt('AIDemoData.config.productDescriptionLength'); $this->productVariantPropertyGroup = $configService->getString('AIDemoData.config.productVariantPropertyGroup'); + + /** @var string[] $tmpImageStyles */ + $tmpImageStyles = $configService->get('AIDemoData.config.productImageStyles'); + $this->productImageStyles = $tmpImageStyles; } /** @@ -79,6 +88,18 @@ public function getProductVariantPropertyGroupId(): string return $this->productVariantPropertyGroup; } + /** + * @return string[] + */ + public function getProductImageStyles(): array + { + if ($this->productImageStyles === null) { + return []; + } + + return $this->productImageStyles; + } + /** * @return string */ diff --git a/src/Service/Generator/ProductGenerator.php b/src/Service/Generator/ProductGenerator.php index 8adc873..1d52aff 100644 --- a/src/Service/Generator/ProductGenerator.php +++ b/src/Service/Generator/ProductGenerator.php @@ -127,10 +127,12 @@ public function setGenerateImages(bool $generateImages, string $imageSize): void * @param string $category * @param string $salesChannel * @param int $descriptionLength + * @param string $variantPropertyGroupId + * @param string[] $imageStyles * @throws \JsonException * @return void */ - public function generate(string $keywords, int $maxCount, string $category, string $salesChannel, int $descriptionLength, string $variantPropertyGroupId) + public function generate(string $keywords, int $maxCount, string $category, string $salesChannel, int $descriptionLength, string $variantPropertyGroupId, array $imageStyles) { if (empty($keywords)) { throw new \Exception('No keywords provided. Please tell the plugin what to generate.'); @@ -145,14 +147,14 @@ public function generate(string $keywords, int $maxCount, string $category, stri $prompt .= 'the following properties should be generated.' . PHP_EOL; $prompt .= 'Every resulting line should be in the order and sort provided below:' . PHP_EOL; $prompt .= PHP_EOL; - $prompt .= 'product count.' . PHP_EOL; - $prompt .= 'product number code. should be 24 unique random alphanumeric.' . PHP_EOL; - $prompt .= 'name of the product.' . PHP_EOL; - $prompt .= 'description (about ' . $descriptionLength . ' characters).' . PHP_EOL; - $prompt .= 'price value (no currency just number).' . PHP_EOL; - $prompt .= 'EAN code.' . PHP_EOL; - $prompt .= 'SEO description (max 100 characters).' . PHP_EOL; - $prompt .= 'variant indicator (1 if variants make sense for the product, 0 if it does not make sense).' . PHP_EOL; + $prompt .= '- product count.' . PHP_EOL; + $prompt .= '- product number code. should be 24 unique random alphanumeric (always unique, maybe consider datetime now).' . PHP_EOL; + $prompt .= '- name of the product.' . PHP_EOL; + $prompt .= '- description (about ' . $descriptionLength . ' characters).' . PHP_EOL; + $prompt .= '- price value (no currency just number).' . PHP_EOL; + $prompt .= '- EAN code.' . PHP_EOL; + $prompt .= '- SEO description (max 100 characters).' . PHP_EOL; + $prompt .= '- variant indicator (1 if variants make sense for the product, 0 if it does not make sense).' . PHP_EOL; $prompt .= PHP_EOL; $prompt .= 'Please only create exactly this number of products: ' . $maxCount . PHP_EOL; $prompt .= PHP_EOL; @@ -214,7 +216,7 @@ public function generate(string $keywords, int $maxCount, string $category, stri $this->callback->onProductImageGenerating(); } - $tmpImageFile = $this->generateImage($name, $description); + $tmpImageFile = $this->generateImage($name, $description, $imageStyles); } else { $tmpImageFile = ''; } @@ -238,9 +240,6 @@ public function generate(string $keywords, int $maxCount, string $category, stri $this->callback->onProductGenerated($number, $name, $currentCount, $maxCount); } } catch (\Exception $ex) { - var_dump($ex->getMessage()); - var_dump($ex->getTraceAsString()); - if ($this->callback !== null) { $this->callback->onProductGenerationFailed($ex->getMessage(), $currentCount, $maxCount); } @@ -394,12 +393,15 @@ private function createProduct(string $id, string $name, string $number, string /** * @param string $productName * @param string $productDescription - * @throws \Exception + * @param string[] $imageStyles + * @throws \JsonException * @return string */ - private function generateImage(string $productName, string $productDescription): string + private function generateImage(string $productName, string $productDescription, array $imageStyles): string { - $prompt = $productName . ' ' . $productDescription; + $prompt = "Generate image for our online shop. It has to be really good and present the product in the best way possible." . PHP_EOL; + $prompt .= "Exactly stick to a style that matches one of these: " . implode(', ', $imageStyles) . PHP_EOL; + $prompt .= "Here are instructions about the product: " . $productName . ' ' . $productDescription . '.'; $url = $this->openAI->generateImage($prompt, $this->imageSize); diff --git a/src/Service/OpenAI/Client.php b/src/Service/OpenAI/Client.php index 1ba3ac3..5abdbcf 100644 --- a/src/Service/OpenAI/Client.php +++ b/src/Service/OpenAI/Client.php @@ -105,6 +105,7 @@ public function generateImage(string $prompt, string $size): string "prompt" => $prompt, "n" => 1, "size" => $size, + "style" => "natural", "response_format" => "url", ]);