tools_transform_service.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import json
  2. import logging
  3. from typing import Optional, Union
  4. from flask import current_app
  5. from core.model_runtime.entities.common_entities import I18nObject
  6. from core.tools.entities.tool_bundle import ApiBasedToolBundle
  7. from core.tools.entities.tool_entities import ApiProviderAuthType, ToolParameter, ToolProviderCredentials
  8. from core.tools.entities.user_entities import UserTool, UserToolProvider
  9. from core.tools.provider.api_tool_provider import ApiBasedToolProviderController
  10. from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
  11. from core.tools.tool.tool import Tool
  12. from core.tools.utils.configuration import ToolConfigurationManager
  13. from models.tools import ApiToolProvider, BuiltinToolProvider
  14. logger = logging.getLogger(__name__)
  15. class ToolTransformService:
  16. @staticmethod
  17. def get_tool_provider_icon_url(provider_type: str, provider_name: str, icon: str) -> Union[str, dict]:
  18. """
  19. get tool provider icon url
  20. """
  21. url_prefix = (current_app.config.get("CONSOLE_API_URL")
  22. + "/console/api/workspaces/current/tool-provider/")
  23. if provider_type == UserToolProvider.ProviderType.BUILTIN.value:
  24. return url_prefix + 'builtin/' + provider_name + '/icon'
  25. elif provider_type == UserToolProvider.ProviderType.API.value:
  26. try:
  27. return json.loads(icon)
  28. except:
  29. return {
  30. "background": "#252525",
  31. "content": "\ud83d\ude01"
  32. }
  33. return ''
  34. @staticmethod
  35. def repack_provider(provider: Union[dict, UserToolProvider]):
  36. """
  37. repack provider
  38. :param provider: the provider dict
  39. """
  40. if isinstance(provider, dict) and 'icon' in provider:
  41. provider['icon'] = ToolTransformService.get_tool_provider_icon_url(
  42. provider_type=provider['type'],
  43. provider_name=provider['name'],
  44. icon=provider['icon']
  45. )
  46. elif isinstance(provider, UserToolProvider):
  47. provider.icon = ToolTransformService.get_tool_provider_icon_url(
  48. provider_type=provider.type.value,
  49. provider_name=provider.name,
  50. icon=provider.icon
  51. )
  52. @staticmethod
  53. def builtin_provider_to_user_provider(
  54. provider_controller: BuiltinToolProviderController,
  55. db_provider: Optional[BuiltinToolProvider],
  56. decrypt_credentials: bool = True
  57. ) -> UserToolProvider:
  58. """
  59. convert provider controller to user provider
  60. """
  61. result = UserToolProvider(
  62. id=provider_controller.identity.name,
  63. author=provider_controller.identity.author,
  64. name=provider_controller.identity.name,
  65. description=I18nObject(
  66. en_US=provider_controller.identity.description.en_US,
  67. zh_Hans=provider_controller.identity.description.zh_Hans,
  68. ),
  69. icon=provider_controller.identity.icon,
  70. label=I18nObject(
  71. en_US=provider_controller.identity.label.en_US,
  72. zh_Hans=provider_controller.identity.label.zh_Hans,
  73. ),
  74. type=UserToolProvider.ProviderType.BUILTIN,
  75. masked_credentials={},
  76. is_team_authorization=False,
  77. tools=[]
  78. )
  79. # get credentials schema
  80. schema = provider_controller.get_credentials_schema()
  81. for name, value in schema.items():
  82. result.masked_credentials[name] = \
  83. ToolProviderCredentials.CredentialsType.default(value.type)
  84. # check if the provider need credentials
  85. if not provider_controller.need_credentials:
  86. result.is_team_authorization = True
  87. result.allow_delete = False
  88. elif db_provider:
  89. result.is_team_authorization = True
  90. if decrypt_credentials:
  91. credentials = db_provider.credentials
  92. # init tool configuration
  93. tool_configuration = ToolConfigurationManager(
  94. tenant_id=db_provider.tenant_id,
  95. provider_controller=provider_controller
  96. )
  97. # decrypt the credentials and mask the credentials
  98. decrypted_credentials = tool_configuration.decrypt_tool_credentials(credentials=credentials)
  99. masked_credentials = tool_configuration.mask_tool_credentials(credentials=decrypted_credentials)
  100. result.masked_credentials = masked_credentials
  101. result.original_credentials = decrypted_credentials
  102. return result
  103. @staticmethod
  104. def api_provider_to_controller(
  105. db_provider: ApiToolProvider,
  106. ) -> ApiBasedToolProviderController:
  107. """
  108. convert provider controller to user provider
  109. """
  110. # package tool provider controller
  111. controller = ApiBasedToolProviderController.from_db(
  112. db_provider=db_provider,
  113. auth_type=ApiProviderAuthType.API_KEY if db_provider.credentials['auth_type'] == 'api_key' else
  114. ApiProviderAuthType.NONE
  115. )
  116. return controller
  117. @staticmethod
  118. def api_provider_to_user_provider(
  119. provider_controller: ApiBasedToolProviderController,
  120. db_provider: ApiToolProvider,
  121. decrypt_credentials: bool = True
  122. ) -> UserToolProvider:
  123. """
  124. convert provider controller to user provider
  125. """
  126. username = 'Anonymous'
  127. try:
  128. username = db_provider.user.name
  129. except Exception as e:
  130. logger.error(f'failed to get user name for api provider {db_provider.id}: {str(e)}')
  131. # add provider into providers
  132. credentials = db_provider.credentials
  133. result = UserToolProvider(
  134. id=db_provider.id,
  135. author=username,
  136. name=db_provider.name,
  137. description=I18nObject(
  138. en_US=db_provider.description,
  139. zh_Hans=db_provider.description,
  140. ),
  141. icon=db_provider.icon,
  142. label=I18nObject(
  143. en_US=db_provider.name,
  144. zh_Hans=db_provider.name,
  145. ),
  146. type=UserToolProvider.ProviderType.API,
  147. masked_credentials={},
  148. is_team_authorization=True,
  149. tools=[]
  150. )
  151. if decrypt_credentials:
  152. # init tool configuration
  153. tool_configuration = ToolConfigurationManager(
  154. tenant_id=db_provider.tenant_id,
  155. provider_controller=provider_controller
  156. )
  157. # decrypt the credentials and mask the credentials
  158. decrypted_credentials = tool_configuration.decrypt_tool_credentials(credentials=credentials)
  159. masked_credentials = tool_configuration.mask_tool_credentials(credentials=decrypted_credentials)
  160. result.masked_credentials = masked_credentials
  161. return result
  162. @staticmethod
  163. def tool_to_user_tool(
  164. tool: Union[ApiBasedToolBundle, Tool], credentials: dict = None, tenant_id: str = None
  165. ) -> UserTool:
  166. """
  167. convert tool to user tool
  168. """
  169. if isinstance(tool, Tool):
  170. # fork tool runtime
  171. tool = tool.fork_tool_runtime(meta={
  172. 'credentials': credentials,
  173. 'tenant_id': tenant_id,
  174. })
  175. # get tool parameters
  176. parameters = tool.parameters or []
  177. # get tool runtime parameters
  178. runtime_parameters = tool.get_runtime_parameters() or []
  179. # override parameters
  180. current_parameters = parameters.copy()
  181. for runtime_parameter in runtime_parameters:
  182. found = False
  183. for index, parameter in enumerate(current_parameters):
  184. if parameter.name == runtime_parameter.name and parameter.form == runtime_parameter.form:
  185. current_parameters[index] = runtime_parameter
  186. found = True
  187. break
  188. if not found and runtime_parameter.form == ToolParameter.ToolParameterForm.FORM:
  189. current_parameters.append(runtime_parameter)
  190. user_tool = UserTool(
  191. author=tool.identity.author,
  192. name=tool.identity.name,
  193. label=tool.identity.label,
  194. description=tool.description.human,
  195. parameters=current_parameters
  196. )
  197. return user_tool
  198. if isinstance(tool, ApiBasedToolBundle):
  199. return UserTool(
  200. author=tool.author,
  201. name=tool.operation_id,
  202. label=I18nObject(
  203. en_US=tool.operation_id,
  204. zh_Hans=tool.operation_id
  205. ),
  206. description=I18nObject(
  207. en_US=tool.summary or '',
  208. zh_Hans=tool.summary or ''
  209. ),
  210. parameters=tool.parameters
  211. )