Skip to content

Conversation

@codeflash-ai
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Jan 5, 2026

⚡️ This pull request contains optimizations for PR #11101

If you approve this dependent PR, these changes will be merged into the original PR branch fix-limiting-saving-flow.

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


📄 11% (0.11x) speedup for remove_api_keys in src/backend/base/langflow/api/utils/core.py

⏱️ Runtime : 863 microseconds 775 microseconds (best of 87 runs)

📝 Explanation and details

The optimization achieves an 11% speedup by reordering condition checks to minimize expensive operations. The key insight is that in the original code, the line profiler shows 79.2% of execution time (20.09ms) is spent on the combined condition check that includes isinstance(), has_api_terms(), and value.get("password").

What changed:
The optimized version restructures the conditional logic by:

  1. Checking isinstance(value, dict) first (cheapest operation)
  2. Caching value.get("password") as has_password before calling has_api_terms()
  3. Only calling has_api_terms() when both type and password checks pass

Why it's faster:
The optimization exploits Python's short-circuit evaluation more effectively:

  • Reduced has_api_terms() calls: The profiler shows calls dropped from 4,523 to 2,718 (40% reduction), saving ~0.94ms in string operations
  • Eliminated redundant dictionary lookups: The original code calls value.get("password") even when has_api_terms() returns False, while the optimized version caches it once
  • Better branch prediction: By checking the boolean has_password before the expensive string operations, the CPU can more efficiently predict and pipeline the execution

Impact on workloads:
This optimization is particularly effective for flows with:

  • Many template values that are dictionaries but don't have password=True (as shown in test_large_scale_no_password_fields)
  • Mixed API and non-API keys where most fields aren't password-protected
  • Large numbers of nodes where the cumulative effect of avoiding string operations compounds

The test results confirm the optimization works best with flows containing many non-password fields or fields that fail the password check, as these scenarios maximize the benefit of avoiding the expensive has_api_terms() string matching.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 29 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Click to see Generated Regression Tests
from __future__ import annotations

import copy

# imports
import pytest
from langflow.api.utils.core import remove_api_keys

# unit tests

# 1. BASIC TEST CASES

def test_removes_single_api_key():
    # Test that a single API key is removed
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {"name": "api_key", "value": "1234", "password": True}
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output

def test_does_not_remove_non_api_key():
    # Test that a non-API-key field is not removed
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "username": {"name": "username", "value": "john", "password": True}
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output

def test_does_not_remove_api_key_if_password_false():
    # Test that an API key is not removed if 'password' is False
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {"name": "api_key", "value": "1234", "password": False}
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output

def test_removes_multiple_api_keys():
    # Test that multiple API keys are removed
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {"name": "api_key", "value": "abcd", "password": True},
                                "service_api_token": {"name": "service_api_token", "value": "efgh", "password": True},
                                "other": {"name": "other", "value": "notsecret", "password": True}
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    tpl = result["data"]["nodes"][0]["data"]["node"]["template"]

def test_removes_api_token_but_not_tokens():
    # Test that "api_token" is removed but "api_tokens" is not
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_token": {"name": "api_token", "value": "token1", "password": True},
                                "api_tokens": {"name": "api_tokens", "value": "token2", "password": True}
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    tpl = result["data"]["nodes"][0]["data"]["node"]["template"]

# 2. EDGE TEST CASES

def test_empty_flow():
    # Test that an empty flow dict does not raise and returns the same dict
    flow = {}
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output

def test_no_nodes_key():
    # Test that a flow with no 'nodes' key does not raise and returns the same dict
    flow = {"data": {}}
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output


def test_template_with_non_dict_values():
    # Test that template values that are not dicts are skipped
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": "not_a_dict",
                                "another": 123
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    tpl = result["data"]["nodes"][0]["data"]["node"]["template"]

def test_missing_value_key_in_template_dict():
    # Test that if a template dict is missing a 'value' key, it does not raise
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {"name": "api_key", "password": True}
                            }
                        }
                    }
                }
            ]
        }
    }
    # Should not raise, and the dict should remain unchanged
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    tpl = result["data"]["nodes"][0]["data"]["node"]["template"]

def test_password_key_missing():
    # Test that if 'password' key is missing, the value is not removed
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {"name": "api_key", "value": "1234"}
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    tpl = result["data"]["nodes"][0]["data"]["node"]["template"]

def test_case_sensitivity_of_api_terms():
    # Test that 'API_KEY' (upper case) is not considered as 'api_key'
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "API_KEY": {"name": "API_KEY", "value": "shouldstay", "password": True}
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    tpl = result["data"]["nodes"][0]["data"]["node"]["template"]

