Skip to content

Commit

Permalink
Merge pull request #195 from openai-php/add-header-information
Browse files Browse the repository at this point in the history
[0.6.x] Add access to meta / header information
  • Loading branch information
nunomaduro authored Aug 22, 2023
2 parents 0d64fdb + 1abd507 commit a0bfba8
Show file tree
Hide file tree
Showing 78 changed files with 1,011 additions and 277 deletions.
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
- [FineTunes Resource](#finetunes-resource)
- [Moderations Resource](#moderations-resource)
- [Images Resource](#images-resource)
- [Meta Information](#meta-information)
- [Testing](#testing)
- [Services](#services)
- [Azure](#azure)
Expand Down Expand Up @@ -760,6 +761,67 @@ foreach ($response->data as $data) {
$response->toArray(); // ['created' => 1589478378, data => ['url' => 'https://oaidalleapiprodscus...', ...]]
```

## Meta Information

On all response objects you can access the meta information returned by the API via the `meta()` method.

```php
$response = $client->completions()->create([
'model' => 'text-davinci-003',
'prompt' => 'Say this is a test',
]);

$meta = $response->meta();

$meta->requestId; // '574a03e2faaf4e9fd703958e4ddc66f5'

$meta->openai->model; // 'text-davinci-003'
$meta->openai->organization; // 'org-jwe45798ASN82s'
$meta->openai->version; // '2020-10-01'
$meta->openai->processingMs; // 425

$meta->requestLimit->limit; // 3000
$meta->requestLimit->remaining; // 2999
$meta->requestLimit->reset; // '20ms'

$meta->tokenLimit->limit; // 250000
$meta->tokenLimit->remaining; // 249984
$meta->tokenLimit->reset; // '3ms'
```

The `toArray()` method returns the meta information in the form originally returned by the API.

```php
$meta->toArray();

// [
// 'x-request-id' => '574a03e2faaf4e9fd703958e4ddc66f5',
// 'openai-model' => 'text-davinci-003',
// 'openai-organization' => 'org-jwe45798ASN82s',
// 'openai-processing-ms' => 402,
// 'openai-version' => '2020-10-01',
// 'x-ratelimit-limit-requests' => 3000,
// 'x-ratelimit-remaining-requests' => 2999,
// 'x-ratelimit-reset-requests' => '20ms',
// 'x-ratelimit-limit-tokens' => 250000,
// 'x-ratelimit-remaining-tokens' => 249983,
// 'x-ratelimit-reset-tokens' => '3ms',
// ]
```

On streaming responses you can access the meta information on the reponse stream object.

```php
$stream = $client->completions()->createStreamed([
'model' => 'text-davinci-003',
'prompt' => 'Say this is a test',
]);

$stream->meta();
```

For further details about the rates limits and what to do if you hit them visit the [OpenAI documentation](https://platform.openai.com/docs/guides/rate-limits/rate-limits).

## Testing

The package provides a fake implementation of the `OpenAI\Client` class that allows you to fake the API responses.
Expand Down
1 change: 0 additions & 1 deletion rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
]);

$rectorConfig->skip([
__DIR__.'/src/Contracts/ResponseContract.php',
__DIR__.'/src/Testing/ClientFake.php' => FinalizeClassesWithoutChildrenRector::class,
]);

Expand Down
52 changes: 52 additions & 0 deletions src/Contracts/MetaInformationContract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace OpenAI\Contracts;

use ArrayAccess;

/**
* @template TArray of array
*
* @extends ArrayAccess<key-of<TArray>, value-of<TArray>>
*
* @internal
*/
interface MetaInformationContract extends ArrayAccess
{
/**
* Returns the array representation of the meta information.
*
* @return TArray
*/
public function toArray(): array;

/**
* @param key-of<TArray> $offset
*/
public function offsetExists(mixed $offset): bool;

/**
* @template TOffsetKey of key-of<TArray>
*
* @param TOffsetKey $offset
* @return TArray[TOffsetKey]
*/
public function offsetGet(mixed $offset): mixed;

/**
* @template TOffsetKey of key-of<TArray>
*
* @param TOffsetKey $offset
* @param TArray[TOffsetKey] $value
*/
public function offsetSet(mixed $offset, mixed $value): never;

/**
* @template TOffsetKey of key-of<TArray>
*
* @param TOffsetKey $offset
*/
public function offsetUnset(mixed $offset): never;
}
12 changes: 12 additions & 0 deletions src/Contracts/ResponseHasMetaInformationContract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace OpenAI\Contracts;

use OpenAI\Responses\Meta\MetaInformation;

interface ResponseHasMetaInformationContract
{
public function meta(): MetaInformation;
}
7 changes: 4 additions & 3 deletions src/Contracts/TransporterContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use OpenAI\Exceptions\TransporterException;
use OpenAI\Exceptions\UnserializableResponse;
use OpenAI\ValueObjects\Transporter\Payload;
use OpenAI\ValueObjects\Transporter\Response;
use Psr\Http\Message\ResponseInterface;

/**
Expand All @@ -17,12 +18,12 @@ interface TransporterContract
{
/**
* Sends a request to a server.
**
* @return array<array-key, mixed>
*
* @return Response<array<array-key, mixed>|string>
*
* @throws ErrorException|UnserializableResponse|TransporterException
*/
public function requestObject(Payload $payload): array|string;
public function requestObject(Payload $payload): Response;

/**
* Sends a content request to a server.
Expand Down
13 changes: 7 additions & 6 deletions src/Resources/Audio.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use OpenAI\Responses\Audio\TranscriptionResponse;
use OpenAI\Responses\Audio\TranslationResponse;
use OpenAI\ValueObjects\Transporter\Payload;
use OpenAI\ValueObjects\Transporter\Response;

final class Audio implements AudioContract
{
Expand All @@ -24,10 +25,10 @@ public function transcribe(array $parameters): TranscriptionResponse
{
$payload = Payload::upload('audio/transcriptions', $parameters);

/** @var array{task: ?string, language: ?string, duration: ?float, segments: array<int, array{id: int, seek: int, start: float, end: float, text: string, tokens: array<int, int>, temperature: float, avg_logprob: float, compression_ratio: float, no_speech_prob: float, transient: bool}>, text: string}|string $result */
$result = $this->transporter->requestObject($payload);
/** @var Response<array{task: ?string, language: ?string, duration: ?float, segments: array<int, array{id: int, seek: int, start: float, end: float, text: string, tokens: array<int, int>, temperature: float, avg_logprob: float, compression_ratio: float, no_speech_prob: float, transient: bool}>, text: string}> $response */
$response = $this->transporter->requestObject($payload);

return TranscriptionResponse::from($result);
return TranscriptionResponse::from($response->data(), $response->meta());
}

/**
Expand All @@ -41,9 +42,9 @@ public function translate(array $parameters): TranslationResponse
{
$payload = Payload::upload('audio/translations', $parameters);

/** @var array{task: ?string, language: ?string, duration: ?float, segments: array<int, array{id: int, seek: int, start: float, end: float, text: string, tokens: array<int, int>, temperature: float, avg_logprob: float, compression_ratio: float, no_speech_prob: float, transient: bool}>, text: string}|string $result */
$result = $this->transporter->requestObject($payload);
/** @var Response<array{task: ?string, language: ?string, duration: ?float, segments: array<int, array{id: int, seek: int, start: float, end: float, text: string, tokens: array<int, int>, temperature: float, avg_logprob: float, compression_ratio: float, no_speech_prob: float, transient: bool}>, text: string}> $response */
$response = $this->transporter->requestObject($payload);

return TranslationResponse::from($result);
return TranslationResponse::from($response->data(), $response->meta());
}
}
7 changes: 4 additions & 3 deletions src/Resources/Chat.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use OpenAI\Responses\Chat\CreateStreamedResponse;
use OpenAI\Responses\StreamResponse;
use OpenAI\ValueObjects\Transporter\Payload;
use OpenAI\ValueObjects\Transporter\Response;

final class Chat implements ChatContract
{
Expand All @@ -28,10 +29,10 @@ public function create(array $parameters): CreateResponse

$payload = Payload::create('chat/completions', $parameters);

/** @var array{id: string, object: string, created: int, model: string, choices: array<int, array{index: int, message: array{role: string, content: ?string, function_call: ?array{name: string, arguments: string}}, finish_reason: string|null}>, usage: array{prompt_tokens: int, completion_tokens: int|null, total_tokens: int}} $result */
$result = $this->transporter->requestObject($payload);
/** @var Response<array{id: string, object: string, created: int, model: string, choices: array<int, array{index: int, message: array{role: string, content: ?string, function_call: ?array{name: string, arguments: string}}, finish_reason: string|null}>, usage: array{prompt_tokens: int, completion_tokens: int|null, total_tokens: int}}> $response */
$response = $this->transporter->requestObject($payload);

return CreateResponse::from($result);
return CreateResponse::from($response->data(), $response->meta());
}

/**
Expand Down
7 changes: 4 additions & 3 deletions src/Resources/Completions.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use OpenAI\Responses\Completions\CreateStreamedResponse;
use OpenAI\Responses\StreamResponse;
use OpenAI\ValueObjects\Transporter\Payload;
use OpenAI\ValueObjects\Transporter\Response;

final class Completions implements CompletionsContract
{
Expand All @@ -28,10 +29,10 @@ public function create(array $parameters): CreateResponse

$payload = Payload::create('completions', $parameters);

/** @var array{id: string, object: string, created: int, model: string, choices: array<int, array{text: string, index: int, logprobs: array{tokens: array<int, string>, token_logprobs: array<int, float>, top_logprobs: array<int, string>|null, text_offset: array<int, int>}|null, finish_reason: string}>, usage: array{prompt_tokens: int, completion_tokens: int, total_tokens: int}} $result */
$result = $this->transporter->requestObject($payload);
/** @var Response<array{id: string, object: string, created: int, model: string, choices: array<int, array{text: string, index: int, logprobs: array{tokens: array<int, string>, token_logprobs: array<int, float>, top_logprobs: array<int, string>|null, text_offset: array<int, int>}|null, finish_reason: string}>, usage: array{prompt_tokens: int, completion_tokens: int, total_tokens: int}}> $response */
$response = $this->transporter->requestObject($payload);

return CreateResponse::from($result);
return CreateResponse::from($response->data(), $response->meta());
}

/**
Expand Down
7 changes: 4 additions & 3 deletions src/Resources/Edits.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use OpenAI\Contracts\Resources\EditsContract;
use OpenAI\Responses\Edits\CreateResponse;
use OpenAI\ValueObjects\Transporter\Payload;
use OpenAI\ValueObjects\Transporter\Response;

final class Edits implements EditsContract
{
Expand All @@ -23,9 +24,9 @@ public function create(array $parameters): CreateResponse
{
$payload = Payload::create('edits', $parameters);

/** @var array{object: string, created: int, choices: array<int, array{text: string, index: int}>, usage: array{prompt_tokens: int, completion_tokens: int, total_tokens: int}} $result */
$result = $this->transporter->requestObject($payload);
/** @var Response<array{object: string, created: int, choices: array<int, array{text: string, index: int}>, usage: array{prompt_tokens: int, completion_tokens: int, total_tokens: int}}> $response */
$response = $this->transporter->requestObject($payload);

return CreateResponse::from($result);
return CreateResponse::from($response->data(), $response->meta());
}
}
7 changes: 4 additions & 3 deletions src/Resources/Embeddings.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use OpenAI\Contracts\Resources\EmbeddingsContract;
use OpenAI\Responses\Embeddings\CreateResponse;
use OpenAI\ValueObjects\Transporter\Payload;
use OpenAI\ValueObjects\Transporter\Response;

final class Embeddings implements EmbeddingsContract
{
Expand All @@ -23,9 +24,9 @@ public function create(array $parameters): CreateResponse
{
$payload = Payload::create('embeddings', $parameters);

/** @var array{object: string, data: array<int, array{object: string, embedding: array<int, float>, index: int}>, usage: array{prompt_tokens: int, total_tokens: int}} $result */
$result = $this->transporter->requestObject($payload);
/** @var Response<array{object: string, data: array<int, array{object: string, embedding: array<int, float>, index: int}>, usage: array{prompt_tokens: int, total_tokens: int}}> $response */
$response = $this->transporter->requestObject($payload);

return CreateResponse::from($result);
return CreateResponse::from($response->data(), $response->meta());
}
}
25 changes: 13 additions & 12 deletions src/Resources/Files.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use OpenAI\Responses\Files\ListResponse;
use OpenAI\Responses\Files\RetrieveResponse;
use OpenAI\ValueObjects\Transporter\Payload;
use OpenAI\ValueObjects\Transporter\Response;

final class Files implements FilesContract
{
Expand All @@ -24,10 +25,10 @@ public function list(): ListResponse
{
$payload = Payload::list('files');

/** @var array{object: string, data: array<int, array{id: string, object: string, created_at: int, bytes: int, filename: string, purpose: string, status: string, status_details: array<array-key, mixed>|string|null}>} $result */
$result = $this->transporter->requestObject($payload);
/** @var Response<array{object: string, data: array<int, array{id: string, object: string, created_at: int, bytes: int, filename: string, purpose: string, status: string, status_details: array<array-key, mixed>|string|null}>}> $response */
$response = $this->transporter->requestObject($payload);

return ListResponse::from($result);
return ListResponse::from($response->data(), $response->meta());
}

/**
Expand All @@ -39,10 +40,10 @@ public function retrieve(string $file): RetrieveResponse
{
$payload = Payload::retrieve('files', $file);

/** @var array{id: string, object: string, created_at: int, bytes: int, filename: string, purpose: string, status: string, status_details: array<array-key, mixed>|string|null} $result */
$result = $this->transporter->requestObject($payload);
/** @var Response<array{id: string, object: string, created_at: int, bytes: int, filename: string, purpose: string, status: string, status_details: array<array-key, mixed>|string|null}> $response */
$response = $this->transporter->requestObject($payload);

return RetrieveResponse::from($result);
return RetrieveResponse::from($response->data(), $response->meta());
}

/**
Expand All @@ -68,10 +69,10 @@ public function upload(array $parameters): CreateResponse
{
$payload = Payload::upload('files', $parameters);

/** @var array{id: string, object: string, created_at: int, bytes: int, filename: string, purpose: string, status: string, status_details: array<array-key, mixed>|string|null} $result */
$result = $this->transporter->requestObject($payload);
/** @var Response<array{id: string, object: string, created_at: int, bytes: int, filename: string, purpose: string, status: string, status_details: array<array-key, mixed>|string|null}> $response */
$response = $this->transporter->requestObject($payload);

return CreateResponse::from($result);
return CreateResponse::from($response->data(), $response->meta());
}

/**
Expand All @@ -83,9 +84,9 @@ public function delete(string $file): DeleteResponse
{
$payload = Payload::delete('files', $file);

/** @var array{id: string, object: string, deleted: bool} $result */
$result = $this->transporter->requestObject($payload);
/** @var Response<array{id: string, object: string, deleted: bool}> $response */
$response = $this->transporter->requestObject($payload);

return DeleteResponse::from($result);
return DeleteResponse::from($response->data(), $response->meta());
}
}
Loading

0 comments on commit a0bfba8

Please sign in to comment.