2024-04-08 18:51:46 +08:00
|
|
|
from collections.abc import Generator
|
|
|
|
from typing import Any, Union
|
|
|
|
|
2024-08-26 19:36:44 +08:00
|
|
|
from openai._exceptions import RateLimitError
|
|
|
|
|
2024-07-12 12:25:38 +08:00
|
|
|
from configs import dify_config
|
2024-04-08 18:51:46 +08:00
|
|
|
from core.app.apps.advanced_chat.app_generator import AdvancedChatAppGenerator
|
|
|
|
from core.app.apps.agent_chat.app_generator import AgentChatAppGenerator
|
|
|
|
from core.app.apps.chat.app_generator import ChatAppGenerator
|
|
|
|
from core.app.apps.completion.app_generator import CompletionAppGenerator
|
|
|
|
from core.app.apps.workflow.app_generator import WorkflowAppGenerator
|
|
|
|
from core.app.entities.app_invoke_entities import InvokeFrom
|
2024-07-10 21:31:35 +08:00
|
|
|
from core.app.features.rate_limiting import RateLimit
|
2024-04-08 18:51:46 +08:00
|
|
|
from models.model import Account, App, AppMode, EndUser
|
2024-08-26 19:36:44 +08:00
|
|
|
from services.errors.llm import InvokeRateLimitError
|
2024-04-08 18:51:46 +08:00
|
|
|
from services.workflow_service import WorkflowService
|
|
|
|
|
|
|
|
|
|
|
|
class AppGenerateService:
|
|
|
|
@classmethod
|
2024-08-26 13:43:57 +08:00
|
|
|
def generate(
|
|
|
|
cls,
|
|
|
|
app_model: App,
|
|
|
|
user: Union[Account, EndUser],
|
|
|
|
args: Any,
|
|
|
|
invoke_from: InvokeFrom,
|
|
|
|
streaming: bool = True,
|
|
|
|
):
|
2024-04-08 18:51:46 +08:00
|
|
|
"""
|
|
|
|
App Content Generate
|
|
|
|
:param app_model: app model
|
|
|
|
:param user: user
|
|
|
|
:param args: args
|
|
|
|
:param invoke_from: invoke from
|
|
|
|
:param streaming: streaming
|
|
|
|
:return:
|
|
|
|
"""
|
2024-07-10 21:31:35 +08:00
|
|
|
max_active_request = AppGenerateService._get_max_active_requests(app_model)
|
|
|
|
rate_limit = RateLimit(app_model.id, max_active_request)
|
|
|
|
request_id = RateLimit.gen_request_key()
|
|
|
|
try:
|
|
|
|
request_id = rate_limit.enter(request_id)
|
|
|
|
if app_model.mode == AppMode.COMPLETION.value:
|
2024-08-26 13:43:57 +08:00
|
|
|
return rate_limit.generate(
|
|
|
|
CompletionAppGenerator().generate(
|
|
|
|
app_model=app_model, user=user, args=args, invoke_from=invoke_from, stream=streaming
|
|
|
|
),
|
|
|
|
request_id,
|
|
|
|
)
|
2024-07-10 21:31:35 +08:00
|
|
|
elif app_model.mode == AppMode.AGENT_CHAT.value or app_model.is_agent:
|
2024-08-26 13:43:57 +08:00
|
|
|
return rate_limit.generate(
|
|
|
|
AgentChatAppGenerator().generate(
|
|
|
|
app_model=app_model, user=user, args=args, invoke_from=invoke_from, stream=streaming
|
|
|
|
),
|
|
|
|
request_id,
|
|
|
|
)
|
2024-07-10 21:31:35 +08:00
|
|
|
elif app_model.mode == AppMode.CHAT.value:
|
2024-08-26 13:43:57 +08:00
|
|
|
return rate_limit.generate(
|
|
|
|
ChatAppGenerator().generate(
|
|
|
|
app_model=app_model, user=user, args=args, invoke_from=invoke_from, stream=streaming
|
|
|
|
),
|
|
|
|
request_id,
|
|
|
|
)
|
2024-07-10 21:31:35 +08:00
|
|
|
elif app_model.mode == AppMode.ADVANCED_CHAT.value:
|
|
|
|
workflow = cls._get_workflow(app_model, invoke_from)
|
2024-08-26 13:43:57 +08:00
|
|
|
return rate_limit.generate(
|
|
|
|
AdvancedChatAppGenerator().generate(
|
|
|
|
app_model=app_model,
|
|
|
|
workflow=workflow,
|
|
|
|
user=user,
|
|
|
|
args=args,
|
|
|
|
invoke_from=invoke_from,
|
|
|
|
stream=streaming,
|
|
|
|
),
|
|
|
|
request_id,
|
|
|
|
)
|
2024-07-10 21:31:35 +08:00
|
|
|
elif app_model.mode == AppMode.WORKFLOW.value:
|
|
|
|
workflow = cls._get_workflow(app_model, invoke_from)
|
2024-08-26 13:43:57 +08:00
|
|
|
return rate_limit.generate(
|
|
|
|
WorkflowAppGenerator().generate(
|
|
|
|
app_model=app_model,
|
|
|
|
workflow=workflow,
|
|
|
|
user=user,
|
|
|
|
args=args,
|
|
|
|
invoke_from=invoke_from,
|
|
|
|
stream=streaming,
|
|
|
|
),
|
|
|
|
request_id,
|
|
|
|
)
|
2024-07-10 21:31:35 +08:00
|
|
|
else:
|
2024-08-26 13:43:57 +08:00
|
|
|
raise ValueError(f"Invalid app mode {app_model.mode}")
|
2024-08-26 19:36:44 +08:00
|
|
|
except RateLimitError as e:
|
|
|
|
raise InvokeRateLimitError(str(e))
|
2024-07-10 21:31:35 +08:00
|
|
|
finally:
|
|
|
|
if not streaming:
|
|
|
|
rate_limit.exit(request_id)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def _get_max_active_requests(app_model: App) -> int:
|
|
|
|
max_active_requests = app_model.max_active_requests
|
|
|
|
if app_model.max_active_requests is None:
|
2024-07-12 12:25:38 +08:00
|
|
|
max_active_requests = int(dify_config.APP_MAX_ACTIVE_REQUESTS)
|
2024-07-10 21:31:35 +08:00
|
|
|
return max_active_requests
|
2024-04-08 18:51:46 +08:00
|
|
|
|
2024-05-27 22:01:11 +08:00
|
|
|
@classmethod
|
2024-08-26 13:43:57 +08:00
|
|
|
def generate_single_iteration(
|
|
|
|
cls, app_model: App, user: Union[Account, EndUser], node_id: str, args: Any, streaming: bool = True
|
|
|
|
):
|
2024-05-27 22:01:11 +08:00
|
|
|
if app_model.mode == AppMode.ADVANCED_CHAT.value:
|
|
|
|
workflow = cls._get_workflow(app_model, InvokeFrom.DEBUGGER)
|
|
|
|
return AdvancedChatAppGenerator().single_iteration_generate(
|
2024-08-26 13:43:57 +08:00
|
|
|
app_model=app_model, workflow=workflow, node_id=node_id, user=user, args=args, stream=streaming
|
2024-05-27 22:01:11 +08:00
|
|
|
)
|
|
|
|
elif app_model.mode == AppMode.WORKFLOW.value:
|
|
|
|
workflow = cls._get_workflow(app_model, InvokeFrom.DEBUGGER)
|
|
|
|
return WorkflowAppGenerator().single_iteration_generate(
|
2024-08-26 13:43:57 +08:00
|
|
|
app_model=app_model, workflow=workflow, node_id=node_id, user=user, args=args, stream=streaming
|
2024-05-27 22:01:11 +08:00
|
|
|
)
|
|
|
|
else:
|
2024-08-26 13:43:57 +08:00
|
|
|
raise ValueError(f"Invalid app mode {app_model.mode}")
|
2024-05-27 22:01:11 +08:00
|
|
|
|
2024-04-08 18:51:46 +08:00
|
|
|
@classmethod
|
2024-08-26 13:43:57 +08:00
|
|
|
def generate_more_like_this(
|
|
|
|
cls,
|
|
|
|
app_model: App,
|
|
|
|
user: Union[Account, EndUser],
|
|
|
|
message_id: str,
|
|
|
|
invoke_from: InvokeFrom,
|
|
|
|
streaming: bool = True,
|
|
|
|
) -> Union[dict, Generator]:
|
2024-04-08 18:51:46 +08:00
|
|
|
"""
|
|
|
|
Generate more like this
|
|
|
|
:param app_model: app model
|
|
|
|
:param user: user
|
|
|
|
:param message_id: message id
|
|
|
|
:param invoke_from: invoke from
|
|
|
|
:param streaming: streaming
|
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
return CompletionAppGenerator().generate_more_like_this(
|
2024-08-26 13:43:57 +08:00
|
|
|
app_model=app_model, message_id=message_id, user=user, invoke_from=invoke_from, stream=streaming
|
2024-04-08 18:51:46 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def _get_workflow(cls, app_model: App, invoke_from: InvokeFrom) -> Any:
|
|
|
|
"""
|
|
|
|
Get workflow
|
|
|
|
:param app_model: app model
|
|
|
|
:param invoke_from: invoke from
|
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
workflow_service = WorkflowService()
|
|
|
|
if invoke_from == InvokeFrom.DEBUGGER:
|
|
|
|
# fetch draft workflow by app_model
|
|
|
|
workflow = workflow_service.get_draft_workflow(app_model=app_model)
|
|
|
|
|
|
|
|
if not workflow:
|
2024-08-26 13:43:57 +08:00
|
|
|
raise ValueError("Workflow not initialized")
|
2024-04-08 18:51:46 +08:00
|
|
|
else:
|
|
|
|
# fetch published workflow by app_model
|
|
|
|
workflow = workflow_service.get_published_workflow(app_model=app_model)
|
|
|
|
|
|
|
|
if not workflow:
|
2024-08-26 13:43:57 +08:00
|
|
|
raise ValueError("Workflow not published")
|
2024-04-08 18:51:46 +08:00
|
|
|
|
|
|
|
return workflow
|