Skip to content

Commit

Permalink
Merge pull request #2 from outl1ne/feature/TB-6
Browse files Browse the repository at this point in the history
feature/TB-6
  • Loading branch information
allantatter authored Feb 20, 2024
2 parents 4707451 + 6077111 commit d4b5a7a
Show file tree
Hide file tree
Showing 13 changed files with 415 additions and 37 deletions.
50 changes: 50 additions & 0 deletions src/Capabilities/Chat/Chat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Outl1ne\NovaOpenAI\Capabilities\Chat;

use Outl1ne\NovaOpenAI\Capabilities\Capability;
use Outl1ne\NovaOpenAI\Capabilities\Chat\Parameters\Messages;
use Outl1ne\NovaOpenAI\Capabilities\Chat\Parameters\ResponseFormat;

class Chat extends Capability
{
public function create(
string $model,
Messages $messages,
?ResponseFormat $responseFormat = null,
?string $user = null,
?float $frequencyPenalty = null,
?array $logitBias = null,
?bool $logprobs = null,
?int $topLogprobs = null,
?int $maxTokens = null,
?int $n = null,
?float $presencePenalty = null,
?int $seed = null,
null|string|array $stop = null,
?float $temperature = null,
?float $topP = null,
?array $tools = null,
null|string|array $toolChoice = null,
) {
return (new CreateChat($this->http))->makeRequest(
$model,
$messages,
$responseFormat,
$user,
$frequencyPenalty,
$logitBias,
$logprobs,
$topLogprobs,
$maxTokens,
$n,
$presencePenalty,
$seed,
$stop,
$temperature,
$topP,
$tools,
$toolChoice,
);
}
}
114 changes: 114 additions & 0 deletions src/Capabilities/Chat/CreateChat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

namespace Outl1ne\NovaOpenAI\Capabilities\Chat;

use Exception;
use Illuminate\Http\Client\PendingRequest;
use Outl1ne\NovaOpenAI\Models\OpenAIRequest;
use Outl1ne\NovaOpenAI\Capabilities\Measurable;
use Outl1ne\NovaOpenAI\Capabilities\Chat\Parameters\Messages;
use Outl1ne\NovaOpenAI\Capabilities\Chat\Parameters\ResponseFormat;
use Outl1ne\NovaOpenAI\Capabilities\Chat\Responses\ChatResponse;
use Outl1ne\NovaOpenAI\Capabilities\Embeddings\Responses\EmbeddingsResponse;

class CreateChat
{
use Measurable;

protected OpenAIRequest $request;

public function __construct(
protected readonly PendingRequest $http,
) {
$this->request = new OpenAIRequest;
$this->request->method = 'chat';
$this->request->arguments = [];
}

public function pending()
{
$this->measure();

$this->request->status = 'pending';
$this->request->save();

return $this->request;
}

public function makeRequest(
string $model,
Messages $messages,
?ResponseFormat $responseFormat = null,
?string $user = null,
?float $frequencyPenalty = null,
?array $logitBias = null,
?bool $logprobs = null,
?int $topLogprobs = null,
?int $maxTokens = null,
?int $n = null,
?float $presencePenalty = null,
?int $seed = null,
null|string|array $stop = null,
?float $temperature = null,
?float $topP = null,
?array $tools = null,
null|string|array $toolChoice = null,
): ChatResponse {
$this->request->model_requested = $model;
$this->request->input = $messages->messages;
$this->request->appendArgument('response_format', $responseFormat);
$this->request->appendArgument('user', $user);
$this->request->appendArgument('frequency_penalty', $frequencyPenalty);
$this->request->appendArgument('logit_bias', $logitBias);
$this->request->appendArgument('logprobs', $logprobs);
$this->request->appendArgument('top_logprobs', $topLogprobs);
$this->request->appendArgument('max_tokens', $maxTokens);
$this->request->appendArgument('n', $n);
$this->request->appendArgument('presence_penalty', $presencePenalty);
$this->request->appendArgument('seed', $seed);
$this->request->appendArgument('stop', $stop);
$this->request->appendArgument('temperature', $temperature);
$this->request->appendArgument('top_p', $topP);
$this->request->appendArgument('tools', $tools);
$this->request->appendArgument('tool_choice', $toolChoice);

$this->pending();

try {
$response = $this->http->withHeader('Content-Type', 'application/json')->post('chat/completions', [
'model' => $model,
'messages' => $messages->messages,
...$this->request->arguments,
]);
$response->throw();

return $this->handleResponse(new ChatResponse($response));
} catch (Exception $e) {
$this->handleException($e);
}
}

protected function handleResponse(ChatResponse $response)
{
$this->request->time_sec = $this->measure();
$this->request->status = 'success';
$this->request->meta = $response->meta;
$this->request->model_used = $response->model;
$this->request->output = $response->choices;
$this->request->usage_prompt_tokens = $response->usage->promptTokens;
$this->request->usage_total_tokens = $response->usage->totalTokens;
$this->request->save();

return $response;
}

public function handleException(Exception $e)
{
$this->request->time_sec = $this->measure();
$this->request->status = 'error';
$this->request->error = $e->getMessage();
$this->request->save();

throw $e;
}
}
73 changes: 73 additions & 0 deletions src/Capabilities/Chat/Parameters/Messages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace Outl1ne\NovaOpenAI\Capabilities\Chat\Parameters;

