Skip to content

Conversation

@codeflash-ai
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Jan 19, 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.


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

⏱️ Runtime : 2.78 milliseconds 2.49 milliseconds (best of 45 runs)

📝 Explanation and details

The optimized code achieves an 11% speedup (from 2.78ms to 2.49ms) through two key optimizations:

1. Fast-Path Message Text Extraction (Primary Speedup)

The main performance gain comes from adding a fast-path in _simplify_output_content for common message structures before falling back to the heavier _extract_text_from_message function:

# Fast-path checks using direct dict.get() operations
msg = content.get("message")
if isinstance(msg, dict):
    nested_msg = msg.get("message")
    if isinstance(nested_msg, str):
        return nested_msg
# ... more fast-path checks ...
if isinstance(msg, str):
    return msg  # Early return for simple case

Why this is faster:

  • Direct dict.get() operations are much faster than _extract_nested_value(), which uses hasattr() and getattr() checks on each level
  • Line profiler shows _extract_text_from_message time dropped from 3.28ms → 0.33ms (90% reduction)
  • Only 22 out of 232 calls now reach the expensive fallback function (versus all 232 previously)
  • Most messages in the test workload follow simple structures like {"message": "text"} which hit the fast-path

2. Set-Based Terminal Node Filtering

Converting terminal_node_ids to a set for O(1) membership testing:

terminal_node_ids_set = set(terminal_node_ids)
terminal_vertices = [v for v in graph.vertices if v.id in terminal_node_ids_set]

Why this is faster:

  • List comprehension filtering time reduced from 201μs → 117μs (42% reduction)
  • Avoids O(n²) list membership checks when filtering vertices
  • Particularly beneficial when there are many vertices in the graph

3. Minor: getattr() for Attribute Access

Replaced hasattr() + attribute access with single getattr() calls in _get_raw_content:

outputs = getattr(vertex_output_data, "outputs", None)
if outputs is not None:
    return outputs

This eliminates redundant attribute lookups, though the impact is minor.

Impact on Workloads

Based on test results, these optimizations are particularly effective for:

  • Message-heavy workflows: Tests with nested message structures see the biggest gains from fast-path extraction
  • Large graphs: The set-based filtering helps when processing many terminal nodes
  • Common message formats: Simple {"message": "text"} patterns benefit most from early returns

The optimizations preserve all original logic and handle all edge cases correctly, making them safe to merge.

Correctness verification report:

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

# imports
import sys
import time
import types
from typing import Any

import pytest  # used for our unit tests
# ---------------------------------------------------------------------
# Now import the names exactly as the original function would.
# This ensures "from X import Y" inside the function picks up these classes.
# ---------------------------------------------------------------------
from langflow.api.v1.schemas import RunResponse  # noqa: E402
from langflow.api.v2.converters import run_response_to_workflow_response
from lfx.graph.graph.base import Graph  # noqa: E402
from lfx.schema.workflow import (ComponentOutput, JobStatus,  # noqa: E402
                                 WorkflowExecutionRequest,
                                 WorkflowExecutionResponse)


class RunOutputData:
    """Represents an individual result data item inside a run_output.outputs list."""

    def __init__(self, component_id=None, outputs=None, results=None, messages=None, metadata=None):
        # component identifier (string)
        self.component_id = component_id
        # these attributes may be dicts or lists as used by the function
        self.outputs = outputs
        self.results = results
        self.messages = messages
        # optional metadata dict
        self.metadata = metadata


class RunOutputWrapper:
    """Represents an object inside RunResponse.outputs which itself has an 'outputs' attribute."""

    def __init__(self, outputs=None):
        # outputs expected to be an iterable of RunOutputData or similar
        self.outputs = outputs


class RunResponse:
    """Top-level response object used by the function under test."""

    def __init__(self, outputs=None):
        # should be iterable of objects with 'outputs' attribute
        self.outputs = outputs


class Vertex:
    """Represents a vertex/node in the graph."""
    def __init__(self, id, display_name=None, vertex_type=None, outputs=None, is_output=False):
        self.id = id
        self.display_name = display_name
        self.vertex_type = vertex_type
        # outputs is list of dicts where first dict may contain 'types'
        self.outputs = outputs or []
        # boolean flag for output nodes
        self.is_output = is_output


