Add env-configurable timeout for proxy providers

This commit is contained in:
Songbird
2025-10-21 14:26:34 +02:00
parent 092a90df5d
commit 22f01562ba
3 changed files with 84 additions and 1 deletions

View File

@@ -201,10 +201,72 @@ def _should_use_responses_api(
return False return False
def _read_positive_int(
candidate: str | None,
*,
var_name: str,
) -> int | None:
if candidate is None:
return None
value = candidate.strip()
if not value:
return None
try:
parsed = int(value)
except ValueError:
log(f"Ignoring non-integer timeout for {var_name}: {value}")
return None
if parsed <= 0:
log(f"Ignoring non-positive timeout for {var_name}: {parsed}")
return None
return parsed
def _lookup_timeout_var(
var_name: str,
env_map: dict[str, str],
bifrost_map: dict[str, str],
) -> int | None:
for source in (
bifrost_map.get(var_name),
env_map.get(var_name),
os.getenv(var_name),
):
parsed = _read_positive_int(source, var_name=var_name)
if parsed is not None:
return parsed
return None
def _get_timeout_seconds(
provider: ProviderSpec,
env_map: dict[str, str],
bifrost_map: dict[str, str],
) -> int | None:
provider_specific_var = f"BIFROST_{provider.name.upper()}_TIMEOUT_SECONDS"
timeout = _lookup_timeout_var(provider_specific_var, env_map, bifrost_map)
if timeout is not None:
return timeout
return _lookup_timeout_var("BIFROST_DEFAULT_TIMEOUT_SECONDS", env_map, bifrost_map)
def build_network_config(
provider: ProviderSpec,
env_map: dict[str, str],
bifrost_map: dict[str, str],
) -> dict[str, object] | None:
timeout = _get_timeout_seconds(provider, env_map, bifrost_map)
if timeout is None:
return None
return {"default_request_timeout_in_seconds": timeout}
def build_provider_config_entry( def build_provider_config_entry(
provider: ProviderSpec, provider: ProviderSpec,
env_map: dict[str, str], env_map: dict[str, str],
bifrost_map: dict[str, str], bifrost_map: dict[str, str],
*,
network_config: dict[str, object] | None = None,
) -> dict[str, object]: ) -> dict[str, object]:
models = get_models_for_provider(provider, env_map, bifrost_map) models = get_models_for_provider(provider, env_map, bifrost_map)
key_entry: dict[str, object] = { key_entry: dict[str, object] = {
@@ -216,6 +278,8 @@ def build_provider_config_entry(
key_entry["openai_key_config"] = {"use_responses_api": True} key_entry["openai_key_config"] = {"use_responses_api": True}
entry: dict[str, object] = {"keys": [key_entry]} entry: dict[str, object] = {"keys": [key_entry]}
if network_config:
entry["network_config"] = network_config
return entry return entry
@@ -371,6 +435,7 @@ def configure_providers() -> dict[str, dict[str, object]]:
if not key_value: if not key_value:
continue continue
network_config = build_network_config(provider, env_map, bifrost_map)
payload = { payload = {
"provider": provider.name, "provider": provider.name,
"keys": [ "keys": [
@@ -381,6 +446,8 @@ def configure_providers() -> dict[str, dict[str, object]]:
} }
], ],
} }
if network_config:
payload["network_config"] = network_config
status, body = post_json("/api/providers", payload) status, body = post_json("/api/providers", payload)
if status in {200, 201}: if status in {200, 201}:
log(f"Configured provider '{provider.name}'") log(f"Configured provider '{provider.name}'")
@@ -403,7 +470,10 @@ def configure_providers() -> dict[str, dict[str, object]]:
bifrost_map[provider.env_var] = key_value bifrost_map[provider.env_var] = key_value
config_updates[provider.name] = build_provider_config_entry( config_updates[provider.name] = build_provider_config_entry(
provider, env_map, bifrost_map provider,
env_map,
bifrost_map,
network_config=network_config,
) )
if bifrost_lines_changed: if bifrost_lines_changed:

View File

@@ -42,6 +42,10 @@ The container binds its SQLite databases underneath the named volume `fuzzforge_
(backed by the `fuzzforge_llm_proxy_data` volume) populated with provider entries, (backed by the `fuzzforge_llm_proxy_data` volume) populated with provider entries,
`client.drop_excess_requests=false`, and an enabled SQLite `config_store`, so `client.drop_excess_requests=false`, and an enabled SQLite `config_store`, so
budgets and UI-driven configuration persist exactly the way the docs expect. budgets and UI-driven configuration persist exactly the way the docs expect.
To raise the upstream timeout beyond the 30s default, set `BIFROST_DEFAULT_TIMEOUT_SECONDS`
or provider-specific overrides such as `BIFROST_ANTHROPIC_TIMEOUT_SECONDS` in
`volumes/env/.env` before bootstrapping; the script propagates them to the proxys
network configuration automatically.
3. (Optional) Set `BIFROST_OPENAI_MODELS` to a comma-separated list if you want 3. (Optional) Set `BIFROST_OPENAI_MODELS` to a comma-separated list if you want
to scope a key to specific models (for example `openai/gpt-5,openai/gpt-5-nano`). to scope a key to specific models (for example `openai/gpt-5,openai/gpt-5-nano`).
When you target Responses-only models, flip `BIFROST_OPENAI_USE_RESPONSES_API=true` When you target Responses-only models, flip `BIFROST_OPENAI_USE_RESPONSES_API=true`

View File

@@ -24,10 +24,19 @@ OPENAI_API_KEY=sk-proxy-default
# BIFROST_OPENAI_KEY= # BIFROST_OPENAI_KEY=
# BIFROST_OPENAI_MODELS=openai/gpt-5,openai/gpt-5-nano # BIFROST_OPENAI_MODELS=openai/gpt-5,openai/gpt-5-nano
# BIFROST_OPENAI_USE_RESPONSES_API=true # BIFROST_OPENAI_USE_RESPONSES_API=true
# Increase the proxy's upstream request timeout (seconds). Applies per provider,
# falling back to BIFROST_DEFAULT_TIMEOUT_SECONDS when the provider-specific
# value is not set.
# BIFROST_DEFAULT_TIMEOUT_SECONDS=60
# BIFROST_OPENAI_TIMEOUT_SECONDS=60
# BIFROST_ANTHROPIC_KEY= # BIFROST_ANTHROPIC_KEY=
# BIFROST_ANTHROPIC_TIMEOUT_SECONDS=60
# BIFROST_GEMINI_KEY= # BIFROST_GEMINI_KEY=
# BIFROST_GEMINI_TIMEOUT_SECONDS=60
# BIFROST_MISTRAL_KEY= # BIFROST_MISTRAL_KEY=
# BIFROST_MISTRAL_TIMEOUT_SECONDS=60
# BIFROST_OPENROUTER_KEY= # BIFROST_OPENROUTER_KEY=
# BIFROST_OPENROUTER_TIMEOUT_SECONDS=60
# LiteLLM proxy (alternative gateway) # LiteLLM proxy (alternative gateway)
# LITELLM_MASTER_KEY=sk-master-key # LITELLM_MASTER_KEY=sk-master-key