Skip to content

⚡️ Speed up method ModelProviderCredentialRequest.validate_provider by 32% in PR #10351 (model-provider-keys-v2)#10441

Closed
codeflash-ai[bot] wants to merge 163 commits into
model-provider-keys-v2from
codeflash/optimize-pr10351-2025-10-29T15.27.18
Closed

⚡️ Speed up method ModelProviderCredentialRequest.validate_provider by 32% in PR #10351 (model-provider-keys-v2)#10441
codeflash-ai[bot] wants to merge 163 commits into
model-provider-keys-v2from
codeflash/optimize-pr10351-2025-10-29T15.27.18

Conversation

@codeflash-ai
Copy link
Copy Markdown
Contributor

@codeflash-ai codeflash-ai Bot commented Oct 29, 2025

⚡️ This pull request contains optimizations for PR #10351

If you approve this dependent PR, these changes will be merged into the original PR branch model-provider-keys-v2.

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


📄 32% (0.32x) speedup for ModelProviderCredentialRequest.validate_provider in src/backend/base/langflow/api/v1/model_provider_credentials.py

⏱️ Runtime : 20.8 microseconds 15.8 microseconds (best of 37 runs)

📝 Explanation and details

The optimization achieves a 31% speedup through two key changes:

  1. Module-level caching: Moves the expensive get_model_provider_metadata().keys() call from inside the validator to module load time, storing it in _VALID_PROVIDERS. This eliminates repeated calls to what appears to be a costly metadata retrieval function every time validation occurs.

  2. Set-based membership testing: Converts the provider keys to a set instead of using a list, changing the membership test from O(n) to O(1) complexity. This is particularly beneficial when there are many supported providers.

The optimization is most effective for scenarios with:

  • Repeated validations: Multiple provider validations benefit from the one-time metadata fetch
  • Large provider lists: The set lookup becomes increasingly advantageous as the number of supported providers grows (as shown in the test_large_number_of_providers_invalid test case)
  • High-frequency validation paths: Any code path that validates providers multiple times sees cumulative benefits

The cached approach trades a small amount of memory for significant runtime improvement, while maintaining identical validation behavior and error messages.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 10 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime
import pytest
from langflow.api.v1.model_provider_credentials import \
    ModelProviderCredentialRequest


# --- Mock get_model_provider_metadata for testing purposes ---
# Since the original function is imported from another module, we'll define a mock version here
def get_model_provider_metadata():
    # Simulate a realistic set of providers
    return {
        "openai": {"description": "OpenAI GPT models"},
        "anthropic": {"description": "Anthropic Claude models"},
        "google": {"description": "Google PaLM models"},
        "azure": {"description": "Azure OpenAI Service"},
        "cohere": {"description": "Cohere models"},
        "huggingface": {"description": "HuggingFace Hub"},
        # Add more as needed for large scale tests
    }

# --- The function to test (as a standalone function for unit testing) ---
def validate_provider(v: str) -> str:
    """Validate that provider is in the valid list of supported providers."""
    valid_providers = list(get_model_provider_metadata().keys())
    if v not in valid_providers:
        msg = f"Invalid provider '{v}'. Must be one of: {', '.join(valid_providers)}"
        raise ValueError(msg)
    return v

# ------------------- UNIT TESTS -------------------

# --------- 1. Basic Test Cases ---------























#------------------------------------------------
import pytest
from langflow.api.v1.model_provider_credentials import \
    ModelProviderCredentialRequest

# --- Function to test (copied and slightly adapted for testability) ---
# We'll mock get_model_provider_metadata to control the valid providers in tests.

def get_model_provider_metadata():
    # This is a placeholder. It will be monkeypatched in the tests.
    return {}
from langflow.api.v1.model_provider_credentials import \
    ModelProviderCredentialRequest

# --- Unit tests ---

# Helper fixture to monkeypatch get_model_provider_metadata
@pytest.fixture
def patch_metadata(monkeypatch):
    def _patch(providers):
        def fake_metadata():
            return {p: {} for p in providers}
        monkeypatch.setattr(__name__ + ".get_model_provider_metadata", fake_metadata)
    return _patch

# ------------------- 1. BASIC TEST CASES -------------------

def test_valid_provider_single(patch_metadata):
    """Test with a single valid provider."""
    patch_metadata(['OpenAI'])
    codeflash_output = ModelProviderCredentialRequest.validate_provider('OpenAI')

def test_valid_provider_multiple(patch_metadata):
    """Test with multiple valid providers."""
    patch_metadata(['OpenAI', 'Anthropic', 'Google'])
    codeflash_output = ModelProviderCredentialRequest.validate_provider('Anthropic')
    codeflash_output = ModelProviderCredentialRequest.validate_provider('Google')

def test_invalid_provider_raises(patch_metadata):
    """Test with an invalid provider, should raise ValueError."""
    patch_metadata(['OpenAI', 'Anthropic'])
    with pytest.raises(ValueError) as excinfo:
        ModelProviderCredentialRequest.validate_provider('NotAProvider')

# ------------------- 2. EDGE TEST CASES -------------------

def test_empty_valid_providers_list(patch_metadata):
    """Test when no providers are valid (empty list)."""
    patch_metadata([])
    with pytest.raises(ValueError) as excinfo:
        ModelProviderCredentialRequest.validate_provider('Anything')

def test_empty_string_provider(patch_metadata):
    """Test when provider is an empty string."""
    patch_metadata(['OpenAI', 'Anthropic'])
    with pytest.raises(ValueError) as excinfo:
        ModelProviderCredentialRequest.validate_provider('')

def test_case_sensitivity(patch_metadata):
    """Test that provider matching is case-sensitive."""
    patch_metadata(['OpenAI'])
    with pytest.raises(ValueError):
        ModelProviderCredentialRequest.validate_provider('openai')  # Lowercase should not match

def test_whitespace_provider(patch_metadata):
    """Test provider string with leading/trailing whitespace."""
    patch_metadata(['OpenAI'])
    with pytest.raises(ValueError):
        ModelProviderCredentialRequest.validate_provider(' OpenAI ')
    # But if whitespace is in the valid list, it should pass
    patch_metadata([' OpenAI '])
    codeflash_output = ModelProviderCredentialRequest.validate_provider(' OpenAI ')







def test_large_number_of_providers_invalid(patch_metadata):
    """Test with a large number of valid providers, and an invalid input."""
    providers = [f'Provider{i}' for i in range(1000)]
    patch_metadata(providers)
    with pytest.raises(ValueError):
        ModelProviderCredentialRequest.validate_provider('NotAProvider')

To edit these changes git checkout codeflash/optimize-pr10351-2025-10-29T15.27.18 and push.

Codeflash

