Chore/remove python dependencies selector (#7494)

This commit is contained in:
Yeuoly
2024-08-21 16:57:14 +08:00
committed by GitHub
parent 715eb8fa32
commit 784b11ce19
17 changed files with 21 additions and 388 deletions

View File

@@ -1,15 +1,13 @@
import logging
import time
from enum import Enum
from threading import Lock
from typing import Literal, Optional
from typing import Optional
from httpx import Timeout, get, post
from httpx import Timeout, post
from pydantic import BaseModel
from yarl import URL
from configs import dify_config
from core.helper.code_executor.entities import CodeDependency
from core.helper.code_executor.javascript.javascript_transformer import NodeJsTemplateTransformer
from core.helper.code_executor.jinja2.jinja2_transformer import Jinja2TemplateTransformer
from core.helper.code_executor.python3.python3_transformer import Python3TemplateTransformer
@@ -66,8 +64,7 @@ class CodeExecutor:
def execute_code(cls,
language: CodeLanguage,
preload: str,
code: str,
dependencies: Optional[list[CodeDependency]] = None) -> str:
code: str) -> str:
"""
Execute code
:param language: code language
@@ -87,9 +84,6 @@ class CodeExecutor:
'enable_network': True
}
if dependencies:
data['dependencies'] = [dependency.model_dump() for dependency in dependencies]
try:
response = post(str(url), json=data, headers=headers, timeout=CODE_EXECUTION_TIMEOUT)
if response.status_code == 503:
@@ -119,7 +113,7 @@ class CodeExecutor:
return response.data.stdout or ''
@classmethod
def execute_workflow_code_template(cls, language: CodeLanguage, code: str, inputs: dict, dependencies: Optional[list[CodeDependency]] = None) -> dict:
def execute_workflow_code_template(cls, language: CodeLanguage, code: str, inputs: dict) -> dict:
"""
Execute code
:param language: code language
@@ -131,67 +125,12 @@ class CodeExecutor:
if not template_transformer:
raise CodeExecutionException(f'Unsupported language {language}')
runner, preload, dependencies = template_transformer.transform_caller(code, inputs, dependencies)
runner, preload = template_transformer.transform_caller(code, inputs)
try:
response = cls.execute_code(language, preload, runner, dependencies)
response = cls.execute_code(language, preload, runner)
except CodeExecutionException as e:
raise e
return template_transformer.transform_response(response)
@classmethod
def list_dependencies(cls, language: str) -> list[CodeDependency]:
if language not in cls.supported_dependencies_languages:
return []
with cls.dependencies_cache_lock:
if language in cls.dependencies_cache:
# check expiration
dependencies = cls.dependencies_cache[language]
if dependencies['expiration'] > time.time():
return dependencies['data']
# remove expired cache
del cls.dependencies_cache[language]
dependencies = cls._get_dependencies(language)
with cls.dependencies_cache_lock:
cls.dependencies_cache[language] = {
'data': dependencies,
'expiration': time.time() + 60
}
return dependencies
@classmethod
def _get_dependencies(cls, language: Literal['python3']) -> list[CodeDependency]:
"""
List dependencies
"""
url = URL(CODE_EXECUTION_ENDPOINT) / 'v1' / 'sandbox' / 'dependencies'
headers = {
'X-Api-Key': CODE_EXECUTION_API_KEY
}
running_language = cls.code_language_to_running_language.get(language)
if isinstance(running_language, Enum):
running_language = running_language.value
data = {
'language': running_language,
}
try:
response = get(str(url), params=data, headers=headers, timeout=CODE_EXECUTION_TIMEOUT)
if response.status_code != 200:
raise Exception(f'Failed to list dependencies, got status code {response.status_code}, please check if the sandbox service is running')
response = response.json()
dependencies = response.get('data', {}).get('dependencies', [])
return [
CodeDependency(**dependency) for dependency in dependencies
if dependency.get('name') not in Python3TemplateTransformer.get_standard_packages()
]
except Exception as e:
logger.exception(f'Failed to list dependencies: {e}')
return []

View File

@@ -2,8 +2,6 @@ from abc import abstractmethod
from pydantic import BaseModel
from core.helper.code_executor.code_executor import CodeExecutor
class CodeNodeProvider(BaseModel):
@staticmethod
@@ -23,10 +21,6 @@ class CodeNodeProvider(BaseModel):
"""
pass
@classmethod
def get_default_available_packages(cls) -> list[dict]:
return [p.model_dump() for p in CodeExecutor.list_dependencies(cls.get_language())]
@classmethod
def get_default_config(cls) -> dict:
return {
@@ -50,6 +44,5 @@ class CodeNodeProvider(BaseModel):
"children": None
}
}
},
"available_dependencies": cls.get_default_available_packages(),
}
}

View File

@@ -1,6 +0,0 @@
from pydantic import BaseModel
class CodeDependency(BaseModel):
name: str
version: str

View File

@@ -3,7 +3,7 @@ from core.helper.code_executor.code_executor import CodeExecutor, CodeLanguage
class Jinja2Formatter:
@classmethod
def format(cls, template: str, inputs: str) -> str:
def format(cls, template: str, inputs: dict) -> str:
"""
Format template
:param template: template

View File

@@ -1,14 +1,9 @@
from textwrap import dedent
from core.helper.code_executor.python3.python3_transformer import Python3TemplateTransformer
from core.helper.code_executor.template_transformer import TemplateTransformer
class Jinja2TemplateTransformer(TemplateTransformer):
@classmethod
def get_standard_packages(cls) -> set[str]:
return {'jinja2'} | Python3TemplateTransformer.get_standard_packages()
@classmethod
def transform_response(cls, response: str) -> dict:
"""

View File

@@ -4,30 +4,6 @@ from core.helper.code_executor.template_transformer import TemplateTransformer
class Python3TemplateTransformer(TemplateTransformer):
@classmethod
def get_standard_packages(cls) -> set[str]:
return {
'base64',
'binascii',
'collections',
'datetime',
'functools',
'hashlib',
'hmac',
'itertools',
'json',
'math',
'operator',
'os',
'random',
're',
'string',
'sys',
'time',
'traceback',
'uuid',
}
@classmethod
def get_runner_script(cls) -> str:
runner_script = dedent(f"""

View File

@@ -2,9 +2,6 @@ import json
import re
from abc import ABC, abstractmethod
from base64 import b64encode
from typing import Optional
from core.helper.code_executor.entities import CodeDependency
class TemplateTransformer(ABC):
@@ -13,12 +10,7 @@ class TemplateTransformer(ABC):
_result_tag: str = '<<RESULT>>'
@classmethod
def get_standard_packages(cls) -> set[str]:
return set()
@classmethod
def transform_caller(cls, code: str, inputs: dict,
dependencies: Optional[list[CodeDependency]] = None) -> tuple[str, str, list[CodeDependency]]:
def transform_caller(cls, code: str, inputs: dict) -> tuple[str, str]:
"""
Transform code to python runner
:param code: code
@@ -28,14 +20,7 @@ class TemplateTransformer(ABC):
runner_script = cls.assemble_runner_script(code, inputs)
preload_script = cls.get_preload_script()
packages = dependencies or []
standard_packages = cls.get_standard_packages()
for package in standard_packages:
if package not in packages:
packages.append(CodeDependency(name=package, version=''))
packages = list({dep.name: dep for dep in packages if dep.name}.values())
return runner_script, preload_script, packages
return runner_script, preload_script
@classmethod
def extract_result_str_from_response(cls, response: str) -> str: