您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. from collections.abc import Generator, Mapping
  2. from typing import Optional, Union
  3. from sqlalchemy import select
  4. from controllers.service_api.wraps import create_or_update_end_user_for_user_id
  5. from core.app.app_config.common.parameters_mapping import get_parameters_from_feature_dict
  6. from core.app.apps.advanced_chat.app_generator import AdvancedChatAppGenerator
  7. from core.app.apps.agent_chat.app_generator import AgentChatAppGenerator
  8. from core.app.apps.chat.app_generator import ChatAppGenerator
  9. from core.app.apps.completion.app_generator import CompletionAppGenerator
  10. from core.app.apps.workflow.app_generator import WorkflowAppGenerator
  11. from core.app.entities.app_invoke_entities import InvokeFrom
  12. from core.plugin.backwards_invocation.base import BaseBackwardsInvocation
  13. from extensions.ext_database import db
  14. from models.account import Account
  15. from models.model import App, AppMode, EndUser
  16. class PluginAppBackwardsInvocation(BaseBackwardsInvocation):
  17. @classmethod
  18. def fetch_app_info(cls, app_id: str, tenant_id: str) -> Mapping:
  19. """
  20. Fetch app info
  21. """
  22. app = cls._get_app(app_id, tenant_id)
  23. """Retrieve app parameters."""
  24. if app.mode in {AppMode.ADVANCED_CHAT.value, AppMode.WORKFLOW.value}:
  25. workflow = app.workflow
  26. if workflow is None:
  27. raise ValueError("unexpected app type")
  28. features_dict = workflow.features_dict
  29. user_input_form = workflow.user_input_form(to_old_structure=True)
  30. else:
  31. app_model_config = app.app_model_config
  32. if app_model_config is None:
  33. raise ValueError("unexpected app type")
  34. features_dict = app_model_config.to_dict()
  35. user_input_form = features_dict.get("user_input_form", [])
  36. return {
  37. "data": get_parameters_from_feature_dict(features_dict=features_dict, user_input_form=user_input_form),
  38. }
  39. @classmethod
  40. def invoke_app(
  41. cls,
  42. app_id: str,
  43. user_id: str,
  44. tenant_id: str,
  45. conversation_id: Optional[str],
  46. query: Optional[str],
  47. stream: bool,
  48. inputs: Mapping,
  49. files: list[dict],
  50. ) -> Generator[Mapping | str, None, None] | Mapping:
  51. """
  52. invoke app
  53. """
  54. app = cls._get_app(app_id, tenant_id)
  55. if not user_id:
  56. user = create_or_update_end_user_for_user_id(app)
  57. else:
  58. user = cls._get_user(user_id)
  59. conversation_id = conversation_id or ""
  60. if app.mode in {AppMode.ADVANCED_CHAT.value, AppMode.AGENT_CHAT.value, AppMode.CHAT.value}:
  61. if not query:
  62. raise ValueError("missing query")
  63. return cls.invoke_chat_app(app, user, conversation_id, query, stream, inputs, files)
  64. elif app.mode == AppMode.WORKFLOW:
  65. return cls.invoke_workflow_app(app, user, stream, inputs, files)
  66. elif app.mode == AppMode.COMPLETION:
  67. return cls.invoke_completion_app(app, user, stream, inputs, files)
  68. raise ValueError("unexpected app type")
  69. @classmethod
  70. def invoke_chat_app(
  71. cls,
  72. app: App,
  73. user: Account | EndUser,
  74. conversation_id: str,
  75. query: str,
  76. stream: bool,
  77. inputs: Mapping,
  78. files: list[dict],
  79. ) -> Generator[Mapping | str, None, None] | Mapping:
  80. """
  81. invoke chat app
  82. """
  83. if app.mode == AppMode.ADVANCED_CHAT.value:
  84. workflow = app.workflow
  85. if not workflow:
  86. raise ValueError("unexpected app type")
  87. return AdvancedChatAppGenerator().generate(
  88. app_model=app,
  89. workflow=workflow,
  90. user=user,
  91. args={
  92. "inputs": inputs,
  93. "query": query,
  94. "files": files,
  95. "conversation_id": conversation_id,
  96. },
  97. invoke_from=InvokeFrom.SERVICE_API,
  98. streaming=stream,
  99. )
  100. elif app.mode == AppMode.AGENT_CHAT.value:
  101. return AgentChatAppGenerator().generate(
  102. app_model=app,
  103. user=user,
  104. args={
  105. "inputs": inputs,
  106. "query": query,
  107. "files": files,
  108. "conversation_id": conversation_id,
  109. },
  110. invoke_from=InvokeFrom.SERVICE_API,
  111. streaming=stream,
  112. )
  113. elif app.mode == AppMode.CHAT.value:
  114. return ChatAppGenerator().generate(
  115. app_model=app,
  116. user=user,
  117. args={
  118. "inputs": inputs,
  119. "query": query,
  120. "files": files,
  121. "conversation_id": conversation_id,
  122. },
  123. invoke_from=InvokeFrom.SERVICE_API,
  124. streaming=stream,
  125. )
  126. else:
  127. raise ValueError("unexpected app type")
  128. @classmethod
  129. def invoke_workflow_app(
  130. cls,
  131. app: App,
  132. user: EndUser | Account,
  133. stream: bool,
  134. inputs: Mapping,
  135. files: list[dict],
  136. ) -> Generator[Mapping | str, None, None] | Mapping:
  137. """
  138. invoke workflow app
  139. """
  140. workflow = app.workflow
  141. if not workflow:
  142. raise ValueError("unexpected app type")
  143. return WorkflowAppGenerator().generate(
  144. app_model=app,
  145. workflow=workflow,
  146. user=user,
  147. args={"inputs": inputs, "files": files},
  148. invoke_from=InvokeFrom.SERVICE_API,
  149. streaming=stream,
  150. call_depth=1,
  151. workflow_thread_pool_id=None,
  152. )
  153. @classmethod
  154. def invoke_completion_app(
  155. cls,
  156. app: App,
  157. user: EndUser | Account,
  158. stream: bool,
  159. inputs: Mapping,
  160. files: list[dict],
  161. ) -> Generator[Mapping | str, None, None] | Mapping:
  162. """
  163. invoke completion app
  164. """
  165. return CompletionAppGenerator().generate(
  166. app_model=app,
  167. user=user,
  168. args={"inputs": inputs, "files": files},
  169. invoke_from=InvokeFrom.SERVICE_API,
  170. streaming=stream,
  171. )
  172. @classmethod
  173. def _get_user(cls, user_id: str) -> Union[EndUser, Account]:
  174. """
  175. get the user by user id
  176. """
  177. stmt = select(EndUser).where(EndUser.id == user_id)
  178. user = db.session.scalar(stmt)
  179. if not user:
  180. stmt = select(Account).where(Account.id == user_id)
  181. user = db.session.scalar(stmt)
  182. if not user:
  183. raise ValueError("user not found")
  184. return user
  185. @classmethod
  186. def _get_app(cls, app_id: str, tenant_id: str) -> App:
  187. """
  188. get app
  189. """
  190. try:
  191. app = db.session.query(App).where(App.id == app_id).where(App.tenant_id == tenant_id).first()
  192. except Exception:
  193. raise ValueError("app not found")
  194. if not app:
  195. raise ValueError("app not found")
  196. return app