Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
v1.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
thejamescollins committed Oct 24, 2022
1 parent ac96f7d commit cd3d8a1
Show file tree
Hide file tree
Showing 91 changed files with 2,797 additions and 197 deletions.
10 changes: 6 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions

on:
# Run on every commit.
- push
# Allow manually triggering the workflow.
- workflow_dispatch
# Run on every commit to all branches, but not on tags.
push:
branches:
- '**'
# Allow manually triggering the workflow.
workflow_dispatch:

# Cancels all previous workflow runs for the same branch that have not yet completed.
concurrency:
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 1.0.1 - 2022-10-24

### Added
- Add support for [Moderation](https://beta.openai.com/docs/guides/moderation) using a new `Moderations::create()` Handler class and Method.
- Add [usage information](https://community.openai.com/t/usage-info-in-api-responses/18862) to response models: `Completions::create()`, `Edits::create()` and `Embeddings::create()`.

### Changed
- Define required properties for response models.
- Rename all nested response models.
- Change default value for `Tectalic\OpenAi\Models\FineTunes\CreateRequest::$prompt_loss_weight`.
- 22 API Methods are now supported, grouped into 14 API Handlers.
- API version updated from 1.0.5 to 1.0.6.

### Fixed
- Don't run CI for tags.
- Use correct model type for nested models: `Tectalic\OpenAi\Models\FineTunes\CreateResponse`, `Tectalic\OpenAi\Models\FineTunes\RetrieveResponse` and `Tectalic\OpenAi\Models\FineTunesCancel\CancelFineTuneResponse`.

## 1.0.0 - 2022-07-11

### Added
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ In the **Usage** code above, customize the `Authentication` constructor to your

The primary class you will interact with is the `Client` class (`Tectalic\OpenAi\Client`).

This `Client` class also contains the helper methods that let you quickly access the 13 API Handlers.
This `Client` class also contains the helper methods that let you quickly access the 14 API Handlers.

Please see below for a complete list of supported handlers and methods.

### Supported API Handlers and Methods

This package supports 21 API Methods, which are grouped into 13 API Handlers.
This package supports 22 API Methods, which are grouped into 14 API Handlers.

See the table below for a full list of API Handlers and Methods.

Expand Down Expand Up @@ -99,6 +99,7 @@ See the table below for a full list of API Handlers and Methods.
|`Models::list()`|Lists the currently available models, and provides basic information about each one such as the owner and availability.|`GET` `/models`|
|`Models::retrieve()`|Retrieves a model instance, providing basic information about the model such as the owner and permissioning.|`GET` `/models/{model}`|
|`Models::delete()`|Delete a fine-tuned model. You must have the Owner role in your organization.|`DELETE` `/models/{model}`|
|`Moderations::create()`|Classifies if text violates OpenAI's Content Policy|`POST` `/moderations`|

### Making a Request

Expand Down
623 changes: 606 additions & 17 deletions artifacts/build-issues.txt

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"libraryVersion": "1.0.0",
"apiVersion": "1.0.5",
"buildVersion": "1.1.3"
"libraryVersion": "1.0.1",
"apiVersion": "1.0.6",
"buildVersion": "1.1.4"
}
18 changes: 15 additions & 3 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use Tectalic\OpenAi\Handlers\FineTunesCancel;
use Tectalic\OpenAi\Handlers\FineTunesEvents;
use Tectalic\OpenAi\Handlers\Models;
use Tectalic\OpenAi\Handlers\Moderations;
use Tectalic\OpenAi\Models\AbstractModel;
use Tectalic\OpenAi\Models\AbstractModelCollection;
use Throwable;
Expand Down Expand Up @@ -210,6 +211,17 @@ public function models(): Models
return new \Tectalic\OpenAi\Handlers\Models($this);
}

/**
* Access to the moderations handler.
*
* @api
* @return Moderations
*/
public function moderations(): Moderations
{
return new \Tectalic\OpenAi\Handlers\Moderations($this);
}