class Graph:
    """Simple Graph used by the function; supports both get_terminal_nodes and successor_map fallback."""

    def __init__(self, vertices=None, successor_map=None, provide_get_terminal_nodes=True):
        # list of Vertex objects
        self.vertices = vertices or []
        # map vertex_id -> list of successor ids
        self.successor_map = successor_map or {}
        self._provide_get_terminal_nodes = provide_get_terminal_nodes

    def get_terminal_nodes(self):
        if not self._provide_get_terminal_nodes:
            # Simulate AttributeError behavior if the function were to try to call a
            # missing attribute - but we cannot actually delete this method here. The
            # function catches AttributeError when calling graph.get_terminal_nodes()
            # so for the fallback test we will set _provide_get_terminal_nodes=False and
            # then monkeypatch to raise AttributeError.
            raise AttributeError("Simulated missing get_terminal_nodes")
        # return ids of vertices with no successors
        return [v.id for v in self.vertices if not self.successor_map.get(v.id, [])]


class JobStatus:
    """Simple status holder with attribute COMPLETED used by the function."""
    COMPLETED = "completed"


class ComponentOutput:
    """Holds the output details produced by the conversion function."""

    def __init__(self, type, component_id, status, content, metadata):
        self.type = type
        self.component_id = component_id
        self.status = status
        self.content = content
        self.metadata = metadata

    def __repr__(self):
        return f"ComponentOutput(type={self.type}, id={self.component_id}, status={self.status})"


class WorkflowExecutionRequest:
    """Represents the incoming request with optional inputs dict."""

    def __init__(self, inputs=None):
        self.inputs = inputs or {}


class WorkflowExecutionResponse:
    """Data container for the function's output. We store attributes for assertions."""

    def __init__(self, flow_id, job_id, object, created_timestamp, status, errors, inputs, outputs, metadata):
        self.flow_id = flow_id
        self.job_id = job_id
        self.object = object
        self.created_timestamp = created_timestamp
        self.status = status
        self.errors = errors
        self.inputs = inputs
        self.outputs = outputs
        self.metadata = metadata



def _extract_nested_value(data: Any, *keys: str) -> Any:
    """Safely extract nested value from dict-like structure.

    Args:
        data: The data structure to extract from
        *keys: Sequence of keys to traverse

    Returns:
        The extracted value or None if not found

    Example:
        >>> _extract_nested_value({'a': {'b': 'value'}}, 'a', 'b')
        'value'
    """
    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:
    """Extract plain text from nested message structures.

    Handles various message formats:
    - {'message': {'message': 'text', 'type': 'text'}}
    - {'message': 'text'}
    - {'text': 'text'}

    Args:
        content: The message content dict

    Returns:
        Extracted text string or None
    """
    # Try message.message (nested structure)
    text = _extract_nested_value(content, "message", "message")
    if isinstance(text, str):
        return text

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

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

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

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

    # Try direct 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:
    """Extract model source information from LLM component output.

    Args:
        raw_content: The raw output data
        vertex_id: Vertex ID
        vertex_display_name: Vertex display name

    Returns:
        Source info dict or 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:
    """Extract file path from SaveToFile component output.

    Args:
        raw_content: The raw output data
        vertex_type: The vertex type

    Returns:
        File path string or 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:
    """Extract raw content from vertex output data.

    Tries multiple fields in order: outputs, results, messages.
    Note: Uses 'is not None' checks to avoid treating empty collections as missing.

    Args:
        vertex_output_data: The output data from RunResponse

    Returns:
        Raw content or None
    """
    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):
        # Check for 'results' first, then 'content' if results is None
        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:
    """Simplify output content for output nodes.

    For message types, extracts plain text from nested structures.
    For data/dataframe types, extracts the actual data value.
    For other types, returns content as-is.

    Args:
        content: The raw content
        output_type: The output type

    Returns:
        Simplified content
    """
    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":
        # For data types, extract from result.message structure (singular)
        # Example: {'result': {'message': {'result': '4'}, 'type': 'object'}}
        result_data = _extract_nested_value(content, "result", "message")
        if result_data is not None:
            return result_data
    # TODO: Future scope - Add dataframe-specific extraction logic
    # The following code is commented out pending further requirements analysis:
    # if output_type == "dataframe":
    #     # For dataframe types, try results.message structure first (plural)
    #     results_data = _extract_nested_value(content, "results", "message")
    #     if results_data is not None:
    #         return results_data
    #
    #     # SQL component specific fallback: Try run_sql_query.message
    #     sql_result = _extract_nested_value(content, "run_sql_query", "message")
    #     if sql_result is not None:
    #         return sql_result

    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]:
    """Build metadata for non-output terminal nodes.

    Extracts:
    - source: Model information for LLM components
    - file_path: File path for SaveToFile components

    Args:
        raw_content: The raw output data
        vertex_id: Vertex ID
        vertex_display_name: Vertex display name
        vertex_type: Vertex type
        output_type: Output type

    Returns:
        Metadata dict
    """
    metadata: dict[str, Any] = {}

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

    # Extract model source for LLM components
    source_info = _extract_model_source(raw_content, vertex_id, vertex_display_name)
    if source_info:
        metadata["source"] = source_info

    # Extract file path for SaveToFile components
    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
