From 4954b3fa6647c45a6b8d90c2048ab2a5c226e6dd Mon Sep 17 00:00:00 2001 From: "codeflash-ai[bot]" <148906541+codeflash-ai[bot]@users.noreply.github.com> Date: Fri, 5 Jul 2024 07:51:50 -0700 Subject: [PATCH] =?UTF-8?q?perf:=20=E2=9A=A1=EF=B8=8F=20Speed=20up=20`conv?= =?UTF-8?q?ert=5Fkwargs()`=20by=209%=20in=20`src/backend/base/langflow/int?= =?UTF-8?q?erface/initialize/loading.py`=20(#2529)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(base.py): refactor logic to find start_component_id based on multiple keywords for improved flexibility and readability * feat(schema.py): add WebhookInput component type to INPUT_COMPONENTS list for handling webhook inputs in the graph schema * refactor(base.py): refactor logic to determine start_component_id based on webhook or chat component presence in input vertices * refactor: prioritize webhook component for determining start_component_id * ⚡️ Speed up convert_kwargs() by 9% To optimize the given Python program, we can focus on a few key areas. 1. **Avoid Repeated Lookups:** Instead of repeatedly looking up keys and values in the dictionary, we can iterate over items directly. 2. **Efficient JSON Parsing:** Using `orjson` is already a good choice for performance. We will handle the exception based on `orjson` capabilities. 3. **In-place Modification:** We can modify the dictionary in place without creating additional lists. Here is the optimized program. ### Changes Made. 1. **Direct Looping:** We iterate directly over `params.items()` to process keys and values together, which helps avoid multiple lookups. 2. **Exception Handling:** We catch `orjson.JSONDecodeError` directly, avoiding unnecessary import and potential mismatches. 3. **Deferred Removal:** We collect keys to remove in `items_to_remove` and then remove them outside the loop, which helps avoid modification issues during iteration. This should result in more efficient iteration and handling while reducing overhead from unnecessary operations. * [autofix.ci] apply automated fixes --------- Co-authored-by: Gabriel Luiz Freitas Almeida Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../langflow/interface/initialize/loading.py | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/backend/base/langflow/interface/initialize/loading.py b/src/backend/base/langflow/interface/initialize/loading.py index 2a70fa9de..3e6a26962 100644 --- a/src/backend/base/langflow/interface/initialize/loading.py +++ b/src/backend/base/langflow/interface/initialize/loading.py @@ -1,5 +1,4 @@ import inspect -import json import os import warnings from typing import TYPE_CHECKING, Any, Type @@ -59,7 +58,10 @@ async def build_component_and_get_results( # Remove code from params class_object: Type["CustomComponent" | "Component"] = eval_custom_component_code(params_copy.pop("code")) custom_component: "CustomComponent" | "Component" = class_object( - user_id=user_id, parameters=params_copy, vertex=vertex, tracing_service=tracing_service + user_id=user_id, + parameters=params_copy, + vertex=vertex, + tracing_service=tracing_service, ) params_copy = update_params_with_load_from_db_fields( custom_component, params_copy, vertex.load_from_db_fields, fallback_to_env_vars @@ -84,22 +86,28 @@ def convert_params_to_sets(params): def convert_kwargs(params): - # if *kwargs are passed as a string, convert to dict - # first find any key that has kwargs or config in it - kwargs_keys = [key for key in params.keys() if "kwargs" in key or "config" in key] - for key in kwargs_keys: - if isinstance(params[key], str): - try: - params[key] = orjson.loads(params[key]) - except json.JSONDecodeError: - # if the string is not a valid json string, we will - # remove the key from the params - params.pop(key, None) + # Loop through items to avoid repeated lookups + items_to_remove = [] + for key, value in params.items(): + if "kwargs" in key or "config" in key: + if isinstance(value, str): + try: + params[key] = orjson.loads(value) + except orjson.JSONDecodeError: + items_to_remove.append(key) + + # Remove invalid keys outside the loop to avoid modifying dict during iteration + for key in items_to_remove: + params.pop(key, None) + return params def update_params_with_load_from_db_fields( - custom_component: "CustomComponent", params, load_from_db_fields, fallback_to_env_vars=False + custom_component: "CustomComponent", + params, + load_from_db_fields, + fallback_to_env_vars=False, ): # For each field in load_from_db_fields, we will check if it's in the params # and if it is, we will get the value from the custom_component.keys(name)