瀏覽代碼

Refactor switch component (#1940)

### What problem does this PR solve?

### Type of change

- [x] Refactoring
tags/v0.10.0
H 1 年之前
父節點
當前提交
c9caccf354
沒有連結到貢獻者的電子郵件帳戶。
共有 2 個檔案被更改,包括 208 行新增29 行删除
  1. 79
    29
      agent/component/switch.py
  2. 129
    0
      agent/test/dsl_examples/baidu_generate_and_switch.json

+ 79
- 29
agent/component/switch.py 查看文件

@@ -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
- 0
agent/test/dsl_examples/baidu_generate_and_switch.json 查看文件

@@ -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…
取消
儲存