Skip to content

Commit 4862079

Browse files
Merge pull request #73 from WordPress/fix-config-values-to-enums
2 parents be59ff8 + 707683d commit 4862079

File tree

2 files changed

+245
-2
lines changed

2 files changed

+245
-2
lines changed

src/Providers/Models/DTO/ModelConfig.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,13 +1068,13 @@ public function toRequiredOptions(): array
10681068
}
10691069

10701070
if ($this->outputFileType !== null) {
1071-
$requiredOptions[] = new RequiredOption(OptionEnum::outputFileType(), $this->outputFileType->value);
1071+
$requiredOptions[] = new RequiredOption(OptionEnum::outputFileType(), $this->outputFileType);
10721072
}
10731073

10741074
if ($this->outputMediaOrientation !== null) {
10751075
$requiredOptions[] = new RequiredOption(
10761076
OptionEnum::outputMediaOrientation(),
1077-
$this->outputMediaOrientation->value
1077+
$this->outputMediaOrientation
10781078
);
10791079
}
10801080

tests/unit/Providers/Models/DTO/ModelConfigTest.php

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use WordPress\AiClient\Files\Enums\MediaOrientationEnum;
1313
use WordPress\AiClient\Messages\Enums\ModalityEnum;
1414
use WordPress\AiClient\Providers\Models\DTO\ModelConfig;
15+
use WordPress\AiClient\Providers\Models\Enums\OptionEnum;
1516
use WordPress\AiClient\Tools\DTO\FunctionDeclaration;
1617
use WordPress\AiClient\Tools\DTO\WebSearch;
1718

@@ -703,4 +704,246 @@ public function testSetCustomOption(): void
703704
$restored = ModelConfig::fromArray($array);
704705
$this->assertEquals($customOptions, $restored->getCustomOptions());
705706
}
707+
708+
/**
709+
* Tests toRequiredOptions method with all properties.
710+
*
711+
* @return void
712+
*/
713+
public function testToRequiredOptionsWithAllProperties(): void
714+
{
715+
$config = new ModelConfig();
716+
717+
// Set all properties that map to RequiredOptions
718+
$config->setOutputModalities([ModalityEnum::text(), ModalityEnum::image()]);
719+
$config->setSystemInstruction('Be helpful');
720+
$config->setCandidateCount(2);
721+
$config->setMaxTokens(1000);
722+
$config->setTemperature(0.7);
723+
$config->setTopP(0.9);
724+
$config->setTopK(40);
725+
$config->setStopSequences(['STOP', 'END']);
726+
$config->setPresencePenalty(0.5);
727+
$config->setFrequencyPenalty(0.3);
728+
$config->setLogprobs(true);
729+
$config->setTopLogprobs(5);
730+
$config->setFunctionDeclarations([$this->createSampleFunctionDeclaration()]);
731+
$config->setWebSearch($this->createSampleWebSearch());
732+
$config->setOutputFileType(FileTypeEnum::inline());
733+
$config->setOutputMimeType('application/json');
734+
$config->setOutputSchema(['type' => 'object']);
735+
$config->setOutputMediaOrientation(MediaOrientationEnum::landscape());
736+
$config->setOutputMediaAspectRatio('16:9');
737+
$config->setCustomOptions(['key1' => 'value1', 'key2' => 'value2']);
738+
739+
$requiredOptions = $config->toRequiredOptions();
740+
741+
$this->assertIsArray($requiredOptions);
742+
$this->assertNotEmpty($requiredOptions);
743+
744+
// Helper function to find option by name
745+
/**
746+
* @param list<\WordPress\AiClient\Providers\Models\DTO\RequiredOption> $options
747+
* @param OptionEnum $name
748+
* @return \WordPress\AiClient\Providers\Models\DTO\RequiredOption|null
749+
*/
750+
$findOption = function (
751+
array $options,
752+
OptionEnum $name
753+
): ?\WordPress\AiClient\Providers\Models\DTO\RequiredOption {
754+
foreach ($options as $option) {
755+
if ($option->getName()->equals($name)) {
756+
return $option;
757+
}
758+
}
759+
return null;
760+
};
761+
762+
// Test output modalities
763+
$outputModalitiesOption = $findOption($requiredOptions, OptionEnum::outputModalities());
764+
$this->assertNotNull($outputModalitiesOption);
765+
$this->assertEquals([ModalityEnum::text(), ModalityEnum::image()], $outputModalitiesOption->getValue());
766+
767+
// Test system instruction
768+
$systemInstructionOption = $findOption($requiredOptions, OptionEnum::systemInstruction());
769+
$this->assertNotNull($systemInstructionOption);
770+
$this->assertEquals('Be helpful', $systemInstructionOption->getValue());
771+
772+
// Test candidate count
773+
$candidateCountOption = $findOption($requiredOptions, OptionEnum::candidateCount());
774+
$this->assertNotNull($candidateCountOption);
775+
$this->assertEquals(2, $candidateCountOption->getValue());
776+
777+
// Test max tokens
778+
$maxTokensOption = $findOption($requiredOptions, OptionEnum::maxTokens());
779+
$this->assertNotNull($maxTokensOption);
780+
$this->assertEquals(1000, $maxTokensOption->getValue());
781+
782+
// Test temperature
783+
$temperatureOption = $findOption($requiredOptions, OptionEnum::temperature());
784+
$this->assertNotNull($temperatureOption);
785+
$this->assertEquals(0.7, $temperatureOption->getValue());
786+
787+
// Test top-p
788+
$topPOption = $findOption($requiredOptions, OptionEnum::topP());
789+
$this->assertNotNull($topPOption);
790+
$this->assertEquals(0.9, $topPOption->getValue());
791+
792+
// Test top-k
793+
$topKOption = $findOption($requiredOptions, OptionEnum::topK());
794+
$this->assertNotNull($topKOption);
795+
$this->assertEquals(40, $topKOption->getValue());
796+
797+
// Test stop sequences
798+
$stopSequencesOption = $findOption($requiredOptions, OptionEnum::stopSequences());
799+
$this->assertNotNull($stopSequencesOption);
800+
$this->assertEquals(['STOP', 'END'], $stopSequencesOption->getValue());
801+
802+
// Test presence penalty
803+
$presencePenaltyOption = $findOption($requiredOptions, OptionEnum::presencePenalty());
804+
$this->assertNotNull($presencePenaltyOption);
805+
$this->assertEquals(0.5, $presencePenaltyOption->getValue());
806+
807+
// Test frequency penalty
808+
$frequencyPenaltyOption = $findOption($requiredOptions, OptionEnum::frequencyPenalty());
809+
$this->assertNotNull($frequencyPenaltyOption);
810+
$this->assertEquals(0.3, $frequencyPenaltyOption->getValue());
811+
812+
// Test logprobs
813+
$logprobsOption = $findOption($requiredOptions, OptionEnum::logprobs());
814+
$this->assertNotNull($logprobsOption);
815+
$this->assertTrue($logprobsOption->getValue());
816+
817+
// Test top logprobs
818+
$topLogprobsOption = $findOption($requiredOptions, OptionEnum::topLogprobs());
819+
$this->assertNotNull($topLogprobsOption);
820+
$this->assertEquals(5, $topLogprobsOption->getValue());
821+
822+
// Test function declarations (should be boolean true)
823+
$functionDeclarationsOption = $findOption($requiredOptions, OptionEnum::functionDeclarations());
824+
$this->assertNotNull($functionDeclarationsOption);
825+
$this->assertTrue($functionDeclarationsOption->getValue());
826+
827+
// Test web search (should be boolean true)
828+
$webSearchOption = $findOption($requiredOptions, OptionEnum::webSearch());
829+
$this->assertNotNull($webSearchOption);
830+
$this->assertTrue($webSearchOption->getValue());
831+
832+
// Test output file type - IMPORTANT: Should be the enum object, not the string value
833+
$outputFileTypeOption = $findOption($requiredOptions, OptionEnum::outputFileType());
834+
$this->assertNotNull($outputFileTypeOption);
835+
$this->assertInstanceOf(FileTypeEnum::class, $outputFileTypeOption->getValue());
836+
$this->assertSame(FileTypeEnum::inline(), $outputFileTypeOption->getValue());
837+
838+
// Test output MIME type
839+
$outputMimeTypeOption = $findOption($requiredOptions, OptionEnum::outputMimeType());
840+
$this->assertNotNull($outputMimeTypeOption);
841+
$this->assertEquals('application/json', $outputMimeTypeOption->getValue());
842+
843+
// Test output schema
844+
$outputSchemaOption = $findOption($requiredOptions, OptionEnum::outputSchema());
845+
$this->assertNotNull($outputSchemaOption);
846+
$this->assertEquals(['type' => 'object'], $outputSchemaOption->getValue());
847+
848+
// Test output media orientation - IMPORTANT: Should be the enum object, not the string value
849+
$outputMediaOrientationOption = $findOption($requiredOptions, OptionEnum::outputMediaOrientation());
850+
$this->assertNotNull($outputMediaOrientationOption);
851+
$this->assertInstanceOf(MediaOrientationEnum::class, $outputMediaOrientationOption->getValue());
852+
$this->assertSame(MediaOrientationEnum::landscape(), $outputMediaOrientationOption->getValue());
853+
854+
// Test output media aspect ratio
855+
$outputMediaAspectRatioOption = $findOption($requiredOptions, OptionEnum::outputMediaAspectRatio());
856+
$this->assertNotNull($outputMediaAspectRatioOption);
857+
$this->assertEquals('16:9', $outputMediaAspectRatioOption->getValue());
858+
859+
// Test custom options - each custom option should be a separate RequiredOption
860+
$customOptions = array_filter($requiredOptions, function ($option) {
861+
return $option->getName()->equals(OptionEnum::customOptions());
862+
});
863+
$this->assertCount(2, $customOptions); // We set 2 custom options
864+
865+
// Verify custom option values
866+
$customOptionValues = array_map(function ($option) {
867+
return $option->getValue();
868+
}, $customOptions);
869+
$this->assertContains(['key1' => 'value1'], $customOptionValues);
870+
$this->assertContains(['key2' => 'value2'], $customOptionValues);
871+
}
872+
873+
/**
874+
* Tests toRequiredOptions method with no properties set.
875+
*
876+
* @return void
877+
*/
878+
public function testToRequiredOptionsWithNoProperties(): void
879+
{
880+
$config = new ModelConfig();
881+
$requiredOptions = $config->toRequiredOptions();
882+
883+
$this->assertIsArray($requiredOptions);
884+
$this->assertEmpty($requiredOptions);
885+
}
886+
887+
/**
888+
* Tests toRequiredOptions method with partial properties.
889+
*
890+
* @return void
891+
*/
892+
public function testToRequiredOptionsWithPartialProperties(): void
893+
{
894+
$config = new ModelConfig();
895+
896+
// Only set a few properties
897+
$config->setTemperature(0.8);
898+
$config->setMaxTokens(500);
899+
$config->setOutputFileType(FileTypeEnum::remote());
900+
$config->setOutputMediaOrientation(MediaOrientationEnum::portrait());
901+
902+
$requiredOptions = $config->toRequiredOptions();
903+
904+
$this->assertIsArray($requiredOptions);
905+
$this->assertCount(4, $requiredOptions);
906+
907+
// Helper function to find option by name
908+
/**
909+
* @param list<\WordPress\AiClient\Providers\Models\DTO\RequiredOption> $options
910+
* @param OptionEnum $name
911+
* @return \WordPress\AiClient\Providers\Models\DTO\RequiredOption|null
912+
*/
913+
$findOption = function (
914+
array $options,
915+
OptionEnum $name
916+
): ?\WordPress\AiClient\Providers\Models\DTO\RequiredOption {
917+
foreach ($options as $option) {
918+
if ($option->getName()->equals($name)) {
919+
return $option;
920+
}
921+
}
922+
return null;
923+
};
924+
925+
// Test temperature
926+
$temperatureOption = $findOption($requiredOptions, OptionEnum::temperature());
927+
$this->assertNotNull($temperatureOption);
928+
$this->assertEquals(0.8, $temperatureOption->getValue());
929+
930+
// Test max tokens
931+
$maxTokensOption = $findOption($requiredOptions, OptionEnum::maxTokens());
932+
$this->assertNotNull($maxTokensOption);
933+
$this->assertEquals(500, $maxTokensOption->getValue());
934+
935+
// Test output file type - Should be the enum object
936+
$outputFileTypeOption = $findOption($requiredOptions, OptionEnum::outputFileType());
937+
$this->assertNotNull($outputFileTypeOption);
938+
$this->assertInstanceOf(FileTypeEnum::class, $outputFileTypeOption->getValue());
939+
$this->assertSame(FileTypeEnum::remote(), $outputFileTypeOption->getValue());
940+
$this->assertTrue($outputFileTypeOption->getValue()->isRemote());
941+
942+
// Test output media orientation - Should be the enum object
943+
$outputMediaOrientationOption = $findOption($requiredOptions, OptionEnum::outputMediaOrientation());
944+
$this->assertNotNull($outputMediaOrientationOption);
945+
$this->assertInstanceOf(MediaOrientationEnum::class, $outputMediaOrientationOption->getValue());
946+
$this->assertSame(MediaOrientationEnum::portrait(), $outputMediaOrientationOption->getValue());
947+
$this->assertTrue($outputMediaOrientationOption->getValue()->isPortrait());
948+
}
706949
}

0 commit comments

Comments
 (0)