Skip to content

Commit a2cc4eb

Browse files
authored
feat(OpenAI): Realtime Ephermal Tokens (#591)
* feat: initial work on realtime tokens * feat: more work on realtime tokens * fix: add realtime class to client * fix: threshold is float, not int * fix: modalities can be null on transcribe * feat: test build out for realtime * chore: correct docblock * test: integration tests for realtime
1 parent 69037e9 commit a2cc4eb

20 files changed

Lines changed: 812 additions & 0 deletions

src/Client.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace OpenAI;
66

77
use OpenAI\Contracts\ClientContract;
8+
use OpenAI\Contracts\Resources\RealtimeContract;
89
use OpenAI\Contracts\Resources\ThreadsContract;
910
use OpenAI\Contracts\Resources\VectorStoresContract;
1011
use OpenAI\Contracts\TransporterContract;
@@ -21,6 +22,7 @@
2122
use OpenAI\Resources\Images;
2223
use OpenAI\Resources\Models;
2324
use OpenAI\Resources\Moderations;
25+
use OpenAI\Resources\Realtime;
2426
use OpenAI\Resources\Responses;
2527
use OpenAI\Resources\Threads;
2628
use OpenAI\Resources\VectorStores;
@@ -168,6 +170,16 @@ public function assistants(): Assistants
168170
return new Assistants($this->transporter);
169171
}
170172

173+
/**
174+
* Communicate with a model in real time using WebRTC or WebSockets.
175+
*
176+
* @see https://platform.openai.com/docs/api-reference/realtime
177+
*/
178+
public function realtime(): RealtimeContract
179+
{
180+
return new Realtime($this->transporter);
181+
}
182+
171183
/**
172184
* Create threads that assistants can interact with.
173185
*

src/Contracts/ClientContract.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use OpenAI\Contracts\Resources\ImagesContract;
1616
use OpenAI\Contracts\Resources\ModelsContract;
1717
use OpenAI\Contracts\Resources\ModerationsContract;
18+
use OpenAI\Contracts\Resources\RealtimeContract;
1819
use OpenAI\Contracts\Resources\ResponsesContract;
1920
use OpenAI\Contracts\Resources\ThreadsContract;
2021
use OpenAI\Contracts\Resources\VectorStoresContract;
@@ -36,6 +37,13 @@ public function completions(): CompletionsContract;
3637
*/
3738
public function responses(): ResponsesContract;
3839

40+
/**
41+
* Communicate with a GPT-4o class model in real time using WebRTC or WebSockets. Supports text and audio inputs and outputs, along with audio transcriptions.
42+
*
43+
* @see https://platform.openai.com/docs/api-reference/realtime-sessions
44+
*/
45+
public function realtime(): RealtimeContract;
46+
3947
/**
4048
* Given a chat conversation, the model will return a chat completion response.
4149
*
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenAI\Contracts\Resources;
6+
7+
use OpenAI\Responses\Realtime\SessionResponse;
8+
use OpenAI\Responses\Realtime\TranscriptionSessionResponse;
9+
10+
interface RealtimeContract
11+
{
12+
/**
13+
* Create an ephemeral API token for real time sessions.
14+
*
15+
* @see https://platform.openai.com/docs/api-reference/realtime-sessions/create
16+
*
17+
* @param array<string, mixed> $parameters
18+
*/
19+
public function token(array $parameters = []): SessionResponse;
20+
21+
/**
22+
* Create an ephemeral API token for real time transcription sessions.
23+
*
24+
* @see https://platform.openai.com/docs/api-reference/realtime-sessions/create-transcription
25+
*
26+
* @param array<string, mixed> $parameters
27+
*/
28+
public function transcribeToken(array $parameters = []): TranscriptionSessionResponse;
29+
}

src/Resources/Realtime.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenAI\Resources;
6+
7+
use OpenAI\Contracts\Resources\RealtimeContract;
8+
use OpenAI\Responses\Realtime\SessionResponse;
9+
use OpenAI\Responses\Realtime\TranscriptionSessionResponse;
10+
use OpenAI\ValueObjects\Transporter\Payload;
11+
use OpenAI\ValueObjects\Transporter\Response;
12+
13+
/**
14+
* @phpstan-import-type SessionType from SessionResponse
15+
* @phpstan-import-type TranscriptionSessionType from TranscriptionSessionResponse
16+
*/
17+
final class Realtime implements RealtimeContract
18+
{
19+
use Concerns\Transportable;
20+
21+
/**
22+
* Create an ephemeral API token for real time sessions.
23+
*
24+
* @see https://platform.openai.com/docs/api-reference/realtime-sessions/create
25+
*
26+
* @param array<string, mixed> $parameters
27+
*/
28+
public function token(array $parameters = []): SessionResponse
29+
{
30+
$payload = Payload::create('realtime/sessions', $parameters);
31+
32+
/** @var Response<SessionType> $response */
33+
$response = $this->transporter->requestObject($payload);
34+
35+
return SessionResponse::from($response->data());
36+
}
37+
38+
/**
39+
* Create an ephemeral API token for real time transcription sessions.
40+
*
41+
* @see https://platform.openai.com/docs/api-reference/realtime-sessions/create-transcription
42+
*
43+
* @param array<string, mixed> $parameters
44+
*/
45+
public function transcribeToken(array $parameters = []): TranscriptionSessionResponse
46+
{
47+
$payload = Payload::create('realtime/transcription_sessions', $parameters);
48+
49+
/** @var Response<TranscriptionSessionType> $response */
50+
$response = $this->transporter->requestObject($payload);
51+
52+
return TranscriptionSessionResponse::from($response->data());
53+
}
54+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenAI\Responses\Realtime\Session;
6+
7+
use OpenAI\Contracts\ResponseContract;
8+
use OpenAI\Responses\Concerns\ArrayAccessible;
9+
use OpenAI\Testing\Responses\Concerns\Fakeable;
10+
11+
/**
12+
* @phpstan-type ClientSecretType array{expires_at: int, value: string}
13+
*
14+
* @implements ResponseContract<ClientSecretType>
15+
*/
16+
final class ClientSecret implements ResponseContract
17+
{
18+
/**
19+
* @use ArrayAccessible<ClientSecretType>
20+
*/
21+
use ArrayAccessible;
22+
23+
use Fakeable;
24+
25+
private function __construct(
26+
public readonly int $expiresAt,
27+
public readonly string $value,
28+
) {}
29+
30+
/**
31+
* @param ClientSecretType $attributes
32+
*/
33+
public static function from(array $attributes): self
34+
{
35+
return new self(
36+
expiresAt: $attributes['expires_at'],
37+
value: $attributes['value'],
38+
);
39+
}
40+
41+
/**
42+
* {@inheritDoc}
43+
*/
44+
public function toArray(): array
45+
{
46+
return [
47+
'expires_at' => $this->expiresAt,
48+
'value' => $this->value,
49+
];
50+
}
51+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenAI\Responses\Realtime\Session;
6+
7+
use OpenAI\Contracts\ResponseContract;
8+
use OpenAI\Responses\Concerns\ArrayAccessible;
9+
use OpenAI\Testing\Responses\Concerns\Fakeable;
10+
11+
/**
12+
* @phpstan-type InputAudioTranscriptionType array{model: 'whisper-1'}
13+
*
14+
* @implements ResponseContract<InputAudioTranscriptionType>
15+
*/
16+
final class InputAudioTranscription implements ResponseContract
17+
{
18+
/**
19+
* @use ArrayAccessible<InputAudioTranscriptionType>
20+
*/
21+
use ArrayAccessible;
22+
23+
use Fakeable;
24+
25+
/**
26+
* @param "whisper-1" $model
27+
*/
28+
private function __construct(
29+
public readonly string $model
30+
) {}
31+
32+
/**
33+
* @param InputAudioTranscriptionType $attributes
34+
*/
35+
public static function from(array $attributes): self
36+
{
37+
return new self(
38+
model: $attributes['model'],
39+
);
40+
}
41+
42+
/**
43+
* {@inheritDoc}
44+
*/
45+
public function toArray(): array
46+
{
47+
return [
48+
'model' => $this->model,
49+
];
50+
}
51+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenAI\Responses\Realtime\Session;
6+
7+
use OpenAI\Contracts\ResponseContract;
8+
use OpenAI\Responses\Concerns\ArrayAccessible;
9+
use OpenAI\Testing\Responses\Concerns\Fakeable;
10+
11+
/**
12+
* @phpstan-type TurnDetectionType array{prefix_padding_ms: int, silence_duration_ms: int, threshold: float, type: 'server_vad'}
13+
*
14+
* @implements ResponseContract<TurnDetectionType>
15+
*/
16+
final class TurnDetection implements ResponseContract
17+
{
18+
/**
19+
* @use ArrayAccessible<TurnDetectionType>
20+
*/
21+
use ArrayAccessible;
22+
23+
use Fakeable;
24+
25+
/**
26+
* @param 'server_vad' $type
27+
*/
28+
private function __construct(
29+
public readonly int $prefixPaddingMs,
30+
public readonly int $silenceDurationMs,
31+
public readonly float $threshold,
32+
public readonly string $type,
33+
) {}
34+
35+
/**
36+
* @param TurnDetectionType $attributes
37+
*/
38+
public static function from(array $attributes): self
39+
{
40+
return new self(
41+
prefixPaddingMs: $attributes['prefix_padding_ms'],
42+
silenceDurationMs: $attributes['silence_duration_ms'],
43+
threshold: $attributes['threshold'],
44+
type: $attributes['type'],
45+
);
46+
}
47+
48+
/**
49+
* {@inheritDoc}
50+
*/
51+
public function toArray(): array
52+
{
53+
return [
54+
'prefix_padding_ms' => $this->prefixPaddingMs,
55+
'silence_duration_ms' => $this->silenceDurationMs,
56+
'threshold' => $this->threshold,
57+
'type' => $this->type,
58+
];
59+
}
60+
}

0 commit comments

Comments
 (0)