Cristhianzl and others added 30 commits October 21, 2025 11:16
🔧 (variable/model.py): add category field to VariableBase and VariableRead models
🔧 (variable/model.py): add validation for category field in VariableBase and VariableUpdate models
🔧 (variable/constants.py): define valid categories and add new categories
🔧 (variable/service.py): update category in db_variable if variable has a category and encrypt value if type is CREDENTIAL_TYPE
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Co-authored-by: Rodrigo Nader <rodrigosilvanader@gmail.com>
Co-authored-by: Deon Sanchez <69873175+deon-sanchez@users.noreply.github.com>
Co-authored-by: April I. Murphy <36110273+aimurphy@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Yuqi Tang <yuqi.tang@datastax.com>
fix: store mcp sse headers and use them on connection (#9148)
fix: prevent unintentional sidebar text selection (#8895)
fix: Exclude base path from custom component loading (#9098)
fix.py): remove unnecessary test case for GitHub issue #8967 and fix test_component_merging_logic method to handle custom component loading failure properly
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…lobal variables

✨ (use-get-categories.ts): introduce use-get-categories query function to fetch category variables
✨ (use-post-global-variables.ts): add category parameter to post global variables function
📝 (global_variables/index.ts): update GlobalVariable type to include category field
- Introduced a new Model Providers page with components for displaying enabled and available providers.
- Updated the settings sidebar to include a link to the Model Providers page.
- Added a custom CSS class for improved text styling.
- Introduced ModelInputComponent for selecting models with enhanced search and filtering capabilities.
- Updated ParameterRenderComponent to handle model_type and related properties.
- Refactored dropdownComponent to improve code organization and readability.
- Added new types for model configuration in the API definitions.
- Removed unused placeholder formatting in Dropdown component.
- Simplified ModelInputComponent by cleaning up imports and restructuring state management.
- Introduced API key input functionality for model selection.
- Enhanced rendering logic for model options and search input.
- Improved code organization and readability across components.
…ategory

- Refactored ModelInputComponent to replace search_category with providers for better clarity and functionality.
- Updated related types and props to accommodate the new providers structure.
- Enhanced the handling of model selection to include additional metadata for selected models.
- Adjusted ParameterRenderComponent to reflect changes in props passed to child components.
…PI key handling

- Made the model_selection input required and added a placeholder for better user guidance.
- Refactored the model selection logic to handle selected models more effectively, including additional metadata.
- Updated the rendering of model options to improve clarity and user experience.
- Implemented a search feature for model selection, allowing users to filter options dynamically.
- Enhanced API key input handling to streamline the process of entering and managing API keys for selected models.
- Added ApiKeyModal component to facilitate API key entry and management for models.
- Integrated modal into ModelInputComponent, allowing users to input and save API keys.
- Refactored input handling and state management for improved user experience.
- Cleaned up imports and organized component structure for better maintainability.
…component

- Introduced new constants for model providers in the API helper.
- Implemented useGetModelProviders hook to fetch and manage model provider data.
- Updated Providers component to utilize the new hook, replacing mock data with dynamic provider information.
- Enhanced UI to display model provider status and count, improving user interaction and experience.
erichare and others added 22 commits October 28, 2025 12:21
The optimization achieves a **31% speedup** through two key changes:

1. **Module-level caching**: Moves the expensive `get_model_provider_metadata().keys()` call from inside the validator to module load time, storing it in `_VALID_PROVIDERS`. This eliminates repeated calls to what appears to be a costly metadata retrieval function every time validation occurs.

2. **Set-based membership testing**: Converts the provider keys to a `set` instead of using a `list`, changing the membership test from O(n) to O(1) complexity. This is particularly beneficial when there are many supported providers.

The optimization is most effective for scenarios with:
- **Repeated validations**: Multiple provider validations benefit from the one-time metadata fetch
- **Large provider lists**: The set lookup becomes increasingly advantageous as the number of supported providers grows (as shown in the `test_large_number_of_providers_invalid` test case)
- **High-frequency validation paths**: Any code path that validates providers multiple times sees cumulative benefits

The cached approach trades a small amount of memory for significant runtime improvement, while maintaining identical validation behavior and error messages.
@codeflash-ai codeflash-ai Bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Oct 29, 2025
@github-actions github-actions Bot added the community Pull Request from an external contributor label Oct 29, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Oct 29, 2025

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Oct 29, 2025

Codecov Report

❌ Patch coverage is 32.82443% with 440 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (model-provider-keys-v2@d58de83). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...Component/components/modelInputComponent/index.tsx 0.00% 142 Missing ⚠️
...base/langflow/api/v1/model_provider_credentials.py 56.96% 68 Missing ⚠️
src/frontend/src/modals/apiKeyModal/index.tsx 0.00% 47 Missing ⚠️
src/lfx/src/lfx/base/models/unified_models.py 34.92% 41 Missing ⚠️
.../pages/ModelProvidersPage/components/Providers.tsx 0.00% 35 Missing ⚠️
src/backend/base/langflow/api/v1/models.py 51.66% 29 Missing ⚠️
...lers/API/queries/models/use-get-model-providers.ts 0.00% 17 Missing ⚠️
...ollers/API/queries/variables/use-get-categories.ts 32.00% 17 Missing ⚠️
...onents/inputComponent/components/popover/index.tsx 0.00% 13 Missing ⚠️
...backend/base/langflow/services/variable/service.py 76.47% 8 Missing ⚠️
... and 7 more

❌ Your patch status has failed because the patch coverage (32.82%) is below the target coverage (40.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@                    Coverage Diff                    @@
##             model-provider-keys-v2   #10441   +/-   ##
=========================================================
  Coverage                          ?   30.21%           
=========================================================
  Files                             ?     1329           
  Lines                             ?    60310           
  Branches                          ?     9021           
=========================================================
  Hits                              ?    18221           
  Misses                            ?    41258           
  Partials                          ?      831           
Flag Coverage Δ
backend 51.02% <58.82%> (?)
lfx 39.52% <55.91%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/backend/base/langflow/api/router.py 100.00% <100.00%> (ø)
src/backend/base/langflow/inputs/inputs.py 0.00% <ø> (ø)
...angflow/services/database/models/variable/model.py 100.00% <100.00%> (ø)
...enderComponent/components/inputComponent/index.tsx 12.64% <ø> (ø)
...rComponent/components/strRenderComponent/index.tsx 0.00% <ø> (ø)
src/frontend/src/constants/constants.ts 95.40% <100.00%> (ø)
.../frontend/src/controllers/API/helpers/constants.ts 55.55% <ø> (ø)
...end/src/controllers/API/queries/variables/index.ts 100.00% <100.00%> (ø)
...PI/queries/variables/use-patch-global-variables.ts 45.45% <ø> (ø)
src/frontend/src/pages/SettingsPage/index.tsx 0.00% <ø> (ø)
... and 24 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@HimavarshaVS HimavarshaVS force-pushed the model-provider-keys-v2 branch from 716d4b3 to bd3f04e Compare November 11, 2025 17:46
@codeflash-ai codeflash-ai Bot closed this Nov 11, 2025
@codeflash-ai
Copy link
Copy Markdown
Contributor Author

codeflash-ai Bot commented Nov 11, 2025

This PR has been automatically closed because the original PR #10351 by HimavarshaVS was closed.

@codeflash-ai codeflash-ai Bot deleted the codeflash/optimize-pr10351-2025-10-29T15.27.18 branch November 11, 2025 17:46
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 community Pull Request from an external contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants