Skip to content

Commit 442e7fa

Browse files
authored
Add follow_redirects parameter to OpenAIHTTPBackend (#148)
This PR adds the ability to set `follow_redirects` on the httpx client used to make requests to the OpenAI backend, allowing it to follow the redirect URL in 3xx responses. Following a discussion with @markurtz, this value defaults to true, but may be overwritten through environment variables or the `OpenAIHTTPBackend` initializer.
1 parent 018e200 commit 442e7fa

File tree

5 files changed

+27
-3
lines changed

5 files changed

+27
-3
lines changed

src/guidellm/backend/openai.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class OpenAIHTTPBackend(Backend):
4949
If not provided, the default timeout provided from settings is used.
5050
:param http2: If True, uses HTTP/2 for requests to the OpenAI server.
5151
Defaults to True.
52+
:param follow_redirects: If True, the HTTP client will follow redirect responses.
53+
If not provided, the default value from settings is used.
5254
:param max_output_tokens: The maximum number of tokens to request for completions.
5355
If not provided, the default maximum tokens provided from settings is used.
5456
"""
@@ -62,6 +64,7 @@ def __init__(
6264
project: Optional[str] = None,
6365
timeout: Optional[float] = None,
6466
http2: Optional[bool] = True,
67+
follow_redirects: Optional[bool] = None,
6568
max_output_tokens: Optional[int] = None,
6669
):
6770
super().__init__(type_="openai_http")
@@ -88,6 +91,11 @@ def __init__(
8891
self.project = project or settings.openai.project
8992
self.timeout = timeout if timeout is not None else settings.request_timeout
9093
self.http2 = http2 if http2 is not None else settings.request_http2
94+
self.follow_redirects = (
95+
follow_redirects
96+
if follow_redirects is not None
97+
else settings.request_follow_redirects
98+
)
9199
self.max_output_tokens = (
92100
max_output_tokens
93101
if max_output_tokens is not None
@@ -120,6 +128,7 @@ def info(self) -> dict[str, Any]:
120128
"max_output_tokens": self.max_output_tokens,
121129
"timeout": self.timeout,
122130
"http2": self.http2,
131+
"follow_redirects": self.follow_redirects,
123132
"authorization": bool(self.authorization),
124133
"organization": self.organization,
125134
"project": self.project,
@@ -319,7 +328,11 @@ def _get_async_client(self) -> httpx.AsyncClient:
319328
:return: The async HTTP client.
320329
"""
321330
if self._async_client is None:
322-
client = httpx.AsyncClient(http2=self.http2, timeout=self.timeout)
331+
client = httpx.AsyncClient(
332+
http2=self.http2,
333+
timeout=self.timeout,
334+
follow_redirects=self.follow_redirects,
335+
)
323336
self._async_client = client
324337
else:
325338
client = self._async_client
@@ -449,12 +462,13 @@ async def _iterative_completions_request(
449462
raise ValueError(f"Unsupported type: {type_}")
450463

451464
logger.info(
452-
"{} making request: {} to target: {} using http2: {} for "
453-
"timeout: {} with headers: {} and payload: {}",
465+
"{} making request: {} to target: {} using http2: {} following "
466+
"redirects: {} for timeout: {} with headers: {} and payload: {}",
454467
self.__class__.__name__,
455468
request_id,
456469
target,
457470
self.http2,
471+
self.follow_redirects,
458472
self.timeout,
459473
headers,
460474
payload,
@@ -544,6 +558,7 @@ async def _iterative_completions_request(
544558
payload=payload,
545559
timeout=self.timeout,
546560
http2=self.http2,
561+
follow_redirects=self.follow_redirects,
547562
),
548563
start_time=start_time,
549564
end_time=iter_time,

src/guidellm/backend/response.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,15 @@ class RequestArgs(StandardBaseModel):
5252
content and other configurations.
5353
:param timeout: The timeout for the request in seconds, if any.
5454
:param http2: Whether HTTP/2 was used for the request, if applicable.
55+
:param follow_redirects: Whether the request should follow redirect responses.
5556
"""
5657

5758
target: str
5859
headers: dict[str, str]
5960
payload: dict[str, Any]
6061
timeout: Optional[float] = None
6162
http2: Optional[bool] = None
63+
follow_redirects: Optional[bool] = None
6264

6365

6466
class ResponseSummary(StandardBaseModel):

src/guidellm/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class Settings(BaseSettings):
115115
default_sweep_number: int = 10
116116

117117
# HTTP settings
118+
request_follow_redirects: bool = True
118119
request_timeout: int = 60 * 5 # 5 minutes
119120
request_http2: bool = True
120121

tests/unit/backend/test_openai_backend.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ def test_openai_http_backend_default_initialization():
1616
assert backend.project == settings.openai.project
1717
assert backend.timeout == settings.request_timeout
1818
assert backend.http2 is True
19+
assert backend.follow_redirects is True
1920
assert backend.max_output_tokens == settings.openai.max_output_tokens
2021

2122

@@ -29,6 +30,7 @@ def test_openai_http_backend_intialization():
2930
project="test-proj",
3031
timeout=10,
3132
http2=False,
33+
follow_redirects=False,
3234
max_output_tokens=100,
3335
)
3436
assert backend.target == "http://test-target"
@@ -38,6 +40,7 @@ def test_openai_http_backend_intialization():
3840
assert backend.project == "test-proj"
3941
assert backend.timeout == 10
4042
assert backend.http2 is False
43+
assert backend.follow_redirects is False
4144
assert backend.max_output_tokens == 100
4245

4346

tests/unit/backend/test_response.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def test_request_args_default_initialization():
8080
)
8181
assert args.timeout is None
8282
assert args.http2 is None
83+
assert args.follow_redirects is None
8384

8485

8586
@pytest.mark.smoke
@@ -94,12 +95,14 @@ def test_request_args_initialization():
9495
},
9596
timeout=10.0,
9697
http2=True,
98+
follow_redirects=True,
9799
)
98100
assert args.target == "http://example.com"
99101
assert args.headers == {"Authorization": "Bearer token"}
100102
assert args.payload == {"query": "Hello, world!"}
101103
assert args.timeout == 10.0
102104
assert args.http2 is True
105+
assert args.follow_redirects is True
103106

104107

105108
@pytest.mark.smoke

0 commit comments

Comments
 (0)