Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Providers/Models/DTO/ModelConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -1068,13 +1068,13 @@ public function toRequiredOptions(): array
}

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

if ($this->outputMediaOrientation !== null) {
$requiredOptions[] = new RequiredOption(
OptionEnum::outputMediaOrientation(),
$this->outputMediaOrientation->value
$this->outputMediaOrientation
);
}

Expand Down
244 changes: 244 additions & 0 deletions tests/unit/Providers/Models/DTO/ModelConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use WordPress\AiClient\Files\Enums\MediaOrientationEnum;
use WordPress\AiClient\Messages\Enums\ModalityEnum;
use WordPress\AiClient\Providers\Models\DTO\ModelConfig;
use WordPress\AiClient\Providers\Models\Enums\OptionEnum;
use WordPress\AiClient\Tools\DTO\FunctionDeclaration;
use WordPress\AiClient\Tools\DTO\WebSearch;

Expand Down Expand Up @@ -703,4 +704,247 @@ public function testSetCustomOption(): void
$restored = ModelConfig::fromArray($array);
$this->assertEquals($customOptions, $restored->getCustomOptions());
}

/**
* Tests toRequiredOptions method with all properties.
*
* @return void
*/
public function testToRequiredOptionsWithAllProperties(): void
{
$config = new ModelConfig();

// Set all properties that map to RequiredOptions
$config->setOutputModalities([ModalityEnum::text(), ModalityEnum::image()]);
$config->setSystemInstruction('Be helpful');
$config->setCandidateCount(2);
$config->setMaxTokens(1000);
$config->setTemperature(0.7);
$config->setTopP(0.9);
$config->setTopK(40);
$config->setStopSequences(['STOP', 'END']);
$config->setPresencePenalty(0.5);
$config->setFrequencyPenalty(0.3);
$config->setLogprobs(true);
$config->setTopLogprobs(5);
$config->setFunctionDeclarations([$this->createSampleFunctionDeclaration()]);
$config->setWebSearch($this->createSampleWebSearch());
$config->setOutputFileType(FileTypeEnum::inline());
$config->setOutputMimeType('application/json');
$config->setOutputSchema(['type' => 'object']);
$config->setOutputMediaOrientation(MediaOrientationEnum::landscape());
$config->setOutputMediaAspectRatio('16:9');
$config->setCustomOptions(['key1' => 'value1', 'key2' => 'value2']);

$requiredOptions = $config->toRequiredOptions();

$this->assertIsArray($requiredOptions);
$this->assertNotEmpty($requiredOptions);

// Helper function to find option by name
/**
* @param list<\WordPress\AiClient\Providers\Models\DTO\RequiredOption> $options
* @param OptionEnum $name
* @return \WordPress\AiClient\Providers\Models\DTO\RequiredOption|null
*/
$findOption = function (
array $options,
OptionEnum $name
): ?\WordPress\AiClient\Providers\Models\DTO\RequiredOption {
foreach ($options as $option) {
if ($option->getName()->equals($name)) {
return $option;
}
}
return null;
};

// Test output modalities
$outputModalitiesOption = $findOption($requiredOptions, OptionEnum::outputModalities());
$this->assertNotNull($outputModalitiesOption);
$this->assertEquals([ModalityEnum::text(), ModalityEnum::image()], $outputModalitiesOption->getValue());

// Test system instruction
$systemInstructionOption = $findOption($requiredOptions, OptionEnum::systemInstruction());
$this->assertNotNull($systemInstructionOption);
$this->assertEquals('Be helpful', $systemInstructionOption->getValue());

// Test candidate count
$candidateCountOption = $findOption($requiredOptions, OptionEnum::candidateCount());
$this->assertNotNull($candidateCountOption);
$this->assertEquals(2, $candidateCountOption->getValue());

// Test max tokens
$maxTokensOption = $findOption($requiredOptions, OptionEnum::maxTokens());
$this->assertNotNull($maxTokensOption);
$this->assertEquals(1000, $maxTokensOption->getValue());

// Test temperature
$temperatureOption = $findOption($requiredOptions, OptionEnum::temperature());
$this->assertNotNull($temperatureOption);
$this->assertEquals(0.7, $temperatureOption->getValue());

// Test top-p
$topPOption = $findOption($requiredOptions, OptionEnum::topP());
$this->assertNotNull($topPOption);
$this->assertEquals(0.9, $topPOption->getValue());

// Test top-k
$topKOption = $findOption($requiredOptions, OptionEnum::topK());
$this->assertNotNull($topKOption);
$this->assertEquals(40, $topKOption->getValue());

// Test stop sequences
$stopSequencesOption = $findOption($requiredOptions, OptionEnum::stopSequences());
$this->assertNotNull($stopSequencesOption);
$this->assertEquals(['STOP', 'END'], $stopSequencesOption->getValue());

// Test presence penalty
$presencePenaltyOption = $findOption($requiredOptions, OptionEnum::presencePenalty());
$this->assertNotNull($presencePenaltyOption);
$this->assertEquals(0.5, $presencePenaltyOption->getValue());

// Test frequency penalty
$frequencyPenaltyOption = $findOption($requiredOptions, OptionEnum::frequencyPenalty());
$this->assertNotNull($frequencyPenaltyOption);
$this->assertEquals(0.3, $frequencyPenaltyOption->getValue());

// Test logprobs
$logprobsOption = $findOption($requiredOptions, OptionEnum::logprobs());
$this->assertNotNull($logprobsOption);
$this->assertTrue($logprobsOption->getValue());

// Test top logprobs
$topLogprobsOption = $findOption($requiredOptions, OptionEnum::topLogprobs());
$this->assertNotNull($topLogprobsOption);
$this->assertEquals(5, $topLogprobsOption->getValue());

// Test function declarations (should be boolean true)
$functionDeclarationsOption = $findOption($requiredOptions, OptionEnum::functionDeclarations());
$this->assertNotNull($functionDeclarationsOption);
$this->assertTrue($functionDeclarationsOption->getValue());

// Test web search (should be boolean true)
$webSearchOption = $findOption($requiredOptions, OptionEnum::webSearch());
$this->assertNotNull($webSearchOption);
$this->assertTrue($webSearchOption->getValue());

// Test output file type - IMPORTANT: Should be the enum object, not the string value
$outputFileTypeOption = $findOption($requiredOptions, OptionEnum::outputFileType());
$this->assertNotNull($outputFileTypeOption);
$this->assertInstanceOf(FileTypeEnum::class, $outputFileTypeOption->getValue());
$this->assertSame(FileTypeEnum::inline(), $outputFileTypeOption->getValue());

// Test output MIME type
$outputMimeTypeOption = $findOption($requiredOptions, OptionEnum::outputMimeType());
$this->assertNotNull($outputMimeTypeOption);
$this->assertEquals('application/json', $outputMimeTypeOption->getValue());

// Test output schema
$outputSchemaOption = $findOption($requiredOptions, OptionEnum::outputSchema());
$this->assertNotNull($outputSchemaOption);
$this->assertEquals(['type' => 'object'], $outputSchemaOption->getValue());

// Test output media orientation - IMPORTANT: Should be the enum object, not the string value
$outputMediaOrientationOption = $findOption($requiredOptions, OptionEnum::outputMediaOrientation());
$this->assertNotNull($outputMediaOrientationOption);
$this->assertInstanceOf(MediaOrientationEnum::class, $outputMediaOrientationOption->getValue());
$this->assertSame(MediaOrientationEnum::landscape(), $outputMediaOrientationOption->getValue());

// Test output media aspect ratio
$outputMediaAspectRatioOption = $findOption($requiredOptions, OptionEnum::outputMediaAspectRatio());
$this->assertNotNull($outputMediaAspectRatioOption);
$this->assertEquals('16:9', $outputMediaAspectRatioOption->getValue());

// Test custom options - each custom option should be a separate RequiredOption
$customOptions = array_filter($requiredOptions, function ($option) {
return $option->getName()->equals(OptionEnum::customOptions());
});
$this->assertCount(2, $customOptions); // We set 2 custom options

// Verify custom option values
$customOptionValues = array_map(function ($option) {
return $option->getValue();
}, $customOptions);
$this->assertContains(['key1' => 'value1'], $customOptionValues);
$this->assertContains(['key2' => 'value2'], $customOptionValues);
}

