2024-11-12 21:51:09 +08:00
|
|
|
from collections.abc import Mapping, Sequence
|
2024-07-22 15:29:39 +08:00
|
|
|
from typing import Any
|
2024-11-12 21:51:09 +08:00
|
|
|
from uuid import uuid4
|
2024-07-22 15:29:39 +08:00
|
|
|
|
2024-08-13 14:44:10 +08:00
|
|
|
from configs import dify_config
|
2024-10-21 10:43:49 +08:00
|
|
|
from core.file import File
|
2024-11-12 21:51:09 +08:00
|
|
|
from core.variables.exc import VariableError
|
|
|
|
from core.variables.segments import (
|
2024-07-27 14:43:51 +08:00
|
|
|
ArrayAnySegment,
|
2024-10-21 10:43:49 +08:00
|
|
|
ArrayFileSegment,
|
|
|
|
ArrayNumberSegment,
|
|
|
|
ArrayObjectSegment,
|
2024-10-30 21:56:38 +08:00
|
|
|
ArraySegment,
|
2024-10-21 10:43:49 +08:00
|
|
|
ArrayStringSegment,
|
|
|
|
FileSegment,
|
|
|
|
FloatSegment,
|
|
|
|
IntegerSegment,
|
|
|
|
NoneSegment,
|
|
|
|
ObjectSegment,
|
|
|
|
Segment,
|
|
|
|
StringSegment,
|
2024-11-12 21:51:09 +08:00
|
|
|
)
|
|
|
|
from core.variables.types import SegmentType
|
|
|
|
from core.variables.variables import (
|
|
|
|
ArrayAnyVariable,
|
|
|
|
ArrayFileVariable,
|
|
|
|
ArrayNumberVariable,
|
|
|
|
ArrayObjectVariable,
|
|
|
|
ArrayStringVariable,
|
|
|
|
FileVariable,
|
|
|
|
FloatVariable,
|
|
|
|
IntegerVariable,
|
|
|
|
NoneVariable,
|
|
|
|
ObjectVariable,
|
|
|
|
SecretVariable,
|
2024-07-22 15:29:39 +08:00
|
|
|
StringVariable,
|
|
|
|
Variable,
|
|
|
|
)
|
2024-11-12 21:51:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
class InvalidSelectorError(ValueError):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class UnsupportedSegmentTypeError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
# Define the constant
|
|
|
|
SEGMENT_TO_VARIABLE_MAP = {
|
|
|
|
StringSegment: StringVariable,
|
|
|
|
IntegerSegment: IntegerVariable,
|
|
|
|
FloatSegment: FloatVariable,
|
|
|
|
ObjectSegment: ObjectVariable,
|
|
|
|
FileSegment: FileVariable,
|
|
|
|
ArrayStringSegment: ArrayStringVariable,
|
|
|
|
ArrayNumberSegment: ArrayNumberVariable,
|
|
|
|
ArrayObjectSegment: ArrayObjectVariable,
|
|
|
|
ArrayFileSegment: ArrayFileVariable,
|
|
|
|
ArrayAnySegment: ArrayAnyVariable,
|
|
|
|
NoneSegment: NoneVariable,
|
|
|
|
}
|
2024-07-22 15:29:39 +08:00
|
|
|
|
|
|
|
|
2024-08-13 14:44:10 +08:00
|
|
|
def build_variable_from_mapping(mapping: Mapping[str, Any], /) -> Variable:
|
2024-09-10 17:00:20 +08:00
|
|
|
if (value_type := mapping.get("value_type")) is None:
|
|
|
|
raise VariableError("missing value type")
|
|
|
|
if not mapping.get("name"):
|
|
|
|
raise VariableError("missing name")
|
|
|
|
if (value := mapping.get("value")) is None:
|
|
|
|
raise VariableError("missing value")
|
2024-07-22 15:29:39 +08:00
|
|
|
match value_type:
|
|
|
|
case SegmentType.STRING:
|
2024-08-13 14:44:10 +08:00
|
|
|
result = StringVariable.model_validate(mapping)
|
2024-07-27 14:43:51 +08:00
|
|
|
case SegmentType.SECRET:
|
2024-08-13 14:44:10 +08:00
|
|
|
result = SecretVariable.model_validate(mapping)
|
2024-07-22 15:29:39 +08:00
|
|
|
case SegmentType.NUMBER if isinstance(value, int):
|
2024-08-13 14:44:10 +08:00
|
|
|
result = IntegerVariable.model_validate(mapping)
|
2024-07-22 15:29:39 +08:00
|
|
|
case SegmentType.NUMBER if isinstance(value, float):
|
2024-08-13 14:44:10 +08:00
|
|
|
result = FloatVariable.model_validate(mapping)
|
2024-07-22 15:29:39 +08:00
|
|
|
case SegmentType.NUMBER if not isinstance(value, float | int):
|
2024-09-10 17:00:20 +08:00
|
|
|
raise VariableError(f"invalid number value {value}")
|
2024-07-27 14:43:51 +08:00
|
|
|
case SegmentType.OBJECT if isinstance(value, dict):
|
2024-08-13 14:44:10 +08:00
|
|
|
result = ObjectVariable.model_validate(mapping)
|
2024-07-27 14:43:51 +08:00
|
|
|
case SegmentType.ARRAY_STRING if isinstance(value, list):
|
2024-08-13 14:44:10 +08:00
|
|
|
result = ArrayStringVariable.model_validate(mapping)
|
2024-07-27 14:43:51 +08:00
|
|
|
case SegmentType.ARRAY_NUMBER if isinstance(value, list):
|
2024-08-13 14:44:10 +08:00
|
|
|
result = ArrayNumberVariable.model_validate(mapping)
|
2024-07-27 14:43:51 +08:00
|
|
|
case SegmentType.ARRAY_OBJECT if isinstance(value, list):
|
2024-08-13 14:44:10 +08:00
|
|
|
result = ArrayObjectVariable.model_validate(mapping)
|
|
|
|
case _:
|
2024-09-10 17:00:20 +08:00
|
|
|
raise VariableError(f"not supported value type {value_type}")
|
2024-08-13 14:44:10 +08:00
|
|
|
if result.size > dify_config.MAX_VARIABLE_SIZE:
|
2024-09-10 17:00:20 +08:00
|
|
|
raise VariableError(f"variable size {result.size} exceeds limit {dify_config.MAX_VARIABLE_SIZE}")
|
2024-08-13 14:44:10 +08:00
|
|
|
return result
|
2024-07-22 15:29:39 +08:00
|
|
|
|
|
|
|
|
2024-07-26 15:03:56 +08:00
|
|
|
def build_segment(value: Any, /) -> Segment:
|
2024-07-23 17:59:32 +08:00
|
|
|
if value is None:
|
2024-07-26 15:03:56 +08:00
|
|
|
return NoneSegment()
|
2024-07-22 15:29:39 +08:00
|
|
|
if isinstance(value, str):
|
2024-07-26 15:03:56 +08:00
|
|
|
return StringSegment(value=value)
|
2024-07-22 15:29:39 +08:00
|
|
|
if isinstance(value, int):
|
2024-07-26 15:03:56 +08:00
|
|
|
return IntegerSegment(value=value)
|
2024-07-22 15:29:39 +08:00
|
|
|
if isinstance(value, float):
|
2024-07-26 15:03:56 +08:00
|
|
|
return FloatSegment(value=value)
|
2024-07-22 15:29:39 +08:00
|
|
|
if isinstance(value, dict):
|
2024-08-07 16:20:22 +08:00
|
|
|
return ObjectSegment(value=value)
|
2024-10-21 10:43:49 +08:00
|
|
|
if isinstance(value, File):
|
|
|
|
return FileSegment(value=value)
|
2024-07-22 15:29:39 +08:00
|
|
|
if isinstance(value, list):
|
2024-10-21 10:43:49 +08:00
|
|
|
items = [build_segment(item) for item in value]
|
|
|
|
types = {item.value_type for item in items}
|
2024-10-30 21:56:38 +08:00
|
|
|
if len(types) != 1 or all(isinstance(item, ArraySegment) for item in items):
|
2024-10-21 10:43:49 +08:00
|
|
|
return ArrayAnySegment(value=value)
|
|
|
|
match types.pop():
|
|
|
|
case SegmentType.STRING:
|
|
|
|
return ArrayStringSegment(value=value)
|
|
|
|
case SegmentType.NUMBER:
|
|
|
|
return ArrayNumberSegment(value=value)
|
|
|
|
case SegmentType.OBJECT:
|
|
|
|
return ArrayObjectSegment(value=value)
|
|
|
|
case SegmentType.FILE:
|
|
|
|
return ArrayFileSegment(value=value)
|
2024-11-05 16:31:49 +08:00
|
|
|
case SegmentType.NONE:
|
|
|
|
return ArrayAnySegment(value=value)
|
2024-10-21 10:43:49 +08:00
|
|
|
case _:
|
|
|
|
raise ValueError(f"not supported value {value}")
|
2024-09-10 17:00:20 +08:00
|
|
|
raise ValueError(f"not supported value {value}")
|
2024-11-12 21:51:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
def segment_to_variable(
|
|
|
|
*,
|
|
|
|
segment: Segment,
|
|
|
|
selector: Sequence[str],
|
|
|
|
id: str | None = None,
|
|
|
|
name: str | None = None,
|
|
|
|
description: str = "",
|
|
|
|
) -> Variable:
|
|
|
|
if isinstance(segment, Variable):
|
|
|
|
return segment
|
|
|
|
name = name or selector[-1]
|
|
|
|
id = id or str(uuid4())
|
|
|
|
|
|
|
|
segment_type = type(segment)
|
|
|
|
if segment_type not in SEGMENT_TO_VARIABLE_MAP:
|
|
|
|
raise UnsupportedSegmentTypeError(f"not supported segment type {segment_type}")
|
|
|
|
|
|
|
|
variable_class = SEGMENT_TO_VARIABLE_MAP[segment_type]
|
|
|
|
return variable_class(
|
|
|
|
id=id,
|
|
|
|
name=name,
|
|
|
|
description=description,
|
|
|
|
value=segment.value,
|
|
|
|
selector=selector,
|
|
|
|
)
|