Tachi67 commited on
Commit
c25e495
·
verified ·
1 Parent(s): 0c6341a

Upload 10 files

Browse files
Files changed (4) hide show
  1. PlanWriterAskUserFlow.py +21 -2
  2. PlanWriterCtrlFlow.py +62 -1
  3. PlanWriterFlow.py +29 -1
  4. README.md +183 -15
PlanWriterAskUserFlow.py CHANGED
@@ -11,11 +11,30 @@ log = logging.get_logger(f"aiflows.{__name__}")
11
 
12
  class PlanWriterAskUserFlow(HumanStandardInputFlow):
13
  """
14
- Refer to: https://huggingface.co/Tachi67/ExtendLibraryFlowModule/blob/main/ExtLibAskUserFlow.py
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  """
16
  def run(self,
17
  input_data: Dict[str, Any]) -> Dict[str, Any]:
18
-
 
 
 
 
 
 
19
  query_message = self._get_message(self.query_message_prompt_template, input_data)
20
  state_update_message = UpdateMessage_Generic(
21
  created_by=self.flow_config['name'],
 
11
 
12
  class PlanWriterAskUserFlow(HumanStandardInputFlow):
13
  """
14
+ Refer to: https://huggingface.co/aiflows/ExtendLibraryFlowModule/blob/main/ExtLibAskUserFlow.py
15
+ This flow is used to ask the user a question and get a response.
16
+
17
+ *Input Interface*:
18
+ - `question`
19
+
20
+ *Output Interface*:
21
+ - `feedback`
22
+ - `plan`
23
+
24
+ *Configuration Parameters*:
25
+ - `query_message_prompt_template`: The message template to prompt the user for input.
26
+ - `request_multi_line_input_flag`: Whether to request multi-line input from the user.
27
+ - `end_of_input_string`: The string to enter to indicate the end of input.
28
  """
29
  def run(self,
30
  input_data: Dict[str, Any]) -> Dict[str, Any]:
31
+ """
32
+ Run the flow module.
33
+ :param input_data: The input data to the flow module.
34
+ :type input_data: Dict[str, Any]
35
+ :return: The output data from the flow module.
36
+ :rtype: Dict[str, Any]
37
+ """
38
  query_message = self._get_message(self.query_message_prompt_template, input_data)
39
  state_update_message = UpdateMessage_Generic(
40
  created_by=self.flow_config['name'],
PlanWriterCtrlFlow.py CHANGED
@@ -14,12 +14,45 @@ class Command:
14
  input_args: List[str]
15
 
16
  class PlanWriterCtrlFlow(ChatAtomicFlow):
17
- """Refer to: https://huggingface.co/Tachi67/JarvisFlowModule/blob/main/Controller_JarvisFlow.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  """
 
19
  def __init__(
20
  self,
21
  commands: List[Command],
22
  **kwargs):
 
 
 
 
 
 
 
23
  super().__init__(**kwargs)
24
  self.system_message_prompt_template = self.system_message_prompt_template.partial(
25
  commands=self._build_commands_manual(commands),
@@ -37,6 +70,13 @@ class PlanWriterCtrlFlow(ChatAtomicFlow):
37
 
38
  @staticmethod
39
  def _build_commands_manual(commands: List[Command]) -> str:
 
 
 
 
 
 
 
40
  ret = ""
41
  for i, command in enumerate(commands):
42
  command_input_json_schema = json.dumps(
@@ -46,6 +86,13 @@ class PlanWriterCtrlFlow(ChatAtomicFlow):
46
 
47
  @classmethod
48
  def instantiate_from_config(cls, config):
 
 
 
 
 
 
 
49
  flow_config = deepcopy(config)
50
 
51
  kwargs = {"flow_config": flow_config}
@@ -68,12 +115,26 @@ class PlanWriterCtrlFlow(ChatAtomicFlow):
68
  return cls(**kwargs)
69
 
70
  def _update_prompts_and_input(self, input_data: Dict[str, Any]):
 
 
 
 
 
 
 
71
  if 'goal' in input_data:
72
  input_data['goal'] += self.hint_for_model
73
  if 'feedback' in input_data:
74
  input_data['feedback'] += self.hint_for_model
75
 
76
  def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
 
 
 
 
 
 
 
77
  self._update_prompts_and_input(input_data)
78
 
79
  # ~~~when conversation is initialized, append the updated system prompts to the chat history ~~~
 
14
  input_args: List[str]
15
 
16
  class PlanWriterCtrlFlow(ChatAtomicFlow):
17
+ """Refer to: https://huggingface.co/aiflows/JarvisFlowModule/blob/main/Controller_JarvisFlow.py
18
+ This flow is a controller flow that controls the PlanWriterFlow.
19
+
20
+ *Input Interface Non Initialized*:
21
+ - `goal`: str
22
+
23
+ *Input Interface Initialized*:
24
+ - `feedback`: str
25
+ - `goal`: str
26
+ - `plan`: str
27
+
28
+ *Output Interface*:
29
+ - `command`: str
30
+ - `command_args`: Dict[str, Any]
31
+
32
+ *Configuration Parameters*:
33
+ - `input_interface_non_initialized`: List[str] = ["goal"]
34
+ - `input_interface_initialized`: List[str] = ["feedback", "goal", "plan"]
35
+ - `output_interface`: List[str] = ["command", "command_args"]
36
+ - `backend`: Dict[str, Any] : backend of the LLM
37
+ - `commands`: List[Dict[str, Any]] : commands that the LLM can execute
38
+ - `system_message_prompt_template`: str : the template of the system message prompt
39
+ - `init_human_message_prompt_template`: str : the template of the initial human message prompt
40
+ - `human_message_prompt_template`: str : the template of the human message prompt
41
+ - `previous_messages`: Dict[str, Any] : the previous messages of the conversation (sliding window)
42
+
43
  """
44
+
45
  def __init__(
46
  self,
47
  commands: List[Command],
48
  **kwargs):
49
+ """
50
+ This function initializes the flow.
51
+ :param commands: List[Command] : commands that the LLM can execute
52
+ :type commands: List[Command]
53
+ :param kwargs: other parameters
54
+ :type kwargs: Dict[str, Any]
55
+ """
56
  super().__init__(**kwargs)
57
  self.system_message_prompt_template = self.system_message_prompt_template.partial(
58
  commands=self._build_commands_manual(commands),
 
70
 
71
  @staticmethod
72
  def _build_commands_manual(commands: List[Command]) -> str:
73
+ """
74
+ This function builds the manual for the commands.
75
+ :param commands: List[Command] : commands that the LLM can execute
76
+ :type commands: List[Command]
77
+ :return: the manual for the commands
78
+ :rtype: str
79
+ """
80
  ret = ""
81
  for i, command in enumerate(commands):
82
  command_input_json_schema = json.dumps(
 
86
 
87
  @classmethod
88
  def instantiate_from_config(cls, config):
89
+ """
90
+ This function instantiates the flow from the config.
91
+ :param config: the config of the flow
92
+ :type config: Dict[str, Any]
93
+ :return: the instantiated flow
94
+ :rtype: ChatAtomicFlow
95
+ """
96
  flow_config = deepcopy(config)
97
 
98
  kwargs = {"flow_config": flow_config}
 
115
  return cls(**kwargs)
116
 
117
  def _update_prompts_and_input(self, input_data: Dict[str, Any]):
118
+ """
119
+ This function updates the prompts and input data.
120
+ :param input_data: the input data
121
+ :type input_data: Dict[str, Any]
122
+ :return: None
123
+ :rtype: None
124
+ """
125
  if 'goal' in input_data:
126
  input_data['goal'] += self.hint_for_model
127
  if 'feedback' in input_data:
128
  input_data['feedback'] += self.hint_for_model
129
 
130
  def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
131
+ """
132
+ This function runs the flow.
133
+ :param input_data: the input data
134
+ :type input_data: Dict[str, Any]
135
+ :return: the output of the flow
136
+ :rtype: Dict[str, Any]
137
+ """
138
  self._update_prompts_and_input(input_data)
139
 
140
  # ~~~when conversation is initialized, append the updated system prompts to the chat history ~~~
PlanWriterFlow.py CHANGED
@@ -7,7 +7,7 @@ from aiflows.base_flows import CircularFlow
7
 
8
  class PlanWriterFlow(ContentWriterFlow):
9
  """This flow inherits from ContentWriterFlow.
10
- In the subflow of the executor, we specify the InteractivePlanGneFlow (https://huggingface.co/Tachi67/InteractivePlanGenFlowModule)
11
 
12
  *Input Interface*:
13
  - `goal`
@@ -17,8 +17,20 @@ class PlanWriterFlow(ContentWriterFlow):
17
  - `result`
18
  - `summary`
19
  - `status`
 
 
 
 
 
 
 
 
 
20
  """
21
  def _on_reach_max_round(self):
 
 
 
22
  self._state_update_dict({
23
  "plan": "The maximum amount of rounds was reached before the model generated the plan.",
24
  "status": "unfinished"
@@ -26,6 +38,15 @@ class PlanWriterFlow(ContentWriterFlow):
26
 
27
  @CircularFlow.output_msg_payload_processor
28
  def detect_finish_or_continue(self, output_payload: Dict[str, Any], src_flow) -> Dict[str, Any]:
 
 
 
 
 
 
 
 
 
29
  command = output_payload["command"]
30
  if command == "finish":
31
  # ~~~ fetch temp file location, plan content, memory file (of upper level flow e.g. ExtLib) from flow state
@@ -74,6 +95,13 @@ class PlanWriterFlow(ContentWriterFlow):
74
  return output_payload
75
 
76
  def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
 
 
 
 
 
 
 
77
  # ~~~ sets the input_data in the flow_state dict ~~~
78
  self._state_update_dict(update_data=input_data)
79
 
 
7
 
8
  class PlanWriterFlow(ContentWriterFlow):
9
  """This flow inherits from ContentWriterFlow.
10
+ In the subflow of the executor, we specify the InteractivePlanGneFlow (https://huggingface.co/aiflows/InteractivePlanGenFlowModule)
11
 
12
  *Input Interface*:
13
  - `goal`
 
17
  - `result`
18
  - `summary`
19
  - `status`
20
+
21
+ *Configuration Parameters*:
22
+ - Also refer to superclass ContentWriterFlow (https://huggingface.co/aiflows/ContentWriterFlowModule)
23
+ - `input_interface`: the input interface of the flow
24
+ - `output_interface`: the output interface of the flow
25
+ - `subflows_config`: the configuration of the subflows
26
+ - `early_exit_key`: the key in the flow state that indicates the early exit condition
27
+ - `topology`: the topology of the flow
28
+
29
  """
30
  def _on_reach_max_round(self):
31
+ """This function is called when the flow reaches the maximum amount of rounds.
32
+ It decides whether to terminate the flow or continue running.
33
+ """
34
  self._state_update_dict({
35
  "plan": "The maximum amount of rounds was reached before the model generated the plan.",
36
  "status": "unfinished"
 
38
 
39
  @CircularFlow.output_msg_payload_processor
40
  def detect_finish_or_continue(self, output_payload: Dict[str, Any], src_flow) -> Dict[str, Any]:
41
+ """This function is called when the subflow finishes running.
42
+ configured in the topology of the subflow config.
43
+ :param output_payload: the output payload of the subflow
44
+ :type output_payload: Dict[str, Any]
45
+ :param src_flow: the subflow that generates the output payload
46
+ :type src_flow: Flow
47
+ :return: the processed output payload
48
+ :rtype: Dict[str, Any]
49
+ """
50
  command = output_payload["command"]
51
  if command == "finish":
52
  # ~~~ fetch temp file location, plan content, memory file (of upper level flow e.g. ExtLib) from flow state
 
95
  return output_payload
96
 
97
  def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
98
+ """
99
+ This function runs the flow.
100
+ :param input_data: the input data of the flow
101
+ :type input_data: Dict[str, Any]
102
+ :return: the output data of the flow
103
+ :rtype: Dict[str, Any]
104
+ """
105
  # ~~~ sets the input_data in the flow_state dict ~~~
106
  self._state_update_dict(update_data=input_data)
107
 
README.md CHANGED
@@ -1,4 +1,24 @@
1
- ### Structure of PlanWriterFlow
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  ```
4
  goal
@@ -39,23 +59,15 @@ write_plan ask_user
39
  ```
40
 
41
  About the branches:
42
- - [ask_user](https://huggingface.co/Tachi67/PlanWriterFlowModule/blob/main/PlanWriterAskUserFlow.py): Ask user for info / confirmation, etc.
43
- - [write_plan](https://huggingface.co/Tachi67/InteractivePlanGenFlowModule): Generates plan (user edit is allowed) and fetches user feedback.
44
 
45
  How it works:
46
  Controller calls write_plan until user is satisfied in the feedback, finish.
47
 
48
 
49
- # Table of Contents
50
 
51
- * [run\_planwriter](#run_planwriter)
52
- * [PlanWriterAskUserFlow](#PlanWriterAskUserFlow)
53
- * [PlanWriterAskUserFlow](#PlanWriterAskUserFlow.PlanWriterAskUserFlow)
54
- * [PlanWriterFlow](#PlanWriterFlow)
55
- * [PlanWriterFlow](#PlanWriterFlow.PlanWriterFlow)
56
- * [\_\_init\_\_](#__init__)
57
- * [PlanWriterCtrlFlow](#PlanWriterCtrlFlow)
58
- * [PlanWriterCtrlFlow](#PlanWriterCtrlFlow.PlanWriterCtrlFlow)
59
 
60
  <a id="run_planwriter"></a>
61
 
@@ -73,7 +85,38 @@ Controller calls write_plan until user is satisfied in the feedback, finish.
73
  class PlanWriterAskUserFlow(HumanStandardInputFlow)
74
  ```
75
 
76
- Refer to: https://huggingface.co/Tachi67/ExtendLibraryFlowModule/blob/main/ExtLibAskUserFlow.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  <a id="PlanWriterFlow"></a>
79
 
@@ -88,7 +131,7 @@ class PlanWriterFlow(ContentWriterFlow)
88
  ```
89
 
90
  This flow inherits from ContentWriterFlow.
91
- In the subflow of the executor, we specify the InteractivePlanGneFlow (https://huggingface.co/Tachi67/InteractivePlanGenFlowModule)
92
 
93
  *Input Interface*:
94
  - `goal`
@@ -99,6 +142,55 @@ In the subflow of the executor, we specify the InteractivePlanGneFlow (https://h
99
  - `summary`
100
  - `status`
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  <a id="__init__"></a>
103
 
104
  # \_\_init\_\_
@@ -115,5 +207,81 @@ In the subflow of the executor, we specify the InteractivePlanGneFlow (https://h
115
  class PlanWriterCtrlFlow(ChatAtomicFlow)
116
  ```
117
 
118
- Refer to: https://huggingface.co/Tachi67/JarvisFlowModule/blob/main/Controller_JarvisFlow.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
 
1
+ # Table of Contents
2
+
3
+ * [Structure of PlanWriterFlow](#structure-of-planwriterflow)
4
+ * [run\_planwriter](#run_planwriter)
5
+ * [PlanWriterAskUserFlow](#PlanWriterAskUserFlow)
6
+ * [PlanWriterAskUserFlow](#PlanWriterAskUserFlow.PlanWriterAskUserFlow)
7
+ * [run](#PlanWriterAskUserFlow.PlanWriterAskUserFlow.run)
8
+ * [PlanWriterFlow](#PlanWriterFlow)
9
+ * [PlanWriterFlow](#PlanWriterFlow.PlanWriterFlow)
10
+ * [detect\_finish\_or\_continue](#PlanWriterFlow.PlanWriterFlow.detect_finish_or_continue)
11
+ * [run](#PlanWriterFlow.PlanWriterFlow.run)
12
+ * [\_\_init\_\_](#__init__)
13
+ * [PlanWriterCtrlFlow](#PlanWriterCtrlFlow)
14
+ * [PlanWriterCtrlFlow](#PlanWriterCtrlFlow.PlanWriterCtrlFlow)
15
+ * [\_\_init\_\_](#PlanWriterCtrlFlow.PlanWriterCtrlFlow.__init__)
16
+ * [instantiate\_from\_config](#PlanWriterCtrlFlow.PlanWriterCtrlFlow.instantiate_from_config)
17
+ * [run](#PlanWriterCtrlFlow.PlanWriterCtrlFlow.run)
18
+
19
+
20
+
21
+ # Structure of PlanWriterFlow
22
 
23
  ```
24
  goal
 
59
  ```
60
 
61
  About the branches:
62
+ - [ask_user](https://huggingface.co/aiflows/PlanWriterFlowModule/blob/main/PlanWriterAskUserFlow.py): Ask user for info / confirmation, etc.
63
+ - [write_plan](https://huggingface.co/aiflows/InteractivePlanGenFlowModule): Generates plan (user edit is allowed) and fetches user feedback.
64
 
65
  How it works:
66
  Controller calls write_plan until user is satisfied in the feedback, finish.
67
 
68
 
 
69
 
70
+
 
 
 
 
 
 
 
71
 
72
  <a id="run_planwriter"></a>
73
 
 
85
  class PlanWriterAskUserFlow(HumanStandardInputFlow)
86
  ```
87
 
88
+ Refer to: https://huggingface.co/aiflows/ExtendLibraryFlowModule/blob/main/ExtLibAskUserFlow.py
89
+ This flow is used to ask the user a question and get a response.
90
+
91
+ *Input Interface*:
92
+ - `question`
93
+
94
+ *Output Interface*:
95
+ - `feedback`
96
+ - `plan`
97
+
98
+ *Configuration Parameters*:
99
+ - `query_message_prompt_template`: The message template to prompt the user for input.
100
+ - `request_multi_line_input_flag`: Whether to request multi-line input from the user.
101
+ - `end_of_input_string`: The string to enter to indicate the end of input.
102
+
103
+ <a id="PlanWriterAskUserFlow.PlanWriterAskUserFlow.run"></a>
104
+
105
+ #### run
106
+
107
+ ```python
108
+ def run(input_data: Dict[str, Any]) -> Dict[str, Any]
109
+ ```
110
+
111
+ Run the flow module.
112
+
113
+ **Arguments**:
114
+
115
+ - `input_data` (`Dict[str, Any]`): The input data to the flow module.
116
+
117
+ **Returns**:
118
+
119
+ `Dict[str, Any]`: The output data from the flow module.
120
 
121
  <a id="PlanWriterFlow"></a>
122
 
 
131
  ```
132
 
133
  This flow inherits from ContentWriterFlow.
134
+ In the subflow of the executor, we specify the InteractivePlanGneFlow (https://huggingface.co/aiflows/InteractivePlanGenFlowModule)
135
 
136
  *Input Interface*:
137
  - `goal`
 
142
  - `summary`
143
  - `status`
144
 
145
+ *Configuration Parameters*:
146
+ - Also refer to superclass ContentWriterFlow (https://huggingface.co/aiflows/ContentWriterFlowModule)
147
+ - `input_interface`: the input interface of the flow
148
+ - `output_interface`: the output interface of the flow
149
+ - `subflows_config`: the configuration of the subflows
150
+ - `early_exit_key`: the key in the flow state that indicates the early exit condition
151
+ - `topology`: the topology of the flow
152
+
153
+ <a id="PlanWriterFlow.PlanWriterFlow.detect_finish_or_continue"></a>
154
+
155
+ #### detect\_finish\_or\_continue
156
+
157
+ ```python
158
+ @CircularFlow.output_msg_payload_processor
159
+ def detect_finish_or_continue(output_payload: Dict[str, Any],
160
+ src_flow) -> Dict[str, Any]
161
+ ```
162
+
163
+ This function is called when the subflow finishes running.
164
+
165
+ configured in the topology of the subflow config.
166
+
167
+ **Arguments**:
168
+
169
+ - `output_payload` (`Dict[str, Any]`): the output payload of the subflow
170
+ - `src_flow` (`Flow`): the subflow that generates the output payload
171
+
172
+ **Returns**:
173
+
174
+ `Dict[str, Any]`: the processed output payload
175
+
176
+ <a id="PlanWriterFlow.PlanWriterFlow.run"></a>
177
+
178
+ #### run
179
+
180
+ ```python
181
+ def run(input_data: Dict[str, Any]) -> Dict[str, Any]
182
+ ```
183
+
184
+ This function runs the flow.
185
+
186
+ **Arguments**:
187
+
188
+ - `input_data` (`Dict[str, Any]`): the input data of the flow
189
+
190
+ **Returns**:
191
+
192
+ `Dict[str, Any]`: the output data of the flow
193
+
194
  <a id="__init__"></a>
195
 
196
  # \_\_init\_\_
 
207
  class PlanWriterCtrlFlow(ChatAtomicFlow)
208
  ```
209
 
210
+ Refer to: https://huggingface.co/aiflows/JarvisFlowModule/blob/main/Controller_JarvisFlow.py
211
+ This flow is a controller flow that controls the PlanWriterFlow.
212
+
213
+ *Input Interface Non Initialized*:
214
+ - `goal`: str
215
+
216
+ *Input Interface Initialized*:
217
+ - `feedback`: str
218
+ - `goal`: str
219
+ - `plan`: str
220
+
221
+ *Output Interface*:
222
+ - `command`: str
223
+ - `command_args`: Dict[str, Any]
224
+
225
+ *Configuration Parameters*:
226
+ - `input_interface_non_initialized`: List[str] = ["goal"]
227
+ - `input_interface_initialized`: List[str] = ["feedback", "goal", "plan"]
228
+ - `output_interface`: List[str] = ["command", "command_args"]
229
+ - `backend`: Dict[str, Any] : backend of the LLM
230
+ - `commands`: List[Dict[str, Any]] : commands that the LLM can execute
231
+ - `system_message_prompt_template`: str : the template of the system message prompt
232
+ - `init_human_message_prompt_template`: str : the template of the initial human message prompt
233
+ - `human_message_prompt_template`: str : the template of the human message prompt
234
+ - `previous_messages`: Dict[str, Any] : the previous messages of the conversation (sliding window)
235
+
236
+ <a id="PlanWriterCtrlFlow.PlanWriterCtrlFlow.__init__"></a>
237
+
238
+ #### \_\_init\_\_
239
+
240
+ ```python
241
+ def __init__(commands: List[Command], **kwargs)
242
+ ```
243
+
244
+ This function initializes the flow.
245
+
246
+ **Arguments**:
247
+
248
+ - `commands` (`List[Command]`): List[Command] : commands that the LLM can execute
249
+ - `kwargs` (`Dict[str, Any]`): other parameters
250
+
251
+ <a id="PlanWriterCtrlFlow.PlanWriterCtrlFlow.instantiate_from_config"></a>
252
+
253
+ #### instantiate\_from\_config
254
+
255
+ ```python
256
+ @classmethod
257
+ def instantiate_from_config(cls, config)
258
+ ```
259
+
260
+ This function instantiates the flow from the config.
261
+
262
+ **Arguments**:
263
+
264
+ - `config` (`Dict[str, Any]`): the config of the flow
265
+
266
+ **Returns**:
267
+
268
+ `ChatAtomicFlow`: the instantiated flow
269
+
270
+ <a id="PlanWriterCtrlFlow.PlanWriterCtrlFlow.run"></a>
271
+
272
+ #### run
273
+
274
+ ```python
275
+ def run(input_data: Dict[str, Any]) -> Dict[str, Any]
276
+ ```
277
+
278
+ This function runs the flow.
279
+
280
+ **Arguments**:
281
+
282
+ - `input_data` (`Dict[str, Any]`): the input data
283
+
284
+ **Returns**:
285
+
286
+ `Dict[str, Any]`: the output of the flow
287