Skip to content

Commit 9460fd2

Browse files
authored
fix(OpenAI): support fine tuning list with failed tuning job (#651)
* fix(OpenAI): support fine tuning with failed tuning job * chore: align fixtures to new order on array * test: add test to assert null hyperparameters
1 parent f6ea6bc commit 9460fd2

File tree

4 files changed

+52
-25
lines changed

4 files changed

+52
-25
lines changed

src/Responses/FineTuning/ListJobsResponse.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
use OpenAI\Testing\Responses\Concerns\Fakeable;
1313

1414
/**
15-
* @implements ResponseContract<array{object: string, data: array<int, array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code: string, param: ?string, message: string}}>, has_more: bool}>
15+
* @implements ResponseContract<array{object: string, data: array<int, array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters?: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code: string, param: ?string, message: string}}>, has_more: bool}>
1616
*/
1717
final class ListJobsResponse implements ResponseContract, ResponseHasMetaInformationContract
1818
{
1919
/**
20-
* @use ArrayAccessible<array{object: string, data: array<int, array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code: string, param: ?string, message: string}}>, has_more: bool}>
20+
* @use ArrayAccessible<array{object: string, data: array<int, array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters?: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code: string, param: ?string, message: string}}>, has_more: bool}>
2121
*/
2222
use ArrayAccessible;
2323

@@ -37,7 +37,7 @@ private function __construct(
3737
/**
3838
* Acts as static factory, and returns a new Response instance.
3939
*
40-
* @param array{object: string, data: array<int, array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code: string, param: ?string, message: string}}>, has_more: bool} $attributes
40+
* @param array{object: string, data: array<int, array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters?: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code: string, param: ?string, message: string}}>, has_more: bool} $attributes
4141
*/
4242
public static function from(array $attributes, MetaInformation $meta): self
4343
{

src/Responses/FineTuning/RetrieveJobResponse.php

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
use OpenAI\Testing\Responses\Concerns\Fakeable;
1313

1414
/**
15-
* @implements ResponseContract<array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code: string, param: ?string, message: string}}>
15+
* @implements ResponseContract<array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters?: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code: string, param: ?string, message: string}}>
1616
*/
1717
final class RetrieveJobResponse implements ResponseContract, ResponseHasMetaInformationContract
1818
{
1919
/**
20-
* @use ArrayAccessible<array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code: string, param: ?string, message: string}}>
20+
* @use ArrayAccessible<array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters?: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code: string, param: ?string, message: string}}>
2121
*/
2222
use ArrayAccessible;
2323

@@ -34,7 +34,7 @@ private function __construct(
3434
public readonly int $createdAt,
3535
public readonly ?int $finishedAt,
3636
public readonly ?string $fineTunedModel,
37-
public readonly RetrieveJobResponseHyperparameters $hyperparameters,
37+
public readonly ?RetrieveJobResponseHyperparameters $hyperparameters,
3838
public readonly string $organizationId,
3939
public readonly array $resultFiles,
4040
public readonly string $status,
@@ -48,7 +48,7 @@ private function __construct(
4848
/**
4949
* Acts as static factory, and returns a new Response instance.
5050
*
51-
* @param array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code?: string, param?: ?string, message?: string}} $attributes
51+
* @param array{id: string, object: string, model: string, created_at: int, finished_at: ?int, fine_tuned_model: ?string, hyperparameters?: array{n_epochs: int|string, batch_size: int|string|null, learning_rate_multiplier: float|string|null}, organization_id: string, result_files: array<int, string>, status: string, validation_file: ?string, training_file: string, trained_tokens: ?int, error: ?array{code?: string, param?: ?string, message?: string}} $attributes
5252
*/
5353
public static function from(array $attributes, MetaInformation $meta): self
5454
{
@@ -59,7 +59,9 @@ public static function from(array $attributes, MetaInformation $meta): self
5959
$attributes['created_at'],
6060
$attributes['finished_at'],
6161
$attributes['fine_tuned_model'],
62-
RetrieveJobResponseHyperparameters::from($attributes['hyperparameters']),
62+
isset($attributes['hyperparameters'])
63+
? RetrieveJobResponseHyperparameters::from($attributes['hyperparameters'])
64+
: null,
6365
$attributes['organization_id'],
6466
$attributes['result_files'],
6567
$attributes['status'],
@@ -81,14 +83,13 @@ public static function from(array $attributes, MetaInformation $meta): self
8183
*/
8284
public function toArray(): array
8385
{
84-
return [
86+
$result = [
8587
'id' => $this->id,
8688
'object' => $this->object,
8789
'model' => $this->model,
8890
'created_at' => $this->createdAt,
8991
'finished_at' => $this->finishedAt,
9092
'fine_tuned_model' => $this->fineTunedModel,
91-
'hyperparameters' => $this->hyperparameters->toArray(),
9293
'organization_id' => $this->organizationId,
9394
'result_files' => $this->resultFiles,
9495
'status' => $this->status,
@@ -97,5 +98,11 @@ public function toArray(): array
9798
'trained_tokens' => $this->trainedTokens,
9899
'error' => $this->error?->toArray(),
99100
];
101+
102+
if ($this->hyperparameters) {
103+
$result['hyperparameters'] = $this->hyperparameters->toArray();
104+
}
105+
106+
return $result;
100107
}
101108
}

tests/Fixtures/FineTuning.php

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,18 @@ function fineTuningJobCreateResource(): array
1212
'created_at' => 1614807352,
1313
'finished_at' => null,
1414
'fine_tuned_model' => null,
15-
'hyperparameters' => [
16-
'n_epochs' => 9,
17-
'batch_size' => 'auto',
18-
'learning_rate_multiplier' => 'auto',
19-
],
2015
'organization_id' => 'org-jwe45798ASN82s',
2116
'result_files' => [],
2217
'status' => 'created',
2318
'validation_file' => null,
2419
'training_file' => 'file-abc123',
2520
'trained_tokens' => null,
2621
'error' => null,
22+
'hyperparameters' => [
23+
'n_epochs' => 9,
24+
'batch_size' => 'auto',
25+
'learning_rate_multiplier' => 'auto',
26+
],
2727
];
2828
}
2929

@@ -39,11 +39,6 @@ function fineTuningJobRetrieveResource(): array
3939
'created_at' => 1614807352,
4040
'finished_at' => 1692819450,
4141
'fine_tuned_model' => 'ft:gpt-3.5-turbo-0613:jwe-dev::7qnxQ0sQ',
42-
'hyperparameters' => [
43-
'n_epochs' => 9,
44-
'batch_size' => 1,
45-
'learning_rate_multiplier' => 2.2,
46-
],
4742
'organization_id' => 'org-jwe45798ASN82s',
4843
'result_files' => [
4944
'file-1bl05WrhsKDDEdg8XSP617QF',
@@ -53,6 +48,11 @@ function fineTuningJobRetrieveResource(): array
5348
'training_file' => 'file-abc123',
5449
'trained_tokens' => 5049,
5550
'error' => null,
51+
'hyperparameters' => [
52+
'n_epochs' => 9,
53+
'batch_size' => 1,
54+
'learning_rate_multiplier' => 2.2,
55+
],
5656
];
5757
}
5858

@@ -68,11 +68,6 @@ function fineTuningFailedJobRetrieveResource(): array
6868
'created_at' => 1614807352,
6969
'finished_at' => null,
7070
'fine_tuned_model' => null,
71-
'hyperparameters' => [
72-
'n_epochs' => 9,
73-
'batch_size' => 'auto',
74-
'learning_rate_multiplier' => 'auto',
75-
],
7671
'organization_id' => 'org-jwe45798ASN82s',
7772
'result_files' => [],
7873
'status' => 'failed',
@@ -84,6 +79,11 @@ function fineTuningFailedJobRetrieveResource(): array
8479
'param' => 'training_file',
8580
'message' => 'Training file has 3 example(s), but must have at least 10 examples',
8681
],
82+
'hyperparameters' => [
83+
'n_epochs' => 9,
84+
'batch_size' => 'auto',
85+
'learning_rate_multiplier' => 'auto',
86+
],
8787
];
8888
}
8989

tests/Responses/FineTuning/RetrieveJobResponse.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@
4747
->meta()->toBeInstanceOf(MetaInformation::class);
4848
});
4949

50+
test('from retrieve response with missing hyperparameters', function () {
51+
$payload = fineTuningJobRetrieveResource();
52+
unset($payload['hyperparameters']);
53+
$result = RetrieveJobResponse::from($payload, meta());
54+
55+
expect($result)
56+
->toBeInstanceOf(RetrieveJobResponse::class)
57+
->hyperparameters->toBeNull();
58+
});
59+
60+
test('from retrieve response with null hyperparameters', function () {
61+
$payload = fineTuningJobRetrieveResource();
62+
$payload['hyperparameters'] = null;
63+
$result = RetrieveJobResponse::from($payload, meta());
64+
65+
expect($result)
66+
->toBeInstanceOf(RetrieveJobResponse::class)
67+
->hyperparameters->toBeNull();
68+
});
69+
5070
test('as array accessible', function () {
5171
$result = RetrieveJobResponse::from(fineTuningJobCreateResource(), meta());
5272

0 commit comments

Comments
 (0)