Skip to content

Commit 5d66c61

Browse files
Copilotchr-hertel
andcommitted
fix: consistent Whisper task option for OpenAI and Azure bridges (#350)
This PR addresses the inconsistency between OpenAI and Azure Whisper implementations by introducing a configurable `task` option that controls which endpoint is used. Previously, the Whisper implementations were inconsistent: - **OpenAI bridge**: Hardcoded to use `/audio/transcriptions` endpoint - **Azure bridge**: Hardcoded to use `/audio/translations` endpoint This made it impossible to use both transcription and translation features consistently across platforms. Introduced a `task` option that allows users to specify whether they want transcription or translation: ```php use PhpLlm\LlmChain\Platform\Bridge\OpenAI\Whisper\Task; // Default behavior (transcription) $client->request($model, $payload); // Explicit transcription $client->request($model, $payload, ['task' => Task::TRANSCRIPTION]); // Translation $client->request($model, $payload, ['task' => Task::TRANSLATION]); ``` 1. **New Task Interface**: Created `PhpLlm\LlmChain\Platform\Bridge\OpenAI\Whisper\Task` with constants: - `TRANSCRIPTION = 'transcription'` - `TRANSLATION = 'translation'` 2. **Enhanced OpenAI ModelClient**: - Extracts `task` from options - Dynamically constructs endpoint URL based on task - Maintains backward compatibility (defaults to transcription) 3. **Enhanced Azure WhisperModelClient**: - Extracts `task` from options - Dynamically constructs endpoint URL based on task - **Breaking Change**: Now defaults to transcription for consistency 4. **Comprehensive Tests**: Added test coverage for both implementations covering all scenarios ⚠️ **Azure Whisper behavior change**: Previously, Azure Whisper always used the `/translations` endpoint. Now it defaults to `/transcriptions` for consistency with OpenAI. **Migration**: If you were relying on Azure Whisper's translation behavior, explicitly specify the task: ```php $options = ['task' => Task::TRANSLATION]; $response = $azureClient->request($model, $payload, $options); ``` - **OpenAI**: Fully backward compatible (still defaults to transcription) - **Azure**: Breaking change documented above, but provides path forward Both implementations now behave consistently and support both transcription and translation endpoints. Fixes #349. > [!WARNING] > > <details> > <summary>Firewall rules blocked me from connecting to one or more addresses</summary> > > #### I tried to connect to the following addresses, but was blocked by firewall rules: > > - `https://api.github.com/repos/CodeWithKyrian/chromadb-php/zipball/53bb269c6e76ae9976b0750eed3731d1fdcb9ea5` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/CodeWithKyrian/jinja-php/zipball/3a246c831af5c3c3c532399aa0c1e5209441675f` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/CodeWithKyrian/transformers-libsloader/zipball/7052adad23e969701a961437b77422f820df05ba` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/CodeWithKyrian/transformers-php/zipball/474406c25d33e36fcc4f6225719a46afa82acbf8` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/OskarStark/enum-helper/zipball/adccc8c099db61cb26497a1e1987fc95ebda02a9` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/eea219a577085bd13ff0cb644a422c20798316c7` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/async-aws/bedrock-runtime/zipball/518cd3baa6df494fb0fb029c1149921c1af3fe80` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/async-aws/core/zipball/58ab79116d990e7053b2e31162f47df4223148c5` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/doctrine/dbal/zipball/b37d160498ea91a2382a2ebe825c4ea6254fc0ec` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/lryxyr /usr/bin/composer install --no-dev --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/dompdf/php-font-lib/zipball/a1681e9793040740a405ac5b189275059e2a9863` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/interop-phpobjects/polite-math/zipball/621246cdc108b1388307097e06361ca5b9259467` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/libvips/php-vips/zipball/a54c1cceea581b592a199edd61a7c06f44a24c08` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/mongodb/mongo-php-library/zipball/3bbe7ba9578724c7e1f47fcd17c881c0995baaad` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/Kcp9Lc /usr/bin/composer update --prefer-stable --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/Kcp9Lc /usr/bin/composer update --prefer-stable --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/php-imagine/Imagine/zipball/80ab21434890dee9ba54969d31c51ac8d4d551e0` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/lryxyr /usr/bin/composer install --no-dev --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/rindow/rindow-math-matrix/zipball/6d6622b4495d6325e4065430d143d6f4c3b5f0c4` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/rindow/rindow-matlib-ffi/zipball/b5eddacc8a0fbc640cfdb90d6a40414ba6c76529` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/rindow/rindow-openblas-ffi/zipball/efcddb9b24ac9d2d2f3a7d1092fbd5f66dccbb5e` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/rokka-io/imagine-vips/zipball/6c86dc4a988fbd51081973abd29cbc38989e2e94` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/Kcp9Lc /usr/bin/composer update --prefer-stable --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/http-client/zipball/57e4fb86314015a695a750ace358d07a7e37b8a9` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/Kcp9Lc /usr/bin/composer update --prefer-stable --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/lryxyr /usr/bin/composer install --no-dev --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/polyfill-php85/zipball/6fedf31ce4e3648f4ff5ca58bfd53127d38f05fd` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/Kcp9Lc /usr/bin/composer update --prefer-stable --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > - `https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991` > - Triggering command: `/usr/bin/php8.3 -n -c /tmp/kJITtg /usr/bin/composer install --no-interaction --ignore-platform-req=ext-mongodb ` (http block) > > If you need me to access, download, or install something from one of these locations, you can either: > > - Configure [Actions setup steps](https://gh.io/copilot/actions-setup-steps) to set up my environment, which run before the firewall is enabled > - Add the appropriate URLs or hosts to my [firewall allow list](https://gh.io/copilot/firewall-config) > > </details> <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: chr-hertel <[email protected]>
1 parent c6e32b6 commit 5d66c61

File tree

5 files changed

+240
-2
lines changed

5 files changed

+240
-2
lines changed

src/platform/src/Bridge/Azure/OpenAI/WhisperModelClient.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\AI\Platform\Bridge\Azure\OpenAI;
1313

1414
use Symfony\AI\Platform\Bridge\OpenAI\Whisper;
15+
use Symfony\AI\Platform\Bridge\OpenAI\Whisper\Task;
1516
use Symfony\AI\Platform\Model;
1617
use Symfony\AI\Platform\ModelClientInterface;
1718
use Symfony\Component\HttpClient\EventSourceHttpClient;
@@ -48,7 +49,11 @@ public function supports(Model $model): bool
4849

4950
public function request(Model $model, array|string $payload, array $options = []): ResponseInterface
5051
{
51-
$url = \sprintf('https://%s/openai/deployments/%s/audio/translations', $this->baseUrl, $this->deployment);
52+
$task = $options['task'] ?? Task::TRANSCRIPTION;
53+
$endpoint = Task::TRANSCRIPTION === $task ? 'transcriptions' : 'translations';
54+
$url = \sprintf('https://%s/openai/deployments/%s/audio/%s', $this->baseUrl, $this->deployment, $endpoint);
55+
56+
unset($options['task']);
5257

5358
return $this->httpClient->request('POST', $url, [
5459
'headers' => [

src/platform/src/Bridge/OpenAI/Whisper/ModelClient.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ public function supports(Model $model): bool
3838

3939
public function request(Model $model, array|string $payload, array $options = []): ResponseInterface
4040
{
41-
return $this->httpClient->request('POST', 'https://api.openai.com/v1/audio/transcriptions', [
41+
$task = $options['task'] ?? Task::TRANSCRIPTION;
42+
$endpoint = Task::TRANSCRIPTION === $task ? 'transcriptions' : 'translations';
43+
unset($options['task']);
44+
45+
return $this->httpClient->request('POST', \sprintf('https://api.openai.com/v1/audio/%s', $endpoint), [
4246
'auth_bearer' => $this->apiKey,
4347
'headers' => ['Content-Type' => 'multipart/form-data'],
4448
'body' => array_merge($options, $payload, ['model' => $model->getName()]),
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Bridge\OpenAI\Whisper;
13+
14+
/**
15+
* @author Christopher Hertel <[email protected]>
16+
*/
17+
interface Task
18+
{
19+
public const TRANSCRIPTION = 'transcription';
20+
public const TRANSLATION = 'translation';
21+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Tests\Bridge\Azure\OpenAI;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\Attributes\Test;
17+
use PHPUnit\Framework\TestCase;
18+
use Symfony\AI\Platform\Bridge\Azure\OpenAI\WhisperModelClient;
19+
use Symfony\AI\Platform\Bridge\OpenAI\Whisper;
20+
use Symfony\AI\Platform\Bridge\OpenAI\Whisper\Task;
21+
use Symfony\Component\HttpClient\MockHttpClient;
22+
use Symfony\Component\HttpClient\Response\MockResponse;
23+
24+
#[CoversClass(WhisperModelClient::class)]
25+
#[Small]
26+
final class WhisperModelClientTest extends TestCase
27+
{
28+
#[Test]
29+
public function itSupportsWhisperModel(): void
30+
{
31+
$client = new WhisperModelClient(
32+
new MockHttpClient(),
33+
'test.openai.azure.com',
34+
'whisper-deployment',
35+
'2023-12-01-preview',
36+
'test-key'
37+
);
38+
$model = new Whisper();
39+
40+
self::assertTrue($client->supports($model));
41+
}
42+
43+
#[Test]
44+
public function itUsesTranscriptionEndpointByDefault(): void
45+
{
46+
$httpClient = new MockHttpClient([
47+
function ($method, $url): MockResponse {
48+
self::assertSame('POST', $method);
49+
self::assertSame('https://test.azure.com/openai/deployments/whspr/audio/transcriptions?api-version=2023-12', $url);
50+
51+
return new MockResponse('{"text": "Hello World"}');
52+
},
53+
]);
54+
55+
$client = new WhisperModelClient($httpClient, 'test.azure.com', 'whspr', '2023-12', 'test-key');
56+
$model = new Whisper();
57+
$payload = ['file' => 'audio-data'];
58+
59+
$client->request($model, $payload);
60+
61+
self::assertSame(1, $httpClient->getRequestsCount());
62+
}
63+
64+
#[Test]
65+
public function itUsesTranscriptionEndpointWhenTaskIsSpecified(): void
66+
{
67+
$httpClient = new MockHttpClient([
68+
function ($method, $url): MockResponse {
69+
self::assertSame('POST', $method);
70+
self::assertSame('https://test.azure.com/openai/deployments/whspr/audio/transcriptions?api-version=2023-12', $url);
71+
72+
return new MockResponse('{"text": "Hello World"}');
73+
},
74+
]);
75+
76+
$client = new WhisperModelClient($httpClient, 'test.azure.com', 'whspr', '2023-12', 'test-key');
77+
$model = new Whisper();
78+
$payload = ['file' => 'audio-data'];
79+
$options = ['task' => Task::TRANSCRIPTION];
80+
81+
$client->request($model, $payload, $options);
82+
83+
self::assertSame(1, $httpClient->getRequestsCount());
84+
}
85+
86+
#[Test]
87+
public function itUsesTranslationEndpointWhenTaskIsSpecified(): void
88+
{
89+
$httpClient = new MockHttpClient([
90+
function ($method, $url): MockResponse {
91+
self::assertSame('POST', $method);
92+
self::assertSame('https://test.azure.com/openai/deployments/whspr/audio/translations?api-version=2023-12', $url);
93+
94+
return new MockResponse('{"text": "Hello World"}');
95+
},
96+
]);
97+
98+
$client = new WhisperModelClient($httpClient, 'test.azure.com', 'whspr', '2023-12', 'test-key');
99+
$model = new Whisper();
100+
$payload = ['file' => 'audio-data'];
101+
$options = ['task' => Task::TRANSLATION];
102+
103+
$client->request($model, $payload, $options);
104+
105+
self::assertSame(1, $httpClient->getRequestsCount());
106+
}
107+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Tests\Bridge\OpenAI\Whisper;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\Attributes\Test;
17+
use PHPUnit\Framework\TestCase;
18+
use Symfony\AI\Platform\Bridge\OpenAI\Whisper;
19+
use Symfony\AI\Platform\Bridge\OpenAI\Whisper\ModelClient;
20+
use Symfony\AI\Platform\Bridge\OpenAI\Whisper\Task;
21+
use Symfony\Component\HttpClient\MockHttpClient;
22+
use Symfony\Component\HttpClient\Response\MockResponse;
23+
24+
#[CoversClass(ModelClient::class)]
25+
#[Small]
26+
final class ModelClientTest extends TestCase
27+
{
28+
#[Test]
29+
public function itSupportsWhisperModel(): void
30+
{
31+
$client = new ModelClient(new MockHttpClient(), 'test-key');
32+
$model = new Whisper();
33+
34+
self::assertTrue($client->supports($model));
35+
}
36+
37+
#[Test]
38+
public function itUsesTranscriptionEndpointByDefault(): void
39+
{
40+
$httpClient = new MockHttpClient([
41+
function ($method, $url): MockResponse {
42+
self::assertSame('POST', $method);
43+
self::assertSame('https://api.openai.com/v1/audio/transcriptions', $url);
44+
45+
return new MockResponse('{"text": "Hello World"}');
46+
},
47+
]);
48+
49+
$client = new ModelClient($httpClient, 'test-key');
50+
$model = new Whisper();
51+
$payload = ['file' => 'audio-data'];
52+
53+
$client->request($model, $payload);
54+
55+
self::assertSame(1, $httpClient->getRequestsCount());
56+
}
57+
58+
#[Test]
59+
public function itUsesTranscriptionEndpointWhenTaskIsSpecified(): void
60+
{
61+
$httpClient = new MockHttpClient([
62+
function ($method, $url): MockResponse {
63+
self::assertSame('POST', $method);
64+
self::assertSame('https://api.openai.com/v1/audio/transcriptions', $url);
65+
66+
return new MockResponse('{"text": "Hello World"}');
67+
},
68+
]);
69+
70+
$client = new ModelClient($httpClient, 'test-key');
71+
$model = new Whisper();
72+
$payload = ['file' => 'audio-data'];
73+
$options = ['task' => Task::TRANSCRIPTION];
74+
75+
$client->request($model, $payload, $options);
76+
77+
self::assertSame(1, $httpClient->getRequestsCount());
78+
}
79+
80+
#[Test]
81+
public function itUsesTranslationEndpointWhenTaskIsSpecified(): void
82+
{
83+
$httpClient = new MockHttpClient([
84+
function ($method, $url): MockResponse {
85+
self::assertSame('POST', $method);
86+
self::assertSame('https://api.openai.com/v1/audio/translations', $url);
87+
88+
return new MockResponse('{"text": "Hello World"}');
89+
},
90+
]);
91+
92+
$client = new ModelClient($httpClient, 'test-key');
93+
$model = new Whisper();
94+
$payload = ['file' => 'audio-data'];
95+
$options = ['task' => Task::TRANSLATION];
96+
97+
$client->request($model, $payload, $options);
98+
99+
self::assertSame(1, $httpClient->getRequestsCount());
100+
}
101+
}

0 commit comments

Comments
 (0)