Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

Commit 97982eb

Browse files
Copilotchr-hertel
andauthored
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. ## Problem 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. ## Solution 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]); ``` ## Changes Made 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 ## Breaking Change ⚠️ **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); ``` ## Backward Compatibility - **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 fb0570c commit 97982eb

File tree

5 files changed

+219
-2
lines changed

5 files changed

+219
-2
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpLlm\LlmChain\Platform\Bridge\Azure\OpenAI;
66

77
use PhpLlm\LlmChain\Platform\Bridge\OpenAI\Whisper;
8+
use PhpLlm\LlmChain\Platform\Bridge\OpenAI\Whisper\Task;
89
use PhpLlm\LlmChain\Platform\Model;
910
use PhpLlm\LlmChain\Platform\ModelClientInterface;
1011
use Symfony\Component\HttpClient\EventSourceHttpClient;
@@ -41,7 +42,11 @@ public function supports(Model $model): bool
4142

4243
public function request(Model $model, array|string $payload, array $options = []): ResponseInterface
4344
{
44-
$url = \sprintf('https://%s/openai/deployments/%s/audio/translations', $this->baseUrl, $this->deployment);
45+
$task = $options['task'] ?? Task::TRANSCRIPTION;
46+
$endpoint = Task::TRANSCRIPTION === $task ? 'transcriptions' : 'translations';
47+
$url = \sprintf('https://%s/openai/deployments/%s/audio/%s', $this->baseUrl, $this->deployment, $endpoint);
48+
49+
unset($options['task']);
4550

4651
return $this->httpClient->request('POST', $url, [
4752
'headers' => [

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

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

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

0 commit comments

Comments
 (0)