Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⚡️ Speed up method HuggingFaceInferenceAPIEmbeddingsComponent.build_embeddings by 40% in PR #6140 (API_Modal) #6626

Open
wants to merge 1 commit into
base: API_Modal
Choose a base branch
from

Conversation

codeflash-ai[bot]
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Feb 14, 2025

⚡️ This pull request contains optimizations for PR #6140

If you approve this dependent PR, these changes will be merged into the original PR branch API_Modal.

This PR will be automatically closed if the original PR is merged.


📄 40% (0.40x) speedup for HuggingFaceInferenceAPIEmbeddingsComponent.build_embeddings in src/backend/base/langflow/components/embeddings/huggingface_inference_api.py

⏱️ Runtime : 37.7 milliseconds 26.9 milliseconds (best of 33 runs)

📝 Explanation and details

Explanation of Optimizations.

These optimizations should enhance both the runtime performance and memory efficiency of your program, making it faster and more scalable.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 4020 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage undefined
🌀 Generated Regression Tests Details
from unittest.mock import MagicMock, patch
from urllib.parse import urlparse

# imports
import pytest  # used for our unit tests
# function to test
import requests
from langchain_community.embeddings.huggingface import \
    HuggingFaceInferenceAPIEmbeddings
from langflow.base.embeddings.model import LCEmbeddingsModel
from langflow.components.embeddings.huggingface_inference_api import \
    HuggingFaceInferenceAPIEmbeddingsComponent
from langflow.field_typing import Embeddings
from pydantic import SecretStr
from tenacity import retry, stop_after_attempt, wait_fixed

# unit tests

# Test valid local inference endpoint
def test_valid_local_inference_endpoint():
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint="http://localhost:8080",
        model_name="test-model",
        api_key=None
    )
    with patch.object(component, 'validate_inference_endpoint', return_value=True):
        with patch.object(component, 'create_huggingface_embeddings', return_value="mocked_embeddings"):
            codeflash_output = component.build_embeddings()

# Test valid remote inference endpoint with API key
def test_valid_remote_inference_endpoint_with_api_key():
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint="https://api.huggingface.co",
        model_name="test-model",
        api_key="test_api_key"
    )
    with patch.object(component, 'create_huggingface_embeddings', return_value="mocked_embeddings"):
        codeflash_output = component.build_embeddings()

# Test invalid inference endpoint format
def test_invalid_inference_endpoint_format():
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint="localhost:8080",
        model_name="test-model",
        api_key=None
    )
    with pytest.raises(ValueError, match="Invalid inference endpoint format"):
        component.build_embeddings()

# Test non-responsive inference endpoint
def test_non_responsive_inference_endpoint():
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint="http://localhost:9999",
        model_name="test-model",
        api_key=None
    )
    with patch('requests.get', side_effect=requests.RequestException):
        with pytest.raises(ValueError, match="Inference endpoint 'http://localhost:9999' is not responding"):
            component.build_embeddings()

# Test valid inference endpoint but health check fails
def test_health_check_fails():
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint="http://localhost:8080",
        model_name="test-model",
        api_key=None
    )
    mock_response = MagicMock()
    mock_response.status_code = 500
    with patch('requests.get', return_value=mock_response):
        with pytest.raises(ValueError, match="HuggingFace health check failed: 500"):
            component.build_embeddings()

# Test missing API key for remote inference endpoint
def test_missing_api_key_for_remote_inference_endpoint():
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint="https://api.huggingface.co",
        model_name="test-model",
        api_key=None
    )
    with pytest.raises(ValueError, match="API Key is required for non-local inference endpoints"):
        component.build_embeddings()

# Test API key provided for local inference endpoint
def test_api_key_provided_for_local_inference_endpoint():
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint="http://localhost:8080",
        model_name="test-model",
        api_key="test_api_key"
    )
    with patch.object(component, 'validate_inference_endpoint', return_value=True):
        with patch.object(component, 'create_huggingface_embeddings', return_value="mocked_embeddings"):
            codeflash_output = component.build_embeddings()

