message_transformer.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import logging
  2. from mimetypes import guess_extension
  3. from core.file.file_obj import FileTransferMethod, FileType
  4. from core.tools.entities.tool_entities import ToolInvokeMessage
  5. from core.tools.tool_file_manager import ToolFileManager
  6. logger = logging.getLogger(__name__)
  7. class ToolFileMessageTransformer:
  8. @classmethod
  9. def transform_tool_invoke_messages(
  10. cls, messages: list[ToolInvokeMessage], user_id: str, tenant_id: str, conversation_id: str
  11. ) -> list[ToolInvokeMessage]:
  12. """
  13. Transform tool message and handle file download
  14. """
  15. result = []
  16. for message in messages:
  17. if message.type == ToolInvokeMessage.MessageType.TEXT:
  18. result.append(message)
  19. elif message.type == ToolInvokeMessage.MessageType.LINK:
  20. result.append(message)
  21. elif message.type == ToolInvokeMessage.MessageType.IMAGE:
  22. # try to download image
  23. try:
  24. file = ToolFileManager.create_file_by_url(
  25. user_id=user_id, tenant_id=tenant_id, conversation_id=conversation_id, file_url=message.message
  26. )
  27. url = f'/files/tools/{file.id}{guess_extension(file.mimetype) or ".png"}'
  28. result.append(
  29. ToolInvokeMessage(
  30. type=ToolInvokeMessage.MessageType.IMAGE_LINK,
  31. message=url,
  32. save_as=message.save_as,
  33. meta=message.meta.copy() if message.meta is not None else {},
  34. )
  35. )
  36. except Exception as e:
  37. logger.exception(e)
  38. result.append(
  39. ToolInvokeMessage(
  40. type=ToolInvokeMessage.MessageType.TEXT,
  41. message=f"Failed to download image: {message.message}, you can try to download it yourself.",
  42. meta=message.meta.copy() if message.meta is not None else {},
  43. save_as=message.save_as,
  44. )
  45. )
  46. elif message.type == ToolInvokeMessage.MessageType.BLOB:
  47. # get mime type and save blob to storage
  48. mimetype = message.meta.get("mime_type", "octet/stream")
  49. # if message is str, encode it to bytes
  50. if isinstance(message.message, str):
  51. message.message = message.message.encode("utf-8")
  52. file = ToolFileManager.create_file_by_raw(
  53. user_id=user_id,
  54. tenant_id=tenant_id,
  55. conversation_id=conversation_id,
  56. file_binary=message.message,
  57. mimetype=mimetype,
  58. )
  59. url = cls.get_tool_file_url(file.id, guess_extension(file.mimetype))
  60. # check if file is image
  61. if "image" in mimetype:
  62. result.append(
  63. ToolInvokeMessage(
  64. type=ToolInvokeMessage.MessageType.IMAGE_LINK,
  65. message=url,
  66. save_as=message.save_as,
  67. meta=message.meta.copy() if message.meta is not None else {},
  68. )
  69. )
  70. else:
  71. result.append(
  72. ToolInvokeMessage(
  73. type=ToolInvokeMessage.MessageType.LINK,
  74. message=url,
  75. save_as=message.save_as,
  76. meta=message.meta.copy() if message.meta is not None else {},
  77. )
  78. )
  79. elif message.type == ToolInvokeMessage.MessageType.FILE_VAR:
  80. file_var = message.meta.get("file_var")
  81. if file_var:
  82. if file_var.transfer_method == FileTransferMethod.TOOL_FILE:
  83. url = cls.get_tool_file_url(file_var.related_id, file_var.extension)
  84. if file_var.type == FileType.IMAGE:
  85. result.append(
  86. ToolInvokeMessage(
  87. type=ToolInvokeMessage.MessageType.IMAGE_LINK,
  88. message=url,
  89. save_as=message.save_as,
  90. meta=message.meta.copy() if message.meta is not None else {},
  91. )
  92. )
  93. else:
  94. result.append(
  95. ToolInvokeMessage(
  96. type=ToolInvokeMessage.MessageType.LINK,
  97. message=url,
  98. save_as=message.save_as,
  99. meta=message.meta.copy() if message.meta is not None else {},
  100. )
  101. )
  102. else:
  103. result.append(message)
  104. return result
  105. @classmethod
  106. def get_tool_file_url(cls, tool_file_id: str, extension: str) -> str:
  107. return f'/files/tools/{tool_file_id}{extension or ".bin"}'