fix: bound Hugging Face config fetch and keep embedding tests off the network

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Devin AI 2026-08-29 09:45:52 +00:00
parent 3993829a21
commit db1b1e2195
3 changed files with 16 additions and 3 deletions

View file

@ -35,6 +35,7 @@ DEFAULT_COOLDOWN_TIME_SECONDS: Final = int(os.getenv("DEFAULT_COOLDOWN_TIME_SECO
DEFAULT_REPLICATE_POLLING_RETRIES: Final = int(os.getenv("DEFAULT_REPLICATE_POLLING_RETRIES", 5))
DEFAULT_REPLICATE_POLLING_DELAY_SECONDS: Final = int(os.getenv("DEFAULT_REPLICATE_POLLING_DELAY_SECONDS", 1))
DEFAULT_IMAGE_TOKEN_COUNT: Final = int(os.getenv("DEFAULT_IMAGE_TOKEN_COUNT", 250))
HF_CONFIG_FETCH_TIMEOUT_SECONDS: Final = float(os.getenv("HF_CONFIG_FETCH_TIMEOUT_SECONDS", 10))
# Maximum wall-clock seconds a streaming response is allowed to run.
# Streams exceeding this duration are terminated with a Timeout error.

View file

@ -69,6 +69,7 @@ from litellm.constants import (
DEFAULT_REASONING_EFFORT_MEDIUM_THINKING_BUDGET,
DEFAULT_TRIM_RATIO,
FUNCTION_DEFINITION_TOKEN_COUNT,
HF_CONFIG_FETCH_TIMEOUT_SECONDS,
INITIAL_RETRY_DELAY,
JITTER,
MAX_RETRY_DELAY,
@ -5168,7 +5169,7 @@ def get_max_tokens(model: str) -> int | None:
config_url: Final = f"https://huggingface.co/{model_name}/raw/main/config.json"
try:
# Make the HTTP request to get the raw JSON file
response: Final = litellm.module_level_client.get(config_url)
response: Final = litellm.module_level_client.get(config_url, timeout=HF_CONFIG_FETCH_TIMEOUT_SECONDS)
response.raise_for_status() # Raise an exception for bad responses (4xx or 5xx)
# Parse the JSON response
@ -5522,7 +5523,7 @@ def _get_max_position_embeddings(model_name: str) -> int | None:
try:
# Make the HTTP request to get the raw JSON file
response: Final = litellm.module_level_client.get(config_url)
response: Final = litellm.module_level_client.get(config_url, timeout=HF_CONFIG_FETCH_TIMEOUT_SECONDS)
response.raise_for_status() # Raise an exception for bad responses (4xx or 5xx)
# Parse the JSON response

View file

@ -4,6 +4,7 @@ from unittest.mock import patch, MagicMock, AsyncMock
import litellm
import pytest
import respx
MOCK_EMBEDDING_RESPONSE = [[0.1, 0.2, 0.3, 0.4, 0.5]]
@ -21,6 +22,16 @@ def mock_embedding_http_handler():
yield mock_post
@pytest.fixture
def mock_hf_config_fetch():
"""Serve the Hugging Face config.json fetched during cost calculation, so no test leaves the process"""
with respx.mock(assert_all_called=False) as respx_mock:
respx_mock.get(url__regex=r"https://huggingface\.co/.*/config\.json").respond(
json={"max_position_embeddings": 512}
)
yield respx_mock
@pytest.fixture
def mock_embedding_async_http_handler():
"""Fixture to mock the async HTTP handler for embedding tests"""
@ -39,7 +50,7 @@ def mock_embedding_async_http_handler():
class TestHuggingFaceEmbedding:
@pytest.fixture(autouse=True)
def setup(self, mock_embedding_http_handler, mock_embedding_async_http_handler):
def setup(self, mock_embedding_http_handler, mock_embedding_async_http_handler, mock_hf_config_fetch):
self.mock_get_task_patcher = patch(
"litellm.llms.huggingface.embedding.handler.get_hf_task_embedding_for_model"
)