| description="Maximum number of concurrent active requests per app (0 for unlimited)", | description="Maximum number of concurrent active requests per app (0 for unlimited)", | ||||
| default=0, | default=0, | ||||
| ) | ) | ||||
| APP_DAILY_RATE_LIMIT: NonNegativeInt = Field( | |||||
| description="Maximum number of requests per app per day", | |||||
| default=5000, | |||||
| ) | |||||
| class CodeExecutionSandboxConfig(BaseSettings): | class CodeExecutionSandboxConfig(BaseSettings): |
| import services | import services | ||||
| from configs import dify_config | from configs import dify_config | ||||
| from controllers.console import api | from controllers.console import api | ||||
| from controllers.console.app.error import ConversationCompletedError, DraftWorkflowNotExist, DraftWorkflowNotSync | |||||
| from controllers.console.app.error import ( | |||||
| ConversationCompletedError, | |||||
| DraftWorkflowNotExist, | |||||
| DraftWorkflowNotSync, | |||||
| ) | |||||
| from controllers.console.app.wraps import get_app_model | from controllers.console.app.wraps import get_app_model | ||||
| from controllers.console.wraps import account_initialization_required, setup_required | from controllers.console.wraps import account_initialization_required, setup_required | ||||
| from controllers.web.error import InvokeRateLimitError as InvokeRateLimitHttpError | |||||
| from core.app.apps.base_app_queue_manager import AppQueueManager | from core.app.apps.base_app_queue_manager import AppQueueManager | ||||
| from core.app.entities.app_invoke_entities import InvokeFrom | from core.app.entities.app_invoke_entities import InvokeFrom | ||||
| from extensions.ext_database import db | from extensions.ext_database import db | ||||
| from models.model import AppMode | from models.model import AppMode | ||||
| from services.app_generate_service import AppGenerateService | from services.app_generate_service import AppGenerateService | ||||
| from services.errors.app import WorkflowHashNotEqualError | from services.errors.app import WorkflowHashNotEqualError | ||||
| from services.errors.llm import InvokeRateLimitError | |||||
| from services.workflow_service import DraftWorkflowDeletionError, WorkflowInUseError, WorkflowService | from services.workflow_service import DraftWorkflowDeletionError, WorkflowInUseError, WorkflowService | ||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
| raise NotFound("Conversation Not Exists.") | raise NotFound("Conversation Not Exists.") | ||||
| except services.errors.conversation.ConversationCompletedError: | except services.errors.conversation.ConversationCompletedError: | ||||
| raise ConversationCompletedError() | raise ConversationCompletedError() | ||||
| except InvokeRateLimitError as ex: | |||||
| raise InvokeRateLimitHttpError(ex.description) | |||||
| except ValueError as e: | except ValueError as e: | ||||
| raise e | raise e | ||||
| except Exception: | except Exception: | ||||
| parser.add_argument("files", type=list, required=False, location="json") | parser.add_argument("files", type=list, required=False, location="json") | ||||
| args = parser.parse_args() | args = parser.parse_args() | ||||
| response = AppGenerateService.generate( | |||||
| app_model=app_model, | |||||
| user=current_user, | |||||
| args=args, | |||||
| invoke_from=InvokeFrom.DEBUGGER, | |||||
| streaming=True, | |||||
| ) | |||||
| try: | |||||
| response = AppGenerateService.generate( | |||||
| app_model=app_model, | |||||
| user=current_user, | |||||
| args=args, | |||||
| invoke_from=InvokeFrom.DEBUGGER, | |||||
| streaming=True, | |||||
| ) | |||||
| return helper.compact_generate_response(response) | |||||
| return helper.compact_generate_response(response) | |||||
| except InvokeRateLimitError as ex: | |||||
| raise InvokeRateLimitHttpError(ex.description) | |||||
| class WorkflowTaskStopApi(Resource): | class WorkflowTaskStopApi(Resource): |
| ) | ) | ||||
| from controllers.console.explore.error import NotChatAppError, NotCompletionAppError | from controllers.console.explore.error import NotChatAppError, NotCompletionAppError | ||||
| from controllers.console.explore.wraps import InstalledAppResource | from controllers.console.explore.wraps import InstalledAppResource | ||||
| from controllers.web.error import InvokeRateLimitError as InvokeRateLimitHttpError | |||||
| from core.app.apps.base_app_queue_manager import AppQueueManager | from core.app.apps.base_app_queue_manager import AppQueueManager | ||||
| from core.app.entities.app_invoke_entities import InvokeFrom | from core.app.entities.app_invoke_entities import InvokeFrom | ||||
| from core.errors.error import ( | from core.errors.error import ( | ||||
| from libs.helper import uuid_value | from libs.helper import uuid_value | ||||
| from models.model import AppMode | from models.model import AppMode | ||||
| from services.app_generate_service import AppGenerateService | from services.app_generate_service import AppGenerateService | ||||
| from services.errors.llm import InvokeRateLimitError | |||||
| # define completion api for user | # define completion api for user | ||||
| raise CompletionRequestError(e.description) | raise CompletionRequestError(e.description) | ||||
| except ValueError as e: | except ValueError as e: | ||||
| raise e | raise e | ||||
| except Exception as e: | |||||
| except Exception: | |||||
| logging.exception("internal server error.") | logging.exception("internal server error.") | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| raise ProviderModelCurrentlyNotSupportError() | raise ProviderModelCurrentlyNotSupportError() | ||||
| except InvokeError as e: | except InvokeError as e: | ||||
| raise CompletionRequestError(e.description) | raise CompletionRequestError(e.description) | ||||
| except InvokeRateLimitError as ex: | |||||
| raise InvokeRateLimitHttpError(ex.description) | |||||
| except ValueError as e: | except ValueError as e: | ||||
| raise e | raise e | ||||
| except Exception as e: | |||||
| except Exception: | |||||
| logging.exception("internal server error.") | logging.exception("internal server error.") | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| ) | ) | ||||
| from controllers.console.explore.error import NotWorkflowAppError | from controllers.console.explore.error import NotWorkflowAppError | ||||
| from controllers.console.explore.wraps import InstalledAppResource | from controllers.console.explore.wraps import InstalledAppResource | ||||
| from controllers.web.error import InvokeRateLimitError as InvokeRateLimitHttpError | |||||
| from core.app.apps.base_app_queue_manager import AppQueueManager | from core.app.apps.base_app_queue_manager import AppQueueManager | ||||
| from core.app.entities.app_invoke_entities import InvokeFrom | from core.app.entities.app_invoke_entities import InvokeFrom | ||||
| from core.errors.error import ( | from core.errors.error import ( | ||||
| from libs.login import current_user | from libs.login import current_user | ||||
| from models.model import AppMode, InstalledApp | from models.model import AppMode, InstalledApp | ||||
| from services.app_generate_service import AppGenerateService | from services.app_generate_service import AppGenerateService | ||||
| from services.errors.llm import InvokeRateLimitError | |||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
| raise ProviderModelCurrentlyNotSupportError() | raise ProviderModelCurrentlyNotSupportError() | ||||
| except InvokeError as e: | except InvokeError as e: | ||||
| raise CompletionRequestError(e.description) | raise CompletionRequestError(e.description) | ||||
| except InvokeRateLimitError as ex: | |||||
| raise InvokeRateLimitHttpError(ex.description) | |||||
| except ValueError as e: | except ValueError as e: | ||||
| raise e | raise e | ||||
| except Exception as e: | |||||
| except Exception: | |||||
| logging.exception("internal server error.") | logging.exception("internal server error.") | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| ProviderQuotaExceededError, | ProviderQuotaExceededError, | ||||
| ) | ) | ||||
| from controllers.service_api.wraps import FetchUserArg, WhereisUserArg, validate_app_token | from controllers.service_api.wraps import FetchUserArg, WhereisUserArg, validate_app_token | ||||
| from controllers.web.error import InvokeRateLimitError as InvokeRateLimitHttpError | |||||
| from core.app.apps.base_app_queue_manager import AppQueueManager | from core.app.apps.base_app_queue_manager import AppQueueManager | ||||
| from core.app.entities.app_invoke_entities import InvokeFrom | from core.app.entities.app_invoke_entities import InvokeFrom | ||||
| from core.errors.error import ( | from core.errors.error import ( | ||||
| from libs.helper import uuid_value | from libs.helper import uuid_value | ||||
| from models.model import App, AppMode, EndUser | from models.model import App, AppMode, EndUser | ||||
| from services.app_generate_service import AppGenerateService | from services.app_generate_service import AppGenerateService | ||||
| from services.errors.llm import InvokeRateLimitError | |||||
| class CompletionApi(Resource): | class CompletionApi(Resource): | ||||
| raise CompletionRequestError(e.description) | raise CompletionRequestError(e.description) | ||||
| except ValueError as e: | except ValueError as e: | ||||
| raise e | raise e | ||||
| except Exception as e: | |||||
| except Exception: | |||||
| logging.exception("internal server error.") | logging.exception("internal server error.") | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| raise ProviderQuotaExceededError() | raise ProviderQuotaExceededError() | ||||
| except ModelCurrentlyNotSupportError: | except ModelCurrentlyNotSupportError: | ||||
| raise ProviderModelCurrentlyNotSupportError() | raise ProviderModelCurrentlyNotSupportError() | ||||
| except InvokeRateLimitError as ex: | |||||
| raise InvokeRateLimitHttpError(ex.description) | |||||
| except InvokeError as e: | except InvokeError as e: | ||||
| raise CompletionRequestError(e.description) | raise CompletionRequestError(e.description) | ||||
| except ValueError as e: | except ValueError as e: | ||||
| raise e | raise e | ||||
| except Exception as e: | |||||
| except Exception: | |||||
| logging.exception("internal server error.") | logging.exception("internal server error.") | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| ProviderQuotaExceededError, | ProviderQuotaExceededError, | ||||
| ) | ) | ||||
| from controllers.service_api.wraps import FetchUserArg, WhereisUserArg, validate_app_token | from controllers.service_api.wraps import FetchUserArg, WhereisUserArg, validate_app_token | ||||
| from controllers.web.error import InvokeRateLimitError as InvokeRateLimitHttpError | |||||
| from core.app.apps.base_app_queue_manager import AppQueueManager | from core.app.apps.base_app_queue_manager import AppQueueManager | ||||
| from core.app.entities.app_invoke_entities import InvokeFrom | from core.app.entities.app_invoke_entities import InvokeFrom | ||||
| from core.errors.error import ( | from core.errors.error import ( | ||||
| from models.model import App, AppMode, EndUser | from models.model import App, AppMode, EndUser | ||||
| from models.workflow import WorkflowRun, WorkflowRunStatus | from models.workflow import WorkflowRun, WorkflowRunStatus | ||||
| from services.app_generate_service import AppGenerateService | from services.app_generate_service import AppGenerateService | ||||
| from services.errors.llm import InvokeRateLimitError | |||||
| from services.workflow_app_service import WorkflowAppService | from services.workflow_app_service import WorkflowAppService | ||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
| raise ProviderQuotaExceededError() | raise ProviderQuotaExceededError() | ||||
| except ModelCurrentlyNotSupportError: | except ModelCurrentlyNotSupportError: | ||||
| raise ProviderModelCurrentlyNotSupportError() | raise ProviderModelCurrentlyNotSupportError() | ||||
| except InvokeRateLimitError as ex: | |||||
| raise InvokeRateLimitHttpError(ex.description) | |||||
| except InvokeError as e: | except InvokeError as e: | ||||
| raise CompletionRequestError(e.description) | raise CompletionRequestError(e.description) | ||||
| except ValueError as e: | except ValueError as e: | ||||
| raise e | raise e | ||||
| except Exception as e: | |||||
| except Exception: | |||||
| logging.exception("internal server error.") | logging.exception("internal server error.") | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| ProviderNotInitializeError, | ProviderNotInitializeError, | ||||
| ProviderQuotaExceededError, | ProviderQuotaExceededError, | ||||
| ) | ) | ||||
| from controllers.web.error import InvokeRateLimitError as InvokeRateLimitHttpError | |||||
| from controllers.web.wraps import WebApiResource | from controllers.web.wraps import WebApiResource | ||||
| from core.app.apps.base_app_queue_manager import AppQueueManager | from core.app.apps.base_app_queue_manager import AppQueueManager | ||||
| from core.app.entities.app_invoke_entities import InvokeFrom | from core.app.entities.app_invoke_entities import InvokeFrom | ||||
| from libs import helper | from libs import helper | ||||
| from models.model import App, AppMode, EndUser | from models.model import App, AppMode, EndUser | ||||
| from services.app_generate_service import AppGenerateService | from services.app_generate_service import AppGenerateService | ||||
| from services.errors.llm import InvokeRateLimitError | |||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
| raise ProviderModelCurrentlyNotSupportError() | raise ProviderModelCurrentlyNotSupportError() | ||||
| except InvokeError as e: | except InvokeError as e: | ||||
| raise CompletionRequestError(e.description) | raise CompletionRequestError(e.description) | ||||
| except InvokeRateLimitError as ex: | |||||
| raise InvokeRateLimitHttpError(ex.description) | |||||
| except ValueError as e: | except ValueError as e: | ||||
| raise e | raise e | ||||
| except Exception as e: | |||||
| except Exception: | |||||
| logging.exception("internal server error.") | logging.exception("internal server error.") | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| from core.app.apps.workflow.app_generator import WorkflowAppGenerator | from core.app.apps.workflow.app_generator import WorkflowAppGenerator | ||||
| from core.app.entities.app_invoke_entities import InvokeFrom | from core.app.entities.app_invoke_entities import InvokeFrom | ||||
| from core.app.features.rate_limiting import RateLimit | from core.app.features.rate_limiting import RateLimit | ||||
| from libs.helper import RateLimiter | |||||
| from models.model import Account, App, AppMode, EndUser | from models.model import Account, App, AppMode, EndUser | ||||
| from models.workflow import Workflow | from models.workflow import Workflow | ||||
| from services.billing_service import BillingService | |||||
| from services.errors.llm import InvokeRateLimitError | from services.errors.llm import InvokeRateLimitError | ||||
| from services.workflow_service import WorkflowService | from services.workflow_service import WorkflowService | ||||
| class AppGenerateService: | class AppGenerateService: | ||||
| system_rate_limiter = RateLimiter("app_daily_rate_limiter", dify_config.APP_DAILY_RATE_LIMIT, 86400) | |||||
| @classmethod | @classmethod | ||||
| def generate( | def generate( | ||||
| cls, | cls, | ||||
| :param streaming: streaming | :param streaming: streaming | ||||
| :return: | :return: | ||||
| """ | """ | ||||
| # system level rate limiter | |||||
| if dify_config.BILLING_ENABLED: | |||||
| # check if it's free plan | |||||
| limit_info = BillingService.get_info(app_model.tenant_id) | |||||
| if limit_info["subscription"]["plan"] == "sandbox": | |||||
| if cls.system_rate_limiter.is_rate_limited(app_model.tenant_id): | |||||
| raise InvokeRateLimitError( | |||||
| "Rate limit exceeded, please upgrade your plan " | |||||
| f"or your RPD was {dify_config.APP_DAILY_RATE_LIMIT} requests/day" | |||||
| ) | |||||
| cls.system_rate_limiter.increment_rate_limit(app_model.tenant_id) | |||||
| # app level rate limiter | |||||
| max_active_request = AppGenerateService._get_max_active_requests(app_model) | max_active_request = AppGenerateService._get_max_active_requests(app_model) | ||||
| rate_limit = RateLimit(app_model.id, max_active_request) | rate_limit = RateLimit(app_model.id, max_active_request) | ||||
| request_id = RateLimit.gen_request_key() | request_id = RateLimit.gen_request_key() |