class Messages
{
public array $messages = [];

public function system(string $content, ?string $name = null): self
{
$message = [
'role' => 'system',
'content' => $content,
];

$message = $this->addOptionalProperty($message, 'name', $name);

$this->messages[] = $message;

return $this;
}

public function user(string $content, ?string $name = null): self
{
$message = [
'role' => 'user',
'content' => $content,
];

$message = $this->addOptionalProperty($message, 'name', $name);

$this->messages[] = $message;

return $this;
}

public function assistant(?string $content = null, ?string $name = null, ?array $toolCalls): self
{
$message = [
'role' => 'assistant',
];

$message = $this->addOptionalProperty($message, 'content', $content);
$message = $this->addOptionalProperty($message, 'name', $name);
$message = $this->addOptionalProperty($message, 'tool_calls', $toolCalls);

$this->messages[] = $message;

return $this;
}

public function tool(string $content, string $toolCallId): self
{
$message = [
'role' => 'system',
'content' => $content,
'tool_call_id' => $toolCallId,
];

$this->messages[] = $message;

return $this;
}

protected function addOptionalProperty(array $message, string $name, ?string $value): array
{
if ($value !== null) {
$message[$name] = $value;
}

return $message;
}
}
22 changes: 22 additions & 0 deletions src/Capabilities/Chat/Parameters/ResponseFormat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Outl1ne\NovaOpenAI\Capabilities\Chat\Parameters;

class ResponseFormat
{
public ?array $responseFormat = null;

public function text(): void
{
$this->responseFormat = [
'type' => 'text',
];
}

public function json(): void
{
$this->responseFormat = [
'type' => 'json_object',
];
}
}
50 changes: 50 additions & 0 deletions src/Capabilities/Chat/Responses/ChatResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Outl1ne\NovaOpenAI\Capabilities\Chat\Responses;

use Illuminate\Http\Client\Response;
use Outl1ne\NovaOpenAI\Capabilities\Responses\AppendsMeta;
use Outl1ne\NovaOpenAI\Capabilities\Responses\Usage;
use Outl1ne\NovaOpenAI\Capabilities\Responses\RateLimit;

class ChatResponse
{
use AppendsMeta;

public string $object;
public string $model;
public array $choices;
public Usage $usage;
public RateLimit $rateLimit;

public function __construct(
protected readonly Response $response,
) {
$data = $response->json();
$headers = $response->headers();

$this->model = $data['model'];
$this->choices = $data['choices'];
$this->appendMeta('id', $data['id']);
$this->appendMeta('object', $data['object']);
$this->appendMeta('system_fingerprint', $data['system_fingerprint']);
$this->usage = new Usage(
promptTokens: $data['usage']['prompt_tokens'],
completionTokens: $data['usage']['completion_tokens'],
totalTokens: $data['usage']['total_tokens'],
);
$this->rateLimit = new RateLimit(
limitRequests: $headers['x-ratelimit-limit-requests'][0],
limitTokens: $headers['x-ratelimit-limit-tokens'][0],
remainingRequests: $headers['x-ratelimit-remaining-requests'][0],
remainingTokens: $headers['x-ratelimit-remaining-tokens'][0],
resetRequests: $headers['x-ratelimit-reset-requests'][0],
resetTokens: $headers['x-ratelimit-reset-tokens'][0],
);
}

public function response()
{
return $this->response;
}
}
7 changes: 3 additions & 4 deletions src/Capabilities/Embeddings/CreateEmbedding.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public function makeRequest(string $model, string $input, ?string $encodingForma
$response = $this->http->withHeader('Content-Type', 'application/json')->post('embeddings', [
'model' => $model,
'input' => $input,
...$this->request->arguments,
]);
$response->throw();

Expand All @@ -59,10 +60,8 @@ protected function handleResponse(EmbeddingsResponse $response)
{
$this->request->time_sec = $this->measure();
$this->request->status = 'success';
$this->request->meta = [
'object' => $response->object
];
$this->request->model_used = $response->modelUsed;
$this->request->meta = $response->meta;
$this->request->model_used = $response->model;
$this->request->output = $response->embedding;
$this->request->usage_prompt_tokens = $response->usage->promptTokens;
$this->request->usage_total_tokens = $response->usage->totalTokens;
Expand Down
1 change: 0 additions & 1 deletion src/Capabilities/Embeddings/Embeddings.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Outl1ne\NovaOpenAI\Capabilities\Capability;


class Embeddings extends Capability
{
public function create(string $model, string $input, ?string $encodingFormat = null, ?int $dimensions = null, ?string $user = null)
Expand Down
8 changes: 5 additions & 3 deletions src/Capabilities/Embeddings/Responses/EmbeddingsResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
use Illuminate\Http\Client\Response;
use Outl1ne\NovaOpenAI\Capabilities\Responses\Usage;
use Outl1ne\NovaOpenAI\Capabilities\Responses\RateLimit;
use Outl1ne\NovaOpenAI\Capabilities\Responses\AppendsMeta;

class EmbeddingsResponse
{
use AppendsMeta;

public string $object;
public string $model;
public string $modelUsed;
Expand All @@ -21,13 +24,12 @@ public function __construct(
$data = $response->json();
$headers = $response->headers();

$this->object = $data['object'];
$this->model = $data['model'];
$this->modelUsed = $headers['openai-model'][0];
$this->appendMeta('object', $data['object']);
$this->usage = new Usage(
promptTokens: $data['usage']['prompt_tokens'],
completionTokens: null,
totalTokens: $data['usage']['total_tokens']
totalTokens: $data['usage']['total_tokens'],
);
$this->rateLimit = new RateLimit(
limitRequests: $headers['x-ratelimit-limit-requests'][0],
Expand Down
22 changes: 22 additions & 0 deletions src/Capabilities/Responses/AppendsMeta.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Outl1ne\NovaOpenAI\Capabilities\Responses;

trait AppendsMeta
{
public array $meta;

protected function appendMeta(string $key, $value)
{
if ($value === null) {
return false;
}

$this->meta = [
...$this->meta ?? [],
$key => $value,
];

return true;
}
}
Loading

0 comments on commit d4b5a7a

Please sign in to comment.