Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import mimetypes
  2. import os
  3. import platform
  4. import re
  5. import urllib.parse
  6. import warnings
  7. from collections.abc import Mapping
  8. from typing import Any
  9. from uuid import uuid4
  10. import httpx
  11. from constants import DEFAULT_FILE_NUMBER_LIMITS
  12. try:
  13. import magic
  14. except ImportError:
  15. if platform.system() == "Windows":
  16. warnings.warn(
  17. "To use python-magic guess MIMETYPE, you need to run `pip install python-magic-bin`", stacklevel=2
  18. )
  19. elif platform.system() == "Darwin":
  20. warnings.warn("To use python-magic guess MIMETYPE, you need to run `brew install libmagic`", stacklevel=2)
  21. elif platform.system() == "Linux":
  22. warnings.warn(
  23. "To use python-magic guess MIMETYPE, you need to run `sudo apt-get install libmagic1`", stacklevel=2
  24. )
  25. else:
  26. warnings.warn("To use python-magic guess MIMETYPE, you need to install `libmagic`", stacklevel=2)
  27. magic = None # type: ignore
  28. from pydantic import BaseModel
  29. from configs import dify_config
  30. class FileInfo(BaseModel):
  31. filename: str
  32. extension: str
  33. mimetype: str
  34. size: int
  35. def guess_file_info_from_response(response: httpx.Response):
  36. url = str(response.url)
  37. # Try to extract filename from URL
  38. parsed_url = urllib.parse.urlparse(url)
  39. url_path = parsed_url.path
  40. filename = os.path.basename(url_path)
  41. # If filename couldn't be extracted, use Content-Disposition header
  42. if not filename:
  43. content_disposition = response.headers.get("Content-Disposition")
  44. if content_disposition:
  45. filename_match = re.search(r'filename="?(.+)"?', content_disposition)
  46. if filename_match:
  47. filename = filename_match.group(1)
  48. # If still no filename, generate a unique one
  49. if not filename:
  50. unique_name = str(uuid4())
  51. filename = f"{unique_name}"
  52. # Guess MIME type from filename first, then URL
  53. mimetype, _ = mimetypes.guess_type(filename)
  54. if mimetype is None:
  55. mimetype, _ = mimetypes.guess_type(url)
  56. if mimetype is None:
  57. # If guessing fails, use Content-Type from response headers
  58. mimetype = response.headers.get("Content-Type", "application/octet-stream")
  59. # Use python-magic to guess MIME type if still unknown or generic
  60. if mimetype == "application/octet-stream" and magic is not None:
  61. try:
  62. mimetype = magic.from_buffer(response.content[:1024], mime=True)
  63. except magic.MagicException:
  64. pass
  65. extension = os.path.splitext(filename)[1]
  66. # Ensure filename has an extension
  67. if not extension:
  68. extension = mimetypes.guess_extension(mimetype) or ".bin"
  69. filename = f"{filename}{extension}"
  70. return FileInfo(
  71. filename=filename,
  72. extension=extension,
  73. mimetype=mimetype,
  74. size=int(response.headers.get("Content-Length", -1)),
  75. )
  76. def get_parameters_from_feature_dict(*, features_dict: Mapping[str, Any], user_input_form: list[dict[str, Any]]):
  77. return {
  78. "opening_statement": features_dict.get("opening_statement"),
  79. "suggested_questions": features_dict.get("suggested_questions", []),
  80. "suggested_questions_after_answer": features_dict.get("suggested_questions_after_answer", {"enabled": False}),
  81. "speech_to_text": features_dict.get("speech_to_text", {"enabled": False}),
  82. "text_to_speech": features_dict.get("text_to_speech", {"enabled": False}),
  83. "retriever_resource": features_dict.get("retriever_resource", {"enabled": False}),
  84. "annotation_reply": features_dict.get("annotation_reply", {"enabled": False}),
  85. "more_like_this": features_dict.get("more_like_this", {"enabled": False}),
  86. "user_input_form": user_input_form,
  87. "sensitive_word_avoidance": features_dict.get(
  88. "sensitive_word_avoidance", {"enabled": False, "type": "", "configs": []}
  89. ),
  90. "file_upload": features_dict.get(
  91. "file_upload",
  92. {
  93. "image": {
  94. "enabled": False,
  95. "number_limits": DEFAULT_FILE_NUMBER_LIMITS,
  96. "detail": "high",
  97. "transfer_methods": ["remote_url", "local_file"],
  98. }
  99. },
  100. ),
  101. "system_parameters": {
  102. "image_file_size_limit": dify_config.UPLOAD_IMAGE_FILE_SIZE_LIMIT,
  103. "video_file_size_limit": dify_config.UPLOAD_VIDEO_FILE_SIZE_LIMIT,
  104. "audio_file_size_limit": dify_config.UPLOAD_AUDIO_FILE_SIZE_LIMIT,
  105. "file_size_limit": dify_config.UPLOAD_FILE_SIZE_LIMIT,
  106. "workflow_file_upload_limit": dify_config.WORKFLOW_FILE_UPLOAD_LIMIT,
  107. },
  108. }