浏览代码

feat: code (#3557)

Yeuoly 1 年之前
父节点
当前提交
c2acb2be60

+ 33 - 15
api/core/helper/code_executor/code_executor.py

@@ -30,34 +30,24 @@ class CodeExecutionResponse(BaseModel):
 
 class CodeExecutor:
     @classmethod
-    def execute_code(cls, language: Literal['python3', 'javascript', 'jinja2'], code: str, inputs: dict) -> dict:
+    def execute_code(cls, language: Literal['python3', 'javascript', 'jinja2'], preload: str, code: str) -> str:
         """
         Execute code
         :param language: code language
         :param code: code
-        :param inputs: inputs
         :return:
         """
-        template_transformer = None
-        if language == 'python3':
-            template_transformer = PythonTemplateTransformer
-        elif language == 'jinja2':
-            template_transformer = Jinja2TemplateTransformer
-        elif language == 'javascript':
-            template_transformer = NodeJsTemplateTransformer
-        else:
-            raise CodeExecutionException('Unsupported language')
-
-        runner, preload = template_transformer.transform_caller(code, inputs)
         url = URL(CODE_EXECUTION_ENDPOINT) / 'v1' / 'sandbox' / 'run'
+
         headers = {
             'X-Api-Key': CODE_EXECUTION_API_KEY
         }
+
         data = {
             'language': 'python3' if language == 'jinja2' else
                         'nodejs' if language == 'javascript' else
                         'python3' if language == 'python3' else None,
-            'code': runner,
+            'code': code,
             'preload': preload
         }
 
@@ -85,4 +75,32 @@ class CodeExecutor:
         if response.data.error:
             raise CodeExecutionException(response.data.error)
         
-        return template_transformer.transform_response(response.data.stdout)
+        return response.data.stdout
+
+    @classmethod
+    def execute_workflow_code_template(cls, language: Literal['python3', 'javascript', 'jinja2'], code: str, inputs: dict) -> dict:
+        """
+        Execute code
+        :param language: code language
+        :param code: code
+        :param inputs: inputs
+        :return:
+        """
+        template_transformer = None
+        if language == 'python3':
+            template_transformer = PythonTemplateTransformer
+        elif language == 'jinja2':
+            template_transformer = Jinja2TemplateTransformer
+        elif language == 'javascript':
+            template_transformer = NodeJsTemplateTransformer
+        else:
+            raise CodeExecutionException('Unsupported language')
+
+        runner, preload = template_transformer.transform_caller(code, inputs)
+
+        try:
+            response = cls.execute_code(language, preload, runner)
+        except CodeExecutionException as e:
+            raise e
+
+        return template_transformer.transform_response(response)

+ 1 - 0
api/core/tools/provider/_position.yaml

@@ -17,6 +17,7 @@
 - model.zhipuai
 - aippt
 - youtube
+- code
 - wolframalpha
 - maths
 - github

文件差异内容过多而无法显示
+ 1 - 0
api/core/tools/provider/builtin/code/_assets/icon.svg


+ 8 - 0
api/core/tools/provider/builtin/code/code.py

@@ -0,0 +1,8 @@
+from typing import Any
+
+from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
+
+
+class CodeToolProvider(BuiltinToolProviderController):
+    def _validate_credentials(self, credentials: dict[str, Any]) -> None:
+        pass

+ 13 - 0
api/core/tools/provider/builtin/code/code.yaml

@@ -0,0 +1,13 @@
+identity:
+  author: Dify
+  name: code
+  label:
+    en_US: Code Interpreter
+    zh_Hans: 代码解释器
+    pt_BR: Interpretador de Código
+  description:
+    en_US: Run a piece of code and get the result back.
+    zh_Hans: 运行一段代码并返回结果。
+    pt_BR: Execute um trecho de código e obtenha o resultado de volta.
+  icon: icon.svg
+credentials_for_provider:

+ 22 - 0
api/core/tools/provider/builtin/code/tools/simple_code.py

@@ -0,0 +1,22 @@
+from typing import Any
+
+from core.helper.code_executor.code_executor import CodeExecutor
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class SimpleCode(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage | list[ToolInvokeMessage]:
+        """
+            invoke simple code
+        """
+
+        language = tool_parameters.get('language', 'python3')
+        code = tool_parameters.get('code', '')
+
+        if language not in ['python3', 'javascript']:
+            raise ValueError(f'Only python3 and javascript are supported, not {language}')
+        
+        result = CodeExecutor.execute_code(language, '', code)
+
+        return self.create_text_message(result)

+ 51 - 0
api/core/tools/provider/builtin/code/tools/simple_code.yaml

@@ -0,0 +1,51 @@
+identity:
+  name: simple_code
+  author: Dify
+  label:
+    en_US: Code Interpreter
+    zh_Hans: 代码解释器
+    pt_BR: Interpretador de Código
+description:
+  human:
+    en_US: Run code and get the result back, when you're using a lower quality model, please make sure there are some tips help LLM to understand how to write the code.
+    zh_Hans: 运行一段代码并返回结果,当您使用较低质量的模型时,请确保有一些提示帮助LLM理解如何编写代码。
+    pt_BR: Execute um trecho de código e obtenha o resultado de volta, quando você estiver usando um modelo de qualidade inferior, certifique-se de que existam algumas dicas para ajudar o LLM a entender como escrever o código.
+  llm: A tool for running code and getting the result back, but only native packages are allowed, network/IO operations are disabled. and you must use print() or console.log() to output the result or result will be empty.
+parameters:
+  - name: language
+    type: string
+    required: true
+    label:
+      en_US: Language
+      zh_Hans: 语言
+      pt_BR: Idioma
+    human_description:
+      en_US: The programming language of the code
+      zh_Hans: 代码的编程语言
+      pt_BR: A linguagem de programação do código
+    llm_description: language of the code, only "python3" and "javascript" are supported
+    form: llm
+    options:
+      - value: python3
+        label:
+          en_US: Python3
+          zh_Hans: Python3
+          pt_BR: Python3
+      - value: javascript
+        label:
+          en_US: JavaScript
+          zh_Hans: JavaScript
+          pt_BR: JavaScript
+  - name: code
+    type: string
+    required: true
+    label:
+      en_US: Code
+      zh_Hans: 代码
+      pt_BR: Código
+    human_description:
+      en_US: The code to be executed
+      zh_Hans: 要执行的代码
+      pt_BR: O código a ser executado
+    llm_description: code to be executed, only native packages are allowed, network/IO operations are disabled.
+    form: llm

+ 1 - 1
api/core/workflow/nodes/code/code_node.py

@@ -112,7 +112,7 @@ class CodeNode(BaseNode):
             variables[variable] = value
         # Run code
         try:
-            result = CodeExecutor.execute_code(
+            result = CodeExecutor.execute_workflow_code_template(
                 language=code_language,
                 code=code,
                 inputs=variables

+ 1 - 1
api/core/workflow/nodes/template_transform/template_transform_node.py

@@ -52,7 +52,7 @@ class TemplateTransformNode(BaseNode):
             variables[variable] = value
         # Run code
         try:
-            result = CodeExecutor.execute_code(
+            result = CodeExecutor.execute_workflow_code_template(
                 language='jinja2',
                 code=node_data.template,
                 inputs=variables

+ 1 - 1
api/tests/integration_tests/workflow/nodes/__mock/code_executor.py

@@ -26,6 +26,6 @@ def setup_code_executor_mock(request, monkeypatch: MonkeyPatch):
         yield
         return
 
-    monkeypatch.setattr(CodeExecutor, "execute_code", MockedCodeExecutor.invoke)
+    monkeypatch.setattr(CodeExecutor, "execute_workflow_code_template", MockedCodeExecutor.invoke)
     yield
     monkeypatch.undo()