mirror of
https://github.com/langgenius/dify.git
synced 2026-05-04 01:18:05 +08:00
refactor app generate
This commit is contained in:
@ -1,180 +1,71 @@
|
||||
import json
|
||||
from collections.abc import Generator
|
||||
from typing import Any, Union
|
||||
|
||||
from sqlalchemy import and_
|
||||
|
||||
from core.app.app_config.features.file_upload.manager import FileUploadConfigManager
|
||||
from core.app.app_manager import EasyUIBasedAppManager
|
||||
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.entities.app_invoke_entities import InvokeFrom
|
||||
from core.file.message_file_parser import MessageFileParser
|
||||
from extensions.ext_database import db
|
||||
from models.model import Account, App, AppMode, AppModelConfig, Conversation, EndUser, Message
|
||||
from services.app_model_config_service import AppModelConfigService
|
||||
from services.errors.app import MoreLikeThisDisabledError
|
||||
from services.errors.app_model_config import AppModelConfigBrokenError
|
||||
from services.errors.conversation import ConversationCompletedError, ConversationNotExistsError
|
||||
from services.errors.message import MessageNotExistsError
|
||||
from models.model import Account, App, AppMode, EndUser
|
||||
|
||||
|
||||
class CompletionService:
|
||||
|
||||
@classmethod
|
||||
def completion(cls, app_model: App, user: Union[Account, EndUser], args: Any,
|
||||
invoke_from: InvokeFrom, streaming: bool = True,
|
||||
is_model_config_override: bool = False) -> Union[dict, Generator]:
|
||||
# is streaming mode
|
||||
inputs = args['inputs']
|
||||
query = args['query']
|
||||
files = args['files'] if 'files' in args and args['files'] else []
|
||||
auto_generate_name = args['auto_generate_name'] \
|
||||
if 'auto_generate_name' in args else True
|
||||
|
||||
if app_model.mode != AppMode.COMPLETION.value:
|
||||
if not query:
|
||||
raise ValueError('query is required')
|
||||
|
||||
if query:
|
||||
if not isinstance(query, str):
|
||||
raise ValueError('query must be a string')
|
||||
|
||||
query = query.replace('\x00', '')
|
||||
|
||||
conversation_id = args['conversation_id'] if 'conversation_id' in args else None
|
||||
|
||||
conversation = None
|
||||
app_model_config_dict = None
|
||||
if conversation_id:
|
||||
conversation_filter = [
|
||||
Conversation.id == args['conversation_id'],
|
||||
Conversation.app_id == app_model.id,
|
||||
Conversation.status == 'normal'
|
||||
]
|
||||
|
||||
if isinstance(user, Account):
|
||||
conversation_filter.append(Conversation.from_account_id == user.id)
|
||||
else:
|
||||
conversation_filter.append(Conversation.from_end_user_id == user.id if user else None)
|
||||
|
||||
conversation = db.session.query(Conversation).filter(and_(*conversation_filter)).first()
|
||||
|
||||
if not conversation:
|
||||
raise ConversationNotExistsError()
|
||||
|
||||
if conversation.status != 'normal':
|
||||
raise ConversationCompletedError()
|
||||
|
||||
app_model_config = db.session.query(AppModelConfig).filter(
|
||||
AppModelConfig.id == conversation.app_model_config_id,
|
||||
AppModelConfig.app_id == app_model.id
|
||||
).first()
|
||||
|
||||
if not app_model_config:
|
||||
raise AppModelConfigBrokenError()
|
||||
else:
|
||||
if app_model.app_model_config_id is None:
|
||||
raise AppModelConfigBrokenError()
|
||||
|
||||
app_model_config = app_model.app_model_config
|
||||
|
||||
if not app_model_config:
|
||||
raise AppModelConfigBrokenError()
|
||||
|
||||
if is_model_config_override:
|
||||
if not isinstance(user, Account):
|
||||
raise Exception("Only account can override model config")
|
||||
|
||||
# validate config
|
||||
app_model_config_dict = AppModelConfigService.validate_configuration(
|
||||
tenant_id=app_model.tenant_id,
|
||||
config=args['model_config'],
|
||||
app_mode=AppMode.value_of(app_model.mode)
|
||||
)
|
||||
|
||||
# parse files
|
||||
message_file_parser = MessageFileParser(tenant_id=app_model.tenant_id, app_id=app_model.id)
|
||||
file_upload_entity = FileUploadConfigManager.convert(app_model_config_dict or app_model_config.to_dict())
|
||||
if file_upload_entity:
|
||||
file_objs = message_file_parser.validate_and_transform_files_arg(
|
||||
files,
|
||||
file_upload_entity,
|
||||
user
|
||||
invoke_from: InvokeFrom, streaming: bool = True) -> Union[dict, Generator]:
|
||||
"""
|
||||
App Completion
|
||||
:param app_model: app model
|
||||
:param user: user
|
||||
:param args: args
|
||||
:param invoke_from: invoke from
|
||||
:param streaming: streaming
|
||||
:return:
|
||||
"""
|
||||
if app_model.mode == AppMode.COMPLETION.value:
|
||||
return CompletionAppGenerator().generate(
|
||||
app_model=app_model,
|
||||
user=user,
|
||||
args=args,
|
||||
invoke_from=invoke_from,
|
||||
stream=streaming
|
||||
)
|
||||
elif app_model.mode == AppMode.CHAT.value:
|
||||
return ChatAppGenerator().generate(
|
||||
app_model=app_model,
|
||||
user=user,
|
||||
args=args,
|
||||
invoke_from=invoke_from,
|
||||
stream=streaming
|
||||
)
|
||||
elif app_model.mode == AppMode.AGENT_CHAT.value:
|
||||
return AgentChatAppGenerator().generate(
|
||||
app_model=app_model,
|
||||
user=user,
|
||||
args=args,
|
||||
invoke_from=invoke_from,
|
||||
stream=streaming
|
||||
)
|
||||
else:
|
||||
file_objs = []
|
||||
|
||||
application_manager = EasyUIBasedAppManager()
|
||||
return application_manager.generate(
|
||||
app_model=app_model,
|
||||
app_model_config=app_model_config,
|
||||
app_model_config_dict=app_model_config_dict,
|
||||
user=user,
|
||||
invoke_from=invoke_from,
|
||||
inputs=inputs,
|
||||
query=query,
|
||||
files=file_objs,
|
||||
conversation=conversation,
|
||||
stream=streaming,
|
||||
extras={
|
||||
"auto_generate_conversation_name": auto_generate_name
|
||||
}
|
||||
)
|
||||
raise ValueError('Invalid app mode')
|
||||
|
||||
@classmethod
|
||||
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]:
|
||||
if not user:
|
||||
raise ValueError('user cannot be None')
|
||||
|
||||
message = db.session.query(Message).filter(
|
||||
Message.id == message_id,
|
||||
Message.app_id == app_model.id,
|
||||
Message.from_source == ('api' if isinstance(user, EndUser) else 'console'),
|
||||
Message.from_end_user_id == (user.id if isinstance(user, EndUser) else None),
|
||||
Message.from_account_id == (user.id if isinstance(user, Account) else None),
|
||||
).first()
|
||||
|
||||
if not message:
|
||||
raise MessageNotExistsError()
|
||||
|
||||
current_app_model_config = app_model.app_model_config
|
||||
more_like_this = current_app_model_config.more_like_this_dict
|
||||
|
||||
if not current_app_model_config.more_like_this or more_like_this.get("enabled", False) is False:
|
||||
raise MoreLikeThisDisabledError()
|
||||
|
||||
app_model_config = message.app_model_config
|
||||
model_dict = app_model_config.model_dict
|
||||
completion_params = model_dict.get('completion_params')
|
||||
completion_params['temperature'] = 0.9
|
||||
model_dict['completion_params'] = completion_params
|
||||
app_model_config.model = json.dumps(model_dict)
|
||||
|
||||
# parse files
|
||||
message_file_parser = MessageFileParser(tenant_id=app_model.tenant_id, app_id=app_model.id)
|
||||
file_upload_entity = FileUploadConfigManager.convert(current_app_model_config.to_dict())
|
||||
if file_upload_entity:
|
||||
file_objs = message_file_parser.transform_message_files(
|
||||
message.files, file_upload_entity
|
||||
)
|
||||
else:
|
||||
file_objs = []
|
||||
|
||||
application_manager = EasyUIBasedAppManager()
|
||||
return application_manager.generate(
|
||||
"""
|
||||
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(
|
||||
app_model=app_model,
|
||||
app_model_config=current_app_model_config,
|
||||
app_model_config_dict=app_model_config.to_dict(),
|
||||
message_id=message_id,
|
||||
user=user,
|
||||
invoke_from=invoke_from,
|
||||
inputs=message.inputs,
|
||||
query=message.query,
|
||||
files=file_objs,
|
||||
conversation=None,
|
||||
stream=streaming,
|
||||
extras={
|
||||
"auto_generate_conversation_name": False
|
||||
}
|
||||
stream=streaming
|
||||
)
|
||||
|
||||
|
||||
@ -8,9 +8,11 @@ from core.app.app_config.entities import (
|
||||
FileUploadEntity,
|
||||
ModelConfigEntity,
|
||||
PromptTemplateEntity,
|
||||
VariableEntity,
|
||||
VariableEntity, EasyUIBasedAppConfig,
|
||||
)
|
||||
from core.app.app_manager import EasyUIBasedAppManager
|
||||
from core.app.apps.agent_chat.app_config_manager import AgentChatAppConfigManager
|
||||
from core.app.apps.chat.app_config_manager import ChatAppConfigManager
|
||||
from core.app.apps.completion.app_config_manager import CompletionAppConfigManager
|
||||
from core.helper import encrypter
|
||||
from core.model_runtime.entities.llm_entities import LLMMode
|
||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||
@ -87,8 +89,7 @@ class WorkflowConverter:
|
||||
new_app_mode = self._get_new_app_mode(app_model)
|
||||
|
||||
# convert app model config
|
||||
application_manager = EasyUIBasedAppManager()
|
||||
app_config = application_manager.convert_to_app_config(
|
||||
app_config = self._convert_to_app_config(
|
||||
app_model=app_model,
|
||||
app_model_config=app_model_config
|
||||
)
|
||||
@ -190,6 +191,30 @@ class WorkflowConverter:
|
||||
|
||||
return workflow
|
||||
|
||||
def _convert_to_app_config(self, app_model: App,
|
||||
app_model_config: AppModelConfig) -> EasyUIBasedAppConfig:
|
||||
app_mode = AppMode.value_of(app_model.mode)
|
||||
if app_mode == AppMode.AGENT_CHAT or app_model.is_agent:
|
||||
app_model.mode = AppMode.AGENT_CHAT.value
|
||||
app_config = AgentChatAppConfigManager.get_app_config(
|
||||
app_model=app_model,
|
||||
app_model_config=app_model_config
|
||||
)
|
||||
elif app_mode == AppMode.CHAT:
|
||||
app_config = ChatAppConfigManager.get_app_config(
|
||||
app_model=app_model,
|
||||
app_model_config=app_model_config
|
||||
)
|
||||
elif app_mode == AppMode.COMPLETION:
|
||||
app_config = CompletionAppConfigManager.get_app_config(
|
||||
app_model=app_model,
|
||||
app_model_config=app_model_config
|
||||
)
|
||||
else:
|
||||
raise ValueError("Invalid app mode")
|
||||
|
||||
return app_config
|
||||
|
||||
def _convert_to_start_node(self, variables: list[VariableEntity]) -> dict:
|
||||
"""
|
||||
Convert to Start Node
|
||||
@ -566,6 +591,6 @@ class WorkflowConverter:
|
||||
:return:
|
||||
"""
|
||||
return db.session.query(APIBasedExtension).filter(
|
||||
APIBasedExtension.tenant_id == tenant_id,
|
||||
APIBasedExtension.id == api_based_extension_id
|
||||
).first()
|
||||
APIBasedExtension.tenant_id == tenant_id,
|
||||
APIBasedExtension.id == api_based_extension_id
|
||||
).first()
|
||||
|
||||
Reference in New Issue
Block a user