def test_multiple_nodes_some_with_api_keys():
    # Test that only the correct nodes have API keys removed
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {"name": "api_key", "value": "a", "password": True}
                            }
                        }
                    }
                },
                {
                    "data": {
                        "node": {
                            "template": {
                                "username": {"name": "username", "value": "b", "password": True}
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    tpl1 = result["data"]["nodes"][0]["data"]["node"]["template"]
    tpl2 = result["data"]["nodes"][1]["data"]["node"]["template"]

# 3. LARGE SCALE TEST CASES

def test_large_number_of_nodes_and_templates():
    # Test with a large number of nodes and templates
    num_nodes = 500
    num_templates = 2
    flow = {
        "data": {
            "nodes": []
        }
    }
    for i in range(num_nodes):
        node = {
            "data": {
                "node": {
                    "template": {
                        f"api_key_{i}": {"name": f"api_key_{i}", "value": f"val{i}", "password": True},
                        f"username_{i}": {"name": f"username_{i}", "value": f"user{i}", "password": True}
                    }
                }
            }
        }
        flow["data"]["nodes"].append(node)
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    for i in range(num_nodes):
        tpl = result["data"]["nodes"][i]["data"]["node"]["template"]

def test_large_number_of_api_token_and_tokens():
    # Test that "api_token" is removed but "api_tokens" is not, at scale
    num_nodes = 250
    flow = {
        "data": {
            "nodes": []
        }
    }
    for i in range(num_nodes):
        node = {
            "data": {
                "node": {
                    "template": {
                        f"api_token_{i}": {"name": "api_token", "value": f"token{i}", "password": True},
                        f"api_tokens_{i}": {"name": "api_tokens", "value": f"tokens{i}", "password": True}
                    }
                }
            }
        }
        flow["data"]["nodes"].append(node)
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    for i in range(num_nodes):
        tpl = result["data"]["nodes"][i]["data"]["node"]["template"]

def test_large_scale_no_password_fields():
    # Test that nothing is removed if no 'password' fields are present
    num_nodes = 300
    flow = {
        "data": {
            "nodes": []
        }
    }
    for i in range(num_nodes):
        node = {
            "data": {
                "node": {
                    "template": {
                        f"api_key_{i}": {"name": f"api_key_{i}", "value": f"val{i}"},
                        f"username_{i}": {"name": f"username_{i}", "value": f"user{i}"}
                    }
                }
            }
        }
        flow["data"]["nodes"].append(node)
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    for i in range(num_nodes):
        tpl = result["data"]["nodes"][i]["data"]["node"]["template"]
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from __future__ import annotations

import copy

# imports
import pytest
from langflow.api.utils.core import remove_api_keys

# unit tests

# --------------------
# BASIC TEST CASES
# --------------------

def test_remove_api_keys_removes_api_key_value():
    # Test that a single API key is nulled out
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {
                                    "name": "openai_api_key",
                                    "password": True,
                                    "value": "sk-123456"
                                }
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output

def test_remove_api_keys_leaves_non_api_fields_untouched():
    # Test that non-API fields are not changed
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "username": {
                                    "name": "username",
                                    "password": False,
                                    "value": "user1"
                                }
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output

def test_remove_api_keys_removes_multiple_api_keys():
    # Test that multiple API keys in one node are nulled out
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {
                                    "name": "service_api_key",
                                    "password": True,
                                    "value": "123"
                                },
                                "api_token": {
                                    "name": "service_api_token",
                                    "password": True,
                                    "value": "456"
                                }
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    tpl = result["data"]["nodes"][0]["data"]["node"]["template"]

def test_remove_api_keys_multiple_nodes():
    # Test that API keys in multiple nodes are nulled out
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {
                                    "name": "api_key",
                                    "password": True,
                                    "value": "abc"
                                }
                            }
                        }
                    }
                },
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_token": {
                                    "name": "api_token",
                                    "password": True,
                                    "value": "def"
                                }
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output

def test_remove_api_keys_returns_original_when_no_api_keys():
    # Test that function returns the same flow when there are no API keys
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "email": {
                                    "name": "email",
                                    "password": False,
                                    "value": "test@example.com"
                                }
                            }
                        }
                    }
                }
            ]
        }
    }
    orig = copy.deepcopy(flow)
    codeflash_output = remove_api_keys(flow); result = codeflash_output

# --------------------
# EDGE TEST CASES
# --------------------

def test_remove_api_keys_empty_flow():
    # Test empty flow dict
    flow = {}
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output

def test_remove_api_keys_no_nodes():
    # Test flow with no nodes
    flow = {"data": {}}
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output


def test_remove_api_keys_template_with_non_dict_values():
    # Test template values that are not dicts
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "foo": 123,
                                "bar": "baz"
                            }
                        }
                    }
                }
            ]
        }
    }
    # Should not raise error
    try:
        remove_api_keys(copy.deepcopy(flow))
    except Exception as e:
        pytest.fail(f"Unexpected exception: {e}")

def test_remove_api_keys_missing_value_field():
    # Test API key dict missing 'value' field
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {
                                    "name": "api_key",
                                    "password": True
                                    # No 'value'
                                }
                            }
                        }
                    }
                }
            ]
        }
    }
    # Should not raise error, and not add 'value'
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output

