message_transformer.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import logging
  2. from mimetypes import guess_extension
  3. from core.file.file_obj import FileTransferMethod, FileType, FileVar
  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(cls, messages: list[ToolInvokeMessage],
  10. user_id: str,
  11. tenant_id: str,
  12. conversation_id: str) -> list[ToolInvokeMessage]:
  13. """
  14. Transform tool message and handle file download
  15. """
  16. result = []
  17. for message in messages:
  18. if message.type == ToolInvokeMessage.MessageType.TEXT:
  19. result.append(message)
  20. elif message.type == ToolInvokeMessage.MessageType.LINK:
  21. result.append(message)
  22. elif message.type == ToolInvokeMessage.MessageType.IMAGE:
  23. # try to download image
  24. try:
  25. file = ToolFileManager.create_file_by_url(
  26. user_id=user_id,
  27. tenant_id=tenant_id,
  28. conversation_id=conversation_id,
  29. file_url=message.message
  30. )
  31. url = f'/files/tools/{file.id}{guess_extension(file.mimetype) or ".png"}'
  32. result.append(ToolInvokeMessage(
  33. type=ToolInvokeMessage.MessageType.IMAGE_LINK,
  34. message=url,
  35. save_as=message.save_as,
  36. meta=message.meta.copy() if message.meta is not None else {},
  37. ))
  38. except Exception as e:
  39. logger.exception(e)
  40. result.append(ToolInvokeMessage(
  41. type=ToolInvokeMessage.MessageType.TEXT,
  42. message=f"Failed to download image: {message.message}, you can try to download it yourself.",
  43. meta=message.meta.copy() if message.meta is not None else {},
  44. save_as=message.save_as,
  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, tenant_id=tenant_id,
  54. conversation_id=conversation_id,
  55. file_binary=message.message,
  56. mimetype=mimetype
  57. )
  58. url = cls.get_tool_file_url(file.id, guess_extension(file.mimetype))
  59. # check if file is image
  60. if 'image' in mimetype:
  61. result.append(ToolInvokeMessage(
  62. type=ToolInvokeMessage.MessageType.IMAGE_LINK,
  63. message=url,
  64. save_as=message.save_as,
  65. meta=message.meta.copy() if message.meta is not None else {},
  66. ))
  67. else:
  68. result.append(ToolInvokeMessage(
  69. type=ToolInvokeMessage.MessageType.LINK,
  70. message=url,
  71. save_as=message.save_as,
  72. meta=message.meta.copy() if message.meta is not None else {},
  73. ))
  74. elif message.type == ToolInvokeMessage.MessageType.FILE_VAR:
  75. file_var: FileVar = message.meta.get('file_var')
  76. if file_var:
  77. if file_var.transfer_method == FileTransferMethod.TOOL_FILE:
  78. url = cls.get_tool_file_url(file_var.related_id, file_var.extension)
  79. if file_var.type == FileType.IMAGE:
  80. result.append(ToolInvokeMessage(
  81. type=ToolInvokeMessage.MessageType.IMAGE_LINK,
  82. message=url,
  83. save_as=message.save_as,
  84. meta=message.meta.copy() if message.meta is not None else {},
  85. ))
  86. else:
  87. result.append(ToolInvokeMessage(
  88. type=ToolInvokeMessage.MessageType.LINK,
  89. message=url,
  90. save_as=message.save_as,
  91. meta=message.meta.copy() if message.meta is not None else {},
  92. ))
  93. else:
  94. result.append(message)
  95. return result
  96. @classmethod
  97. def get_tool_file_url(cls, tool_file_id: str, extension: str) -> str:
  98. return f'/files/tools/{tool_file_id}{extension or ".bin"}'