app.py 5.9 KB

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