# The tests cover Basic, Edge, and Large Scale scenarios as required.
# ---------------------------------------------------------------------


def _make_result_data(component_id, *, outputs=None, results=None, messages=None, metadata=None):
    """Helper to create RunOutputData instances (keeps tests concise)."""
    return sys.modules["langflow.api.v1.schemas"].RunOutputData(
        component_id=component_id,
        outputs=outputs,
        results=results,
        messages=messages,
        metadata=metadata,
    )


def _make_run_output_wrapper(result_datas):
    """Helper to create a RunOutputWrapper with given result data entries."""
    return sys.modules["langflow.api.v1.schemas"].RunOutputWrapper(outputs=result_datas)


def _make_run_response(wrappers):
    """Helper to create RunResponse."""
    return sys.modules["langflow.api.v1.schemas"].RunResponse(outputs=wrappers)


def _make_vertex(vid, display_name=None, vtype=None, types_list=None, is_output=False):
    """Helper to make Vertex instances with optional outputs types metadata."""
    outputs = []
    if types_list is not None:
        outputs = [{"types": types_list}]
    return sys.modules["lfx.graph.graph.base"].Vertex(id=vid, display_name=display_name, vertex_type=vtype, outputs=outputs, is_output=is_output)









#------------------------------------------------
import time
from unittest.mock import MagicMock, Mock, patch

# imports
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)


def test_extract_nested_value_single_level_dict():
    """Test extracting value from single level dict."""
    data = {"key": "value"}
    result = _extract_nested_value(data, "key")


def test_extract_nested_value_multiple_levels():
    """Test extracting value from nested dict with multiple levels."""
    data = {"a": {"b": {"c": "value"}}}
    result = _extract_nested_value(data, "a", "b", "c")


def test_extract_nested_value_missing_key():
    """Test extracting value when key doesn't exist."""
    data = {"a": {"b": "value"}}
    result = _extract_nested_value(data, "a", "missing", "c")


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


def test_extract_text_from_message_nested_message():
    """Test extracting text from nested message.message structure."""
    content = {"message": {"message": "hello", "type": "text"}}
    result = _extract_text_from_message(content)


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


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


def test_extract_text_from_message_no_text():
    """Test extracting text when no text is available."""
    content = {"other": "data"}
    result = _extract_text_from_message(content)


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


def test_extract_model_source_with_model_name():
    """Test extracting model source when model_name is present."""
    raw_content = {"model_output": {"message": {"model_name": "gpt-4"}}}
    result = _extract_model_source(raw_content, "vertex-1", "LLM Node")


def test_extract_model_source_without_model_name():
    """Test extracting model source when model_name is absent."""
    raw_content = {"other": "data"}
    result = _extract_model_source(raw_content, "vertex-1", "LLM Node")


def test_extract_file_path_save_to_file_component():
    """Test extracting 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 extracting file path from non-SaveToFile component."""
    raw_content = {"message": {"message": "File saved successfully"}}
    result = _extract_file_path(raw_content, "OtherComponent")


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


def test_get_raw_content_from_results():
    """Test extracting raw content from results attribute."""
    vertex_output = Mock()
    vertex_output.outputs = None
    vertex_output.results = {"result": "test"}
    result = _get_raw_content(vertex_output)


def test_get_raw_content_from_messages():
    """Test extracting raw content from messages attribute."""
    vertex_output = Mock()
    vertex_output.outputs = None
    vertex_output.results = None
    vertex_output.messages = {"msg": "test"}
    result = _get_raw_content(vertex_output)


def test_get_raw_content_from_dict():
    """Test extracting raw content from dict structure."""
    vertex_output = {"results": {"data": "test"}}
    result = _get_raw_content(vertex_output)