def test_remove_api_keys_password_false():
    # Test that API key with password=False is not nulled
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "api_key": {
                                    "name": "api_key",
                                    "password": False,
                                    "value": "should_stay"
                                }
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output

def test_remove_api_keys_token_plural():
    # Test that 'tokens' is not matched by has_api_terms
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": {
                                "tokens": {
                                    "name": "api_tokens",
                                    "password": True,
                                    "value": "should_stay"
                                }
                            }
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output


def test_remove_api_keys_many_nodes_and_keys():
    # Test with many nodes, each with multiple API keys
    num_nodes = 100
    num_keys = 5
    nodes = []
    for i in range(num_nodes):
        template = {}
        for j in range(num_keys):
            template[f"api_key_{j}"] = {
                "name": f"service_{j}_api_key",
                "password": True,
                "value": f"secret_{i}_{j}"
            }
            template[f"non_api_{j}"] = {
                "name": f"non_api_{j}",
                "password": False,
                "value": f"visible_{i}_{j}"
            }
        node = {
            "data": {
                "node": {
                    "template": template
                }
            }
        }
        nodes.append(node)
    flow = {"data": {"nodes": nodes}}
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    for node in result["data"]["nodes"]:
        tpl = node["data"]["node"]["template"]
        for j in range(num_keys):
            pass

def test_remove_api_keys_large_template():
    # Test with a single node with a large template
    template = {}
    for i in range(500):
        template[f"api_key_{i}"] = {
            "name": f"api_key_{i}",
            "password": True,
            "value": f"secret_{i}"
        }
        template[f"other_{i}"] = {
            "name": f"other_{i}",
            "password": False,
            "value": f"val_{i}"
        }
    flow = {
        "data": {
            "nodes": [
                {
                    "data": {
                        "node": {
                            "template": template
                        }
                    }
                }
            ]
        }
    }
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    tpl = result["data"]["nodes"][0]["data"]["node"]["template"]
    for i in range(500):
        pass

def test_remove_api_keys_performance_with_mixed_data():
    # Test performance and correctness with mixed API/non-API keys in many nodes
    num_nodes = 200
    nodes = []
    for i in range(num_nodes):
        template = {
            "api_key": {
                "name": "api_key",
                "password": True,
                "value": f"api_secret_{i}"
            },
            "random": {
                "name": "random",
                "password": False,
                "value": f"random_{i}"
            }
        }
        node = {
            "data": {
                "node": {
                    "template": template
                }
            }
        }
        nodes.append(node)
    flow = {"data": {"nodes": nodes}}
    codeflash_output = remove_api_keys(copy.deepcopy(flow)); result = codeflash_output
    for i, node in enumerate(result["data"]["nodes"]):
        tpl = node["data"]["node"]["template"]
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

To edit these changes git checkout codeflash/optimize-pr11101-2026-01-05T22.56.04 and push.

Codeflash

Olayinka Adelakun and others added 6 commits December 16, 2025 13:53
…saving-flow"

This reverts commit ee71d3a, reversing
changes made to 5cf5d3f.
The optimization achieves an 11% speedup by reordering condition checks to minimize expensive operations. The key insight is that in the original code, the line profiler shows 79.2% of execution time (20.09ms) is spent on the combined condition check that includes `isinstance()`, `has_api_terms()`, and `value.get("password")`.

**What changed:**
The optimized version restructures the conditional logic by:
1. Checking `isinstance(value, dict)` first (cheapest operation)
2. Caching `value.get("password")` as `has_password` before calling `has_api_terms()`
3. Only calling `has_api_terms()` when both type and password checks pass

**Why it's faster:**
The optimization exploits Python's short-circuit evaluation more effectively:
- **Reduced `has_api_terms()` calls**: The profiler shows calls dropped from 4,523 to 2,718 (40% reduction), saving ~0.94ms in string operations
- **Eliminated redundant dictionary lookups**: The original code calls `value.get("password")` even when `has_api_terms()` returns `False`, while the optimized version caches it once
- **Better branch prediction**: By checking the boolean `has_password` before the expensive string operations, the CPU can more efficiently predict and pipeline the execution

**Impact on workloads:**
This optimization is particularly effective for flows with:
- Many template values that are dictionaries but don't have `password=True` (as shown in `test_large_scale_no_password_fields`)
- Mixed API and non-API keys where most fields aren't password-protected
- Large numbers of nodes where the cumulative effect of avoiding string operations compounds

The test results confirm the optimization works best with flows containing many non-password fields or fields that fail the password check, as these scenarios maximize the benefit of avoiding the expensive `has_api_terms()` string matching.
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Jan 5, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

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.

@github-actions github-actions bot added the community Pull Request from an external contributor label Jan 5, 2026
Base automatically changed from fix-limiting-saving-flow to main January 6, 2026 22:47
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.

1 participant