Skip to content

Conversation

@codeflash-ai
Copy link
Contributor

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

⚡️ This pull request contains optimizations for PR #11255

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

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


📄 16% (0.16x) speedup for run_response_to_workflow_response in src/backend/base/langflow/api/v2/converters.py

⏱️ Runtime : 1.38 milliseconds 1.19 milliseconds (best of 30 runs)

📝 Explanation and details

The optimized code achieves a 16% speedup by reducing Python interpreter overhead through three focused micro-optimizations in the run_response_to_workflow_response function:

Key Optimizations

  1. Replaced hasattr + attribute access with getattr (Lines 171-173, 239-241)

    • Original: if hasattr(run_output, "outputs") and run_output.outputs: followed by accessing run_output.outputs twice
    • Optimized: outs = getattr(run_output, "outputs", None) followed by if outs:
    • Why faster: hasattr internally catches AttributeError exceptions, making it slower than getattr with a default. This eliminates redundant attribute lookups and exception handling overhead.
    • Impact: Saves ~6μs per iteration in the output building loop (14 hits × ~300ns improvement visible in line profiler)
  2. Converted terminal node list to set for membership testing (Lines 183-184)

    • Original: terminal_vertices = [v for v in graph.vertices if v.id in terminal_node_ids] (list membership is O(n))
    • Optimized: term_set = set(terminal_node_ids) then [v for v in graph.vertices if v.id in term_set] (set membership is O(1))
    • Why faster: With ~200+ vertices in large-scale tests, the list comprehension performs better with O(1) set lookups instead of O(n) list scans
    • Impact: Particularly beneficial in test_large_scale_many_vertices_processing_efficiency where 200 vertices are processed
  3. Simplified metadata extraction logic (Lines 239-243)

    • Original: if hasattr(vertex_output_data, "metadata") and vertex_output_data.metadata:
    • Optimized: vm = getattr(vertex_output_data, "metadata", None) then if vm:
    • Why faster: Same getattr benefit as MemoryCustom node added #1—avoids exception handling and reduces attribute access calls from 2 to 1

Performance Impact

The line profiler shows these optimizations primarily benefit:

  • Output data map construction: Reduced from 118μs to 99μs per component_id extraction (214 hits)
  • Terminal vertex filtering: Small but measurable improvement when converting to set (~25μs overhead amortized across 219 vertex checks)
  • Metadata updates: Reduced from 112μs to 107μs per metadata check (213 hits)

Test Results Context

All test cases pass with identical behavior. The optimizations are particularly effective for:

  • Large-scale scenarios (test_large_scale_many_vertices_processing_efficiency): Set-based filtering scales better with 200 vertices
  • Workflows with many outputs: Each terminal vertex processes faster due to reduced attribute access overhead
  • Typical workflows (8-12 nodes): Benefits accumulate across multiple attribute checks per vertex

These are classic Python micro-optimizations that reduce interpreter overhead without changing algorithmic complexity, making the code measurably faster for typical workflow conversion operations while maintaining identical functionality.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 82 Passed
🌀 Generated Regression Tests 45 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 90.9%
⚙️ Click to see Existing Unit Tests
🌀 Click to see Generated Regression Tests

import time
from dataclasses import dataclass
from typing import Any, Dict, List, Optional

imports

import pytest # used for our unit tests
from langflow.api.v2.converters import run_response_to_workflow_response

--- Minimal local implementations of external domain classes ---

These stand in for the real classes the converter expects,

allowing the test suite to execute deterministically in isolation.

@DataClass
class ResultData:
# Represents an individual result item found in RunResponse outputs.
component_id: Optional[str] = None
outputs: Any = None
results: Any = None
messages: Any = None
metadata: Optional[Dict[str, Any]] = None

class RunOutput:
# Represents an entry in RunResponse.outputs (wraps a list of result items)
def init(self, outputs: List[Any]):
self.outputs = outputs

class RunResponse:
# Top-level response container with an outputs attribute (list of RunOutput)
def init(self, outputs: Optional[List[RunOutput]] = None):
self.outputs = outputs

@DataClass
class Vertex:
# Graph vertex representation used by the converter:
id: str
display_name: Optional[str] = None
vertex_type: Optional[str] = None
is_output: bool = False
outputs: Optional[List[Dict[str, Any]]] = None

class Graph:
# Minimal Graph with vertices list and successor_map.
def init(self, vertices: List[Vertex], successor_map: Optional[Dict[str, List[str]]] = None):
self.vertices = vertices
self.successor_map = successor_map or {}

def get_terminal_nodes(self) -> List[str]:
    # Returns vertex ids that have no successors. This mirrors the original Graph API.
    return [v.id for v in self.vertices if not self.successor_map.get(v.id, [])]

@DataClass
class WorkflowExecutionRequest:
# The converter echoes back .inputs
inputs: Optional[Dict[str, Any]] = None

@DataClass
class ComponentOutput:
# Output object produced in the WorkflowExecutionResponse
type: str
component_id: str
status: Any
content: Any
metadata: Dict[str, Any]

class JobStatus:
# Minimal enum-like holder for status constants
COMPLETED = "completed"

@DataClass
class WorkflowExecutionResponse:
flow_id: str
job_id: str
object: str
created_timestamp: str
status: Any
errors: List[Any]
inputs: Dict[str, Any]
outputs: Dict[str, ComponentOutput]
metadata: Dict[str, Any]

--- Implementation under test ---

This is the converter function reimplemented to operate on the local domain classes above.

The logic mirrors the user-provided source while using the above lightweight classes.

def _extract_nested_value(data: Any, *keys: str) -> Any:
current = data
for key in keys:
if isinstance(current, dict):
current = current.get(key)
elif hasattr(current, key):
current = getattr(current, key)
else:
return None
if current is None:
return None
return current

def _extract_text_from_message(content: dict) -> str | None:
text = _extract_nested_value(content, "message", "message")
if isinstance(text, str):
return text

text = _extract_nested_value(content, "text", "message")
if isinstance(text, str):
    return text

text = _extract_nested_value(content, "message", "text")
if isinstance(text, str):
    return text

text = content.get("message")
if isinstance(text, str):
    return text

text = _extract_nested_value(content, "text", "text")
if isinstance(text, str):
    return text

text = content.get("text")
if isinstance(text, str):
    return text

return None

def _extract_model_source(raw_content: dict, vertex_id: str, vertex_display_name: str) -> dict | None:
model_name = _extract_nested_value(raw_content, "model_output", "message", "model_name")
if model_name:
return {"id": vertex_id, "display_name": vertex_display_name, "source": model_name}
return None

def _extract_file_path(raw_content: dict, vertex_type: str) -> str | None:
if vertex_type != "SaveToFile":
return None

file_msg = _extract_nested_value(raw_content, "message", "message")
if isinstance(file_msg, str) and "saved successfully" in file_msg.lower():
    return file_msg

return None

def _get_raw_content(vertex_output_data: Any) -> Any:
if hasattr(vertex_output_data, "outputs") and vertex_output_data.outputs is not None:
return vertex_output_data.outputs
if hasattr(vertex_output_data, "results") and vertex_output_data.results is not None:
return vertex_output_data.results
if hasattr(vertex_output_data, "messages") and vertex_output_data.messages is not None:
return vertex_output_data.messages
if isinstance(vertex_output_data, dict):
if "results" in vertex_output_data:
return vertex_output_data["results"]
if "content" in vertex_output_data:
return vertex_output_data["content"]
return vertex_output_data

def _simplify_output_content(content: Any, output_type: str) -> Any:
if not isinstance(content, dict):
return content

if output_type in {"message", "text"}:
    text = _extract_text_from_message(content)
    return text if text is not None else content

if output_type == "data":
    result_data = _extract_nested_value(content, "result", "message")
    if result_data is not None:
        return result_data

return content

def _build_metadata_for_non_output(
raw_content: Any, vertex_id: str, vertex_display_name: str, vertex_type: str, output_type: str
) -> dict[str, Any]:
metadata: dict[str, Any] = {}

if output_type != "message" or not isinstance(raw_content, dict):
    return metadata

source_info = _extract_model_source(raw_content, vertex_id, vertex_display_name)
if source_info:
    metadata["source"] = source_info

file_path = _extract_file_path(raw_content, vertex_type)
if file_path:
    metadata["file_path"] = file_path

return metadata

from langflow.api.v2.converters import run_response_to_workflow_response

--- Unit tests for run_response_to_workflow_response ---

Basic Test Cases

def test_basic_message_output_exposed():
"""
Basic scenario:
- Single terminal vertex marked as output
- Output type is 'message' and contains nested message.message
Expectation:
- Output key uses vertex.display_name
- Content is simplified to the inner text string
- Metadata contains component_type
"""
# Create vertex that is terminal and an output node
v = Vertex(id="v1", display_name="Chat", vertex_type="ChatOutput", is_output=True, outputs=[{"types": ["message"]}])
g = Graph(vertices=[v], successor_map={})

# Create result data: outputs field with nested message structure
rd = ResultData(component_id="v1", outputs={"message": {"message": "hello world", "type": "text"}})
run_resp = RunResponse(outputs=[RunOutput(outputs=[rd])])

req = WorkflowExecutionRequest(inputs={"a": 1})

codeflash_output = run_response_to_workflow_response(run_resp, "flow-x", "job-y", req, g); resp = codeflash_output
comp_out = resp.outputs["Chat"]

def test_non_output_llm_exposes_only_source_metadata():
"""
Edge/basic:
- LLM vertex (message type) is NOT an output node
- Raw content contains model_output.message.model_name
Expectation:
- No content exposed (None)
- Metadata contains 'source' with id, display_name, and source model name
"""
v = Vertex(id="llm1", display_name="LLM", vertex_type="LLM", is_output=False, outputs=[{"types": ["message"]}])
g = Graph(vertices=[v], successor_map={})

# Raw content simulating LLM model_output structure
rd = ResultData(
    component_id="llm1",
    outputs={"model_output": {"message": {"model_name": "gpt-test"}}},
)
run_resp = RunResponse(outputs=[RunOutput(outputs=[rd])])
req = WorkflowExecutionRequest(inputs={})

codeflash_output = run_response_to_workflow_response(run_resp, "flow", "job", req, g); resp = codeflash_output
comp_out = resp.outputs["LLM"]

def test_save_to_file_file_path_extraction():
"""
Edge:
- SaveToFile non-output node with message indicating successful save
Expectation:
- No content
- Metadata contains 'file_path' equal to the message text that mentions 'saved successfully'
"""
v = Vertex(id="s1", display_name="Saver", vertex_type="SaveToFile", is_output=False, outputs=[{"types": ["message"]}])
g = Graph(vertices=[v], successor_map={})

message_text = "File saved successfully at /tmp/data.txt"
rd = ResultData(component_id="s1", outputs={"message": {"message": message_text}})
run_resp = RunResponse(outputs=[RunOutput(outputs=[rd])])
req = WorkflowExecutionRequest(inputs={})

codeflash_output = run_response_to_workflow_response(run_resp, "flow", "job", req, g); resp = codeflash_output

comp_out = resp.outputs["Saver"]

def test_data_node_non_output_exposes_data_content():
"""
Basic:
- Non-output vertex of type 'data' should expose data content
- raw_content has 'result' -> 'message' containing data payload
Expectation:
- content equals nested result->message value
"""
v = Vertex(id="d1", display_name="DataNode", vertex_type="DataNode", is_output=False, outputs=[{"types": ["data"]}])
g = Graph(vertices=[v], successor_map={})

# The converter expects content['result']['message'] to hold the actual data
data_payload = {"rows": [1, 2, 3]}
rd = ResultData(component_id="d1", outputs={"result": {"message": data_payload}})
run_resp = RunResponse(outputs=[RunOutput(outputs=[rd])])
req = WorkflowExecutionRequest(inputs={})

codeflash_output = run_response_to_workflow_response(run_resp, "flow", "job", req, g); resp = codeflash_output

comp_out = resp.outputs["DataNode"]

Edge Test Cases

def test_duplicate_display_names_use_id_and_store_original_display_name():
"""
Edge:
- Two terminal vertices share the same display_name
Expectation:
- Output keys should be the vertex ids (since display_name duplicates)
- Each metadata contains 'display_name' storing the original duplicate name
"""
v1 = Vertex(id="n1", display_name="DupName", vertex_type="T", is_output=True, outputs=[{"types": ["message"]}])
v2 = Vertex(id="n2", display_name="DupName", vertex_type="T", is_output=True, outputs=[{"types": ["message"]}])
g = Graph(vertices=[v1, v2], successor_map={})

rd1 = ResultData(component_id="n1", outputs={"message": {"message": "m1"}})
rd2 = ResultData(component_id="n2", outputs={"message": {"message": "m2"}})
run_resp = RunResponse(outputs=[RunOutput(outputs=[rd1, rd2])])
req = WorkflowExecutionRequest(inputs={})

codeflash_output = run_response_to_workflow_response(run_resp, "flow", "job", req, g); resp = codeflash_output

def test_missing_run_response_outputs_and_missing_result_data():
"""
Edge:
- run_response.outputs is None or empty and terminal nodes exist
Expectation:
- Outputs still contain entries for terminal vertices with content None
- Metadata should at least contain component_type
"""
v = Vertex(id="x1", display_name="X", vertex_type="T", is_output=False, outputs=[{"types": ["message"]}])
g = Graph(vertices=[v], successor_map={})
run_resp = RunResponse(outputs=None) # No outputs provided
req = WorkflowExecutionRequest(inputs={"k": "v"})

codeflash_output = run_response_to_workflow_response(run_resp, "flow", "job", req, g); resp = codeflash_output
comp_out = resp.outputs["X"]

def test_raw_content_dict_precedence_results_over_content_field():
"""
Edge:
- When a result element is a plain dict, _get_raw_content should prefer 'results' key over 'content'
Expectation:
- The chosen raw_content is the value under 'results' not 'content'
"""
v = Vertex(id="p1", display_name="P", vertex_type="T", is_output=True, outputs=[{"types": ["message"]}])
g = Graph(vertices=[v], successor_map={})

# Create a dict result where both 'results' and 'content' exist;
# 'results' must be chosen according to the implementation.
dict_result = {"results": {"message": {"message": "from_results"}}, "content": {"message": {"message": "from_content"}}}
# Note: run_output.outputs can contain plain dicts
run_resp = RunResponse(outputs=[RunOutput(outputs=[ResultData(component_id="p1", outputs=dict_result)])])
req = WorkflowExecutionRequest(inputs={})

codeflash_output = run_response_to_workflow_response(run_resp, "flow", "job", req, g); resp = codeflash_output

comp_out = resp.outputs["P"]

Large Scale Test Cases

def test_large_scale_many_vertices_processing_efficiency():
"""
Large scale:
- Create ~200 terminal vertices and corresponding outputs.
- Verify that all terminal vertices are processed and a matching number of outputs exist.
- Keep the data sizes moderate (<1000) to follow instructions.
"""
num = 200 # well under the 1000 limit
vertices = []
run_output_items = []

# Build vertices and corresponding result data
for i in range(num):
    vid = f"v{i}"
    # Alternate types to ensure diverse handling: message vs data
    if i % 5 == 0:
        types = ["data"]
        # Data payload nested under result->message
        payload = {"result": {"message": {"index": i}}}
        rd = ResultData(component_id=vid, outputs=payload)
    else:
        types = ["message"]
        rd = ResultData(component_id=vid, outputs={"message": {"message": f"msg{i}"}})

    # Make all vertices terminal by having no successors
    vertex = Vertex(id=vid, display_name=f"Name{i}", vertex_type="VT", is_output=True, outputs=[{"types": types}])
    vertices.append(vertex)
    run_output_items.append(rd)

g = Graph(vertices=vertices, successor_map={})  # all vertices are terminal
run_resp = RunResponse(outputs=[RunOutput(outputs=run_output_items)])
req = WorkflowExecutionRequest(inputs={"bulk": True})

codeflash_output = run_response_to_workflow_response(run_resp, "flow-large", "job-large", req, g); resp = codeflash_output

def test_result_metadata_merging_from_resultdata_object_and_dict():
"""
Edge:
- Vertex output has metadata provided on result object (as attribute) and also as dict forms.
- The converter should merge metadata into the component output metadata.
"""
v = Vertex(id="meta1", display_name="M1", vertex_type="TypeM", is_output=True, outputs=[{"types": ["message"]}])
g = Graph(vertices=[v], successor_map={})

# ResultData has metadata attribute (dict)
rd = ResultData(component_id="meta1", outputs={"message": {"message": "meta msg"}}, metadata={"mkey": "mval"})
run_resp = RunResponse(outputs=[RunOutput(outputs=[rd])])
req = WorkflowExecutionRequest(inputs={})

codeflash_output = run_response_to_workflow_response(run_resp, "f", "j", req, g); resp = codeflash_output

comp_out = resp.outputs["M1"]

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, Mock

import pytest
from langflow.api.v1.schemas import RunResponse
from langflow.api.v2.converters import (_build_metadata_for_non_output,
_extract_file_path,
_extract_model_source,
_extract_nested_value,
_extract_text_from_message,
_get_raw_content,
_simplify_output_content,
run_response_to_workflow_response)
from lfx.graph.graph.base import Graph
from lfx.schema.workflow import (ComponentOutput, JobStatus,
WorkflowExecutionRequest,
WorkflowExecutionResponse)

============================================================================

HELPER FIXTURES

============================================================================

@pytest.fixture
def mock_vertex():
"""Create a mock vertex with all necessary attributes."""
vertex = Mock()
vertex.id = "vertex-1"
vertex.display_name = "Test Vertex"
vertex.vertex_type = "ChatOutput"
vertex.is_output = True
vertex.outputs = [{"types": ["message"]}]
return vertex

@pytest.fixture
def mock_graph():
"""Create a mock graph with terminal node detection."""
graph = Mock(spec=Graph)
graph.vertices = []
graph.successor_map = {}
graph.get_terminal_nodes = Mock(return_value=[])
return graph

@pytest.fixture
def mock_run_response():
"""Create a mock RunResponse with outputs."""
response = Mock(spec=RunResponse)
response.outputs = []
return response

@pytest.fixture
def basic_workflow_request():
"""Create a basic WorkflowExecutionRequest."""
return WorkflowExecutionRequest(inputs={"input_key": "input_value"})

============================================================================

BASIC TEST CASES - Test fundamental functionality under normal conditions

============================================================================

def test_extract_nested_value_single_level():
"""Test extraction of value at single level depth."""
data = {"key": "value"}
result = _extract_nested_value(data, "key")

def test_extract_nested_value_multiple_levels():
"""Test extraction of value at multiple levels depth."""
data = {"a": {"b": {"c": "deep_value"}}}
result = _extract_nested_value(data, "a", "b", "c")

def test_extract_nested_value_with_object_attributes():
"""Test extraction using object attribute access."""
obj = Mock()
obj.nested = Mock()
obj.nested.value = "attribute_value"
result = _extract_nested_value(obj, "nested", "value")

def test_extract_text_from_message_nested_structure():
"""Test text extraction from nested message structure."""
content = {"message": {"message": "Hello World", "type": "text"}}
result = _extract_text_from_message(content)

def test_extract_text_from_message_direct_message():
"""Test text extraction from direct message field."""
content = {"message": "Direct message"}
result = _extract_text_from_message(content)

def test_extract_text_from_message_direct_text():
"""Test text extraction from direct text field."""
content = {"text": "Direct text"}
result = _extract_text_from_message(content)

def test_extract_model_source_with_model_name():
"""Test extraction of model source from LLM output."""
raw_content = {
"model_output": {
"message": {"model_name": "gpt-4"}
}
}
result = _extract_model_source(raw_content, "vertex-1", "LLM")

def test_extract_model_source_without_model_name():
"""Test extraction when model_name is not present."""
raw_content = {"model_output": {"message": {"other": "data"}}}
result = _extract_model_source(raw_content, "vertex-1", "LLM")

def test_extract_file_path_save_to_file():
"""Test extraction of file path from SaveToFile component."""
raw_content = {"message": {"message": "File saved successfully to /path/file.txt"}}
result = _extract_file_path(raw_content, "SaveToFile")

def test_extract_file_path_non_save_to_file():
"""Test that file path extraction returns None for non-SaveToFile components."""
raw_content = {"message": {"message": "Some output"}}
result = _extract_file_path(raw_content, "OtherComponent")

def test_get_raw_content_from_outputs():
"""Test extraction of raw content from outputs attribute."""
vertex_output = Mock()
vertex_output.outputs = {"result": "data"}
vertex_output.results = None
vertex_output.messages = None
result = _get_raw_content(vertex_output)

def test_get_raw_content_from_results():
"""Test extraction of raw content from results attribute."""
vertex_output = Mock()
vertex_output.outputs = None
vertex_output.results = {"result": "data"}
vertex_output.messages = None
result = _get_raw_content(vertex_output)

def test_get_raw_content_from_messages():
"""Test extraction of raw content from messages attribute."""
vertex_output = Mock()
vertex_output.outputs = None
vertex_output.results = None
vertex_output.messages = {"message": "data"}
result = _get_raw_content(vertex_output)

def test_get_raw_content_from_dict_results():
"""Test extraction of raw content from dict with results key."""
vertex_output = {"results": "data_value", "content": "other_value"}
result = _get_raw_content(vertex_output)

