segments.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import json
  2. from collections.abc import Mapping, Sequence
  3. from typing import Any
  4. from pydantic import BaseModel, ConfigDict, field_validator
  5. from core.file.file_obj import FileVar
  6. from .types import SegmentType
  7. class Segment(BaseModel):
  8. model_config = ConfigDict(frozen=True)
  9. value_type: SegmentType
  10. value: Any
  11. @field_validator('value_type')
  12. def validate_value_type(cls, value):
  13. """
  14. This validator checks if the provided value is equal to the default value of the 'value_type' field.
  15. If the value is different, a ValueError is raised.
  16. """
  17. if value != cls.model_fields['value_type'].default:
  18. raise ValueError("Cannot modify 'value_type'")
  19. return value
  20. @property
  21. def text(self) -> str:
  22. return str(self.value)
  23. @property
  24. def log(self) -> str:
  25. return str(self.value)
  26. @property
  27. def markdown(self) -> str:
  28. return str(self.value)
  29. def to_object(self) -> Any:
  30. return self.value
  31. class NoneSegment(Segment):
  32. value_type: SegmentType = SegmentType.NONE
  33. value: None = None
  34. @property
  35. def text(self) -> str:
  36. return 'null'
  37. @property
  38. def log(self) -> str:
  39. return 'null'
  40. @property
  41. def markdown(self) -> str:
  42. return 'null'
  43. class StringSegment(Segment):
  44. value_type: SegmentType = SegmentType.STRING
  45. value: str
  46. class FloatSegment(Segment):
  47. value_type: SegmentType = SegmentType.NUMBER
  48. value: float
  49. class IntegerSegment(Segment):
  50. value_type: SegmentType = SegmentType.NUMBER
  51. value: int
  52. class FileSegment(Segment):
  53. value_type: SegmentType = SegmentType.FILE
  54. # TODO: embed FileVar in this model.
  55. value: FileVar
  56. @property
  57. def markdown(self) -> str:
  58. return self.value.to_markdown()
  59. class ObjectSegment(Segment):
  60. value_type: SegmentType = SegmentType.OBJECT
  61. value: Mapping[str, Segment]
  62. @property
  63. def text(self) -> str:
  64. # TODO: Process variables.
  65. return json.dumps(self.model_dump()['value'], ensure_ascii=False)
  66. @property
  67. def log(self) -> str:
  68. # TODO: Process variables.
  69. return json.dumps(self.model_dump()['value'], ensure_ascii=False, indent=2)
  70. @property
  71. def markdown(self) -> str:
  72. # TODO: Use markdown code block
  73. return json.dumps(self.model_dump()['value'], ensure_ascii=False, indent=2)
  74. def to_object(self):
  75. return {k: v.to_object() for k, v in self.value.items()}
  76. class ArraySegment(Segment):
  77. @property
  78. def markdown(self) -> str:
  79. return '\n'.join(['- ' + item.markdown for item in self.value])
  80. def to_object(self):
  81. return [v.to_object() for v in self.value]
  82. class ArrayAnySegment(ArraySegment):
  83. value_type: SegmentType = SegmentType.ARRAY_ANY
  84. value: Sequence[Segment]
  85. class ArrayStringSegment(ArraySegment):
  86. value_type: SegmentType = SegmentType.ARRAY_STRING
  87. value: Sequence[StringSegment]
  88. class ArrayNumberSegment(ArraySegment):
  89. value_type: SegmentType = SegmentType.ARRAY_NUMBER
  90. value: Sequence[FloatSegment | IntegerSegment]
  91. class ArrayObjectSegment(ArraySegment):
  92. value_type: SegmentType = SegmentType.ARRAY_OBJECT
  93. value: Sequence[ObjectSegment]
  94. class ArrayFileSegment(ArraySegment):
  95. value_type: SegmentType = SegmentType.ARRAY_FILE
  96. value: Sequence[FileSegment]