tools.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. import json
  2. from datetime import datetime
  3. from typing import Any, Optional, 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 schema_type(self) -> ApiProviderSchemaType:
  149. return ApiProviderSchemaType.value_of(self.schema_type_str)
  150. @property
  151. def user(self) -> Account | None:
  152. return db.session.query(Account).filter(Account.id == self.user_id).first()
  153. @property
  154. def tenant(self) -> Tenant | None:
  155. return db.session.query(Tenant).filter(Tenant.id == self.tenant_id).first()
  156. @property
  157. def parameter_configurations(self) -> list[WorkflowToolParameterConfiguration]:
  158. return [WorkflowToolParameterConfiguration(**config) for config in json.loads(self.parameter_configuration)]
  159. @property
  160. def app(self) -> App | None:
  161. return db.session.query(App).filter(App.id == self.app_id).first()
  162. class ToolModelInvoke(Base):
  163. """
  164. store the invoke logs from tool invoke
  165. """
  166. __tablename__ = "tool_model_invokes"
  167. __table_args__ = (db.PrimaryKeyConstraint("id", name="tool_model_invoke_pkey"),)
  168. id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  169. # who invoke this tool
  170. user_id = db.Column(StringUUID, nullable=False)
  171. # tenant id
  172. tenant_id = db.Column(StringUUID, nullable=False)
  173. # provider
  174. provider = db.Column(db.String(255), nullable=False)
  175. # type
  176. tool_type = db.Column(db.String(40), nullable=False)
  177. # tool name
  178. tool_name = db.Column(db.String(40), nullable=False)
  179. # invoke parameters
  180. model_parameters = db.Column(db.Text, nullable=False)
  181. # prompt messages
  182. prompt_messages = db.Column(db.Text, nullable=False)
  183. # invoke response
  184. model_response = db.Column(db.Text, nullable=False)
  185. prompt_tokens = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
  186. answer_tokens = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
  187. answer_unit_price = db.Column(db.Numeric(10, 4), nullable=False)
  188. answer_price_unit = db.Column(db.Numeric(10, 7), nullable=False, server_default=db.text("0.001"))
  189. provider_response_latency = db.Column(db.Float, nullable=False, server_default=db.text("0"))
  190. total_price = db.Column(db.Numeric(10, 7))
  191. currency = db.Column(db.String(255), nullable=False)
  192. created_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
  193. updated_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
  194. @deprecated
  195. class ToolConversationVariables(Base):
  196. """
  197. store the conversation variables from tool invoke
  198. """
  199. __tablename__ = "tool_conversation_variables"
  200. __table_args__ = (
  201. db.PrimaryKeyConstraint("id", name="tool_conversation_variables_pkey"),
  202. # add index for user_id and conversation_id
  203. db.Index("user_id_idx", "user_id"),
  204. db.Index("conversation_id_idx", "conversation_id"),
  205. )
  206. id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  207. # conversation user id
  208. user_id = db.Column(StringUUID, nullable=False)
  209. # tenant id
  210. tenant_id = db.Column(StringUUID, nullable=False)
  211. # conversation id
  212. conversation_id = db.Column(StringUUID, nullable=False)
  213. # variables pool
  214. variables_str = db.Column(db.Text, nullable=False)
  215. created_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
  216. updated_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
  217. @property
  218. def variables(self) -> Any:
  219. return json.loads(self.variables_str)
  220. class ToolFile(Base):
  221. """
  222. store the file created by agent
  223. """
  224. __tablename__ = "tool_files"
  225. __table_args__ = (
  226. db.PrimaryKeyConstraint("id", name="tool_file_pkey"),
  227. db.Index("tool_file_conversation_id_idx", "conversation_id"),
  228. )
  229. id: Mapped[str] = mapped_column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  230. # conversation user id
  231. user_id: Mapped[str] = mapped_column(StringUUID)
  232. # tenant id
  233. tenant_id: Mapped[str] = mapped_column(StringUUID)
  234. # conversation id
  235. conversation_id: Mapped[str] = mapped_column(StringUUID, nullable=True)
  236. # file key
  237. file_key: Mapped[str] = mapped_column(db.String(255), nullable=False)
  238. # mime type
  239. mimetype: Mapped[str] = mapped_column(db.String(255), nullable=False)
  240. # original url
  241. original_url: Mapped[str] = mapped_column(db.String(2048), nullable=True)
  242. # name
  243. name: Mapped[str] = mapped_column(default="")
  244. # size
  245. size: Mapped[int] = mapped_column(default=-1)
  246. @deprecated
  247. class DeprecatedPublishedAppTool(Base):
  248. """
  249. The table stores the apps published as a tool for each person.
  250. """
  251. __tablename__ = "tool_published_apps"
  252. __table_args__ = (
  253. db.PrimaryKeyConstraint("id", name="published_app_tool_pkey"),
  254. db.UniqueConstraint("app_id", "user_id", name="unique_published_app_tool"),
  255. )
  256. # id of the app
  257. app_id = db.Column(StringUUID, ForeignKey("apps.id"), nullable=False)
  258. # who published this tool
  259. description = db.Column(db.Text, nullable=False)
  260. # llm_description of the tool, for LLM
  261. llm_description = db.Column(db.Text, nullable=False)
  262. # query description, query will be seem as a parameter of the tool,
  263. # to describe this parameter to llm, we need this field
  264. query_description = db.Column(db.Text, nullable=False)
  265. # query name, the name of the query parameter
  266. query_name = db.Column(db.String(40), nullable=False)
  267. # name of the tool provider
  268. tool_name = db.Column(db.String(40), nullable=False)
  269. # author
  270. author = db.Column(db.String(40), nullable=False)
  271. created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
  272. updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)"))
  273. @property
  274. def description_i18n(self) -> I18nObject:
  275. return I18nObject(**json.loads(self.description))
  276. id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
  277. user_id: Mapped[str] = db.Column(StringUUID, nullable=False)
  278. tenant_id: Mapped[str] = db.Column(StringUUID, nullable=False)
  279. conversation_id: Mapped[Optional[str]] = db.Column(StringUUID, nullable=True)
  280. file_key: Mapped[str] = db.Column(db.String(255), nullable=False)
  281. mimetype: Mapped[str] = db.Column(db.String(255), nullable=False)
  282. original_url: Mapped[Optional[str]] = db.Column(db.String(2048), nullable=True)
  283. name: Mapped[str] = mapped_column(default="")
  284. size: Mapped[int] = mapped_column(default=-1)
  285. def __init__(
  286. self,
  287. *,
  288. user_id: str,
  289. tenant_id: str,
  290. conversation_id: Optional[str] = None,
  291. file_key: str,
  292. mimetype: str,
  293. original_url: Optional[str] = None,
  294. name: str,
  295. size: int,
  296. ):
  297. self.user_id = user_id
  298. self.tenant_id = tenant_id
  299. self.conversation_id = conversation_id
  300. self.file_key = file_key
  301. self.mimetype = mimetype
  302. self.original_url = original_url
  303. self.name = name
  304. self.size = size