mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-14 19:55:56 +08:00
Refactor switch component (#1940)
### What problem does this PR solve? ### Type of change - [x] Refactoring
This commit is contained in:
parent
eedec157a7
commit
c9caccf354
@ -14,50 +14,36 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
from abc import ABC
|
||||
|
||||
import pandas as pd
|
||||
from agent.component.base import ComponentBase, ComponentParamBase
|
||||
|
||||
|
||||
class SwitchParam(ComponentParamBase):
|
||||
|
||||
"""
|
||||
Define the Switch component parameters.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
"""
|
||||
{
|
||||
"cpn_id": "categorize:0",
|
||||
"not": False,
|
||||
"operator": "gt/gte/lt/lte/eq/in",
|
||||
"value": "",
|
||||
"logical_operator" : "and | or"
|
||||
"items" : [
|
||||
{"cpn_id": "categorize:0", "operator": "contains", "value": ""},
|
||||
{"cpn_id": "categorize:0", "operator": "contains", "value": ""},...],
|
||||
"to": ""
|
||||
}
|
||||
"""
|
||||
self.conditions = []
|
||||
self.default = ""
|
||||
self.end_cpn_id = "answer:0"
|
||||
self.operators = ['contains', 'not contains', 'start with', 'end with', 'empty', 'not empty', '=', '≠', '>',
|
||||
'<', '≥', '≤']
|
||||
|
||||
def check(self):
|
||||
self.check_empty(self.conditions, "[Switch] conditions")
|
||||
self.check_empty(self.default, "[Switch] Default path")
|
||||
for cond in self.conditions:
|
||||
if not cond["to"]: raise ValueError(f"[Switch] 'To' can not be empty!")
|
||||
|
||||
def operators(self, field, op, value):
|
||||
if op == "gt":
|
||||
return float(field) > float(value)
|
||||
if op == "gte":
|
||||
return float(field) >= float(value)
|
||||
if op == "lt":
|
||||
return float(field) < float(value)
|
||||
if op == "lte":
|
||||
return float(field) <= float(value)
|
||||
if op == "eq":
|
||||
return str(field) == str(value)
|
||||
if op == "in":
|
||||
return str(field).find(str(value)) >= 0
|
||||
return False
|
||||
if cond["logical_operator"] not in ["and", "or"] and len(cond["items"]) > 1:
|
||||
raise ValueError(f"[Switch] Please set logical_operator correctly!")
|
||||
|
||||
|
||||
class Switch(ComponentBase, ABC):
|
||||
@ -65,13 +51,77 @@ class Switch(ComponentBase, ABC):
|
||||
|
||||
def _run(self, history, **kwargs):
|
||||
for cond in self._param.conditions:
|
||||
input = self._canvas.get_component(cond["cpn_id"])["obj"].output()[1]
|
||||
if self._param.operators(input.iloc[0, 0], cond["operator"], cond["value"]):
|
||||
if not cond["not"]:
|
||||
return pd.DataFrame([{"content": cond["to"]}])
|
||||
|
||||
return pd.DataFrame([{"content": self._param.default}])
|
||||
if len(cond["items"]) == 1:
|
||||
out = self._canvas.get_component(cond["items"][0]["cpn_id"])["obj"].output()[1]
|
||||
cpn_input = "" if "content" not in out.columns else " ".join(out["content"])
|
||||
if self.process_operator(cpn_input, cond["items"][0]["operator"], cond["items"][0]["value"]):
|
||||
return Switch.be_output(cond["to"])
|
||||
continue
|
||||
|
||||
if cond["logical_operator"] == "and":
|
||||
res = True
|
||||
for item in cond["items"]:
|
||||
out = self._canvas.get_component(item["cpn_id"])["obj"].output()[1]
|
||||
cpn_input = "" if "content" not in out.columns else " ".join(out["content"])
|
||||
if not self.process_operator(cpn_input, item["operator"], item["value"]):
|
||||
res = False
|
||||
break
|
||||
if res:
|
||||
return Switch.be_output(cond["to"])
|
||||
continue
|
||||
|
||||
res = False
|
||||
for item in cond["items"]:
|
||||
out = self._canvas.get_component(item["cpn_id"])["obj"].output()[1]
|
||||
cpn_input = "" if "content" not in out.columns else " ".join(out["content"])
|
||||
if self.process_operator(cpn_input, item["operator"], item["value"]):
|
||||
res = True
|
||||
break
|
||||
if res:
|
||||
return Switch.be_output(cond["to"])
|
||||
|
||||
return Switch.be_output(self._param.end_cpn_id)
|
||||
|
||||
def process_operator(self, input: str, operator: str, value: str) -> bool:
|
||||
if not isinstance(input, str) or not isinstance(value, str):
|
||||
raise ValueError('Invalid input or value type: string')
|
||||
|
||||
if operator == "contains":
|
||||
return True if value.lower() in input.lower() else False
|
||||
elif operator == "not contains":
|
||||
return True if value.lower() not in input.lower() else False
|
||||
elif operator == "start with":
|
||||
return True if input.lower().startswith(value.lower()) else False
|
||||
elif operator == "end with":
|
||||
return True if input.lower().endswith(value.lower()) else False
|
||||
elif operator == "empty":
|
||||
return True if not input else False
|
||||
elif operator == "not empty":
|
||||
return True if input else False
|
||||
elif operator == "=":
|
||||
return True if input == value else False
|
||||
elif operator == "≠":
|
||||
return True if input != value else False
|
||||
elif operator == ">":
|
||||
try:
|
||||
return True if float(input) > float(value) else False
|
||||
except Exception as e:
|
||||
return True if input > value else False
|
||||
elif operator == "<":
|
||||
try:
|
||||
return True if float(input) < float(value) else False
|
||||
except Exception as e:
|
||||
return True if input < value else False
|
||||
elif operator == "≥":
|
||||
try:
|
||||
return True if float(input) >= float(value) else False
|
||||
except Exception as e:
|
||||
return True if input >= value else False
|
||||
elif operator == "≤":
|
||||
try:
|
||||
return True if float(input) <= float(value) else False
|
||||
except Exception as e:
|
||||
return True if input <= value else False
|
||||
|
||||
raise ValueError('Not supported operator' + operator)
|
||||
|
129
agent/test/dsl_examples/baidu_generate_and_switch.json
Normal file
129
agent/test/dsl_examples/baidu_generate_and_switch.json
Normal file
@ -0,0 +1,129 @@
|
||||
{
|
||||
"components": {
|
||||
"begin": {
|
||||
"obj":{
|
||||
"component_name": "Begin",
|
||||
"params": {
|
||||
"prologue": "Hi there!"
|
||||
}
|
||||
},
|
||||
"downstream": ["answer:0"],
|
||||
"upstream": []
|
||||
},
|
||||
"answer:0": {
|
||||
"obj": {
|
||||
"component_name": "Answer",
|
||||
"params": {}
|
||||
},
|
||||
"downstream": ["baidu:0"],
|
||||
"upstream": ["begin", "message:0","message:1"]
|
||||
},
|
||||
"baidu:0": {
|
||||
"obj": {
|
||||
"component_name": "Baidu",
|
||||
"params": {}
|
||||
},
|
||||
"downstream": ["generate:0"],
|
||||
"upstream": ["answer:0"]
|
||||
},
|
||||
"generate:0": {
|
||||
"obj": {
|
||||
"component_name": "Generate",
|
||||
"params": {
|
||||
"llm_id": "deepseek-chat",
|
||||
"prompt": "You are an intelligent assistant. Please answer the user's question based on what Baidu searched. First, please output the user's question and the content searched by Baidu, and then answer yes, no, or i don't know.Here is the user's question:{user_input}The above is the user's question.Here is what Baidu searched for:{baidu}The above is the content searched by Baidu.",
|
||||
"temperature": 0.2
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"component_id": "answer:0",
|
||||
"id": "69415446-49bf-4d4b-8ec9-ac86066f7709",
|
||||
"key": "user_input"
|
||||
},
|
||||
{
|
||||
"component_id": "baidu:0",
|
||||
"id": "83363c2a-00a8-402f-a45c-ddc4097d7d8b",
|
||||
"key": "baidu"
|
||||
}
|
||||
]
|
||||
},
|
||||
"downstream": ["switch:0"],
|
||||
"upstream": ["baidu:0"]
|
||||
},
|
||||
"switch:0": {
|
||||
"obj": {
|
||||
"component_name": "Switch",
|
||||
"params": {
|
||||
"conditions": [
|
||||
{
|
||||
"logical_operator" : "or",
|
||||
"items" : [
|
||||
{"cpn_id": "generate:0", "operator": "contains", "value": "yes"},
|
||||
{"cpn_id": "generate:0", "operator": "contains", "value": "yeah"}
|
||||
],
|
||||
"to": "message:0"
|
||||
},
|
||||
{
|
||||
"logical_operator" : "and",
|
||||
"items" : [
|
||||
{"cpn_id": "generate:0", "operator": "contains", "value": "no"},
|
||||
{"cpn_id": "generate:0", "operator": "not contains", "value": "yes"},
|
||||
{"cpn_id": "generate:0", "operator": "not contains", "value": "know"}
|
||||
],
|
||||
"to": "message:1"
|
||||
},
|
||||
{
|
||||
"logical_operator" : "",
|
||||
"items" : [
|
||||
{"cpn_id": "generate:0", "operator": "contains", "value": "know"}
|
||||
],
|
||||
"to": "message:2"
|
||||
}
|
||||
],
|
||||
"end_cpn_id": "answer:0"
|
||||
|
||||
}
|
||||
},
|
||||
"downstream": ["message:0","message:1"],
|
||||
"upstream": ["generate:0"]
|
||||
},
|
||||
"message:0": {
|
||||
"obj": {
|
||||
"component_name": "Message",
|
||||
"params": {
|
||||
"messages": ["YES YES YES YES YES YES YES YES YES YES YES YES"]
|
||||
}
|
||||
},
|
||||
|
||||
"upstream": ["switch:0"],
|
||||
"downstream": ["answer:0"]
|
||||
},
|
||||
"message:1": {
|
||||
"obj": {
|
||||
"component_name": "Message",
|
||||
"params": {
|
||||
"messages": ["NO NO NO NO NO NO NO NO NO NO NO NO NO NO"]
|
||||
}
|
||||
},
|
||||
|
||||
"upstream": ["switch:0"],
|
||||
"downstream": ["answer:0"]
|
||||
},
|
||||
"message:2": {
|
||||
"obj": {
|
||||
"component_name": "Message",
|
||||
"params": {
|
||||
"messages": ["I DON'T KNOW---------------------------"]
|
||||
}
|
||||
},
|
||||
|
||||
"upstream": ["switch:0"],
|
||||
"downstream": ["answer:0"]
|
||||
}
|
||||
},
|
||||
"history": [],
|
||||
"messages": [],
|
||||
"reference": {},
|
||||
"path": [],
|
||||
"answer": []
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user