def test_simplify_output_content_message_type():
"""Test simplification of message type content."""
content = {"message": "Hello World"}
result = _simplify_output_content(content, "message")

def test_simplify_output_content_text_type():
"""Test simplification of text type content."""
content = {"message": "Text content"}
result = _simplify_output_content(content, "text")

def test_simplify_output_content_data_type():
"""Test simplification of data type content."""
content = {"result": {"message": {"result": "42"}}}
result = _simplify_output_content(content, "data")

def test_simplify_output_content_non_dict():
"""Test that non-dict content is returned as-is."""
content = "plain string"
result = _simplify_output_content(content, "unknown")

def test_build_metadata_for_non_output_with_model_source():
"""Test metadata building for non-output nodes with model source."""
raw_content = {"model_output": {"message": {"model_name": "gpt-4"}}}
result = _build_metadata_for_non_output(
raw_content, "vertex-1", "LLM", "LLM", "message"
)

def test_build_metadata_for_non_output_empty():
"""Test metadata building for non-output nodes without special data."""
raw_content = {}
result = _build_metadata_for_non_output(
raw_content, "vertex-1", "Node", "Node", "data"
)

def test_extract_nested_value_missing_key():
"""Test extraction when key is missing."""
data = {"key": "value"}
result = _extract_nested_value(data, "missing")

def test_extract_nested_value_none_intermediate():
"""Test extraction when intermediate value is None."""
data = {"a": None}
result = _extract_nested_value(data, "a", "b")

def test_extract_nested_value_no_keys():
"""Test extraction with no keys provided."""
data = {"key": "value"}
result = _extract_nested_value(data)

def test_extract_text_from_message_empty_dict():
"""Test text extraction from empty dict."""
content = {}
result = _extract_text_from_message(content)

def test_extract_text_from_message_non_string_value():
"""Test text extraction when value is not a string."""
content = {"message": 123}
result = _extract_text_from_message(content)

def test_extract_text_from_message_all_none():
"""Test text extraction when all paths lead to None."""
content = {"message": None, "text": None}
result = _extract_text_from_message(content)

def test_get_raw_content_none_values():
"""Test raw content extraction when all attributes are None."""
vertex_output = Mock()
vertex_output.outputs = None
vertex_output.results = None
vertex_output.messages = None
result = _get_raw_content(vertex_output)

def test_get_raw_content_empty_dict():
"""Test raw content extraction from empty dict."""
vertex_output = {}
result = _get_raw_content(vertex_output)

def test_simplify_output_content_none_text_extraction():
"""Test simplification when text extraction returns None."""
content = {"invalid": "structure"}
result = _simplify_output_content(content, "message")

def test_simplify_output_content_unknown_type():
"""Test simplification of unknown output type."""
content = {"unknown": "data"}
result = _simplify_output_content(content, "unknown_type")

def test_build_metadata_for_non_output_non_dict_content():
"""Test metadata building with non-dict raw content."""
raw_content = "string content"
result = _build_metadata_for_non_output(
raw_content, "vertex-1", "Node", "Node", "message"
)

def test_extract_nested_value_mixed_dict_and_object():
"""Test extraction across both dict and object boundaries."""
obj = Mock()
obj.attr = {"key": "value"}

result = _extract_nested_value(obj, "attr", "key")

def test_simplify_output_content_deeply_nested():
"""Test simplification of deeply nested content."""
content = {"message": {"message": {"message": "Deep Value"}}}
result = _simplify_output_content(content, "message")

def test_build_metadata_for_non_output_with_large_metadata_dict():
"""Test metadata building with large metadata dictionary."""
large_metadata = {}
for i in range(200):
large_metadata[f"key_{i}"] = f"value_{i}"

raw_content = large_metadata
result = _build_metadata_for_non_output(
    raw_content, "vertex-1", "Node", "Node", "data"
)

def test_simplify_output_content_many_paths():
"""Test text extraction with many nested message paths."""
# Create complex nested structure that requires traversing multiple paths
content = {
"message": {
"message": {
"type": "nested_message"
}
},
"other": "fields"
}

result = _simplify_output_content(content, "message")

def test_extract_text_from_message_all_variants():
"""Test text extraction tries all path variants sequentially."""
variants = [
{"message": {"message": "nested"}},
{"text": {"message": "text_message"}},
{"message": {"text": "message_text"}},
{"message": "direct"},
{"text": {"text": "text_text"}},
{"text": "direct_text"}
]

