Skip to content

Commit 72a83ad

Browse files
committed
feat: add openai compatibility support for google gemini
1 parent 4a565d1 commit 72a83ad

File tree

10 files changed

+187
-10
lines changed

10 files changed

+187
-10
lines changed

src/Responses/Chat/CreateResponse.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ final class CreateResponse implements ResponseContract, ResponseHasMetaInformati
2828
* @param array<int, CreateResponseChoice> $choices
2929
*/
3030
private function __construct(
31-
public readonly string $id,
31+
public readonly ?string $id,
3232
public readonly string $object,
3333
public readonly int $created,
3434
public readonly string $model,
3535
public readonly ?string $systemFingerprint,
3636
public readonly array $choices,
37-
public readonly CreateResponseUsage $usage,
37+
public readonly ?CreateResponseUsage $usage,
3838
private readonly MetaInformation $meta,
3939
) {}
4040

@@ -50,13 +50,13 @@ public static function from(array $attributes, MetaInformation $meta): self
5050
), $attributes['choices']);
5151

5252
return new self(
53-
$attributes['id'],
53+
$attributes['id'] ?? null,
5454
$attributes['object'],
5555
$attributes['created'],
5656
$attributes['model'],
5757
$attributes['system_fingerprint'] ?? null,
5858
$choices,
59-
CreateResponseUsage::from($attributes['usage']),
59+
isset($attributes['usage']) ? CreateResponseUsage::from($attributes['usage']) : null,
6060
$meta,
6161
);
6262
}

src/Responses/Chat/CreateStreamedResponse.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ final class CreateStreamedResponse implements ResponseContract
2424
* @param array<int, CreateStreamedResponseChoice> $choices
2525
*/
2626
private function __construct(
27-
public readonly string $id,
27+
public readonly ?string $id,
2828
public readonly string $object,
2929
public readonly int $created,
3030
public readonly string $model,
@@ -44,7 +44,7 @@ public static function from(array $attributes): self
4444
), $attributes['choices']);
4545

4646
return new self(
47-
$attributes['id'],
47+
$attributes['id'] ?? null,
4848
$attributes['object'],
4949
$attributes['created'],
5050
$attributes['model'],

src/Responses/Embeddings/CreateResponse.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ final class CreateResponse implements ResponseContract, ResponseHasMetaInformati
3030
private function __construct(
3131
public readonly string $object,
3232
public readonly array $embeddings,
33-
public readonly CreateResponseUsage $usage,
33+
public readonly ?CreateResponseUsage $usage,
3434
private readonly MetaInformation $meta,
3535
) {}
3636

@@ -48,7 +48,7 @@ public static function from(array $attributes, MetaInformation $meta): self
4848
return new self(
4949
$attributes['object'],
5050
$embeddings,
51-
CreateResponseUsage::from($attributes['usage']),
51+
isset($attributes['usage']) ? CreateResponseUsage::from($attributes['usage']) : null,
5252
$meta,
5353
);
5454
}

src/Responses/Embeddings/CreateResponseEmbedding.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ final class CreateResponseEmbedding
1111
*/
1212
private function __construct(
1313
public readonly string $object,
14-
public readonly int $index,
14+
public readonly ?int $index,
1515
public readonly array $embedding,
1616
) {}
1717

@@ -22,7 +22,7 @@ public static function from(array $attributes): self
2222
{
2323
return new self(
2424
$attributes['object'],
25-
$attributes['index'],
25+
$attributes['index'] ?? null,
2626
$attributes['embedding'],
2727
);
2828
}

tests/Fixtures/Chat.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,64 @@ function chatCompletion(): array
3636
];
3737
}
3838

39+
/**
40+
* @return array<string, mixed>
41+
*/
42+
function chatCompletionWithoutId(): array
43+
{
44+
return [
45+
'object' => 'chat.completion',
46+
'created' => 1677652288,
47+
'model' => 'gpt-3.5-turbo',
48+
'choices' => [
49+
[
50+
'index' => 0,
51+
'message' => [
52+
'role' => 'assistant',
53+
'content' => "\n\nHello there, how may I assist you today?",
54+
],
55+
'finish_reason' => 'stop',
56+
],
57+
],
58+
'usage' => [
59+
'prompt_tokens' => 9,
60+
'completion_tokens' => 12,
61+
'total_tokens' => 21,
62+
'prompt_tokens_details' => [
63+
'cached_tokens' => 5,
64+
],
65+
'completion_tokens_details' => [
66+
'reasoning_tokens' => 0,
67+
'accepted_prediction_tokens' => 0,
68+
'rejected_prediction_tokens' => 0,
69+
],
70+
],
71+
];
72+
}
73+
74+
/**
75+
* @return array<string, mixed>
76+
*/
77+
function chatCompletionWithoutUsage(): array
78+
{
79+
return [
80+
'id' => 'chatcmpl-123',
81+
'object' => 'chat.completion',
82+
'created' => 1677652288,
83+
'model' => 'gpt-3.5-turbo',
84+
'choices' => [
85+
[
86+
'index' => 0,
87+
'message' => [
88+
'role' => 'assistant',
89+
'content' => "\n\nHello there, how may I assist you today?",
90+
],
91+
'finish_reason' => 'stop',
92+
],
93+
],
94+
];
95+
}
96+
3997
/**
4098
* @return array<string, mixed>
4199
*/
@@ -195,6 +253,24 @@ function chatCompletionStreamFirstChunk(): array
195253
];
196254
}
197255

256+
function chatCompletionStreamFirstChunkWithoutId(): array
257+
{
258+
return [
259+
'object' => 'chat.completion.chunk',
260+
'created' => 1679432086,
261+
'model' => 'gpt-4-0314',
262+
'choices' => [
263+
[
264+
'index' => 0,
265+
'delta' => [
266+
'role' => 'assistant',
267+
],
268+
'finish_reason' => null,
269+
],
270+
],
271+
];
272+
}
273+
198274
function chatCompletionStreamContentChunk(): array
199275
{
200276
return [

tests/Fixtures/Embedding.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ function embedding(): array
1616
];
1717
}
1818

19+
/**
20+
* @return array<string, mixed>
21+
*/
22+
function embeddingWithoutIndex(): array
23+
{
24+
return [
25+
'object' => 'embedding',
26+
'embedding' => [
27+
-0.008906792,
28+
-0.013743395,
29+
0.009874112,
30+
],
31+
];
32+
}
33+
1934
/**
2035
* @return array<string, mixed>
2136
*/
@@ -33,3 +48,17 @@ function embeddingList(): array
3348
],
3449
];
3550
}
51+
52+
/**
53+
* @return array<string, mixed>
54+
*/
55+
function embeddingListWithoutUsage(): array
56+
{
57+
return [
58+
'object' => 'list',
59+
'data' => [
60+
embedding(),
61+
embedding(),
62+
],
63+
];
64+
}

tests/Responses/Chat/CreateResponse.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,38 @@
2121
->meta()->toBeInstanceOf(MetaInformation::class);
2222
});
2323

24+
test('from without id', function () {
25+
$completion = CreateResponse::from(chatCompletionWithoutId(), meta());
26+
27+
expect($completion)
28+
->toBeInstanceOf(CreateResponse::class)
29+
->id->toBeNull()
30+
->object->toBe('chat.completion')
31+
->created->toBe(1677652288)
32+
->model->toBe('gpt-3.5-turbo')
33+
->systemFingerprint->toBeNull()
34+
->choices->toBeArray()->toHaveCount(1)
35+
->choices->each->toBeInstanceOf(CreateResponseChoice::class)
36+
->usage->toBeInstanceOf(CreateResponseUsage::class)
37+
->meta()->toBeInstanceOf(MetaInformation::class);
38+
});
39+
40+
test('from without usage', function () {
41+
$completion = CreateResponse::from(chatCompletionWithoutUsage(), meta());
42+
43+
expect($completion)
44+
->toBeInstanceOf(CreateResponse::class)
45+
->id->toBe('chatcmpl-123')
46+
->object->toBe('chat.completion')
47+
->created->toBe(1677652288)
48+
->model->toBe('gpt-3.5-turbo')
49+
->systemFingerprint->toBeNull()
50+
->choices->toBeArray()->toHaveCount(1)
51+
->choices->each->toBeInstanceOf(CreateResponseChoice::class)
52+
->usage->toBeNull()
53+
->meta()->toBeInstanceOf(MetaInformation::class);
54+
});
55+
2456
test('from with system fingerprint', function () {
2557
$completion = CreateResponse::from(chatCompletionWithSystemFingerprint(), meta());
2658

tests/Responses/Chat/CreateStreamedResponse.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@
1717
->choices->each->toBeInstanceOf(CreateStreamedResponseChoice::class);
1818
});
1919

20+
test('from without id', function () {
21+
$completion = CreateStreamedResponse::from(chatCompletionStreamFirstChunkWithoutId());
22+
23+
expect($completion)
24+
->toBeInstanceOf(CreateStreamedResponse::class)
25+
->id->toBeNull()
26+
->object->toBe('chat.completion.chunk')
27+
->created->toBe(1679432086)
28+
->model->toBe('gpt-4-0314')
29+
->choices->toBeArray()->toHaveCount(1)
30+
->choices->each->toBeInstanceOf(CreateStreamedResponseChoice::class);
31+
});
32+
2033
test('from usage chunk', function () {
2134
$completion = CreateStreamedResponse::from(chatCompletionStreamUsageChunk());
2235

tests/Responses/Embeddings/CreateResponse.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
use OpenAI\Responses\Embeddings\CreateResponse;
4+
use OpenAI\Responses\Embeddings\CreateResponseUsage;
45
use OpenAI\Responses\Embeddings\CreateResponseEmbedding;
56
use OpenAI\Responses\Meta\MetaInformation;
67

@@ -12,6 +13,19 @@
1213
->object->toBe('list')
1314
->embeddings->toBeArray()->toHaveCount(2)
1415
->embeddings->each->toBeInstanceOf(CreateResponseEmbedding::class)
16+
->usage->toBeInstanceOf(CreateResponseUsage::class)
17+
->meta()->toBeInstanceOf(MetaInformation::class);
18+
});
19+
20+
test('from without usage', function () {
21+
$response = CreateResponse::from(embeddingListWithoutUsage(), meta());
22+
23+
expect($response)
24+
->toBeInstanceOf(CreateResponse::class)
25+
->object->toBe('list')
26+
->embeddings->toBeArray()->toHaveCount(2)
27+
->embeddings->each->toBeInstanceOf(CreateResponseEmbedding::class)
28+
->usage->toBeNull()
1529
->meta()->toBeInstanceOf(MetaInformation::class);
1630
});
1731

tests/Responses/Embeddings/CreateResponseEmbedding.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@
1515
]);
1616
});
1717

18+
test('from without index', function () {
19+
$result = CreateResponseEmbedding::from(embeddingWithoutIndex());
20+
21+
expect($result)
22+
->object->toBe('embedding')
23+
->index->toBeNull()
24+
->embedding->toBeArray()->toBe([
25+
-0.008906792,
26+
-0.013743395,
27+
0.009874112,
28+
]);
29+
});
30+
1831
test('to array', function () {
1932
$result = CreateResponseEmbedding::from(embedding());
2033

0 commit comments

Comments
 (0)