# Test retry logic for transient failures

def test_large_scale_valid_local_inference_endpoint():
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint="http://localhost:8080",
        model_name="test-model",
        api_key=None
    )
    with patch.object(component, 'validate_inference_endpoint', return_value=True):
        with patch.object(component, 'create_huggingface_embeddings', return_value="mocked_embeddings"):
            for _ in range(1000):
                codeflash_output = component.build_embeddings()

# Test large scale with valid remote inference endpoint
def test_large_scale_valid_remote_inference_endpoint():
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint="https://api.huggingface.co",
        model_name="test-model",
        api_key="test_api_key"
    )
    with patch.object(component, 'create_huggingface_embeddings', return_value="mocked_embeddings"):
        for _ in range(1000):
            codeflash_output = component.build_embeddings()

# Test empty string for inference endpoint
def test_empty_inference_endpoint():
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint="",
        model_name="test-model",
        api_key=None
    )
    with pytest.raises(ValueError, match="Invalid inference endpoint format"):
        component.build_embeddings()

# Test extremely long inference endpoint URL
def test_extremely_long_inference_endpoint():
    long_url = "http://" + "a" * 1000 + ".com"
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint=long_url,
        model_name="test-model",
        api_key=None
    )
    with patch.object(component, 'validate_inference_endpoint', return_value=True):
        with patch.object(component, 'create_huggingface_embeddings', return_value="mocked_embeddings"):
            codeflash_output = component.build_embeddings()

# Test special characters in inference endpoint
def test_special_characters_in_inference_endpoint():
    special_url = "http://localhost:8080/!@#$%^&*()"
    component = HuggingFaceInferenceAPIEmbeddingsComponent(
        inference_endpoint=special_url,
        model_name="test-model",
        api_key=None
    )
    with patch.object(component, 'validate_inference_endpoint', return_value=True):
        with patch.object(component, 'create_huggingface_embeddings', return_value="mocked_embeddings"):
            codeflash_output = component.build_embeddings()
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

from unittest.mock import MagicMock, patch
from urllib.parse import urlparse

# imports
import pytest  # used for our unit tests
# function to test
import requests
from langchain_community.embeddings.huggingface import \
    HuggingFaceInferenceAPIEmbeddings
from langflow.base.embeddings.model import LCEmbeddingsModel
from langflow.components.embeddings.huggingface_inference_api import \
    HuggingFaceInferenceAPIEmbeddingsComponent
from langflow.field_typing import Embeddings
from pydantic import SecretStr
from tenacity import retry, stop_after_attempt, wait_fixed

# unit tests

# Test valid local URL with API key
def test_valid_local_url_with_api_key():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "http://localhost:8000"
    component.api_key = "valid_api_key"
    component.model_name = "test-model"
    
    with patch.object(component, 'create_huggingface_embeddings', return_value="Embeddings Created") as mock_method:
        codeflash_output = component.build_embeddings()
        mock_method.assert_called_once()

# Test valid local URL without API key
def test_valid_local_url_without_api_key():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "http://localhost:8000"
    component.api_key = None
    component.model_name = "test-model"
    
    with patch.object(component, 'create_huggingface_embeddings', return_value="Embeddings Created") as mock_method, \
         patch.object(component, 'validate_inference_endpoint', return_value=True):
        codeflash_output = component.build_embeddings()
        mock_method.assert_called_once()

# Test valid remote URL with API key
def test_valid_remote_url_with_api_key():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "https://api.huggingface.co"
    component.api_key = "valid_api_key"
    component.model_name = "test-model"
    
    with patch.object(component, 'create_huggingface_embeddings', return_value="Embeddings Created") as mock_method:
        codeflash_output = component.build_embeddings()
        mock_method.assert_called_once()

# Test invalid URL format