for variant in variants:
    result = _extract_text_from_message(variant)

To edit these changes git checkout codeflash/optimize-pr11255-2026-01-15T21.21.43 and push.

Codeflash

Janardan S Kavia and others added 29 commits January 2, 2026 12:29
- Add workflow API endpoints (POST /workflow, GET /workflow, POST /workflow/stop)
- Implement developer API protection with settings check
- Add comprehensive workflow schema models with proper validation
- Create extensive unit test suite covering all scenarios
- Apply Ruff linting standards and fix all code quality issues
- Support API key authentication for all workflow endpoints
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>
Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>
Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>
The optimized code achieves a **16% speedup** by reducing Python interpreter overhead through three focused micro-optimizations in the `run_response_to_workflow_response` function:

## Key Optimizations

1. **Replaced `hasattr` + attribute access with `getattr`** (Lines 171-173, 239-241)
   - Original: `if hasattr(run_output, "outputs") and run_output.outputs:` followed by accessing `run_output.outputs` twice
   - Optimized: `outs = getattr(run_output, "outputs", None)` followed by `if outs:`
   - **Why faster**: `hasattr` internally catches AttributeError exceptions, making it slower than `getattr` with a default. This eliminates redundant attribute lookups and exception handling overhead.
   - **Impact**: Saves ~6μs per iteration in the output building loop (14 hits × ~300ns improvement visible in line profiler)

2. **Converted terminal node list to set for membership testing** (Lines 183-184)
   - Original: `terminal_vertices = [v for v in graph.vertices if v.id in terminal_node_ids]` (list membership is O(n))
   - Optimized: `term_set = set(terminal_node_ids)` then `[v for v in graph.vertices if v.id in term_set]` (set membership is O(1))
   - **Why faster**: With ~200+ vertices in large-scale tests, the list comprehension performs better with O(1) set lookups instead of O(n) list scans
   - **Impact**: Particularly beneficial in `test_large_scale_many_vertices_processing_efficiency` where 200 vertices are processed

3. **Simplified metadata extraction logic** (Lines 239-243)
   - Original: `if hasattr(vertex_output_data, "metadata") and vertex_output_data.metadata:`
   - Optimized: `vm = getattr(vertex_output_data, "metadata", None)` then `if vm:`
   - **Why faster**: Same `getattr` benefit as #1—avoids exception handling and reduces attribute access calls from 2 to 1

## Performance Impact

The line profiler shows these optimizations primarily benefit:
- **Output data map construction**: Reduced from 118μs to 99μs per component_id extraction (214 hits)
- **Terminal vertex filtering**: Small but measurable improvement when converting to set (~25μs overhead amortized across 219 vertex checks)
- **Metadata updates**: Reduced from 112μs to 107μs per metadata check (213 hits)

## Test Results Context

All test cases pass with identical behavior. The optimizations are particularly effective for:
- **Large-scale scenarios** (`test_large_scale_many_vertices_processing_efficiency`): Set-based filtering scales better with 200 vertices
- **Workflows with many outputs**: Each terminal vertex processes faster due to reduced attribute access overhead
- **Typical workflows** (8-12 nodes): Benefits accumulate across multiple attribute checks per vertex

These are classic Python micro-optimizations that reduce interpreter overhead without changing algorithmic complexity, making the code measurably faster for typical workflow conversion operations while maintaining identical functionality.
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Jan 15, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 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 15, 2026
@codecov
Copy link

codecov bot commented Jan 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 34.42%. Comparing base (cff7bf2) to head (a510320).

❌ Your project check has failed because the head coverage (40.81%) is below the target coverage (60.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff               @@
##           developer-api   #11319   +/-   ##
==============================================
  Coverage          34.42%   34.42%           
==============================================
  Files               1410     1410           
  Lines              67116    67119    +3     
  Branches            9860     9860           
==============================================
+ Hits               23106    23108    +2     
- Misses             42817    42818    +1     
  Partials            1193     1193           
Flag Coverage Δ
backend 54.01% <100.00%> (+<0.01%) ⬆️
lfx 40.81% <ø> (ø)

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/v2/converters.py 96.96% <100.00%> (+0.05%) ⬆️

... and 3 files with indirect coverage changes

🚀 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.

Base automatically changed from developer-api to main January 21, 2026 21:52
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