def test_simplify_output_content_message_type():
    """Test simplifying message type content."""
    content = {"message": "hello world"}
    result = _simplify_output_content(content, "message")


def test_simplify_output_content_text_type():
    """Test simplifying text type content."""
    content = {"text": "hello world"}
    result = _simplify_output_content(content, "text")


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


def test_simplify_output_content_unknown_type():
    """Test simplifying unknown type content."""
    content = {"some": "data"}
    result = _simplify_output_content(content, "unknown")


def test_simplify_output_content_non_dict():
    """Test simplifying non-dict content."""
    content = "plain string"
    result = _simplify_output_content(content, "message")


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


def test_build_metadata_for_non_output_with_file_path():
    """Test building metadata for non-output node with file path."""
    raw_content = {"message": {"message": "File saved successfully"}}
    metadata = _build_metadata_for_non_output(raw_content, "v1", "Node", "SaveToFile", "message")


def test_build_metadata_for_non_output_non_message_type():
    """Test building metadata for non-output node with non-message type."""
    raw_content = {"data": "value"}
    metadata = _build_metadata_for_non_output(raw_content, "v1", "Node", "Component", "data")


def test_build_metadata_for_non_output_non_dict_content():
    """Test building metadata when content is not a dict."""
    raw_content = "string content"
    metadata = _build_metadata_for_non_output(raw_content, "v1", "Node", "Component", "message")




def test_extract_nested_value_empty_dict():
    """Test extracting from empty dict."""
    data = {}
    result = _extract_nested_value(data, "key")


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


def test_extract_nested_value_with_object_attribute():
    """Test extracting from object with attributes."""
    obj = Mock()
    obj.nested = Mock()
    obj.nested.value = "found"
    
    result = _extract_nested_value(obj, "nested", "value")


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


def test_extract_text_from_message_none_value():
    """Test extracting text when message is None."""
    content = {"message": None}
    result = _extract_text_from_message(content)


def test_extract_text_from_message_empty_string():
    """Test extracting text that is empty string."""
    content = {"message": ""}
    result = _extract_text_from_message(content)


def test_extract_file_path_missing_message_structure():
    """Test extracting file path when message structure is missing."""
    raw_content = {"other": "data"}
    result = _extract_file_path(raw_content, "SaveToFile")


def test_extract_file_path_no_saved_keyword():
    """Test extracting file path when 'saved' keyword is missing."""
    raw_content = {"message": {"message": "File processing"}}
    result = _extract_file_path(raw_content, "SaveToFile")


def test_get_raw_content_empty_outputs():
    """Test getting raw content when outputs is empty dict."""
    vertex_output = Mock()
    vertex_output.outputs = {}
    result = _get_raw_content(vertex_output)


def test_get_raw_content_empty_list():
    """Test getting raw content when outputs is empty list."""
    vertex_output = Mock()
    vertex_output.outputs = []
    result = _get_raw_content(vertex_output)


def test_get_raw_content_no_relevant_attributes():
    """Test getting raw content when object has no relevant attributes."""
    vertex_output = Mock(spec=[])
    vertex_output.outputs = None
    vertex_output.results = None
    vertex_output.messages = None
    result = _get_raw_content(vertex_output)


def test_simplify_output_content_with_none_text_extraction():
    """Test simplifying when text extraction returns None."""
    content = {"random": "data"}
    result = _simplify_output_content(content, "message")


def test_simplify_output_content_missing_result_in_data():
    """Test simplifying data type when result key is missing."""
    content = {"other": "structure"}
    result = _simplify_output_content(content, "data")


def test_build_metadata_for_non_output_empty_dict():
    """Test building metadata with empty dict content."""
    metadata = _build_metadata_for_non_output({}, "v1", "Node", "Comp", "message")












def test_extract_text_from_message_text_text_structure():
    """Test extracting from text.text nested structure."""
    content = {"text": {"text": "nested text"}}
    result = _extract_text_from_message(content)


def test_extract_text_from_message_message_text_structure():
    """Test extracting from message.text nested structure."""
    content = {"message": {"text": "message text"}}
    result = _extract_text_from_message(content)


def test_extract_text_from_message_text_message_structure():
    """Test extracting from text.message nested structure."""
    content = {"text": {"message": "text message"}}
    result = _extract_text_from_message(content)






def test_extract_nested_value_many_levels():
    """Test extracting from very deep nesting."""
    # Create 100-level deep dict
    data = {"value": "target"}
    for i in range(100):
        data = {f"level_{i}": data}
    
    keys = [f"level_{i}" for i in range(99, -1, -1)] + ["value"]
    result = _extract_nested_value(data, *keys)


def test_extract_nested_value_many_keys_missing():
    """Test extracting when trying multiple key paths."""
    data = {"a": {"b": "value"}}
    
    # Try many non-existent paths
    for i in range(100):
        result = _extract_nested_value(data, f"missing_{i}")





def test_extract_text_from_message_with_large_content():
    """Test text extraction with large message content."""
    large_message = "x" * 10000
    content = {"message": large_message}
    result = _extract_text_from_message(content)


def test_build_metadata_for_non_output_complex_structure():
    """Test building metadata with complex nested structure."""
    raw_content = {
        "model_output": {
            "message": {
                "model_name": "gpt-4",
                "nested": {
                    "deep": {
                        "value": "test"
                    }
                }
            }
        }
    }
    metadata = _build_metadata_for_non_output(raw_content, "v1", "Node", "LLM", "message")

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

Codeflash

Janardan S Kavia and others added 30 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 an **11% speedup** (from 2.78ms to 2.49ms) through two key optimizations:

## 1. Fast-Path Message Text Extraction (Primary Speedup)

The main performance gain comes from adding a fast-path in `_simplify_output_content` for common message structures **before** falling back to the heavier `_extract_text_from_message` function:

```python
# Fast-path checks using direct dict.get() operations
msg = content.get("message")
if isinstance(msg, dict):
    nested_msg = msg.get("message")
    if isinstance(nested_msg, str):
        return nested_msg
# ... more fast-path checks ...
if isinstance(msg, str):
    return msg  # Early return for simple case
```

**Why this is faster:**
- Direct `dict.get()` operations are much faster than `_extract_nested_value()`, which uses `hasattr()` and `getattr()` checks on each level
- Line profiler shows `_extract_text_from_message` time dropped from **3.28ms → 0.33ms** (90% reduction)
- Only **22 out of 232 calls** now reach the expensive fallback function (versus all 232 previously)
- Most messages in the test workload follow simple structures like `{"message": "text"}` which hit the fast-path

## 2. Set-Based Terminal Node Filtering

Converting `terminal_node_ids` to a set for O(1) membership testing:

```python
terminal_node_ids_set = set(terminal_node_ids)
terminal_vertices = [v for v in graph.vertices if v.id in terminal_node_ids_set]
```

**Why this is faster:**
- List comprehension filtering time reduced from **201μs → 117μs** (42% reduction)
- Avoids O(n²) list membership checks when filtering vertices
- Particularly beneficial when there are many vertices in the graph

## 3. Minor: getattr() for Attribute Access

Replaced `hasattr()` + attribute access with single `getattr()` calls in `_get_raw_content`:

```python
outputs = getattr(vertex_output_data, "outputs", None)
if outputs is not None:
    return outputs
```

This eliminates redundant attribute lookups, though the impact is minor.

## Impact on Workloads

Based on test results, these optimizations are particularly effective for:
- **Message-heavy workflows**: Tests with nested message structures see the biggest gains from fast-path extraction
- **Large graphs**: The set-based filtering helps when processing many terminal nodes
- **Common message formats**: Simple `{"message": "text"}` patterns benefit most from early returns

The optimizations preserve all original logic and handle all edge cases correctly, making them safe to merge.
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Jan 19, 2026
@coderabbitai
Copy link
Contributor

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

codecov bot commented Jan 19, 2026

Codecov Report

❌ Patch coverage is 69.69697% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 34.73%. Comparing base (021d4f3) to head (4da2a5b).

Files with missing lines Patch % Lines
src/backend/base/langflow/api/v2/converters.py 69.69% 10 Missing ⚠️

❌ Your project check has failed because the head coverage (41.60%) 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   #11359      +/-   ##
=================================================
+ Coverage          34.72%   34.73%   +0.01%     
=================================================
  Files               1415     1415              
  Lines              67426    67452      +26     
  Branches            9910     9910              
=================================================
+ Hits               23411    23427      +16     
- Misses             42800    42809       +9     
- Partials            1215     1216       +1     
Flag Coverage Δ
backend 54.01% <69.69%> (+0.01%) ⬆️
lfx 41.60% <ø> (-0.01%) ⬇️

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 92.02% <69.69%> (-4.90%) ⬇️

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