feat: Enhance ConditionalRouterComponent with Regex Matching and UI Improvements (#5217)
* fix: revert response return type to Message for compatibility * Change the max_iterations and case_sensitive advanced options * feat: add regex matching and real-time refresh functionality * Refactor evaluate_condition method to use elif statements for clarity - Changed if statements to elif in the evaluate_condition method to improve readability and indicate mutually exclusive conditions. - Removed redundant advanced=True line from BoolInput for case sensitivity. * [autofix.ci] apply automated fixes * Format code using make format - Applied code formatting to ensure consistency and adherence to style guidelines. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Eric Hare <ericrhare@gmail.com>
This commit is contained in:
parent
dffc2d51cd
commit
ef6226d25d
1 changed files with 29 additions and 8 deletions
|
|
@ -1,3 +1,5 @@
|
||||||
|
import re
|
||||||
|
|
||||||
from langflow.custom import Component
|
from langflow.custom import Component
|
||||||
from langflow.io import BoolInput, DropdownInput, IntInput, MessageInput, MessageTextInput, Output
|
from langflow.io import BoolInput, DropdownInput, IntInput, MessageInput, MessageTextInput, Output
|
||||||
from langflow.schema.message import Message
|
from langflow.schema.message import Message
|
||||||
|
|
@ -27,16 +29,16 @@ class ConditionalRouterComponent(Component):
|
||||||
DropdownInput(
|
DropdownInput(
|
||||||
name="operator",
|
name="operator",
|
||||||
display_name="Operator",
|
display_name="Operator",
|
||||||
options=["equals", "not equals", "contains", "starts with", "ends with"],
|
options=["equals", "not equals", "contains", "starts with", "ends with", "matches regex"],
|
||||||
info="The operator to apply for comparing the texts.",
|
info="The operator to apply for comparing the texts.",
|
||||||
value="equals",
|
value="equals",
|
||||||
|
real_time_refresh=True,
|
||||||
),
|
),
|
||||||
BoolInput(
|
BoolInput(
|
||||||
name="case_sensitive",
|
name="case_sensitive",
|
||||||
display_name="Case Sensitive",
|
display_name="Case Sensitive",
|
||||||
info="If true, the comparison will be case sensitive.",
|
info="If true, the comparison will be case sensitive.",
|
||||||
value=False,
|
value=False,
|
||||||
advanced=True,
|
|
||||||
),
|
),
|
||||||
MessageInput(
|
MessageInput(
|
||||||
name="message",
|
name="message",
|
||||||
|
|
@ -49,6 +51,7 @@ class ConditionalRouterComponent(Component):
|
||||||
display_name="Max Iterations",
|
display_name="Max Iterations",
|
||||||
info="The maximum number of iterations for the conditional router.",
|
info="The maximum number of iterations for the conditional router.",
|
||||||
value=10,
|
value=10,
|
||||||
|
advanced=True,
|
||||||
),
|
),
|
||||||
DropdownInput(
|
DropdownInput(
|
||||||
name="default_route",
|
name="default_route",
|
||||||
|
|
@ -69,7 +72,7 @@ class ConditionalRouterComponent(Component):
|
||||||
self.__iteration_updated = False
|
self.__iteration_updated = False
|
||||||
|
|
||||||
def evaluate_condition(self, input_text: str, match_text: str, operator: str, *, case_sensitive: bool) -> bool:
|
def evaluate_condition(self, input_text: str, match_text: str, operator: str, *, case_sensitive: bool) -> bool:
|
||||||
if not case_sensitive:
|
if not case_sensitive and operator != "matches regex":
|
||||||
input_text = input_text.lower()
|
input_text = input_text.lower()
|
||||||
match_text = match_text.lower()
|
match_text = match_text.lower()
|
||||||
|
|
||||||
|
|
@ -83,6 +86,11 @@ class ConditionalRouterComponent(Component):
|
||||||
return input_text.startswith(match_text)
|
return input_text.startswith(match_text)
|
||||||
if operator == "ends with":
|
if operator == "ends with":
|
||||||
return input_text.endswith(match_text)
|
return input_text.endswith(match_text)
|
||||||
|
if operator == "matches regex":
|
||||||
|
try:
|
||||||
|
return bool(re.match(match_text, input_text))
|
||||||
|
except re.error:
|
||||||
|
return False # Return False if the regex is invalid
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def iterate_and_stop_once(self, route_to_stop: str):
|
def iterate_and_stop_once(self, route_to_stop: str):
|
||||||
|
|
@ -90,11 +98,10 @@ class ConditionalRouterComponent(Component):
|
||||||
self.update_ctx({f"{self._id}_iteration": self.ctx.get(f"{self._id}_iteration", 0) + 1})
|
self.update_ctx({f"{self._id}_iteration": self.ctx.get(f"{self._id}_iteration", 0) + 1})
|
||||||
self.__iteration_updated = True
|
self.__iteration_updated = True
|
||||||
if self.ctx.get(f"{self._id}_iteration", 0) >= self.max_iterations and route_to_stop == self.default_route:
|
if self.ctx.get(f"{self._id}_iteration", 0) >= self.max_iterations and route_to_stop == self.default_route:
|
||||||
# We need to stop the other route
|
|
||||||
route_to_stop = "true_result" if route_to_stop == "false_result" else "false_result"
|
route_to_stop = "true_result" if route_to_stop == "false_result" else "false_result"
|
||||||
self.stop(route_to_stop)
|
self.stop(route_to_stop)
|
||||||
|
|
||||||
def true_response(self) -> Message | str:
|
def true_response(self) -> Message:
|
||||||
result = self.evaluate_condition(
|
result = self.evaluate_condition(
|
||||||
self.input_text, self.match_text, self.operator, case_sensitive=self.case_sensitive
|
self.input_text, self.match_text, self.operator, case_sensitive=self.case_sensitive
|
||||||
)
|
)
|
||||||
|
|
@ -103,9 +110,9 @@ class ConditionalRouterComponent(Component):
|
||||||
self.iterate_and_stop_once("false_result")
|
self.iterate_and_stop_once("false_result")
|
||||||
return self.message
|
return self.message
|
||||||
self.iterate_and_stop_once("true_result")
|
self.iterate_and_stop_once("true_result")
|
||||||
return ""
|
return Message(content="")
|
||||||
|
|
||||||
def false_response(self) -> Message | str:
|
def false_response(self) -> Message:
|
||||||
result = self.evaluate_condition(
|
result = self.evaluate_condition(
|
||||||
self.input_text, self.match_text, self.operator, case_sensitive=self.case_sensitive
|
self.input_text, self.match_text, self.operator, case_sensitive=self.case_sensitive
|
||||||
)
|
)
|
||||||
|
|
@ -114,4 +121,18 @@ class ConditionalRouterComponent(Component):
|
||||||
self.iterate_and_stop_once("true_result")
|
self.iterate_and_stop_once("true_result")
|
||||||
return self.message
|
return self.message
|
||||||
self.iterate_and_stop_once("false_result")
|
self.iterate_and_stop_once("false_result")
|
||||||
return ""
|
return Message(content="")
|
||||||
|
|
||||||
|
def update_build_config(self, build_config: dict, field_value: str, field_name: str | None = None) -> dict:
|
||||||
|
if field_name == "operator":
|
||||||
|
if field_value == "matches regex":
|
||||||
|
if "case_sensitive" in build_config:
|
||||||
|
del build_config["case_sensitive"]
|
||||||
|
# Ensure case_sensitive is present for all other operators
|
||||||
|
elif "case_sensitive" not in build_config:
|
||||||
|
case_sensitive_input = next(
|
||||||
|
(input_field for input_field in self.inputs if input_field.name == "case_sensitive"), None
|
||||||
|
)
|
||||||
|
if case_sensitive_input:
|
||||||
|
build_config["case_sensitive"] = case_sensitive_input.to_dict()
|
||||||
|
return build_config
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue