Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor switch component #1940

Merged
merged 37 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
69a1b56
Update wikipedia.py
guoyuhao2330 Jul 15, 2024
6bbb1df
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 15, 2024
4e3067a
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 17, 2024
bc8d5ad
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 17, 2024
678994d
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 17, 2024
268c0c7
Update requirements.txt
guoyuhao2330 Jul 17, 2024
757ca5b
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 18, 2024
dfe71cb
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 18, 2024
7aba129
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 18, 2024
e52e08f
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 19, 2024
c140c70
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 19, 2024
92cf451
Update llm_service.py
guoyuhao2330 Jul 19, 2024
ad5a5b8
Update index.tsx
guoyuhao2330 Jul 19, 2024
4b49bb9
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 22, 2024
12baffc
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 22, 2024
585a0f6
Update init_data.py
guoyuhao2330 Jul 22, 2024
f3b3451
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 25, 2024
31af72c
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 25, 2024
e23f5b5
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 26, 2024
941c29d
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 26, 2024
bace5b5
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 26, 2024
8936941
Merge branch 'infiniflow:main' into main
guoyuhao2330 Jul 29, 2024
4fe66d8
Merge branch 'infiniflow:main' into main
guoyuhao2330 Aug 2, 2024
3cad1dd
Merge branch 'infiniflow:main' into main
guoyuhao2330 Aug 5, 2024
4ce659e
Merge branch 'infiniflow:main' into main
guoyuhao2330 Aug 7, 2024
764de5b
Merge branch 'infiniflow:main' into main
guoyuhao2330 Aug 8, 2024
addfea5
Update __init__.py
guoyuhao2330 Aug 8, 2024
ab10427
Merge branch 'infiniflow:main' into main
guoyuhao2330 Aug 9, 2024
898dcbd
Merge branch 'infiniflow:main' into main
guoyuhao2330 Aug 9, 2024
6b7e08b
Merge branch 'infiniflow:main' into main
guoyuhao2330 Aug 12, 2024
f0936b2
Merge branch 'infiniflow:main' into main
guoyuhao2330 Aug 14, 2024
7cf0381
Update switch.py
guoyuhao2330 Aug 14, 2024
fb585aa
Add files via upload
guoyuhao2330 Aug 14, 2024
b662973
Update switch.py
guoyuhao2330 Aug 14, 2024
dcabaf3
Update switch.py
guoyuhao2330 Aug 14, 2024
fa4167d
Update baidu_generate_and_switch.json
guoyuhao2330 Aug 14, 2024
0cc3ef1
Update baidu_generate_and_switch.json
guoyuhao2330 Aug 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 79 additions & 29 deletions agent/component/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,64 +14,114 @@
# 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):
component_name = "Switch"

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 changes: 129 additions & 0 deletions agent/test/dsl_examples/baidu_generate_and_switch.json
Original file line number Diff line number Diff line change
@@ -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": []
}