Streamline Open Responses PDF support on Azure and OpenAI

This commit is contained in:
Christopher Hertel
2026-03-04 23:55:57 +01:00
parent 1aaf5fb4bd
commit f8a4c9e404
5 changed files with 35 additions and 125 deletions

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\AI\Platform\Bridge\Azure\OpenAi\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Document;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
require_once dirname(__DIR__).'/bootstrap.php';
$platform = PlatformFactory::create(
env('AZURE_OPENAI_BASEURL'),
env('AZURE_OPENAI_GPT_DEPLOYMENT'),
env('AZURE_OPENAI_GPT_API_VERSION'),
env('AZURE_OPENAI_KEY'),
http_client(),
);
$messages = new MessageBag(
Message::ofUser(
'What is this document about?',
Document::fromFile(dirname(__DIR__, 2).'/fixtures/document.pdf'),
),
);
$result = $platform->invoke('gpt-5-mini', $messages);
echo $result->asText().\PHP_EOL;

View File

@@ -1,49 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\AI\Platform\Bridge\OpenAi\Contract;
use Symfony\AI\Platform\Capability;
use Symfony\AI\Platform\Contract\Normalizer\ModelContractNormalizer;
use Symfony\AI\Platform\Message\Content\Document;
use Symfony\AI\Platform\Model;
/**
* @author Guillermo Lengemann <guillermo.lengemann@gmail.com>
*/
class DocumentNormalizer extends ModelContractNormalizer
{
/**
* @param Document $data
*
* @return array{type: 'file', file: array{filename: string, file_data: string}}
*/
public function normalize(mixed $data, ?string $format = null, array $context = []): array
{
return [
'type' => 'file',
'file' => [
'filename' => $data->getFilename(),
'file_data' => $data->asDataUrl(),
],
];
}
protected function supportedDataClass(): string
{
return Document::class;
}
protected function supportsModel(Model $model): bool
{
return $model->supports(Capability::INPUT_PDF);
}
}

View File

@@ -25,7 +25,6 @@ final class OpenAiContract extends Contract
{
return OpenResponsesContract::create(
new AudioNormalizer(),
new DocumentNormalizer(),
...$normalizer,
);
}

View File

@@ -1,74 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\AI\Platform\Bridge\OpenAi\Tests\Contract;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\AI\Platform\Bridge\OpenAi\Contract\DocumentNormalizer;
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
use Symfony\AI\Platform\Capability;
use Symfony\AI\Platform\Contract;
use Symfony\AI\Platform\Message\Content\Document;
final class DocumentNormalizerTest extends TestCase
{
public function testSupportsNormalization()
{
$normalizer = new DocumentNormalizer();
$this->assertTrue($normalizer->supportsNormalization(new Document('some content', 'application/pdf'), context: [
Contract::CONTEXT_MODEL => new Gpt('gpt-4o', [Capability::INPUT_PDF]),
]));
$this->assertFalse($normalizer->supportsNormalization(new Document('some content', 'application/pdf'), context: [
Contract::CONTEXT_MODEL => new Gpt('gpt-4o'),
]));
$this->assertFalse($normalizer->supportsNormalization('not a document'));
}
public function testGetSupportedTypes()
{
$normalizer = new DocumentNormalizer();
$expected = [
Document::class => true,
];
$this->assertSame($expected, $normalizer->getSupportedTypes(null));
}
/**
* @param array{type: 'file', file: array{filename: string, file_data: string}} $expected
*/
#[DataProvider('normalizeDataProvider')]
public function testNormalize(Document $document, array $expected)
{
$normalizer = new DocumentNormalizer();
$normalized = $normalizer->normalize($document);
$this->assertEquals($expected, $normalized);
}
public static function normalizeDataProvider(): iterable
{
yield 'document from file' => [
Document::fromFile(\dirname(__DIR__, 7).'/fixtures/document.pdf'),
[
'type' => 'file',
'file' => [
'filename' => 'document.pdf',
'file_data' => 'data:application/pdf;base64,'.base64_encode(file_get_contents(\dirname(__DIR__, 7).'/fixtures/document.pdf')),
],
],
];
}
}

View File

@@ -20,7 +20,6 @@ use Symfony\AI\Platform\Exception\RuntimeException;
use Symfony\AI\Platform\Result\ChoiceResult;
use Symfony\AI\Platform\Result\InMemoryRawResult;
use Symfony\AI\Platform\Result\RawHttpResult;
use Symfony\AI\Platform\Result\RawResultInterface;
use Symfony\AI\Platform\Result\StreamResult;
use Symfony\AI\Platform\Result\TextResult;
use Symfony\AI\Platform\Result\ToolCallResult;