Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

variable_loader.py 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import abc
  2. from collections.abc import Mapping, Sequence
  3. from typing import Any, Protocol
  4. from core.variables import Variable
  5. from core.variables.consts import MIN_SELECTORS_LENGTH
  6. from core.workflow.entities.variable_pool import VariablePool
  7. from core.workflow.utils import variable_utils
  8. class VariableLoader(Protocol):
  9. """Interface for loading variables based on selectors.
  10. A `VariableLoader` is responsible for retrieving additional variables required during the execution
  11. of a single node, which are not provided as user inputs.
  12. NOTE(QuantumGhost): Typically, all variables loaded by a `VariableLoader` should belong to the same
  13. application and share the same `app_id`. However, this interface does not enforce that constraint,
  14. and the `app_id` parameter is intentionally omitted from `load_variables` to achieve separation of
  15. concern and allow for flexible implementations.
  16. Implementations of `VariableLoader` should almost always have an `app_id` parameter in
  17. their constructor.
  18. TODO(QuantumGhost): this is a temporally workaround. If we can move the creation of node instance into
  19. `WorkflowService.single_step_run`, we may get rid of this interface.
  20. """
  21. @abc.abstractmethod
  22. def load_variables(self, selectors: list[list[str]]) -> list[Variable]:
  23. """Load variables based on the provided selectors. If the selectors are empty,
  24. this method should return an empty list.
  25. The order of the returned variables is not guaranteed. If the caller wants to ensure
  26. a specific order, they should sort the returned list themselves.
  27. :param: selectors: a list of string list, each inner list should have at least two elements:
  28. - the first element is the node ID,
  29. - the second element is the variable name.
  30. :return: a list of Variable objects that match the provided selectors.
  31. """
  32. pass
  33. class _DummyVariableLoader(VariableLoader):
  34. """A dummy implementation of VariableLoader that does not load any variables.
  35. Serves as a placeholder when no variable loading is needed.
  36. """
  37. def load_variables(self, selectors: list[list[str]]) -> list[Variable]:
  38. return []
  39. DUMMY_VARIABLE_LOADER = _DummyVariableLoader()
  40. def load_into_variable_pool(
  41. variable_loader: VariableLoader,
  42. variable_pool: VariablePool,
  43. variable_mapping: Mapping[str, Sequence[str]],
  44. user_inputs: Mapping[str, Any],
  45. ):
  46. # Loading missing variable from draft var here, and set it into
  47. # variable_pool.
  48. variables_to_load: list[list[str]] = []
  49. for key, selector in variable_mapping.items():
  50. # NOTE(QuantumGhost): this logic needs to be in sync with
  51. # `WorkflowEntry.mapping_user_inputs_to_variable_pool`.
  52. node_variable_list = key.split(".")
  53. if len(node_variable_list) < 1:
  54. raise ValueError(f"Invalid variable key: {key}. It should have at least one element.")
  55. if key in user_inputs:
  56. continue
  57. node_variable_key = ".".join(node_variable_list[1:])
  58. if node_variable_key in user_inputs:
  59. continue
  60. if variable_pool.get(selector) is None:
  61. variables_to_load.append(list(selector))
  62. loaded = variable_loader.load_variables(variables_to_load)
  63. for var in loaded:
  64. assert len(var.selector) >= MIN_SELECTORS_LENGTH, f"Invalid variable {var}"
  65. variable_utils.append_variables_recursively(
  66. variable_pool, node_id=var.selector[0], variable_key_list=list(var.selector[1:]), variable_value=var
  67. )