You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. import json
  2. from datetime import datetime
  3. from typing import Any, cast
  4. import sqlalchemy as sa
  5. from deprecated import deprecated
  6. from sqlalchemy import ForeignKey, func
  7. from sqlalchemy.orm import Mapped, mapped_column
  8. from core.tools.entities.common_entities import I18nObject
  9. from core.tools.entities.tool_bundle import ApiToolBundle
  10. from core.tools.entities.tool_entities import ApiProviderSchemaType, WorkflowToolParameterConfiguration
  11. from models.base import Base
  12. from .engine import db
  13. from .model import Account, App, Tenant
  14. from .types import StringUUID
  15. class BuiltinToolProvider(Base):
  16. """
  17. This table stores the tool provider information for built-in tools for each tenant.
  18. """
  19. __tablename__ = "tool_builtin_providers"
  20. __table_args__ = (
  21. db.PrimaryKeyConstraint("id", name="tool_builtin_provider_pkey"),
  22. # one tenant can only have one tool provider with the same name
  23. db.UniqueConstraint("tenant_id", "provider", name="unique_builtin_tool_provider"),
  24. )
  25. # id of the tool provider
  26. id: Mapped[str] = mapped_column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  27. # id of the tenant
  28. tenant_id: Mapped[str] = mapped_column(StringUUID, nullable=True)
  29. # who created this tool provider
  30. user_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
  31. # name of the tool provider
  32. provider: Mapped[str] = mapped_column(db.String(256), nullable=False)
  33. # credential of the tool provider
  34. encrypted_credentials: Mapped[str] = mapped_column(db.Text, nullable=True)
  35. created_at: Mapped[datetime] = mapped_column(
  36. db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)")
  37. )
  38. updated_at: Mapped[datetime] = mapped_column(
  39. db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)")
  40. )
  41. @property
  42. def credentials(self) -> dict:
  43. return cast(dict, json.loads(self.encrypted_credentials))
  44. class ApiToolProvider(Base):
  45. """
  46. The table stores the api providers.
  47. """
  48. __tablename__ = "tool_api_providers"
  49. __table_args__ = (
  50. db.PrimaryKeyConstraint("id", name="tool_api_provider_pkey"),
  51. db.UniqueConstraint("name", "tenant_id", name="unique_api_tool_provider"),
  52. )
  53. id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  54. # name of the api provider
  55. name = db.Column(db.String(255), nullable=False)
  56. # icon
  57. icon = db.Column(db.String(255), nullable=False)
  58. # original schema
  59. schema = db.Column(db.Text, nullable=False)
  60. schema_type_str: Mapped[str] = db.Column(db.String(40), nullable=False)
  61. # who created this tool
  62. user_id = db.Column(StringUUID, nullable=False)
  63. # tenant id
  64. tenant_id = db.Column(StringUUID, nullable=False)
  65. # description of the provider
  66. description = db.Column(db.Text, nullable=False)
  67. # json format tools
  68. tools_str = db.Column(db.Text, nullable=False)
  69. # json format credentials
  70. credentials_str = db.Column(db.Text, nullable=False)
  71. # privacy policy
  72. privacy_policy = db.Column(db.String(255), nullable=True)
  73. # custom_disclaimer
  74. custom_disclaimer: Mapped[str] = mapped_column(sa.TEXT, default="")
  75. created_at: Mapped[datetime] = mapped_column(db.DateTime, nullable=False, server_default=func.current_timestamp())
  76. updated_at: Mapped[datetime] = mapped_column(db.DateTime, nullable=False, server_default=func.current_timestamp())
  77. @property
  78. def schema_type(self) -> ApiProviderSchemaType:
  79. return ApiProviderSchemaType.value_of(self.schema_type_str)
  80. @property
  81. def tools(self) -> list[ApiToolBundle]:
  82. return [ApiToolBundle(**tool) for tool in json.loads(self.tools_str)]
  83. @property
  84. def credentials(self) -> dict:
  85. return dict(json.loads(self.credentials_str))
  86. @property
  87. def user(self) -> Account | None:
  88. if not self.user_id:
  89. return None
  90. return db.session.query(Account).filter(Account.id == self.user_id).first()
  91. @property
  92. def tenant(self) -> Tenant | None:
  93. return db.session.query(Tenant).filter(Tenant.id == self.tenant_id).first()
  94. class ToolLabelBinding(Base):
  95. """
  96. The table stores the labels for tools.
  97. """
  98. __tablename__ = "tool_label_bindings"
  99. __table_args__ = (
  100. db.PrimaryKeyConstraint("id", name="tool_label_bind_pkey"),
  101. db.UniqueConstraint("tool_id", "label_name", name="unique_tool_label_bind"),
  102. )
  103. id: Mapped[str] = mapped_column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  104. # tool id
  105. tool_id: Mapped[str] = mapped_column(db.String(64), nullable=False)
  106. # tool type
  107. tool_type: Mapped[str] = mapped_column(db.String(40), nullable=False)
  108. # label name
  109. label_name: Mapped[str] = mapped_column(db.String(40), nullable=False)
  110. class WorkflowToolProvider(Base):
  111. """
  112. The table stores the workflow providers.
  113. """
  114. __tablename__ = "tool_workflow_providers"
  115. __table_args__ = (
  116. db.PrimaryKeyConstraint("id", name="tool_workflow_provider_pkey"),
  117. db.UniqueConstraint("name", "tenant_id", name="unique_workflow_tool_provider"),
  118. db.UniqueConstraint("tenant_id", "app_id", name="unique_workflow_tool_provider_app_id"),
  119. )
  120. id: Mapped[str] = mapped_column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  121. # name of the workflow provider
  122. name: Mapped[str] = mapped_column(db.String(255), nullable=False)
  123. # label of the workflow provider
  124. label: Mapped[str] = mapped_column(db.String(255), nullable=False, server_default="")
  125. # icon
  126. icon: Mapped[str] = mapped_column(db.String(255), nullable=False)
  127. # app id of the workflow provider
  128. app_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
  129. # version of the workflow provider
  130. version: Mapped[str] = mapped_column(db.String(255), nullable=False, server_default="")
  131. # who created this tool
  132. user_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
  133. # tenant id
  134. tenant_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
  135. # description of the provider
  136. description: Mapped[str] = mapped_column(db.Text, nullable=False)
  137. # parameter configuration
  138. parameter_configuration: Mapped[str] = mapped_column(db.Text, nullable=False, server_default="[]")
  139. # privacy policy
  140. privacy_policy: Mapped[str] = mapped_column(db.String(255), nullable=True, server_default="")
  141. created_at: Mapped[datetime] = mapped_column(
  142. db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)")
  143. )
  144. updated_at: Mapped[datetime] = mapped_column(
  145. db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)")
  146. )
  147. @property
  148. def user(self) -> Account | None:
  149. return db.session.query(Account).filter(Account.id == self.user_id).first()
  150. @property
  151. def tenant(self) -> Tenant | None:
  152. return db.session.query(Tenant).filter(Tenant.id == self.tenant_id).first()
  153. @property
  154. def parameter_configurations(self) -> list[WorkflowToolParameterConfiguration]:
  155. return [WorkflowToolParameterConfiguration(**config) for config in json.loads(self.parameter_configuration)]
  156. @property
  157. def app(self) -> App | None:
  158. return db.session.query(App).filter(App.id == self.app_id).first()
  159. class ToolModelInvoke(Base):
  160. """
  161. store the invoke logs from tool invoke
  162. """
  163. __tablename__ = "tool_model_invokes"
  164. __table_args__ = (db.PrimaryKeyConstraint("id", name="tool_model_invoke_pkey"),)
  165. id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  166. # who invoke this tool
  167. user_id = db.Column(StringUUID, nullable=False)
  168. # tenant id
  169. tenant_id = db.Column(StringUUID, nullable=False)
  170. # provider
  171. provider = db.Column(db.String(255), nullable=False)
  172. # type
  173. tool_type = db.Column(db.String(40), nullable=False)
  174. # tool name
  175. tool_name = db.Column(db.String(40), nullable=False)
  176. # invoke parameters
  177. model_parameters = db.Column(db.Text, nullable=False)
  178. # prompt messages
  179. prompt_messages = db.Column(db.Text, nullable=False)
  180. # invoke response
  181. model_response = db.Column(db.Text, nullable=False)
  182. prompt_tokens = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
  183. answer_tokens = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
  184. answer_unit_price = db.Column(db.Numeric(10, 4), nullable=False)
  185. answer_price_unit = db.Column(db.Numeric(10, 7), nullable=False, server_default=db.text("0.001"))
  186. provider_response_latency = db.Column(db.Float, nullable=False, server_default=db.text("0"))
  187. total_price = db.Column(db.Numeric(10, 7))
  188. currency = db.Column(db.String(255), nullable=False)
  189. created_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
  190. updated_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
  191. @deprecated
  192. class ToolConversationVariables(Base):
  193. """
  194. store the conversation variables from tool invoke
  195. """
  196. __tablename__ = "tool_conversation_variables"
  197. __table_args__ = (
  198. db.PrimaryKeyConstraint("id", name="tool_conversation_variables_pkey"),
  199. # add index for user_id and conversation_id
  200. db.Index("user_id_idx", "user_id"),
  201. db.Index("conversation_id_idx", "conversation_id"),
  202. )
  203. id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  204. # conversation user id
  205. user_id = db.Column(StringUUID, nullable=False)
  206. # tenant id
  207. tenant_id = db.Column(StringUUID, nullable=False)
  208. # conversation id
  209. conversation_id = db.Column(StringUUID, nullable=False)
  210. # variables pool
  211. variables_str = db.Column(db.Text, nullable=False)
  212. created_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
  213. updated_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
  214. @property
  215. def variables(self) -> Any:
  216. return json.loads(self.variables_str)
  217. class ToolFile(Base):
  218. """This table stores file metadata generated in workflows,
  219. not only files created by agent.
  220. """
  221. __tablename__ = "tool_files"
  222. __table_args__ = (
  223. db.PrimaryKeyConstraint("id", name="tool_file_pkey"),
  224. db.Index("tool_file_conversation_id_idx", "conversation_id"),
  225. )
  226. id: Mapped[str] = mapped_column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  227. # conversation user id
  228. user_id: Mapped[str] = mapped_column(StringUUID)
  229. # tenant id
  230. tenant_id: Mapped[str] = mapped_column(StringUUID)
  231. # conversation id
  232. conversation_id: Mapped[str] = mapped_column(StringUUID, nullable=True)
  233. # file key
  234. file_key: Mapped[str] = mapped_column(db.String(255), nullable=False)
  235. # mime type
  236. mimetype: Mapped[str] = mapped_column(db.String(255), nullable=False)
  237. # original url
  238. original_url: Mapped[str] = mapped_column(db.String(2048), nullable=True)
  239. # name
  240. name: Mapped[str] = mapped_column(default="")
  241. # size
  242. size: Mapped[int] = mapped_column(default=-1)
  243. @deprecated
  244. class DeprecatedPublishedAppTool(Base):
  245. """
  246. The table stores the apps published as a tool for each person.
  247. """
  248. __tablename__ = "tool_published_apps"
  249. __table_args__ = (
  250. db.PrimaryKeyConstraint("id", name="published_app_tool_pkey"),
  251. db.UniqueConstraint("app_id", "user_id", name="unique_published_app_tool"),
  252. )
  253. id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  254. # id of the app
  255. app_id = db.Column(StringUUID, ForeignKey("apps.id"), nullable=False)
  256. user_id: Mapped[str] = db.Column(StringUUID, nullable=False)
  257. # who published this tool
  258. description = db.Column(db.Text, nullable=False)
  259. # llm_description of the tool, for LLM
  260. llm_description = db.Column(db.Text, nullable=False)
  261. # query description, query will be seem as a parameter of the tool,
  262. # to describe this parameter to llm, we need this field
  263. query_description = db.Column(db.Text, nullable=False)
  264. # query name, the name of the query parameter
  265. query_name = db.Column(db.String(40), nullable=False)
  266. # name of the tool provider
  267. tool_name = db.Column(db.String(40), nullable=False)
  268. # author
  269. author = db.Column(db.String(40), nullable=False)
  270. created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
  271. updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
  272. @property
  273. def description_i18n(self) -> I18nObject:
  274. return I18nObject(**json.loads(self.description))