def test_unreachable_inference_endpoint():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "http://localhost:8000"
    component.api_key = None
    component.model_name = "test-model"
    
    with patch('requests.get', side_effect=requests.RequestException):
        with pytest.raises(ValueError, match="Inference endpoint 'http://localhost:8000' is not responding"):
            component.build_embeddings()

# Test inference endpoint health check failure
def test_inference_endpoint_health_check_failure():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "http://localhost:8000"
    component.api_key = None
    component.model_name = "test-model"
    
    response_mock = MagicMock()
    response_mock.status_code = 500
    with patch('requests.get', return_value=response_mock):
        with pytest.raises(ValueError, match="HuggingFace health check failed"):
            component.build_embeddings()

# Test API key required but not provided
def test_api_key_required_but_not_provided():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "https://api.huggingface.co"
    component.api_key = None
    component.model_name = "test-model"
    
    with pytest.raises(ValueError, match="API Key is required for non-local inference endpoints"):
        component.build_embeddings()

# Test API key provided but invalid
def test_api_key_provided_but_invalid():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "https://api.huggingface.co"
    component.api_key = "invalid_api_key"
    component.model_name = "test-model"
    
    with patch.object(component, 'create_huggingface_embeddings', side_effect=Exception):
        with pytest.raises(ValueError, match="Could not connect to HuggingFace Inference API"):
            component.build_embeddings()

# Test valid HuggingFace URL with model name
def test_valid_huggingface_url_with_model_name():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "https://api.huggingface.co"
    component.api_key = "valid_api_key"
    component.model_name = "bert-base-uncased"
    
    with patch.object(component, 'create_huggingface_embeddings', return_value="Embeddings Created") as mock_method:
        codeflash_output = component.build_embeddings()
        mock_method.assert_called_once()

# Test edge cases for URL parsing
def test_edge_case_url_with_path():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "http://localhost:8000/path"
    component.api_key = None
    component.model_name = "test-model"
    
    with patch.object(component, 'create_huggingface_embeddings', return_value="Embeddings Created") as mock_method, \
         patch.object(component, 'validate_inference_endpoint', return_value=True):
        codeflash_output = component.build_embeddings()
        mock_method.assert_called_once()

def test_edge_case_url_with_query():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "http://localhost:8000?query=param"
    component.api_key = None
    component.model_name = "test-model"
    
    with patch.object(component, 'create_huggingface_embeddings', return_value="Embeddings Created") as mock_method, \
         patch.object(component, 'validate_inference_endpoint', return_value=True):
        codeflash_output = component.build_embeddings()
        mock_method.assert_called_once()

# Test retries on transient errors

def test_large_scale_local_url():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "http://localhost:8000"
    component.api_key = None
    component.model_name = "test-model"
    
    with patch.object(component, 'create_huggingface_embeddings', return_value="Embeddings Created") as mock_method, \
         patch.object(component, 'validate_inference_endpoint', return_value=True):
        for _ in range(1000):
            codeflash_output = component.build_embeddings()

def test_large_scale_remote_url():
    component = HuggingFaceInferenceAPIEmbeddingsComponent()
    component.inference_endpoint = "https://api.huggingface.co"
    component.api_key = "valid_api_key"
    component.model_name = "test-model"
    
    with patch.object(component, 'create_huggingface_embeddings', return_value="Embeddings Created") as mock_method:
        for _ in range(1000):
            codeflash_output = component.build_embeddings()
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

Codeflash

…embeddings` by 40% in PR #6140 (`API_Modal`)

### Explanation of Optimizations.

These optimizations should enhance both the runtime performance and memory efficiency of your program, making it faster and more scalable.
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Feb 14, 2025
@dosubot dosubot bot added size:S This PR changes 10-29 lines, ignoring generated files. enhancement New feature or request labels Feb 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⚡️ codeflash Optimization PR opened by Codeflash AI enhancement New feature or request size:S This PR changes 10-29 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0 participants