diff --git a/api/controllers/console/app/model_config.py b/api/controllers/console/app/model_config.py index d822f859bc..1301d12da4 100644 --- a/api/controllers/console/app/model_config.py +++ b/api/controllers/console/app/model_config.py @@ -2,7 +2,7 @@ import json from flask import request from flask_login import current_user -from flask_restful import Resource, reqparse +from flask_restful import Resource from controllers.console import api from controllers.console.app.wraps import get_app_model @@ -137,38 +137,4 @@ class ModelConfigResource(Resource): return {'result': 'success'} -class FeaturesResource(Resource): - - @setup_required - @login_required - @account_initialization_required - @get_app_model(mode=[AppMode.ADVANCED_CHAT, AppMode.WORKFLOW]) - def put(self, app_model): - """Get app features""" - parser = reqparse.RequestParser() - parser.add_argument('features', type=dict, required=True, nullable=False, location='json') - args = parser.parse_args() - - model_configuration = AppModelConfigService.validate_features( - tenant_id=current_user.current_tenant_id, - config=args.get('features'), - app_mode=AppMode.value_of(app_model.mode) - ) - - # update config - app_model_config = app_model.app_model_config - app_model_config.from_model_config_dict(model_configuration) - db.session.commit() - - app_model_config_was_updated.send( - app_model, - app_model_config=app_model_config - ) - - return { - 'result': 'success' - } - - api.add_resource(ModelConfigResource, '/apps//model-config') -api.add_resource(FeaturesResource, '/apps//features') diff --git a/api/core/app/advanced_chat/config_validator.py b/api/core/app/advanced_chat/config_validator.py index 39c00c028e..a20198ef4a 100644 --- a/api/core/app/advanced_chat/config_validator.py +++ b/api/core/app/advanced_chat/config_validator.py @@ -9,12 +9,13 @@ from core.app.validators.text_to_speech import TextToSpeechValidator class AdvancedChatAppConfigValidator: @classmethod - def config_validate(cls, tenant_id: str, config: dict) -> dict: + def config_validate(cls, tenant_id: str, config: dict, only_structure_validate: bool = False) -> dict: """ Validate for advanced chat app model config :param tenant_id: tenant id :param config: app model config args + :param only_structure_validate: if True, only structure validation will be performed """ related_config_keys = [] @@ -43,7 +44,11 @@ class AdvancedChatAppConfigValidator: related_config_keys.extend(current_related_config_keys) # moderation validation - config, current_related_config_keys = ModerationValidator.validate_and_set_defaults(tenant_id, config) + config, current_related_config_keys = ModerationValidator.validate_and_set_defaults( + tenant_id=tenant_id, + config=config, + only_structure_validate=only_structure_validate + ) related_config_keys.extend(current_related_config_keys) related_config_keys = list(set(related_config_keys)) diff --git a/api/core/app/validators/moderation.py b/api/core/app/validators/moderation.py index 4813385588..7a5dff55c9 100644 --- a/api/core/app/validators/moderation.py +++ b/api/core/app/validators/moderation.py @@ -7,7 +7,8 @@ logger = logging.getLogger(__name__) class ModerationValidator: @classmethod - def validate_and_set_defaults(cls, tenant_id, config: dict) -> tuple[dict, list[str]]: + def validate_and_set_defaults(cls, tenant_id, config: dict, only_structure_validate: bool = False) \ + -> tuple[dict, list[str]]: if not config.get("sensitive_word_avoidance"): config["sensitive_word_avoidance"] = { "enabled": False @@ -23,13 +24,14 @@ class ModerationValidator: if not config["sensitive_word_avoidance"].get("type"): raise ValueError("sensitive_word_avoidance.type is required") - typ = config["sensitive_word_avoidance"]["type"] - config = config["sensitive_word_avoidance"]["config"] + if not only_structure_validate: + typ = config["sensitive_word_avoidance"]["type"] + config = config["sensitive_word_avoidance"]["config"] - ModerationFactory.validate_config( - name=typ, - tenant_id=tenant_id, - config=config - ) + ModerationFactory.validate_config( + name=typ, + tenant_id=tenant_id, + config=config + ) return config, ["sensitive_word_avoidance"] diff --git a/api/core/app/workflow/config_validator.py b/api/core/app/workflow/config_validator.py index b76eabaeb5..e8381146a7 100644 --- a/api/core/app/workflow/config_validator.py +++ b/api/core/app/workflow/config_validator.py @@ -5,12 +5,13 @@ from core.app.validators.text_to_speech import TextToSpeechValidator class WorkflowAppConfigValidator: @classmethod - def config_validate(cls, tenant_id: str, config: dict) -> dict: + def config_validate(cls, tenant_id: str, config: dict, only_structure_validate: bool = False) -> dict: """ Validate for workflow app model config :param tenant_id: tenant id :param config: app model config args + :param only_structure_validate: only validate the structure of the config """ related_config_keys = [] @@ -23,7 +24,11 @@ class WorkflowAppConfigValidator: related_config_keys.extend(current_related_config_keys) # moderation validation - config, current_related_config_keys = ModerationValidator.validate_and_set_defaults(tenant_id, config) + config, current_related_config_keys = ModerationValidator.validate_and_set_defaults( + tenant_id=tenant_id, + config=config, + only_structure_validate=only_structure_validate + ) related_config_keys.extend(current_related_config_keys) related_config_keys = list(set(related_config_keys)) diff --git a/api/services/app_model_config_service.py b/api/services/app_model_config_service.py index 789d74ed2c..a35b0dd36e 100644 --- a/api/services/app_model_config_service.py +++ b/api/services/app_model_config_service.py @@ -18,12 +18,3 @@ class AppModelConfigService: return CompletionAppConfigValidator.config_validate(tenant_id, config) else: raise ValueError(f"Invalid app mode: {app_mode}") - - @classmethod - def validate_features(cls, tenant_id: str, config: dict, app_mode: AppMode) -> dict: - if app_mode == AppMode.ADVANCED_CHAT: - return AdvancedChatAppConfigValidator.config_validate(tenant_id, config) - elif app_mode == AppMode.WORKFLOW: - return WorkflowAppConfigValidator.config_validate(tenant_id, config) - else: - raise ValueError(f"Invalid app mode: {app_mode}") diff --git a/api/services/workflow_service.py b/api/services/workflow_service.py index 006bc44e41..102c861733 100644 --- a/api/services/workflow_service.py +++ b/api/services/workflow_service.py @@ -2,6 +2,8 @@ import json from datetime import datetime from typing import Optional +from core.app.advanced_chat.config_validator import AdvancedChatAppConfigValidator +from core.app.workflow.config_validator import WorkflowAppConfigValidator from extensions.ext_database import db from models.account import Account from models.model import App, AppMode @@ -56,7 +58,11 @@ class WorkflowService: # fetch draft workflow by app_model workflow = self.get_draft_workflow(app_model=app_model) - # TODO validate features + # validate features structure + self.validate_features_structure( + app_model=app_model, + features=features + ) # create draft workflow if not found if not workflow: @@ -100,7 +106,7 @@ class WorkflowService: if not draft_workflow: raise ValueError('No valid workflow found.') - # TODO check if the workflow is valid, basic check + # TODO check if the workflow structure is valid # create new workflow workflow = Workflow( @@ -153,3 +159,19 @@ class WorkflowService: ) return new_app + + def validate_features_structure(self, app_model: App, features: dict) -> dict: + if app_model.mode == AppMode.ADVANCED_CHAT.value: + return AdvancedChatAppConfigValidator.config_validate( + tenant_id=app_model.tenant_id, + config=features, + only_structure_validate=True + ) + elif app_model.mode == AppMode.WORKFLOW.value: + return WorkflowAppConfigValidator.config_validate( + tenant_id=app_model.tenant_id, + config=features, + only_structure_validate=True + ) + else: + raise ValueError(f"Invalid app mode: {app_model.mode}")