Co-authored-by: Joel <iamjoel007@gmail.com>tags/0.6.3
| tool_parameters[parameter.name] = float(tool_parameters[parameter.name]) | tool_parameters[parameter.name] = float(tool_parameters[parameter.name]) | ||||
| elif parameter.type == ToolParameter.ToolParameterType.BOOLEAN: | elif parameter.type == ToolParameter.ToolParameterType.BOOLEAN: | ||||
| if not isinstance(tool_parameters[parameter.name], bool): | if not isinstance(tool_parameters[parameter.name], bool): | ||||
| tool_parameters[parameter.name] = bool(tool_parameters[parameter.name]) | |||||
| # check if it is a string | |||||
| if isinstance(tool_parameters[parameter.name], str): | |||||
| # check true false | |||||
| if tool_parameters[parameter.name].lower() in ['true', 'false']: | |||||
| tool_parameters[parameter.name] = tool_parameters[parameter.name].lower() == 'true' | |||||
| # check 1 0 | |||||
| elif tool_parameters[parameter.name] in ['1', '0']: | |||||
| tool_parameters[parameter.name] = tool_parameters[parameter.name] == '1' | |||||
| else: | |||||
| tool_parameters[parameter.name] = bool(tool_parameters[parameter.name]) | |||||
| elif isinstance(tool_parameters[parameter.name], int | float): | |||||
| tool_parameters[parameter.name] = tool_parameters[parameter.name] != 0 | |||||
| else: | |||||
| tool_parameters[parameter.name] = bool(tool_parameters[parameter.name]) | |||||
| return tool_parameters | return tool_parameters | ||||
| @abstractmethod | @abstractmethod |
| from typing import Literal, Union | |||||
| from typing import Any, Literal, Union | |||||
| from pydantic import BaseModel, validator | from pydantic import BaseModel, validator | ||||
| from core.workflow.entities.base_node_data_entities import BaseNodeData | from core.workflow.entities.base_node_data_entities import BaseNodeData | ||||
| ToolParameterValue = Union[str, int, float, bool] | |||||
| class ToolEntity(BaseModel): | class ToolEntity(BaseModel): | ||||
| provider_id: str | provider_id: str | ||||
| provider_name: str # redundancy | provider_name: str # redundancy | ||||
| tool_name: str | tool_name: str | ||||
| tool_label: str # redundancy | tool_label: str # redundancy | ||||
| tool_configurations: dict[str, ToolParameterValue] | |||||
| tool_configurations: dict[str, Any] | |||||
| @validator('tool_configurations', pre=True, always=True) | |||||
| def validate_tool_configurations(cls, value, values): | |||||
| if not isinstance(value, dict): | |||||
| raise ValueError('tool_configurations must be a dictionary') | |||||
| for key in values.get('tool_configurations', {}).keys(): | |||||
| value = values.get('tool_configurations', {}).get(key) | |||||
| if not isinstance(value, str | int | float | bool): | |||||
| raise ValueError(f'{key} must be a string') | |||||
| return value | |||||
| class ToolNodeData(BaseNodeData, ToolEntity): | class ToolNodeData(BaseNodeData, ToolEntity): | ||||
| class ToolInput(BaseModel): | class ToolInput(BaseModel): | ||||
| value: Union[ToolParameterValue, list[str]] | |||||
| value: Union[Any, list[str]] | |||||
| type: Literal['mixed', 'variable', 'constant'] | type: Literal['mixed', 'variable', 'constant'] | ||||
| @validator('type', pre=True, always=True) | @validator('type', pre=True, always=True) | ||||
| value = values.get('value') | value = values.get('value') | ||||
| if typ == 'mixed' and not isinstance(value, str): | if typ == 'mixed' and not isinstance(value, str): | ||||
| raise ValueError('value must be a string') | raise ValueError('value must be a string') | ||||
| elif typ == 'variable' and not isinstance(value, list): | |||||
| raise ValueError('value must be a list') | |||||
| elif typ == 'constant' and not isinstance(value, ToolParameterValue): | |||||
| elif typ == 'variable': | |||||
| if not isinstance(value, list): | |||||
| raise ValueError('value must be a list') | |||||
| for val in value: | |||||
| if not isinstance(val, str): | |||||
| raise ValueError('value must be a list of strings') | |||||
| elif typ == 'constant' and not isinstance(value, str | int | float | bool): | |||||
| raise ValueError('value must be a string, int, float, or bool') | raise ValueError('value must be a string, int, float, or bool') | ||||
| return typ | return typ | ||||
| """ | """ | ||||
| Tool Node Schema | Tool Node Schema | ||||
| """ | """ |
| import { useCallback, useEffect, useState } from 'react' | |||||
| import { useCallback, useEffect, useMemo, useState } from 'react' | |||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import produce from 'immer' | import produce from 'immer' | ||||
| import { useBoolean } from 'ahooks' | import { useBoolean } from 'ahooks' | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const language = useLanguage() | const language = useLanguage() | ||||
| const { inputs, setInputs } = useNodeCrud<ToolNodeType>(id, payload) | |||||
| const { inputs, setInputs: doSetInputs } = useNodeCrud<ToolNodeType>(id, payload) | |||||
| /* | /* | ||||
| * tool_configurations: tool setting, not dynamic setting | * tool_configurations: tool setting, not dynamic setting | ||||
| * tool_parameters: tool dynamic setting(by user) | * tool_parameters: tool dynamic setting(by user) | ||||
| }, [currCollection?.name, hideSetAuthModal, t, handleFetchAllTools, provider_type]) | }, [currCollection?.name, hideSetAuthModal, t, handleFetchAllTools, provider_type]) | ||||
| const currTool = currCollection?.tools.find(tool => tool.name === tool_name) | const currTool = currCollection?.tools.find(tool => tool.name === tool_name) | ||||
| const formSchemas = currTool ? toolParametersToFormSchemas(currTool.parameters) : [] | |||||
| const formSchemas = useMemo(() => { | |||||
| return currTool ? toolParametersToFormSchemas(currTool.parameters) : [] | |||||
| }, [currTool]) | |||||
| const toolInputVarSchema = formSchemas.filter((item: any) => item.form === 'llm') | const toolInputVarSchema = formSchemas.filter((item: any) => item.form === 'llm') | ||||
| // use setting | // use setting | ||||
| const toolSettingSchema = formSchemas.filter((item: any) => item.form !== 'llm') | const toolSettingSchema = formSchemas.filter((item: any) => item.form !== 'llm') | ||||
| const hasShouldTransferTypeSettingInput = toolSettingSchema.some(item => item.type === 'boolean' || item.type === 'number-input') | |||||
| const setInputs = useCallback((value: ToolNodeType) => { | |||||
| if (!hasShouldTransferTypeSettingInput) { | |||||
| doSetInputs(value) | |||||
| return | |||||
| } | |||||
| const newInputs = produce(value, (draft) => { | |||||
| const newConfig = { ...draft.tool_configurations } | |||||
| Object.keys(draft.tool_configurations).forEach((key) => { | |||||
| const schema = formSchemas.find(item => item.variable === key) | |||||
| const value = newConfig[key] | |||||
| if (schema?.type === 'boolean') { | |||||
| if (typeof value === 'string') | |||||
| newConfig[key] = parseInt(value, 10) | |||||
| if (typeof value === 'boolean') | |||||
| newConfig[key] = value ? 1 : 0 | |||||
| } | |||||
| if (schema?.type === 'number-input') { | |||||
| if (typeof value === 'string' && value !== '') | |||||
| newConfig[key] = parseFloat(value) | |||||
| } | |||||
| }) | |||||
| draft.tool_configurations = newConfig | |||||
| }) | |||||
| doSetInputs(newInputs) | |||||
| }, [doSetInputs, formSchemas, hasShouldTransferTypeSettingInput]) | |||||
| const [notSetDefaultValue, setNotSetDefaultValue] = useState(false) | const [notSetDefaultValue, setNotSetDefaultValue] = useState(false) | ||||
| const toolSettingValue = (() => { | const toolSettingValue = (() => { | ||||
| if (notSetDefaultValue) | if (notSetDefaultValue) |