/**
* Tests toRequiredOptions method with no properties set.
*
* @return void
*/
public function testToRequiredOptionsWithNoProperties(): void
{
$config = new ModelConfig();
$requiredOptions = $config->toRequiredOptions();

$this->assertIsArray($requiredOptions);
$this->assertEmpty($requiredOptions);
}

/**
* Tests toRequiredOptions method with partial properties.
*
* @return void
*/
public function testToRequiredOptionsWithPartialProperties(): void
{
$config = new ModelConfig();

// Only set a few properties
$config->setTemperature(0.8);
$config->setMaxTokens(500);
$config->setOutputFileType(FileTypeEnum::remote());
$config->setOutputMediaOrientation(MediaOrientationEnum::portrait());

$requiredOptions = $config->toRequiredOptions();

$this->assertIsArray($requiredOptions);
$this->assertCount(4, $requiredOptions);

// Helper function to find option by name
/**
* @param list<\WordPress\AiClient\Providers\Models\DTO\RequiredOption> $options
* @param OptionEnum $name
* @return \WordPress\AiClient\Providers\Models\DTO\RequiredOption|null
*/
$findOption = function (
array $options,
OptionEnum $name
): ?\WordPress\AiClient\Providers\Models\DTO\RequiredOption {
foreach ($options as $option) {
if ($option->getName()->equals($name)) {
return $option;
}
}
return null;
};

// Test temperature
$temperatureOption = $findOption($requiredOptions, OptionEnum::temperature());
$this->assertNotNull($temperatureOption);
$this->assertEquals(0.8, $temperatureOption->getValue());

// Test max tokens
$maxTokensOption = $findOption($requiredOptions, OptionEnum::maxTokens());
$this->assertNotNull($maxTokensOption);
$this->assertEquals(500, $maxTokensOption->getValue());

// Test output file type - Should be the enum object
$outputFileTypeOption = $findOption($requiredOptions, OptionEnum::outputFileType());
$this->assertNotNull($outputFileTypeOption);
$this->assertInstanceOf(FileTypeEnum::class, $outputFileTypeOption->getValue());
$this->assertSame(FileTypeEnum::remote(), $outputFileTypeOption->getValue());
$this->assertTrue($outputFileTypeOption->getValue()->isRemote());

// Test output media orientation - Should be the enum object
$outputMediaOrientationOption = $findOption($requiredOptions, OptionEnum::outputMediaOrientation());
$this->assertNotNull($outputMediaOrientationOption);
$this->assertInstanceOf(MediaOrientationEnum::class, $outputMediaOrientationOption->getValue());
$this->assertSame(MediaOrientationEnum::portrait(), $outputMediaOrientationOption->getValue());
$this->assertTrue($outputMediaOrientationOption->getValue()->isPortrait());
}

}
Loading