Browse Source

fix: issues by pydantic2 upgrade (#5171)

takatost 10 months ago
parent
commit
5ec7d85629

+ 3 - 0
api/core/entities/provider_entities.py

@@ -97,3 +97,6 @@ class ModelSettings(BaseModel):
     model_type: ModelType
     enabled: bool = True
     load_balancing_configs: list[ModelLoadBalancingConfiguration] = []
+
+    # pydantic configs
+    model_config = ConfigDict(protected_namespaces=())

+ 2 - 2
api/core/tools/entities/api_entities.py

@@ -28,8 +28,8 @@ class UserToolProvider(BaseModel):
     icon: str
     label: I18nObject # label
     type: ToolProviderType
-    masked_credentials: dict = None
-    original_credentials: dict = None
+    masked_credentials: Optional[dict] = None
+    original_credentials: Optional[dict] = None
     is_team_authorization: bool = False
     allow_delete: bool = True
     tools: list[UserTool] = None

+ 2 - 2
api/core/tools/provider/builtin/aippt/tools/aippt.py

@@ -507,9 +507,9 @@ class AIPPTGenerateTool(BuiltinTool):
             colors, styles = self.get_styles(user_id='__dify_system__')
         except Exception as e:
             colors, styles = [
-                {'id': -1, 'name': '__default__', 'en_name': '__default__'}
+                {'id': '-1', 'name': '__default__', 'en_name': '__default__'}
             ], [
-                {'id': -1, 'name': '__default__', 'en_name': '__default__'}
+                {'id': '-1', 'name': '__default__', 'en_name': '__default__'}
             ]
 
         return [

+ 1 - 1
api/core/tools/provider/builtin/bing/tools/bing_web_search.yaml

@@ -263,7 +263,7 @@ parameters:
           en_US: New Zealand
           zh_Hans: 新西兰
           pt_BR: New Zealand
-      - value: NO
+      - value: 'NO'
         label:
           en_US: Norway
           zh_Hans: 挪威

+ 0 - 174
api/core/tools/provider/builtin/duckduckgo/tools/duckduckgo_search.py

@@ -1,174 +0,0 @@
-<<<<<<< HEAD
-=======
-from typing import Any, Optional
-
-from pydantic import BaseModel, Field
-
-from core.tools.entities.tool_entities import ToolInvokeMessage
-from core.tools.tool.builtin_tool import BuiltinTool
-
-
-class DuckDuckGoSearchAPIWrapper(BaseModel):
-    """Wrapper for DuckDuckGo Search API.
-
-    Free and does not require any setup.
-    """
-
-    region: Optional[str] = "wt-wt"
-    safesearch: str = "moderate"
-    time: Optional[str] = "y"
-    max_results: int = 5
-
-    def get_snippets(self, query: str) -> list[str]:
-        """Run query through DuckDuckGo and return concatenated results."""
-        from duckduckgo_search import DDGS
-
-        with DDGS() as ddgs:
-            results = ddgs.text(
-                query,
-                region=self.region,
-                safesearch=self.safesearch,
-                timelimit=self.time,
-            )
-            if results is None:
-                return ["No good DuckDuckGo Search Result was found"]
-            snippets = []
-            for i, res in enumerate(results, 1):
-                if res is not None:
-                    snippets.append(res["body"])
-                if len(snippets) == self.max_results:
-                    break
-        return snippets
-
-    def run(self, query: str) -> str:
-        snippets = self.get_snippets(query)
-        return " ".join(snippets)
-
-    def results(
-        self, query: str, num_results: int, backend: str = "api"
-    ) -> list[dict[str, str]]:
-        """Run query through DuckDuckGo and return metadata.
-
-        Args:
-            query: The query to search for.
-            num_results: The number of results to return.
-
-        Returns:
-            A list of dictionaries with the following keys:
-                snippet - The description of the result.
-                title - The title of the result.
-                link - The link to the result.
-        """
-        from duckduckgo_search import DDGS
-
-        with DDGS() as ddgs:
-            results = ddgs.text(
-                query,
-                region=self.region,
-                safesearch=self.safesearch,
-                timelimit=self.time,
-                backend=backend,
-            )
-            if results is None:
-                return [{"Result": "No good DuckDuckGo Search Result was found"}]
-
-            def to_metadata(result: dict) -> dict[str, str]:
-                if backend == "news":
-                    return {
-                        "date": result["date"],
-                        "title": result["title"],
-                        "snippet": result["body"],
-                        "source": result["source"],
-                        "link": result["url"],
-                    }
-                return {
-                    "snippet": result["body"],
-                    "title": result["title"],
-                    "link": result["href"],
-                }
-
-            formatted_results = []
-            for i, res in enumerate(results, 1):
-                if res is not None:
-                    formatted_results.append(to_metadata(res))
-                if len(formatted_results) == num_results:
-                    break
-        return formatted_results
-
-
-class DuckDuckGoSearchRun(BaseModel):
-    """Tool that queries the DuckDuckGo search API."""
-
-    name: str = "duckduckgo_search"
-    description: str = (
-        "A wrapper around DuckDuckGo Search. "
-        "Useful for when you need to answer questions about current events. "
-        "Input should be a search query."
-    )
-    api_wrapper: DuckDuckGoSearchAPIWrapper = Field(
-        default_factory=DuckDuckGoSearchAPIWrapper
-    )
-
-    def _run(
-        self,
-        query: str,
-    ) -> str:
-        """Use the tool."""
-        return self.api_wrapper.run(query)
-
-
-class DuckDuckGoSearchResults(BaseModel):
-    """Tool that queries the DuckDuckGo search API and gets back json."""
-
-    name: str = "DuckDuckGo Results JSON"
-    description: str = (
-        "A wrapper around Duck Duck Go Search. "
-        "Useful for when you need to answer questions about current events. "
-        "Input should be a search query. Output is a JSON array of the query results"
-    )
-    num_results: int = 4
-    api_wrapper: DuckDuckGoSearchAPIWrapper = Field(
-        default_factory=DuckDuckGoSearchAPIWrapper
-    )
-    backend: str = "api"
-
-    def _run(
-        self,
-        query: str,
-    ) -> str:
-        """Use the tool."""
-        res = self.api_wrapper.results(query, self.num_results, backend=self.backend)
-        res_strs = [", ".join([f"{k}: {v}" for k, v in d.items()]) for d in res]
-        return ", ".join([f"[{rs}]" for rs in res_strs])
-
-class DuckDuckGoInput(BaseModel):
-    query: str = Field(..., description="Search query.")
-
-class DuckDuckGoSearchTool(BuiltinTool):
-    """
-    Tool for performing a search using DuckDuckGo search engine.
-    """
-
-    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage | list[ToolInvokeMessage]:
-        """
-        Invoke the DuckDuckGo search tool.
-
-        Args:
-            user_id (str): The ID of the user invoking the tool.
-            tool_parameters (dict[str, Any]): The parameters for the tool invocation.
-
-        Returns:
-            ToolInvokeMessage | list[ToolInvokeMessage]: The result of the tool invocation.
-        """
-        query = tool_parameters.get('query', '')
-
-        if not query:
-            return self.create_text_message('Please input query')
-
-        tool = DuckDuckGoSearchRun(args_schema=DuckDuckGoInput)
-
-        result = tool._run(query)
-
-        return self.create_text_message(self.summary(user_id=user_id, content=result))
-    
->>>>>>> 4c2ba442b (missing type in DuckDuckGoSearchAPIWrapper)

+ 3 - 3
api/core/tools/provider/builtin/firecrawl/tools/crawl.yaml

@@ -67,12 +67,12 @@ parameters:
       zh_Hans: 如果启用,爬虫将仅返回页面的主要内容,不包括标题、导航、页脚等。
     form: form
     options:
-      - value: true
+      - value: 'true'
         label:
           en_US: 'Yes'
           zh_Hans: 
-      - value: false
+      - value: 'false'
         label:
           en_US: 'No'
           zh_Hans: 
-    default: false
+    default: 'false'

+ 1 - 1
api/core/tools/provider/builtin/searchapi/tools/google.yaml

@@ -185,7 +185,7 @@ parameters:
           en_US: New Zealand
           zh_Hans: 新西兰
           pt_BR: New Zealand
-      - value: NO
+      - value: 'NO'
         label:
           en_US: Norway
           zh_Hans: 挪威

+ 3 - 3
api/core/tools/provider/builtin/searchapi/tools/google_jobs.yaml

@@ -185,7 +185,7 @@ parameters:
           en_US: New Zealand
           zh_Hans: 新西兰
           pt_BR: New Zealand
-      - value: NO
+      - value: 'NO'
         label:
           en_US: Norway
           zh_Hans: 挪威
@@ -468,11 +468,11 @@ parameters:
     required: false
     form: form
     options:
-      - value: true
+      - value: 'true'
         label:
           en_US: "true"
           zh_Hans: "true"
-      - value: false
+      - value: 'false'
         label:
           en_US: "false"
           zh_Hans: "false"

+ 1 - 1
api/core/tools/provider/builtin/searchapi/tools/google_news.yaml

@@ -185,7 +185,7 @@ parameters:
           en_US: New Zealand
           zh_Hans: 新西兰
           pt_BR: New Zealand
-      - value: NO
+      - value: 'NO'
         label:
           en_US: Norway
           zh_Hans: 挪威

+ 1 - 1
api/core/tools/provider/builtin/stackexchange/stackexchange.yaml

@@ -6,7 +6,7 @@ identity:
     zh_Hans: Stack Exchange
   description:
     en_US: Access questions and answers from the Stack Exchange and its sub-sites.
-    zh_Hans: 从Stack Exchange和其子论坛获取问题和答案。
+    zh_Hans:  Stack Exchange 和其子论坛获取问题和答案。
   icon: icon.svg
   tags:
     - search

+ 3 - 3
api/core/tools/provider/builtin/stackexchange/tools/searchStackExQuestions.yaml

@@ -96,15 +96,15 @@ parameters:
       zh_Hans: 是否限制为只有已接受答案的问题。
     form: form
     options:
-      - value: true
+      - value: 'true'
         label:
           en_US: 'Yes'
           zh_Hans: 
-      - value: false
+      - value: 'false'
         label:
           en_US: 'No'
           zh_Hans: 
-    default: true
+    default: 'true'
   - name: pagesize
     type: number
     required: true

+ 9 - 9
api/core/tools/provider/builtin/tavily/tools/tavily_search.yaml

@@ -62,17 +62,17 @@ parameters:
       pt_BR: Include images in the search results
     form: form
     options:
-      - value: true
+      - value: 'true'
         label:
           en_US: 'Yes'
           zh_Hans: 
           pt_BR: 'Yes'
-      - value: false
+      - value: 'false'
         label:
           en_US: 'No'
           zh_Hans: 
           pt_BR: 'No'
-    default: false
+    default: 'false'
   - name: include_answer
     type: boolean
     required: false
@@ -86,17 +86,17 @@ parameters:
       pt_BR: Include answers in the search results
     form: form
     options:
-      - value: true
+      - value: 'true'
         label:
           en_US: 'Yes'
           zh_Hans: 
           pt_BR: 'Yes'
-      - value: false
+      - value: 'false'
         label:
           en_US: 'No'
           zh_Hans: 
           pt_BR: 'No'
-    default: false
+    default: 'false'
   - name: include_raw_content
     type: boolean
     required: false
@@ -110,17 +110,17 @@ parameters:
       pt_BR: Include raw content in the search results
     form: form
     options:
-      - value: true
+      - value: 'true'
         label:
           en_US: 'Yes'
           zh_Hans: 
           pt_BR: 'Yes'
-      - value: false
+      - value: 'false'
         label:
           en_US: 'No'
           zh_Hans: 
           pt_BR: 'No'
-    default: false
+    default: 'false'
   - name: max_results
     type: number
     required: false

+ 3 - 3
api/core/tools/provider/builtin/webscraper/tools/webscraper.yaml

@@ -49,12 +49,12 @@ parameters:
       zh_Hans: 如果启用,爬虫将仅返回页面摘要内容。
     form: form
     options:
-      - value: true
+      - value: 'true'
         label:
           en_US: 'Yes'
           zh_Hans: 
-      - value: false
+      - value: 'false'
         label:
           en_US: 'No'
           zh_Hans: 
-    default: false
+    default: 'false'

+ 10 - 10
api/core/tools/tool/tool.py

@@ -24,9 +24,9 @@ from core.tools.utils.tool_parameter_converter import ToolParameterConverter
 
 
 class Tool(BaseModel, ABC):
-    identity: ToolIdentity = None
+    identity: Optional[ToolIdentity] = None
     parameters: Optional[list[ToolParameter]] = None
-    description: ToolDescription = None
+    description: Optional[ToolDescription] = None
     is_team_authorization: bool = False
 
     # pydantic configs
@@ -46,15 +46,15 @@ class Tool(BaseModel, ABC):
             if not self.runtime_parameters:
                 self.runtime_parameters = {}
 
-        tenant_id: str = None
-        tool_id: str = None
-        invoke_from: InvokeFrom = None
-        tool_invoke_from: ToolInvokeFrom = None
-        credentials: dict[str, Any] = None
-        runtime_parameters: dict[str, Any] = None
+        tenant_id: Optional[str] = None
+        tool_id: Optional[str] = None
+        invoke_from: Optional[InvokeFrom] = None
+        tool_invoke_from: Optional[ToolInvokeFrom] = None
+        credentials: Optional[dict[str, Any]] = None
+        runtime_parameters: Optional[dict[str, Any]] = None
 
-    runtime: Runtime = None
-    variables: ToolRuntimeVariablePool = None
+    runtime: Optional[Runtime] = None
+    variables: Optional[ToolRuntimeVariablePool] = None
 
     def __init__(self, **data: Any):
         super().__init__(**data)

+ 23 - 20
api/services/tools/builtin_tools_manage_service.py

@@ -201,26 +201,29 @@ class BuiltinToolManageService:
         result: list[UserToolProvider] = []
 
         for provider_controller in provider_controllers:
-            # convert provider controller to user provider
-            user_builtin_provider = ToolTransformService.builtin_provider_to_user_provider(
-                provider_controller=provider_controller,
-                db_provider=find_provider(provider_controller.identity.name),
-                decrypt_credentials=True
-            )
-
-            # add icon
-            ToolTransformService.repack_provider(user_builtin_provider)
-
-            tools = provider_controller.get_tools()
-            for tool in tools:
-                user_builtin_provider.tools.append(ToolTransformService.tool_to_user_tool(
-                    tenant_id=tenant_id,
-                    tool=tool, 
-                    credentials=user_builtin_provider.original_credentials, 
-                    labels=ToolLabelManager.get_tool_labels(provider_controller)
-                ))
-
-            result.append(user_builtin_provider)
+            try:
+                # convert provider controller to user provider
+                user_builtin_provider = ToolTransformService.builtin_provider_to_user_provider(
+                    provider_controller=provider_controller,
+                    db_provider=find_provider(provider_controller.identity.name),
+                    decrypt_credentials=True
+                )
+
+                # add icon
+                ToolTransformService.repack_provider(user_builtin_provider)
+
+                tools = provider_controller.get_tools()
+                for tool in tools:
+                    user_builtin_provider.tools.append(ToolTransformService.tool_to_user_tool(
+                        tenant_id=tenant_id,
+                        tool=tool,
+                        credentials=user_builtin_provider.original_credentials,
+                        labels=ToolLabelManager.get_tool_labels(provider_controller)
+                    ))
+
+                result.append(user_builtin_provider)
+            except Exception as e:
+                raise e
 
         return BuiltinToolProviderSort.sort(result)
     

+ 3 - 1
api/services/tools/tools_transform_service.py

@@ -4,8 +4,8 @@ from typing import Optional, Union
 
 from flask import current_app
 
-from core.model_runtime.entities.common_entities import I18nObject
 from core.tools.entities.api_entities import UserTool, UserToolProvider
+from core.tools.entities.common_entities import I18nObject
 from core.tools.entities.tool_bundle import ApiToolBundle
 from core.tools.entities.tool_entities import (
     ApiProviderAuthType,
@@ -81,11 +81,13 @@ class ToolTransformService:
             description=I18nObject(
                 en_US=provider_controller.identity.description.en_US,
                 zh_Hans=provider_controller.identity.description.zh_Hans,
+                pt_BR=provider_controller.identity.description.pt_BR,
             ),
             icon=provider_controller.identity.icon,
             label=I18nObject(
                 en_US=provider_controller.identity.label.en_US,
                 zh_Hans=provider_controller.identity.label.zh_Hans,
+                pt_BR=provider_controller.identity.label.pt_BR,
             ),
             type=ToolProviderType.BUILT_IN,
             masked_credentials={},