A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 14, 05:30 UTC
[CI] Speed up Whisper tests by reusing server (#22859)
Signed-off-by: mgoin <mgoin64@gmail.com>
Michael Goin committed
Aug 15, 2025 at 16:56 UTC
8a87cd27d94f03068b9cbc85058636fc16222e24
2 files changed
+263
-291
tests/entrypoints/openai/test_transcription_validation.py
+141
-179
@@ -4,19 +4,20 @@
4
# imports for guided decoding tests
5
import io
6
import json
7
-from unittest.mock import patch
7
8
import librosa
9
import numpy as np
10
import openai
11
import pytest
12
+import pytest_asyncio
13
import soundfile as sf
14
-from openai._base_client import AsyncAPIClient
14
15
from vllm.assets.audio import AudioAsset
16
17
from ...utils import RemoteOpenAIServer
18
19
+MODEL_NAME = "openai/whisper-large-v3-turbo"
20
+SERVER_ARGS = ["--enforce-eager"]
21
MISTRAL_FORMAT_ARGS = [
22
"--tokenizer_mode", "mistral", "--config_format", "mistral",
23
"--load_format", "mistral"
@@ -37,6 +38,18 @@ def winning_call():
38
yield f
39
40
41
+@pytest.fixture(scope="module")
42
+def server():
43
+ with RemoteOpenAIServer(MODEL_NAME, SERVER_ARGS) as remote_server:
44
+ yield remote_server
45
+
46
+
47
+@pytest_asyncio.fixture
48
+async def client(server):
49
+ async with server.get_async_client() as async_client:
50
+ yield async_client
51
+
52
+
53
@pytest.mark.asyncio
54
@pytest.mark.parametrize(
55
"model_name",
@@ -61,25 +74,33 @@ async def test_basic_audio(mary_had_lamb, model_name):
74
75
76
@pytest.mark.asyncio
64
-async def test_bad_requests(mary_had_lamb):
65
- model_name = "openai/whisper-small"
66
- server_args = ["--enforce-eager"]
67
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
77
+async def test_non_asr_model(winning_call):
78
+ # text to text model
79
+ model_name = "JackFram/llama-68m"
80
+ with RemoteOpenAIServer(model_name, SERVER_ARGS) as remote_server:
81
client = remote_server.get_async_client()
69
-
70
- # invalid language
71
- with pytest.raises(openai.BadRequestError):
72
- await client.audio.transcriptions.create(model=model_name,
73
- file=mary_had_lamb,
74
- language="hh",
75
- temperature=0.0)
82
+ res = await client.audio.transcriptions.create(model=model_name,
83
+ file=winning_call,
84
+ language="en",
85
+ temperature=0.0)
86
+ err = res.error
87
+ assert err["code"] == 400 and not res.text
88
+ assert err[
89
+ "message"] == "The model does not support Transcriptions API"
90
91
92
@pytest.mark.asyncio
79
-@pytest.mark.parametrize("model_name", ["openai/whisper-large-v3-turbo"])
80
-async def test_long_audio_request(mary_had_lamb, model_name):
81
- server_args = ["--enforce-eager"]
93
+async def test_bad_requests(mary_had_lamb, client):
94
+ # invalid language
95
+ with pytest.raises(openai.BadRequestError):
96
+ await client.audio.transcriptions.create(model=MODEL_NAME,
97
+ file=mary_had_lamb,
98
+ language="hh",
99
+ temperature=0.0)
100
+
101
102
+@pytest.mark.asyncio
103
+async def test_long_audio_request(mary_had_lamb, client):
104
mary_had_lamb.seek(0)
105
audio, sr = librosa.load(mary_had_lamb)
106
# Add small silence after each audio for repeatability in the split process
@@ -89,188 +110,129 @@ async def test_long_audio_request(mary_had_lamb, model_name):
110
buffer = io.BytesIO()
111
sf.write(buffer, repeated_audio, sr, format='WAV')
112
buffer.seek(0)
92
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
93
- client = remote_server.get_async_client()
94
- transcription = await client.audio.transcriptions.create(
95
- model=model_name,
96
- file=buffer,
97
- language="en",
98
- response_format="text",
99
- temperature=0.0)
100
- out = json.loads(transcription)['text']
101
- counts = out.count("Mary had a little lamb")
102
- assert counts == 10, counts
103
-
104
-
105
-@pytest.mark.asyncio
106
-async def test_non_asr_model(winning_call):
107
- # text to text model
108
- model_name = "JackFram/llama-68m"
109
- server_args = ["--enforce-eager"]
110
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
111
- client = remote_server.get_async_client()
112
- res = await client.audio.transcriptions.create(model=model_name,
113
- file=winning_call,
114
- language="en",
115
- temperature=0.0)
116
- err = res.error
117
- assert err["code"] == 400 and not res.text
118
- assert err[
119
- "message"] == "The model does not support Transcriptions API"
113
+ transcription = await client.audio.transcriptions.create(
114
+ model=MODEL_NAME,
115
+ file=buffer,
116
+ language="en",
117
+ response_format="text",
118
+ temperature=0.0)
119
+ out = json.loads(transcription)['text']
120
+ counts = out.count("Mary had a little lamb")
121
+ assert counts == 10, counts
122
123
124
@pytest.mark.asyncio
123
-async def test_completion_endpoints():
125
+async def test_completion_endpoints(client):
126
# text to text model
125
- model_name = "openai/whisper-small"
126
- server_args = ["--enforce-eager"]
127
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
128
- client = remote_server.get_async_client()
129
- res = await client.chat.completions.create(
130
- model=model_name,
131
- messages=[{
132
- "role": "system",
133
- "content": "You are a helpful assistant."
134
- }])
135
- err = res.error
136
- assert err["code"] == 400
137
- assert err[
138
- "message"] == "The model does not support Chat Completions API"
139
-
140
- res = await client.completions.create(model=model_name, prompt="Hello")
141
- err = res.error
142
- assert err["code"] == 400
143
- assert err["message"] == "The model does not support Completions API"
127
+ res = await client.chat.completions.create(
128
+ model=MODEL_NAME,
129
+ messages=[{
130
+ "role": "system",
131
+ "content": "You are a helpful assistant."
132
+ }])
133
+ err = res.error
134
+ assert err["code"] == 400
135
+ assert err["message"] == "The model does not support Chat Completions API"
136
+
137
+ res = await client.completions.create(model=MODEL_NAME, prompt="Hello")
138
+ err = res.error
139
+ assert err["code"] == 400
140
+ assert err["message"] == "The model does not support Completions API"
141
142
143
@pytest.mark.asyncio
147
-async def test_streaming_response(winning_call):
148
- model_name = "openai/whisper-small"
149
- server_args = ["--enforce-eager"]
144
+async def test_streaming_response(winning_call, client):
145
transcription = ""
151
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
152
- client = remote_server.get_async_client()
153
- res_no_stream = await client.audio.transcriptions.create(
154
- model=model_name,
155
- file=winning_call,
156
- response_format="json",
157
- language="en",
158
- temperature=0.0)
159
- # Unfortunately this only works when the openai client is patched
160
- # to use streaming mode, not exposed in the transcription api.
161
- original_post = AsyncAPIClient.post
162
-
163
- async def post_with_stream(*args, **kwargs):
164
- kwargs['stream'] = True
165
- return await original_post(*args, **kwargs)
166
-
167
- with patch.object(AsyncAPIClient, "post", new=post_with_stream):
168
- client = remote_server.get_async_client()
169
- res = await client.audio.transcriptions.create(
170
- model=model_name,
171
- file=winning_call,
172
- language="en",
173
- temperature=0.0,
174
- extra_body=dict(stream=True),
175
- timeout=30)
176
- # Reconstruct from chunks and validate
177
- async for chunk in res:
178
- # just a chunk
179
- text = chunk.choices[0]['delta']['content']
180
- transcription += text
181
-
182
- assert transcription == res_no_stream.text
146
+ res_no_stream = await client.audio.transcriptions.create(
147
+ model=MODEL_NAME,
148
+ file=winning_call,
149
+ response_format="json",
150
+ language="en",
151
+ temperature=0.0)
152
+ res = await client.audio.transcriptions.create(model=MODEL_NAME,
153
+ file=winning_call,
154
+ language="en",
155
+ temperature=0.0,
156
+ stream=True,
157
+ timeout=30)
158
+ # Reconstruct from chunks and validate
159
+ async for chunk in res:
160
+ text = chunk.choices[0]['delta']['content']
161
+ transcription += text
162
+
163
+ assert transcription == res_no_stream.text
164
165
166
@pytest.mark.asyncio
186
-async def test_stream_options(winning_call):
187
- model_name = "openai/whisper-small"
188
- server_args = ["--enforce-eager"]
189
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
190
- original_post = AsyncAPIClient.post
191
-
192
- async def post_with_stream(*args, **kwargs):
193
- kwargs['stream'] = True
194
- return await original_post(*args, **kwargs)
195
-
196
- with patch.object(AsyncAPIClient, "post", new=post_with_stream):
197
- client = remote_server.get_async_client()
198
- res = await client.audio.transcriptions.create(
199
- model=model_name,
200
- file=winning_call,
201
- language="en",
202
- temperature=0.0,
203
- extra_body=dict(stream=True,
204
- stream_include_usage=True,
205
- stream_continuous_usage_stats=True),
206
- timeout=30)
207
- final = False
208
- continuous = True
209
- async for chunk in res:
210
- if not len(chunk.choices):
211
- # final usage sent
212
- final = True
213
- else:
214
- continuous = continuous and hasattr(chunk, 'usage')
215
- assert final and continuous
167
+async def test_stream_options(winning_call, client):
168
+ res = await client.audio.transcriptions.create(
169
+ model=MODEL_NAME,
170
+ file=winning_call,
171
+ language="en",
172
+ temperature=0.0,
173
+ stream=True,
174
+ extra_body=dict(stream_include_usage=True,
175
+ stream_continuous_usage_stats=True),
176
+ timeout=30)
177
+ final = False
178
+ continuous = True
179
+ async for chunk in res:
180
+ if not len(chunk.choices):
181
+ # final usage sent
182
+ final = True
183
+ else:
184
+ continuous = continuous and hasattr(chunk, 'usage')
185
+ assert final and continuous
186
187
188
@pytest.mark.asyncio
219
-async def test_sampling_params(mary_had_lamb):
189
+async def test_sampling_params(mary_had_lamb, client):
190
"""
191
Compare sampling with params and greedy sampling to assert results
192
are different when extreme sampling parameters values are picked.
193
"""
224
- model_name = "openai/whisper-small"
225
- server_args = ["--enforce-eager"]
226
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
227
- client = remote_server.get_async_client()
228
- transcription = await client.audio.transcriptions.create(
229
- model=model_name,
230
- file=mary_had_lamb,
231
- language="en",
232
- temperature=0.8,
233
- extra_body=dict(seed=42,
234
- repetition_penalty=1.9,
235
- top_k=12,
236
- top_p=0.4,
237
- min_p=0.5,
238
- frequency_penalty=1.8,
239
- presence_penalty=2.0))
240
-
241
- greedy_transcription = await client.audio.transcriptions.create(
242
- model=model_name,
243
- file=mary_had_lamb,
244
- language="en",
245
- temperature=0.0,
246
- extra_body=dict(seed=42))
247
-
248
- assert greedy_transcription.text != transcription.text
194
+ transcription = await client.audio.transcriptions.create(
195
+ model=MODEL_NAME,
196
+ file=mary_had_lamb,
197
+ language="en",
198
+ temperature=0.8,
199
+ extra_body=dict(seed=42,
200
+ repetition_penalty=1.9,
201
+ top_k=12,
202
+ top_p=0.4,
203
+ min_p=0.5,
204
+ frequency_penalty=1.8,
205
+ presence_penalty=2.0))
206
+
207
+ greedy_transcription = await client.audio.transcriptions.create(
208
+ model=MODEL_NAME,
209
+ file=mary_had_lamb,
210
+ language="en",
211
+ temperature=0.0,
212
+ extra_body=dict(seed=42))
213
+
214
+ assert greedy_transcription.text != transcription.text
215
216
217
@pytest.mark.asyncio
252
-async def test_audio_prompt(mary_had_lamb):
253
- model_name = "openai/whisper-large-v3-turbo"
254
- server_args = ["--enforce-eager"]
218
+async def test_audio_prompt(mary_had_lamb, client):
219
prompt = "This is a speech, recorded in a phonograph."
256
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
257
- #Prompts should not omit the part of original prompt while transcribing.
258
- prefix = "The first words I spoke in the original phonograph"
259
- client = remote_server.get_async_client()
260
- transcription = await client.audio.transcriptions.create(
261
- model=model_name,
262
- file=mary_had_lamb,
263
- language="en",
264
- response_format="text",
265
- temperature=0.0)
266
- out = json.loads(transcription)['text']
267
- assert prefix in out
268
- transcription_wprompt = await client.audio.transcriptions.create(
269
- model=model_name,
270
- file=mary_had_lamb,
271
- language="en",
272
- response_format="text",
273
- prompt=prompt,
274
- temperature=0.0)
275
- out_prompt = json.loads(transcription_wprompt)['text']
276
- assert prefix in out_prompt
220
+ #Prompts should not omit the part of original prompt while transcribing.
221
+ prefix = "The first words I spoke in the original phonograph"
222
+ transcription = await client.audio.transcriptions.create(
223
+ model=MODEL_NAME,
224
+ file=mary_had_lamb,
225
+ language="en",
226
+ response_format="text",
227
+ temperature=0.0)
228
+ out = json.loads(transcription)['text']
229
+ assert prefix in out
230
+ transcription_wprompt = await client.audio.transcriptions.create(
231
+ model=MODEL_NAME,
232
+ file=mary_had_lamb,
233
+ language="en",
234
+ response_format="text",
235
+ prompt=prompt,
236
+ temperature=0.0)
237
+ out_prompt = json.loads(transcription_wprompt)['text']
238
+ assert prefix in out_prompt
tests/entrypoints/openai/test_translation_validation.py
+122
-112
@@ -4,18 +4,21 @@
4
import io
5
# imports for guided decoding tests
6
import json
7
-from unittest.mock import patch
7
8
+import httpx
9
import librosa
10
import numpy as np
11
import pytest
12
+import pytest_asyncio
13
import soundfile as sf
13
-from openai._base_client import AsyncAPIClient
14
15
from vllm.assets.audio import AudioAsset
16
17
from ...utils import RemoteOpenAIServer
18
19
+MODEL_NAME = "openai/whisper-small"
20
+SERVER_ARGS = ["--enforce-eager"]
21
+
22
23
@pytest.fixture
24
def foscolo():
@@ -25,50 +28,23 @@ def foscolo():
28
yield f
29
30
28
-# NOTE: (NickLucche) the large-v3-turbo model was not trained on translation!
29
-@pytest.mark.asyncio
30
-async def test_basic_audio(foscolo):
31
- model_name = "openai/whisper-small"
32
- server_args = ["--enforce-eager"]
33
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
34
- client = remote_server.get_async_client()
35
- translation = await client.audio.translations.create(
36
- model=model_name,
37
- file=foscolo,
38
- response_format="text",
39
- # TODO remove once language detection is implemented
40
- extra_body=dict(language="it"),
41
- temperature=0.0)
42
- out = json.loads(translation)['text'].strip().lower()
43
- assert "greek sea" in out
31
+@pytest.fixture(scope="module")
32
+def server():
33
+ with RemoteOpenAIServer(MODEL_NAME, SERVER_ARGS) as remote_server:
34
+ yield remote_server
35
36
46
-@pytest.mark.asyncio
47
-async def test_audio_prompt(foscolo):
48
- model_name = "openai/whisper-small"
49
- server_args = ["--enforce-eager"]
50
- # Condition whisper on starting text
51
- prompt = "Nor have I ever"
52
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
53
- client = remote_server.get_async_client()
54
- transcription = await client.audio.translations.create(
55
- model=model_name,
56
- file=foscolo,
57
- prompt=prompt,
58
- extra_body=dict(language="it"),
59
- response_format="text",
60
- temperature=0.0)
61
- out = json.loads(transcription)['text']
62
- assert "Nor will I ever touch the sacred" not in out
63
- assert prompt not in out
37
+@pytest_asyncio.fixture
38
+async def client(server):
39
+ async with server.get_async_client() as async_client:
40
+ yield async_client
41
42
43
@pytest.mark.asyncio
44
async def test_non_asr_model(foscolo):
45
# text to text model
46
model_name = "JackFram/llama-68m"
70
- server_args = ["--enforce-eager"]
71
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
47
+ with RemoteOpenAIServer(model_name, SERVER_ARGS) as remote_server:
48
client = remote_server.get_async_client()
49
res = await client.audio.translations.create(model=model_name,
50
file=foscolo,
@@ -78,81 +54,117 @@ async def test_non_asr_model(foscolo):
54
assert err["message"] == "The model does not support Translations API"
55
56
57
+# NOTE: (NickLucche) the large-v3-turbo model was not trained on translation!
58
+@pytest.mark.asyncio
59
+async def test_basic_audio(foscolo, client):
60
+ translation = await client.audio.translations.create(
61
+ model=MODEL_NAME,
62
+ file=foscolo,
63
+ response_format="text",
64
+ # TODO remove once language detection is implemented
65
+ extra_body=dict(language="it"),
66
+ temperature=0.0)
67
+ out = json.loads(translation)['text'].strip().lower()
68
+ assert "greek sea" in out
69
+
70
+
71
+@pytest.mark.asyncio
72
+async def test_audio_prompt(foscolo, client):
73
+ # Condition whisper on starting text
74
+ prompt = "Nor have I ever"
75
+ transcription = await client.audio.translations.create(
76
+ model=MODEL_NAME,
77
+ file=foscolo,
78
+ prompt=prompt,
79
+ extra_body=dict(language="it"),
80
+ response_format="text",
81
+ temperature=0.0)
82
+ out = json.loads(transcription)['text']
83
+ assert "Nor will I ever touch the sacred" not in out
84
+ assert prompt not in out
85
+
86
+
87
@pytest.mark.asyncio
82
-async def test_streaming_response(foscolo):
83
- model_name = "openai/whisper-small"
84
- server_args = ["--enforce-eager"]
88
+async def test_streaming_response(foscolo, client, server):
89
translation = ""
86
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
87
- client = remote_server.get_async_client()
88
- res_no_stream = await client.audio.translations.create(
89
- model=model_name,
90
- file=foscolo,
91
- response_format="json",
92
- extra_body=dict(language="it"),
93
- temperature=0.0)
94
- # Unfortunately this only works when the openai client is patched
95
- # to use streaming mode, not exposed in the translation api.
96
- original_post = AsyncAPIClient.post
97
-
98
- async def post_with_stream(*args, **kwargs):
99
- kwargs['stream'] = True
100
- return await original_post(*args, **kwargs)
101
-
102
- with patch.object(AsyncAPIClient, "post", new=post_with_stream):
103
- client = remote_server.get_async_client()
104
- res = await client.audio.translations.create(model=model_name,
105
- file=foscolo,
106
- temperature=0.0,
107
- extra_body=dict(
108
- stream=True,
109
- language="it"))
110
- # Reconstruct from chunks and validate
111
- async for chunk in res:
112
- # just a chunk
113
- text = chunk.choices[0]['delta']['content']
114
- translation += text
115
-
116
- assert translation == res_no_stream.text
90
+ res_no_stream = await client.audio.translations.create(
91
+ model=MODEL_NAME,
92
+ file=foscolo,
93
+ response_format="json",
94
+ extra_body=dict(language="it"),
95
+ temperature=0.0)
96
+ # Stream via HTTPX since OpenAI translation client doesn't expose streaming
97
+ url = server.url_for("v1/audio/translations")
98
+ headers = {"Authorization": f"Bearer {server.DUMMY_API_KEY}"}
99
+ data = {
100
+ "model": MODEL_NAME,
101
+ "language": "it",
102
+ "stream": True,
103
+ "temperature": 0.0,
104
+ }
105
+ foscolo.seek(0)
106
+ async with httpx.AsyncClient() as http_client:
107
+ files = {"file": foscolo}
108
+ async with http_client.stream("POST",
109
+ url,
110
+ headers=headers,
111
+ data=data,
112
+ files=files) as response:
113
+ async for line in response.aiter_lines():
114
+ if not line:
115
+ continue
116
+ if line.startswith("data: "):
117
+ line = line[len("data: "):]
118
+ if line.strip() == "[DONE]":
119
+ break
120
+ chunk = json.loads(line)
121
+ text = chunk["choices"][0].get("delta", {}).get("content")
122
+ translation += text or ""
123
+
124
+ assert translation == res_no_stream.text
125
126
127
@pytest.mark.asyncio
120
-async def test_stream_options(foscolo):
121
- model_name = "openai/whisper-small"
122
- server_args = ["--enforce-eager"]
123
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
124
- original_post = AsyncAPIClient.post
125
-
126
- async def post_with_stream(*args, **kwargs):
127
- kwargs['stream'] = True
128
- return await original_post(*args, **kwargs)
129
-
130
- with patch.object(AsyncAPIClient, "post", new=post_with_stream):
131
- client = remote_server.get_async_client()
132
- res = await client.audio.translations.create(
133
- model=model_name,
134
- file=foscolo,
135
- temperature=0.0,
136
- extra_body=dict(language="it",
137
- stream=True,
138
- stream_include_usage=True,
139
- stream_continuous_usage_stats=True))
140
- final = False
141
- continuous = True
142
- async for chunk in res:
143
- if not len(chunk.choices):
128
+async def test_stream_options(foscolo, client, server):
129
+ url = server.url_for("v1/audio/translations")
130
+ headers = {"Authorization": f"Bearer {server.DUMMY_API_KEY}"}
131
+ data = {
132
+ "model": MODEL_NAME,
133
+ "language": "it",
134
+ "stream": True,
135
+ "stream_include_usage": True,
136
+ "stream_continuous_usage_stats": True,
137
+ "temperature": 0.0,
138
+ }
139
+ foscolo.seek(0)
140
+ final = False
141
+ continuous = True
142
+ async with httpx.AsyncClient() as http_client:
143
+ files = {"file": foscolo}
144
+ async with http_client.stream("POST",
145
+ url,
146
+ headers=headers,
147
+ data=data,
148
+ files=files) as response:
149
+ async for line in response.aiter_lines():
150
+ if not line:
151
+ continue
152
+ if line.startswith("data: "):
153
+ line = line[len("data: "):]
154
+ if line.strip() == "[DONE]":
155
+ break
156
+ chunk = json.loads(line)
157
+ choices = chunk.get("choices", [])
158
+ if not choices:
159
# final usage sent
160
final = True
161
else:
147
- continuous = continuous and hasattr(chunk, 'usage')
148
- assert final and continuous
162
+ continuous = continuous and ("usage" in chunk)
163
+ assert final and continuous
164
165
166
@pytest.mark.asyncio
152
-async def test_long_audio_request(foscolo):
153
- model_name = "openai/whisper-small"
154
- server_args = ["--enforce-eager"]
155
-
167
+async def test_long_audio_request(foscolo, client):
168
foscolo.seek(0)
169
audio, sr = librosa.load(foscolo)
170
repeated_audio = np.tile(audio, 2)
@@ -160,13 +172,11 @@ async def test_long_audio_request(foscolo):
172
buffer = io.BytesIO()
173
sf.write(buffer, repeated_audio, sr, format='WAV')
174
buffer.seek(0)
163
- with RemoteOpenAIServer(model_name, server_args) as remote_server:
164
- client = remote_server.get_async_client()
165
- translation = await client.audio.translations.create(
166
- model=model_name,
167
- file=buffer,
168
- extra_body=dict(language="it"),
169
- response_format="text",
170
- temperature=0.0)
171
- out = json.loads(translation)['text'].strip().lower()
172
- assert out.count("greek sea") == 2
175
+ translation = await client.audio.translations.create(
176
+ model=MODEL_NAME,
177
+ file=buffer,
178
+ extra_body=dict(language="it"),
179
+ response_format="text",
180
+ temperature=0.0)
181
+ out = json.loads(translation)['text'].strip().lower()
182
+ assert out.count("greek sea") == 2