Skip to content

Commit 757cff4

Browse files
committed
Merge branch 'v2-c' into knowledge_workflow
# Conflicts: # apps/common/utils/tool_code.py
2 parents 18445b5 + 5e909a4 commit 757cff4

File tree

7 files changed

+263
-110
lines changed

7 files changed

+263
-110
lines changed

apps/common/utils/tool_code.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ def __init__(self, sandbox=False):
2727
else:
2828
self.sandbox_path = os.path.join(PROJECT_DIR, 'data', 'sandbox')
2929
self.user = None
30-
self.banned_keywords = CONFIG.get("SANDBOX_PYTHON_BANNED_KEYWORDS", 'nothing_is_banned').split(',');
3130
self.sandbox_so_path = f'{self.sandbox_path}/sandbox.so'
31+
self.process_timeout_seconds = int(CONFIG.get("SANDBOX_PYTHON_PROCESS_TIMEOUT_SECONDS", '3600'))
3232
try:
3333
self._init_dir()
3434
except Exception as e:
@@ -60,21 +60,22 @@ def _init_dir(self):
6060
os.system(f"chown -R {self.user}:root {tmp_dir_path}")
6161
if os.path.exists(self.sandbox_so_path):
6262
os.chmod(self.sandbox_so_path, 0o440)
63-
# 初始化host黑名单
64-
banned_hosts_file_path = f'{self.sandbox_path}/.SANDBOX_BANNED_HOSTS'
65-
if os.path.exists(banned_hosts_file_path):
66-
os.remove(banned_hosts_file_path)
63+
# 初始化sandbox配置文件
64+
sandbox_conf_file_path = f'{self.sandbox_path}/.sandbox.conf'
65+
if os.path.exists(sandbox_conf_file_path):
66+
os.remove(sandbox_conf_file_path)
67+
allow_subprocess = CONFIG.get("SANDBOX_PYTHON_ALLOW_SUBPROCESS", '0')
6768
banned_hosts = CONFIG.get("SANDBOX_PYTHON_BANNED_HOSTS", '').strip()
6869
if banned_hosts:
6970
hostname = socket.gethostname()
7071
local_ip = socket.gethostbyname(hostname)
7172
banned_hosts = f"{banned_hosts},{hostname},{local_ip}"
72-
with open(banned_hosts_file_path, "w") as f:
73-
f.write(banned_hosts)
74-
os.chmod(banned_hosts_file_path, 0o440)
73+
with open(sandbox_conf_file_path, "w") as f:
74+
f.write(f"SANDBOX_PYTHON_BANNED_HOSTS={banned_hosts}\n")
75+
f.write(f"SANDBOX_PYTHON_ALLOW_SUBPROCESS={allow_subprocess}\n")
76+
os.chmod(sandbox_conf_file_path, 0o440)
7577

7678
def exec_code(self, code_str, keywords, function_name=None):
77-
self.validate_banned_keywords(code_str)
7879
_id = str(uuid.uuid7())
7980
success = '{"code":200,"msg":"成功","data":exec_result}'
8081
err = '{"code":500,"msg":str(e),"data":None}'
@@ -115,8 +116,6 @@ def exec_code(self, code_str, keywords, function_name=None):
115116
raise Exception(result.get('msg'))
116117

117118
def _generate_mcp_server_code(self, _code, params):
118-
self.validate_banned_keywords(_code)
119-
120119
# 解析代码,提取导入语句和函数定义
121120
try:
122121
tree = ast.parse(_code)
@@ -230,19 +229,19 @@ def _exec_sandbox(self, _code):
230229
}
231230
maxkb_logger.debug(f"Sandbox execute code: {_code}")
232231
compressed_and_base64_encoded_code_str = base64.b64encode(gzip.compress(_code.encode())).decode()
233-
subprocess_result = subprocess.run(
234-
['su', '-s', python_directory, '-c',
235-
f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\'{compressed_and_base64_encoded_code_str}\')).decode())',
236-
self.user],
237-
text=True,
238-
capture_output=True, **kwargs)
232+
try:
233+
subprocess_result = subprocess.run(
234+
['su', '-s', python_directory, '-c',
235+
f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\'{compressed_and_base64_encoded_code_str}\')).decode())',
236+
self.user],
237+
text=True,
238+
capture_output=True,
239+
timeout=self.process_timeout_seconds,
240+
**kwargs)
241+
except subprocess.TimeoutExpired:
242+
raise Exception(_("Sandbox process execution timeout, consider increasing MAXKB_SANDBOX_PYTHON_PROCESS_TIMEOUT_SECONDS."))
239243
return subprocess_result
240244

241-
def validate_banned_keywords(self, code_str):
242-
matched = next((bad for bad in self.banned_keywords if bad in code_str), None)
243-
if matched:
244-
raise Exception(f"keyword '{matched}' is banned in the tool.")
245-
246245
def validate_mcp_transport(self, code_str):
247246
servers = json.loads(code_str)
248247
for server, config in servers.items():

apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/tti.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from models_provider.base_model_provider import BaseModelCredential, ValidCode
1010
from common.utils.logger import maxkb_logger
1111

12+
1213
class QwenModelParams(BaseForm):
1314
"""
1415
Parameters class for the Qwen Text-to-Image model.
@@ -26,7 +27,8 @@ class QwenModelParams(BaseForm):
2627
{'value': '1280*720', 'label': '1280*720'},
2728
],
2829
text_field='label',
29-
value_field='value'
30+
value_field='value',
31+
attrs={'allow-create': True, 'filterable': True}
3032
)
3133

3234
n = SliderField(

apps/models_provider/impl/aliyun_bai_lian_model_provider/model/tti.py

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from http import HTTPStatus
33
from typing import Dict
44

5-
from dashscope import ImageSynthesis
5+
from dashscope import ImageSynthesis, MultiModalConversation
66
from django.utils.translation import gettext
77
from langchain_community.chat_models import ChatTongyi
88
from langchain_core.messages import HumanMessage
@@ -46,17 +46,48 @@ def check_auth(self):
4646
chat.invoke([HumanMessage([{"type": "text", "text": gettext('Hello')}])])
4747

4848
def generate_image(self, prompt: str, negative_prompt: str = None):
49-
rsp = ImageSynthesis.call(api_key=self.api_key,
50-
model=self.model_name,
51-
base_url='https://dashscope.aliyuncs.com/compatible-mode/v1',
52-
prompt=prompt,
53-
negative_prompt=negative_prompt,
54-
**self.params)
55-
file_urls = []
56-
if rsp.status_code == HTTPStatus.OK:
57-
for result in rsp.output.results:
58-
file_urls.append(result.url)
59-
else:
60-
maxkb_logger.error('sync_call Failed, status_code: %s, code: %s, message: %s' %
61-
(rsp.status_code, rsp.code, rsp.message))
62-
return file_urls
49+
if self.model_name.startswith("wan"):
50+
rsp = ImageSynthesis.call(api_key=self.api_key,
51+
model=self.model_name,
52+
base_url='https://dashscope.aliyuncs.com/compatible-mode/v1',
53+
prompt=prompt,
54+
negative_prompt=negative_prompt,
55+
**self.params)
56+
file_urls = []
57+
if rsp.status_code == HTTPStatus.OK:
58+
for result in rsp.output.results:
59+
file_urls.append(result.url)
60+
else:
61+
maxkb_logger.error('sync_call Failed, status_code: %s, code: %s, message: %s' %
62+
(rsp.status_code, rsp.code, rsp.message))
63+
return file_urls
64+
elif self.model_name.startswith("qwen"):
65+
messages = [
66+
{
67+
"role": "user",
68+
"content": [
69+
{
70+
"type": "text",
71+
"text": prompt
72+
}
73+
]
74+
}
75+
]
76+
rsp = MultiModalConversation.call(
77+
api_key=self.api_key,
78+
model=self.model_name,
79+
messages=messages,
80+
result_format='message',
81+
base_url='https://dashscope.aliyuncs.com/v1',
82+
stream=False,
83+
negative_prompt=negative_prompt,
84+
**self.params
85+
)
86+
file_urls = []
87+
if rsp.status_code == HTTPStatus.OK:
88+
for result in rsp.output.choices:
89+
file_urls.append(result.message.content[0].get('image'))
90+
else:
91+
maxkb_logger.error('sync_call Failed, status_code: %s, code: %s, message: %s' %
92+
(rsp.status_code, rsp.code, rsp.message))
93+
return file_urls

apps/tools/serializers/tool.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,6 @@ def insert(self, instance, with_valid=True):
354354
self.is_valid(raise_exception=True)
355355
ToolCreateRequest(data=instance).is_valid(raise_exception=True)
356356
# 校验代码是否包括禁止的关键字
357-
ToolExecutor().validate_banned_keywords(instance.get('code', ''))
358357
if instance.get('tool_type') == ToolType.MCP:
359358
ToolExecutor().validate_mcp_transport(instance.get('code', ''))
360359

@@ -391,7 +390,6 @@ class TestConnection(serializers.Serializer):
391390
def test_connection(self):
392391
self.is_valid(raise_exception=True)
393392
# 校验代码是否包括禁止的关键字
394-
ToolExecutor().validate_banned_keywords(self.data.get('code', ''))
395393
ToolExecutor().validate_mcp_transport(self.data.get('code', ''))
396394

397395
# 校验mcp json
@@ -486,7 +484,6 @@ def edit(self, instance, with_valid=True):
486484
self.is_valid(raise_exception=True)
487485
ToolEditRequest(data=instance).is_valid(raise_exception=True)
488486
# 校验代码是否包括禁止的关键字
489-
ToolExecutor().validate_banned_keywords(instance.get('code', ''))
490487
if instance.get('tool_type') == ToolType.MCP:
491488
ToolExecutor().validate_mcp_transport(instance.get('code', ''))
492489

installer/Dockerfile-base

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ ENV PATH=/opt/py3/bin:$PATH \
4848
MAXKB_SANDBOX=1 \
4949
MAXKB_SANDBOX_HOME=/opt/maxkb-app/sandbox \
5050
MAXKB_SANDBOX_PYTHON_PACKAGE_PATHS="/opt/py3/lib/python3.11/site-packages,/opt/maxkb-app/sandbox/python-packages,/opt/maxkb/python-packages" \
51-
MAXKB_SANDBOX_PYTHON_BANNED_KEYWORDS="subprocess.,system(,exec(,execve(,pty.,eval(,compile(,shutil.,input(,__import__" \
5251
MAXKB_SANDBOX_PYTHON_BANNED_HOSTS="127.0.0.1,localhost,host.docker.internal,maxkb,pgsql,redis" \
5352
MAXKB_ADMIN_PATH=/admin
5453

0 commit comments

Comments
 (0)