Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

utils.py 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. from contextlib import contextmanager
  2. from datetime import datetime
  3. from typing import Optional, Union
  4. from urllib.parse import urlparse
  5. from sqlalchemy import select
  6. from extensions.ext_database import db
  7. from models.model import Message
  8. def filter_none_values(data: dict):
  9. new_data = {}
  10. for key, value in data.items():
  11. if value is None:
  12. continue
  13. if isinstance(value, datetime):
  14. new_data[key] = value.isoformat()
  15. else:
  16. new_data[key] = value
  17. return new_data
  18. def get_message_data(message_id: str):
  19. return db.session.scalar(select(Message).where(Message.id == message_id))
  20. @contextmanager
  21. def measure_time():
  22. timing_info = {"start": datetime.now(), "end": None}
  23. try:
  24. yield timing_info
  25. finally:
  26. timing_info["end"] = datetime.now()
  27. def replace_text_with_content(data):
  28. if isinstance(data, dict):
  29. new_data = {}
  30. for key, value in data.items():
  31. if key == "text":
  32. new_data["content"] = value
  33. else:
  34. new_data[key] = replace_text_with_content(value)
  35. return new_data
  36. elif isinstance(data, list):
  37. return [replace_text_with_content(item) for item in data]
  38. else:
  39. return data
  40. def generate_dotted_order(
  41. run_id: str, start_time: Union[str, datetime], parent_dotted_order: Optional[str] = None
  42. ) -> str:
  43. """
  44. generate dotted_order for langsmith
  45. """
  46. start_time = datetime.fromisoformat(start_time) if isinstance(start_time, str) else start_time
  47. timestamp = start_time.strftime("%Y%m%dT%H%M%S%f")[:-3] + "Z"
  48. current_segment = f"{timestamp}{run_id}"
  49. if parent_dotted_order is None:
  50. return current_segment
  51. return f"{parent_dotted_order}.{current_segment}"
  52. def validate_url(url: str, default_url: str, allowed_schemes: tuple = ("https", "http")) -> str:
  53. """
  54. Validate and normalize URL with proper error handling.
  55. NOTE: This function does not retain the `path` component of the provided URL.
  56. In most cases, it is recommended to use `validate_url_with_path` instead.
  57. This function is deprecated and retained only for compatibility purposes.
  58. New implementations should use `validate_url_with_path`.
  59. Args:
  60. url: The URL to validate
  61. default_url: Default URL to use if input is None or empty
  62. allowed_schemes: Tuple of allowed URL schemes (default: https, http)
  63. Returns:
  64. Normalized URL string
  65. Raises:
  66. ValueError: If URL format is invalid or scheme not allowed
  67. """
  68. if not url or url.strip() == "":
  69. return default_url
  70. # Parse URL to validate format
  71. parsed = urlparse(url)
  72. # Check if scheme is allowed
  73. if parsed.scheme not in allowed_schemes:
  74. raise ValueError(f"URL scheme must be one of: {', '.join(allowed_schemes)}")
  75. # Reconstruct URL with only scheme, netloc (removing path, query, fragment)
  76. normalized_url = f"{parsed.scheme}://{parsed.netloc}"
  77. return normalized_url
  78. def validate_url_with_path(url: str, default_url: str, required_suffix: str | None = None) -> str:
  79. """
  80. Validate URL that may include path components
  81. Args:
  82. url: The URL to validate
  83. default_url: Default URL to use if input is None or empty
  84. required_suffix: Optional suffix that URL must end with
  85. Returns:
  86. Validated URL string
  87. Raises:
  88. ValueError: If URL format is invalid or doesn't match required suffix
  89. """
  90. if not url or url.strip() == "":
  91. return default_url
  92. # Parse URL to validate format
  93. parsed = urlparse(url)
  94. # Check if scheme is allowed
  95. if parsed.scheme not in ("https", "http"):
  96. raise ValueError("URL must start with https:// or http://")
  97. # Check required suffix if specified
  98. if required_suffix and not url.endswith(required_suffix):
  99. raise ValueError(f"URL should end with {required_suffix}")
  100. return url
  101. def validate_project_name(project: str, default_name: str) -> str:
  102. """
  103. Validate and normalize project name
  104. Args:
  105. project: Project name to validate
  106. default_name: Default name to use if input is None or empty
  107. Returns:
  108. Normalized project name
  109. """
  110. if not project or project.strip() == "":
  111. return default_name
  112. return project.strip()