/**
* Encode the request body.
*
Expand Down Expand Up @@ -301,7 +313,7 @@ private function encodeMultipart(MultipartStreamBuilder $builder, $body): Stream
// Property is a full path to a file.
// Attempt to open the file.
/** @var string $value */
\set_error_handler(function ($t, $m) use ($value) {
\set_error_handler(function ($errorNumber, $errorString) use ($value) {
throw new ClientException(\sprintf('Unable to read file: %s', $value));
});
try {
Expand Down Expand Up @@ -369,7 +381,7 @@ private function mergeRequestParts(

$request = $request->withHeader(
'User-Agent',
'Tectalic OpenAI REST API Client'
'Tectalic OpenAI REST API Client/1.0.1'
);

// Merge Headers.
Expand Down Expand Up @@ -515,7 +527,7 @@ public function sendRequest(RequestInterface $request): ResponseInterface
} finally {
// Close any open file pointers from the request.
foreach ($this->fileHandles as $file) {
\set_error_handler(function ($t, $m) {
\set_error_handler(function ($errorNumber, $errorString) {
throw new ClientException();
});
try {
Expand Down
180 changes: 180 additions & 0 deletions src/Handlers/Moderations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<?php

/**
* Copyright (c) 2022 Tectalic (https://tectalic.com)
*
* For copyright and license information, please view the LICENSE file that was distributed with this source code.
*
* Please see the README.md file for usage instructions.
*/

declare(strict_types=1);

namespace Tectalic\OpenAi\Handlers;

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Tectalic\OpenAi\Client;
use Tectalic\OpenAi\ClientException;
use Tectalic\OpenAi\Manager;
use Tectalic\OpenAi\Models\AbstractModel;
use Tectalic\OpenAi\Models\AbstractModelCollection;
use Tectalic\OpenAi\Models\Moderations\CreateRequest;
use Tectalic\OpenAi\Models\Moderations\CreateResponse;
use Throwable;

final class Moderations
{
/** @var Client */
private $client;

/** @var RequestInterface|null */
private $request = null;

/** @var ResponseInterface|null */
private $response = null;

/** @var class-string<AbstractModel|AbstractModelCollection> */
private $modelType;

public function __construct(?Client $client = null)
{
$this->client = $client ?? Manager::access();
}

/**
* Classifies if text violates OpenAI's Content Policy
*
* Operation URL: POST /moderations
* Operation ID: createModeration
*
* @param CreateRequest|array $body
*
* @api
* @return self
*/
public function create($body): self
{
$url = '/moderations';
$this->setRequest($this->client->post(
$url,
\is_array($body) ? new CreateRequest($body) : $body,
['Content-Type' => 'application/json']
));
$this->modelType = CreateResponse::class;
return $this;
}

/**
* Convert response body to an array.
*
* @return array
* @throws ClientException
*/
private function parseResponse(ResponseInterface $response): array
{
$contentType = \strtolower($response->getHeaderLine('Content-Type'));
if (substr($contentType, 0, 16) !== 'application/json' && \strlen($contentType) !== 0) {
throw new ClientException(\sprintf('Unsupported content type: %s', $contentType));
}

$body = (string) $response->getBody();
$body = \strlen($body) === 0 ? '[]' : $body;
$data = (array) \json_decode($body, true);

if (\json_last_error()) {
throw new ClientException(
'Failed to parse JSON response body: ' . \json_last_error_msg()
);
}
return $data;
}

/**
* Sets the PSR 7 Response object.
* Also removes the previous response.
*
* @param RequestInterface $request
*
* @return void
*/
private function setRequest(RequestInterface $request): void
{
$this->request = $request;
$this->response = null;
}

/**
* Returns the PSR 7 Response object.
*
* @internal
* @return RequestInterface
* @throws ClientException
*/
public function getRequest(): RequestInterface
{
if (\is_null($this->request)) {
throw new ClientException('Request not configured.');
}
return $this->request;
}

/**
* Returns the PSR 7 Response object.
*
* @api
* @return ResponseInterface
*/
public function getResponse(): ResponseInterface
{
if (!\is_null($this->response)) {
return $this->response;
}

$this->response = $this->client->sendRequest($this->getRequest());
$this->request = null;
return $this->response;
}

/**
* Returns the response body as a model/DTO.
*
* @api
* @return AbstractModel|AbstractModelCollection
* @throws ClientException if an unsuccessful HTTP response occurs.
* @throws ClientException if the response body cannot be parsed.
*/
public function toModel(): object
{
if ($this->getResponse()->getStatusCode() < 200 || $this->getResponse()->getStatusCode() >= 300) {
throw new ClientException(
\sprintf(
'Unsuccessful response. HTTP status code: %s (%s).',
$this->getResponse()->getStatusCode(),
$this->getResponse()->getReasonPhrase()
)
);
}
$class = $this->modelType;
try {
return new $class($this->parseResponse($this->getResponse()));
} catch (Throwable $e) {
throw new ClientException(
'Response body parse failed. See previous exception for details.',
0,
$e
);
}
}

/**
* Returns the response body as an associative array.
*
* @api
* @return array<string,mixed>
*/
public function toArray(): array
{
return $this->parseResponse($this->getResponse());
}
}
2 changes: 1 addition & 1 deletion src/Models/Answers/CreateRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ final class CreateRequest extends AbstractModel
* 5 most likely tokens. The API will always return the logprob of the sampled
* token, so there may be up to logprobs+1 elements in the response.
* The maximum value for logprobs is 5. If you need more than this, please contact
* [email protected] and describe your use case.
* us through our Help center and describe your use case.
* When logprobs is set, completion will be automatically added into expand to get
* the logprobs.
*
Expand Down
2 changes: 1 addition & 1 deletion src/Models/Answers/CreateResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ final class CreateResponse extends AbstractModel
/** @var string[] */
public $answers;

/** @var \Tectalic\OpenAi\Models\Answers\CreateResponseItem[] */
/** @var \Tectalic\OpenAi\Models\Answers\CreateResponseSelectedDocumentsItem[] */
public $selected_documents;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use Tectalic\OpenAi\Models\AbstractModel;

final class CreateResponseItem extends AbstractModel
final class CreateResponseSelectedDocumentsItem extends AbstractModel
{
/** @var int */
public $document;
Expand Down
6 changes: 3 additions & 3 deletions src/Models/Classifications/CreateRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ final class CreateRequest extends AbstractModel
* risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones
* with a well-defined answer.
*
* Example: 0
*
* Default Value: 0
*
* Example: 0
*
* @var float|int|null
*/
public $temperature;
Expand All @@ -103,7 +103,7 @@ final class CreateRequest extends AbstractModel
* 5 most likely tokens. The API will always return the logprob of the sampled
* token, so there may be up to logprobs+1 elements in the response.
* The maximum value for logprobs is 5. If you need more than this, please contact
* [email protected] and describe your use case.
* us through our Help center and describe your use case.
* When logprobs is set, completion will be automatically added into expand to get
* the logprobs.
*
Expand Down
2 changes: 1 addition & 1 deletion src/Models/Classifications/CreateResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ final class CreateResponse extends AbstractModel
/** @var string */
public $label;

/** @var \Tectalic\OpenAi\Models\Classifications\CreateResponseItem[] */
/** @var \Tectalic\OpenAi\Models\Classifications\CreateResponseSelectedExamplesItem[] */
public $selected_examples;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use Tectalic\OpenAi\Models\AbstractModel;

final class CreateResponseItem extends AbstractModel
final class CreateResponseSelectedExamplesItem extends AbstractModel
{
/** @var int */
public $document;
Expand Down
Loading

0 comments on commit cd3d8a1

Please sign in to comment.