mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-07-25 12:34:26 +08:00
fix: parameter type handling in API tool and parser (#2574)
This commit is contained in:
parent
07fbeb6cf0
commit
ac96d192a6
@ -200,7 +200,7 @@ class ApiTool(Tool):
|
|||||||
|
|
||||||
# replace path parameters
|
# replace path parameters
|
||||||
for name, value in path_params.items():
|
for name, value in path_params.items():
|
||||||
url = url.replace(f'{{{name}}}', value)
|
url = url.replace(f'{{{name}}}', f'{value}')
|
||||||
|
|
||||||
# parse http body data if needed, for GET/HEAD/OPTIONS/TRACE, the body is ignored
|
# parse http body data if needed, for GET/HEAD/OPTIONS/TRACE, the body is ignored
|
||||||
if 'Content-Type' in headers:
|
if 'Content-Type' in headers:
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
import re
|
||||||
|
import uuid
|
||||||
from json import loads as json_loads
|
from json import loads as json_loads
|
||||||
|
|
||||||
from requests import get
|
from requests import get
|
||||||
@ -46,7 +48,7 @@ class ApiBasedToolSchemaParser:
|
|||||||
parameters = []
|
parameters = []
|
||||||
if 'parameters' in interface['operation']:
|
if 'parameters' in interface['operation']:
|
||||||
for parameter in interface['operation']['parameters']:
|
for parameter in interface['operation']['parameters']:
|
||||||
parameters.append(ToolParameter(
|
tool_parameter = ToolParameter(
|
||||||
name=parameter['name'],
|
name=parameter['name'],
|
||||||
label=I18nObject(
|
label=I18nObject(
|
||||||
en_US=parameter['name'],
|
en_US=parameter['name'],
|
||||||
@ -61,7 +63,14 @@ class ApiBasedToolSchemaParser:
|
|||||||
form=ToolParameter.ToolParameterForm.LLM,
|
form=ToolParameter.ToolParameterForm.LLM,
|
||||||
llm_description=parameter.get('description'),
|
llm_description=parameter.get('description'),
|
||||||
default=parameter['schema']['default'] if 'schema' in parameter and 'default' in parameter['schema'] else None,
|
default=parameter['schema']['default'] if 'schema' in parameter and 'default' in parameter['schema'] else None,
|
||||||
))
|
)
|
||||||
|
|
||||||
|
# check if there is a type
|
||||||
|
typ = ApiBasedToolSchemaParser._get_tool_parameter_type(parameter)
|
||||||
|
if typ:
|
||||||
|
tool_parameter.type = typ
|
||||||
|
|
||||||
|
parameters.append(tool_parameter)
|
||||||
# create tool bundle
|
# create tool bundle
|
||||||
# check if there is a request body
|
# check if there is a request body
|
||||||
if 'requestBody' in interface['operation']:
|
if 'requestBody' in interface['operation']:
|
||||||
@ -80,13 +89,14 @@ class ApiBasedToolSchemaParser:
|
|||||||
root = root[ref]
|
root = root[ref]
|
||||||
# overwrite the content
|
# overwrite the content
|
||||||
interface['operation']['requestBody']['content'][content_type]['schema'] = root
|
interface['operation']['requestBody']['content'][content_type]['schema'] = root
|
||||||
|
|
||||||
# parse body parameters
|
# parse body parameters
|
||||||
if 'schema' in interface['operation']['requestBody']['content'][content_type]:
|
if 'schema' in interface['operation']['requestBody']['content'][content_type]:
|
||||||
body_schema = interface['operation']['requestBody']['content'][content_type]['schema']
|
body_schema = interface['operation']['requestBody']['content'][content_type]['schema']
|
||||||
required = body_schema['required'] if 'required' in body_schema else []
|
required = body_schema['required'] if 'required' in body_schema else []
|
||||||
properties = body_schema['properties'] if 'properties' in body_schema else {}
|
properties = body_schema['properties'] if 'properties' in body_schema else {}
|
||||||
for name, property in properties.items():
|
for name, property in properties.items():
|
||||||
parameters.append(ToolParameter(
|
tool = ToolParameter(
|
||||||
name=name,
|
name=name,
|
||||||
label=I18nObject(
|
label=I18nObject(
|
||||||
en_US=name,
|
en_US=name,
|
||||||
@ -101,7 +111,14 @@ class ApiBasedToolSchemaParser:
|
|||||||
form=ToolParameter.ToolParameterForm.LLM,
|
form=ToolParameter.ToolParameterForm.LLM,
|
||||||
llm_description=property['description'] if 'description' in property else '',
|
llm_description=property['description'] if 'description' in property else '',
|
||||||
default=property['default'] if 'default' in property else None,
|
default=property['default'] if 'default' in property else None,
|
||||||
))
|
)
|
||||||
|
|
||||||
|
# check if there is a type
|
||||||
|
typ = ApiBasedToolSchemaParser._get_tool_parameter_type(property)
|
||||||
|
if typ:
|
||||||
|
tool.type = typ
|
||||||
|
|
||||||
|
parameters.append(tool)
|
||||||
|
|
||||||
# check if parameters is duplicated
|
# check if parameters is duplicated
|
||||||
parameters_count = {}
|
parameters_count = {}
|
||||||
@ -119,7 +136,11 @@ class ApiBasedToolSchemaParser:
|
|||||||
path = interface['path']
|
path = interface['path']
|
||||||
if interface['path'].startswith('/'):
|
if interface['path'].startswith('/'):
|
||||||
path = interface['path'][1:]
|
path = interface['path'][1:]
|
||||||
path = path.replace('/', '_')
|
# remove special characters like / to ensure the operation id is valid ^[a-zA-Z0-9_-]{1,64}$
|
||||||
|
path = re.sub(r'[^a-zA-Z0-9_-]', '', path)
|
||||||
|
if not path:
|
||||||
|
path = str(uuid.uuid4())
|
||||||
|
|
||||||
interface['operation']['operationId'] = f'{path}_{interface["method"]}'
|
interface['operation']['operationId'] = f'{path}_{interface["method"]}'
|
||||||
|
|
||||||
bundles.append(ApiBasedToolBundle(
|
bundles.append(ApiBasedToolBundle(
|
||||||
@ -134,7 +155,23 @@ class ApiBasedToolSchemaParser:
|
|||||||
))
|
))
|
||||||
|
|
||||||
return bundles
|
return bundles
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_tool_parameter_type(parameter: dict) -> ToolParameter.ToolParameterType:
|
||||||
|
parameter = parameter or {}
|
||||||
|
typ = None
|
||||||
|
if 'type' in parameter:
|
||||||
|
typ = parameter['type']
|
||||||
|
elif 'schema' in parameter and 'type' in parameter['schema']:
|
||||||
|
typ = parameter['schema']['type']
|
||||||
|
|
||||||
|
if typ == 'integer' or typ == 'number':
|
||||||
|
return ToolParameter.ToolParameterType.NUMBER
|
||||||
|
elif typ == 'boolean':
|
||||||
|
return ToolParameter.ToolParameterType.BOOLEAN
|
||||||
|
elif typ == 'string':
|
||||||
|
return ToolParameter.ToolParameterType.STRING
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_openapi_yaml_to_tool_bundle(yaml: str, extra_info: dict = None, warning: dict = None) -> list[ApiBasedToolBundle]:
|
def parse_openapi_yaml_to_tool_bundle(yaml: str, extra_info: dict = None, warning: dict = None) -> list[ApiBasedToolBundle]:
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user