diff --git a/src/Builders/PromptBuilder.php b/src/Builders/PromptBuilder.php index 27b12279..48bd8dd2 100644 --- a/src/Builders/PromptBuilder.php +++ b/src/Builders/PromptBuilder.php @@ -11,6 +11,7 @@ use WordPress\AiClient\Events\BeforeGenerateResultEvent; use WordPress\AiClient\Files\DTO\File; use WordPress\AiClient\Files\Enums\FileTypeEnum; +use WordPress\AiClient\Files\Enums\MediaOrientationEnum; use WordPress\AiClient\Messages\DTO\Message; use WordPress\AiClient\Messages\DTO\MessagePart; use WordPress\AiClient\Messages\DTO\UserMessage; @@ -459,7 +460,7 @@ public function usingTopK(int $topK): self */ public function usingStopSequences(string ...$stopSequences): self { - $this->modelConfig->setCustomOption('stopSequences', $stopSequences); + $this->modelConfig->setStopSequences($stopSequences); return $this; } @@ -627,6 +628,51 @@ public function asOutputFileType(FileTypeEnum $fileType): self return $this; } + /** + * Sets the output media orientation. + * + * @since n.e.x.t + * + * @param MediaOrientationEnum $orientation The output media orientation. + * @return self + */ + public function asOutputMediaOrientation(MediaOrientationEnum $orientation): self + { + $this->modelConfig->setOutputMediaOrientation($orientation); + return $this; + } + + /** + * Sets the output media aspect ratio. + * + * If set, this supersedes the output media orientation, as it is a more + * specific configuration. + * + * @since n.e.x.t + * + * @param string $aspectRatio The aspect ratio (e.g. "16:9", "3:2"). + * @return self + */ + public function asOutputMediaAspectRatio(string $aspectRatio): self + { + $this->modelConfig->setOutputMediaAspectRatio($aspectRatio); + return $this; + } + + /** + * Sets the output speech voice. + * + * @since n.e.x.t + * + * @param string $voice The output speech voice. + * @return self + */ + public function asOutputSpeechVoice(string $voice): self + { + $this->modelConfig->setOutputSpeechVoice($voice); + return $this; + } + /** * Configures the prompt for JSON response output. * diff --git a/tests/unit/Builders/PromptBuilderTest.php b/tests/unit/Builders/PromptBuilderTest.php index 47950ccd..fd76b401 100644 --- a/tests/unit/Builders/PromptBuilderTest.php +++ b/tests/unit/Builders/PromptBuilderTest.php @@ -10,6 +10,7 @@ use WordPress\AiClient\Builders\PromptBuilder; use WordPress\AiClient\Files\DTO\File; use WordPress\AiClient\Files\Enums\FileTypeEnum; +use WordPress\AiClient\Files\Enums\MediaOrientationEnum; use WordPress\AiClient\Messages\DTO\Message; use WordPress\AiClient\Messages\DTO\MessagePart; use WordPress\AiClient\Messages\DTO\ModelMessage; @@ -1055,19 +1056,17 @@ public function testUsingModelConfigWithCustomOptions(): void $this->assertArrayHasKey('otherOption', $customOptions); $this->assertEquals('value', $customOptions['otherOption']); - // Now set a builder value that overrides one of the custom options + // Now set stop sequences via the dedicated method $builder->usingStopSequences('STOP'); // Get the config again $mergedConfig = $configProperty->getValue($builder); - $customOptions = $mergedConfig->getCustomOptions(); - // Assert builder's stop sequences override the config's - $this->assertArrayHasKey('stopSequences', $customOptions); - $this->assertIsArray($customOptions['stopSequences']); - $this->assertEquals(['STOP'], $customOptions['stopSequences']); + // Assert builder's stop sequences are set on the dedicated property + $this->assertEquals(['STOP'], $mergedConfig->getStopSequences()); - // Assert other custom options are still preserved + // Assert custom options are still preserved + $customOptions = $mergedConfig->getCustomOptions(); $this->assertArrayHasKey('otherOption', $customOptions); $this->assertEquals('value', $customOptions['otherOption']); } @@ -1215,9 +1214,7 @@ public function testUsingStopSequences(): void /** @var ModelConfig $config */ $config = $configProperty->getValue($builder); - $customOptions = $config->getCustomOptions(); - $this->assertArrayHasKey('stopSequences', $customOptions); - $this->assertEquals(['STOP', 'END', '###'], $customOptions['stopSequences']); + $this->assertEquals(['STOP', 'END', '###'], $config->getStopSequences()); } /** @@ -3605,4 +3602,113 @@ public function testCloneWorksWithNullRequestOptions(): void $this->assertNull($optionsProperty->getValue($cloned)); } + + /** + * Tests asOutputMediaOrientation method. + * + * @return void + */ + public function testAsOutputMediaOrientation(): void + { + $builder = new PromptBuilder($this->registry); + $result = $builder->asOutputMediaOrientation(MediaOrientationEnum::landscape()); + + $this->assertSame($builder, $result); + + $reflection = new \ReflectionClass($builder); + $configProperty = $reflection->getProperty('modelConfig'); + $configProperty->setAccessible(true); + /** @var ModelConfig $config */ + $config = $configProperty->getValue($builder); + + $outputMediaOrientation = $config->getOutputMediaOrientation(); + $this->assertNotNull($outputMediaOrientation); + $this->assertTrue($outputMediaOrientation->isLandscape()); + } + + /** + * Tests asOutputMediaOrientation method with portrait orientation. + * + * @return void + */ + public function testAsOutputMediaOrientationWithPortrait(): void + { + $builder = new PromptBuilder($this->registry); + $result = $builder->asOutputMediaOrientation(MediaOrientationEnum::portrait()); + + $this->assertSame($builder, $result); + + $reflection = new \ReflectionClass($builder); + $configProperty = $reflection->getProperty('modelConfig'); + $configProperty->setAccessible(true); + /** @var ModelConfig $config */ + $config = $configProperty->getValue($builder); + + $outputMediaOrientation = $config->getOutputMediaOrientation(); + $this->assertNotNull($outputMediaOrientation); + $this->assertTrue($outputMediaOrientation->isPortrait()); + } + + /** + * Tests asOutputMediaAspectRatio method. + * + * @return void + */ + public function testAsOutputMediaAspectRatio(): void + { + $builder = new PromptBuilder($this->registry); + $result = $builder->asOutputMediaAspectRatio('16:9'); + + $this->assertSame($builder, $result); + + $reflection = new \ReflectionClass($builder); + $configProperty = $reflection->getProperty('modelConfig'); + $configProperty->setAccessible(true); + /** @var ModelConfig $config */ + $config = $configProperty->getValue($builder); + + $this->assertEquals('16:9', $config->getOutputMediaAspectRatio()); + } + + /** + * Tests asOutputSpeechVoice method. + * + * @return void + */ + public function testAsOutputSpeechVoice(): void + { + $builder = new PromptBuilder($this->registry); + $result = $builder->asOutputSpeechVoice('alloy'); + + $this->assertSame($builder, $result); + + $reflection = new \ReflectionClass($builder); + $configProperty = $reflection->getProperty('modelConfig'); + $configProperty->setAccessible(true); + /** @var ModelConfig $config */ + $config = $configProperty->getValue($builder); + + $this->assertEquals('alloy', $config->getOutputSpeechVoice()); + } + + /** + * Tests usingStopSequences sets the dedicated property. + * + * @return void + */ + public function testUsingStopSequencesSetsProperty(): void + { + $builder = new PromptBuilder($this->registry); + $result = $builder->usingStopSequences('STOP', 'END'); + + $this->assertSame($builder, $result); + + $reflection = new \ReflectionClass($builder); + $configProperty = $reflection->getProperty('modelConfig'); + $configProperty->setAccessible(true); + /** @var ModelConfig $config */ + $config = $configProperty->getValue($builder); + + $this->assertEquals(['STOP', 'END'], $config->getStopSequences()); + } }