refactor: agent strategy parameter

This commit is contained in:
Yeuoly 2024-12-12 19:16:06 +08:00
parent 46bb246ecc
commit dedc1b0c3a
No known key found for this signature in database
GPG Key ID: A66E7E320FB19F61
7 changed files with 168 additions and 15 deletions

View File

@ -340,7 +340,7 @@ class BaseAgentRunner(AppRunner):
if isinstance(tool_input, dict):
try:
tool_input = json.dumps(tool_input, ensure_ascii=False)
except Exception as e:
except Exception:
tool_input = json.dumps(tool_input)
updated_agent_thought.tool_input = tool_input
@ -349,7 +349,7 @@ class BaseAgentRunner(AppRunner):
if isinstance(observation, dict):
try:
observation = json.dumps(observation, ensure_ascii=False)
except Exception as e:
except Exception:
observation = json.dumps(observation)
updated_agent_thought.observation = observation
@ -389,7 +389,7 @@ class BaseAgentRunner(AppRunner):
if isinstance(tool_invoke_meta, dict):
try:
tool_invoke_meta = json.dumps(tool_invoke_meta, ensure_ascii=False)
except Exception as e:
except Exception:
tool_invoke_meta = json.dumps(tool_invoke_meta)
updated_agent_thought.tool_meta_str = tool_invoke_meta
@ -433,11 +433,11 @@ class BaseAgentRunner(AppRunner):
tool_call_response: list[ToolPromptMessage] = []
try:
tool_inputs = json.loads(agent_thought.tool_input)
except Exception as e:
except Exception:
tool_inputs = {tool: {} for tool in tools}
try:
tool_responses = json.loads(agent_thought.observation)
except Exception as e:
except Exception:
tool_responses = dict.fromkeys(tools, agent_thought.observation)
for tool in tools:

View File

@ -1,17 +1,164 @@
from typing import Optional
import enum
from typing import Any, Optional, Union
from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, field_validator
from core.entities.parameter_entities import CommonParameterType
from core.tools.entities.common_entities import I18nObject
from core.tools.entities.tool_entities import ToolIdentity, ToolParameter, ToolProviderIdentity
from core.tools.entities.tool_entities import (
ToolIdentity,
ToolParameterOption,
ToolProviderIdentity,
)
class AgentStrategyProviderIdentity(ToolProviderIdentity):
pass
class AgentStrategyParameter(ToolParameter):
pass
class AgentStrategyParameter(BaseModel):
class AgentStrategyParameterType(enum.StrEnum):
STRING = CommonParameterType.STRING.value
NUMBER = CommonParameterType.NUMBER.value
BOOLEAN = CommonParameterType.BOOLEAN.value
SELECT = CommonParameterType.SELECT.value
SECRET_INPUT = CommonParameterType.SECRET_INPUT.value
FILE = CommonParameterType.FILE.value
FILES = CommonParameterType.FILES.value
APP_SELECTOR = CommonParameterType.APP_SELECTOR.value
TOOL_SELECTOR = CommonParameterType.TOOL_SELECTOR.value
MODEL_SELECTOR = CommonParameterType.MODEL_SELECTOR.value
TOOLS_SELECTOR = CommonParameterType.TOOLS_SELECTOR.value
# deprecated, should not use.
SYSTEM_FILES = CommonParameterType.SYSTEM_FILES.value
def as_normal_type(self):
if self in {
AgentStrategyParameter.AgentStrategyParameterType.SECRET_INPUT,
AgentStrategyParameter.AgentStrategyParameterType.SELECT,
}:
return "string"
return self.value
def cast_value(self, value: Any, /):
try:
match self:
case (
AgentStrategyParameter.AgentStrategyParameterType.STRING
| AgentStrategyParameter.AgentStrategyParameterType.SECRET_INPUT
| AgentStrategyParameter.AgentStrategyParameterType.SELECT
):
if value is None:
return ""
else:
return value if isinstance(value, str) else str(value)
case AgentStrategyParameter.AgentStrategyParameterType.BOOLEAN:
if value is None:
return False
elif isinstance(value, str):
# Allowed YAML boolean value strings: https://yaml.org/type/bool.html
# and also '0' for False and '1' for True
match value.lower():
case "true" | "yes" | "y" | "1":
return True
case "false" | "no" | "n" | "0":
return False
case _:
return bool(value)
else:
return value if isinstance(value, bool) else bool(value)
case AgentStrategyParameter.AgentStrategyParameterType.NUMBER:
if isinstance(value, int | float):
return value
elif isinstance(value, str) and value:
if "." in value:
return float(value)
else:
return int(value)
case (
AgentStrategyParameter.AgentStrategyParameterType.SYSTEM_FILES
| AgentStrategyParameter.AgentStrategyParameterType.FILES
):
if not isinstance(value, list):
return [value]
return value
case AgentStrategyParameter.AgentStrategyParameterType.FILE:
if isinstance(value, list):
if len(value) != 1:
raise ValueError(
"This parameter only accepts one file but got multiple files while invoking."
)
else:
return value[0]
return value
case (
AgentStrategyParameter.AgentStrategyParameterType.TOOL_SELECTOR
| AgentStrategyParameter.AgentStrategyParameterType.MODEL_SELECTOR
| AgentStrategyParameter.AgentStrategyParameterType.APP_SELECTOR
| AgentStrategyParameter.AgentStrategyParameterType.TOOLS_SELECTOR
):
if not isinstance(value, dict):
raise ValueError("The selector must be a dictionary.")
return value
case _:
return str(value)
except Exception:
raise ValueError(f"The tool parameter value {value} is not in correct type of {self.as_normal_type()}.")
name: str = Field(..., description="The name of the parameter")
label: I18nObject = Field(..., description="The label presented to the user")
placeholder: Optional[I18nObject] = Field(default=None, description="The placeholder presented to the user")
type: AgentStrategyParameterType = Field(..., description="The type of the parameter")
scope: str | None = None
required: Optional[bool] = False
default: Optional[Union[float, int, str]] = None
min: Optional[Union[float, int]] = None
max: Optional[Union[float, int]] = None
options: list[ToolParameterOption] = Field(default_factory=list)
@field_validator("options", mode="before")
@classmethod
def transform_options(cls, v):
if not isinstance(v, list):
return []
return v
@classmethod
def get_simple_instance(
cls,
name: str,
type: AgentStrategyParameterType,
required: bool,
options: Optional[list[str]] = None,
):
"""
get a simple tool parameter
:param name: the name of the parameter
:param llm_description: the description presented to the LLM
:param type: the type of the parameter
:param required: if the parameter is required
:param options: the options of the parameter
"""
# convert options to ToolParameterOption
if options:
option_objs = [
ToolParameterOption(value=option, label=I18nObject(en_US=option, zh_Hans=option)) for option in options
]
else:
option_objs = []
return cls(
name=name,
label=I18nObject(en_US="", zh_Hans=""),
placeholder=None,
type=type,
required=required,
options=option_objs,
)
class AgentStrategyProviderEntity(BaseModel):

View File

@ -14,6 +14,7 @@ class CommonParameterType(Enum):
APP_SELECTOR = "app-selector"
TOOL_SELECTOR = "tool-selector"
MODEL_SELECTOR = "model-selector"
TOOLS_SELECTOR = "array[tools]"
class AppSelectorScope(Enum):

View File

@ -14,7 +14,12 @@ from core.file import FileType
from core.file.models import FileTransferMethod
from core.ops.ops_trace_manager import TraceQueueManager
from core.tools.__base.tool import Tool
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolInvokeMessageBinary, ToolInvokeMeta, ToolParameter
from core.tools.entities.tool_entities import (
ToolInvokeMessage,
ToolInvokeMessageBinary,
ToolInvokeMeta,
ToolParameter,
)
from core.tools.errors import (
ToolEngineInvokeError,
ToolInvokeError,
@ -66,7 +71,7 @@ class ToolEngine:
else:
try:
tool_parameters = json.loads(tool_parameters)
except Exception as e:
except Exception:
pass
if not isinstance(tool_parameters, dict):
raise ValueError(f"tool_parameters should be a dict, but got a string: {tool_parameters}")

View File

@ -548,7 +548,7 @@ class ToolManager:
cls._builtin_tools_labels[tool.entity.identity.name] = tool.entity.identity.label
yield provider
except Exception as e:
except Exception:
logger.exception(f"load builtin provider {provider}")
continue
# set builtin providers loaded
@ -670,7 +670,7 @@ class ToolManager:
workflow_provider_controllers.append(
ToolTransformService.workflow_provider_to_controller(db_provider=provider)
)
except Exception as e:
except Exception:
# app has been deleted
pass

View File

@ -202,7 +202,7 @@ class WorkflowTool(Tool):
file_dict["url"] = file.generate_url()
files.append(file_dict)
except Exception as e:
except Exception:
logger.exception(f"Failed to transform file {file}")
else:
parameters_result[parameter.name] = tool_parameters.get(parameter.name)

View File

@ -197,7 +197,7 @@ class ToolTransformService:
raise ValueError("user not found")
username = user.name
except Exception as e:
except Exception:
logger.exception(f"failed to get user name for api provider {db_provider.id}")
# add provider into providers
credentials = db_provider.credentials