Skip to content

Commit

Permalink
Add OpenAI Assistant ID validation
Browse files Browse the repository at this point in the history
  • Loading branch information
Remg committed Feb 5, 2024
1 parent d9b80fd commit 8571cf0
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Admin/OpenAI/AssistantAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ protected function configureFormFields(FormMapper $form): void
])
->add('openAiId', TextType::class, [
'label' => 'ID OpenAI',
'help_html' => true,
'help' => 'ID commençant par <b>asst_</b>',
])
->end()
;
Expand Down
2 changes: 2 additions & 0 deletions src/Entity/OpenAI/Assistant.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use App\Entity\EntityIdentityTrait;
use App\Entity\EntityTimestampableTrait;
use App\OpenAI\Model\AssistantInterface;
use App\Validator\OpenAI\ValidAssistantId;
use Doctrine\ORM\Mapping as ORM;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
Expand Down Expand Up @@ -35,6 +36,7 @@ class Assistant implements AssistantInterface
* @ORM\Column(unique=true)
*
* @Assert\NotBlank
* @ValidAssistantId
*/
public ?string $openAiId = null;

Expand Down
14 changes: 14 additions & 0 deletions src/OpenAI/Client/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
use App\OpenAI\Enum\MessageRoleEnum;
use App\OpenAI\Enum\RunStatusEnum;
use OpenAI\Client as OpenAIClient;
use OpenAI\Exceptions\ErrorException;
use OpenAI\Exceptions\TransporterException;
use OpenAI\Exceptions\UnserializableResponse;

class Client implements ClientInterface
{
Expand All @@ -16,6 +19,17 @@ public function __construct(string $openAIApiKey)
$this->openAI = \OpenAI::client($openAIApiKey);
}

public function hasAssistant(string $assistantId): bool
{
try {
$this->openAI->assistants()->retrieve($assistantId);

return true;
} catch (ErrorException|UnserializableResponse|TransporterException $e) {
return false;
}
}

public function createThread(): string
{
$threadResponse = $this->openAI->threads()->create([]);
Expand Down
2 changes: 2 additions & 0 deletions src/OpenAI/Client/ClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

interface ClientInterface
{
public function hasAssistant(string $assistantId): bool;

public function createThread(): string;

public function createUserMessage(string $threadId, string $content): string;
Expand Down
14 changes: 14 additions & 0 deletions src/Validator/OpenAI/ValidAssistantId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace App\Validator\OpenAI;

use Symfony\Component\Validator\Constraint;

/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*/
class ValidAssistantId extends Constraint
{
public string $errorMessage = 'admin.openai.assistant.not_valid';
}
39 changes: 39 additions & 0 deletions src/Validator/OpenAI/ValidAssistantIdValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Validator\OpenAI;

use App\OpenAI\Client\ClientInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;

class ValidAssistantIdValidator extends ConstraintValidator
{
public function __construct(private readonly ClientInterface $client)
{
}

public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof ValidAssistantId) {
throw new UnexpectedTypeException($constraint, ValidAssistantId::class);
}

if (null === $value) {
return;
}

if (!\is_string($value)) {
throw new UnexpectedValueException($value, 'string');
}

if (!$this->client->hasAssistant($value)) {
$this->context
->buildViolation($constraint->errorMessage)
->setParameter('{{ value }}', $value)
->addViolation()
;
}
}
}
5 changes: 5 additions & 0 deletions tests/OpenAI/Client/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ public function __construct()
$this->faker = Factory::create('fr_FR');
}

public function hasAssistant(string $assistantId): bool
{
return str_starts_with($assistantId, 'asst_');
}

public function createThread(): string
{
return uniqid('thread_');
Expand Down
2 changes: 2 additions & 0 deletions translations/validators.fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -620,3 +620,5 @@ admin.adherent.renaissance.membership_type.invalid_choice: Ce type d'adhésion n

admin.membership.cotisation_amount_choice.not_blank: Veuillez spécifier un montant de cotisation.
admin.membership.cotisation_amount_choice.invalid_choice: Ce montant de cotisation est invalide.

admin.openai.assistant.not_valid: Impossible de récupérer les données de l'assistant "{{ value }}".

0 comments on commit 8571cf0

Please sign in to comment.