Upload 7 files
Browse files- NewPlanGenFlow.py +16 -0
- NewPlanGenFlow.yaml +93 -0
- ReplanningAskUserFlow.py +31 -0
- ReplanningAskUserFlow.yaml +9 -0
- ReplanningFlow.py +67 -0
- ReplanningFlow.yaml +154 -0
- __init__.py +15 -0
NewPlanGenFlow.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
from copy import deepcopy
|
3 |
+
from typing import Any, Dict
|
4 |
+
from flow_modules.Tachi67.PlanGeneratorFlowModule import PlanGeneratorAtomicFlow
|
5 |
+
|
6 |
+
|
7 |
+
class NewPlanGenFlow(PlanGeneratorAtomicFlow):
|
8 |
+
def __init__(self, **kwargs):
|
9 |
+
super().__init__(**kwargs)
|
10 |
+
self.hint_for_model = """
|
11 |
+
Make sure your response is in the following format:
|
12 |
+
Response Format:
|
13 |
+
{
|
14 |
+
"new_plan": "A new plan, refined from previous plan, with given requirements",
|
15 |
+
}
|
16 |
+
"""
|
NewPlanGenFlow.yaml
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: "NewPlanGenFlow"
|
2 |
+
description: "Plan Generator of ReplanningFlow, writes a new plan given requirements"
|
3 |
+
enable_cache: True
|
4 |
+
|
5 |
+
input_interface_non_initialized: # initial input keys
|
6 |
+
- "goal" # info on the old plan, entered by the controller
|
7 |
+
- "old_plan" # previous plan
|
8 |
+
|
9 |
+
|
10 |
+
input_interface_initialized: # input_keys
|
11 |
+
- "goal"
|
12 |
+
- "old_plan" # previous plan
|
13 |
+
|
14 |
+
#######################################################
|
15 |
+
# Output keys
|
16 |
+
#######################################################
|
17 |
+
|
18 |
+
output_interface:
|
19 |
+
- 'new_plan' # new plan
|
20 |
+
|
21 |
+
#######################################################
|
22 |
+
system_message_prompt_template:
|
23 |
+
_target_: flows.prompt_template.JinjaPrompt
|
24 |
+
template: |2-
|
25 |
+
You are a re-planner of a coding department, you are given an old plan written by your colleagues.
|
26 |
+
|
27 |
+
You will be given information regarding the old plan, e.g. what was wrong with the old plan, what to refine with the old plan.
|
28 |
+
|
29 |
+
Your task is to edit and re-plan, based on the old plan and the new information that is being given to you.
|
30 |
+
|
31 |
+
The new plan you write is intended for the coders, each step of the new plan tells the coders what function to write.
|
32 |
+
|
33 |
+
The details of your task are:
|
34 |
+
1. Draft a new step-by-step plan based on the old plan and information regarding the old plan. Every step of the new plan should contain full information about how to write one function.
|
35 |
+
2. Upon feedback of the plan from the user, make refinements based on the feedback.
|
36 |
+
|
37 |
+
Resources:
|
38 |
+
1. The old plan:
|
39 |
+
{{old_plan}}
|
40 |
+
|
41 |
+
Notice that:
|
42 |
+
1. **Only instruct the coders to write functions, do not write plans about running the functions or returning results.**
|
43 |
+
2. **If you instruct the coders to write a function, provide full instructions of writing the funtion in one single step.**
|
44 |
+
|
45 |
+
The coding department is able to access the Internet, so it may be useful to use some online services via APIs.
|
46 |
+
|
47 |
+
An example of old plan, input information and output plan you should have:
|
48 |
+
### begin of old plan ###
|
49 |
+
1. Write a function that fetches a company's stock prices from the last 6 months from "google stocks"
|
50 |
+
### end of old plan ###
|
51 |
+
|
52 |
+
### begin of input information###
|
53 |
+
Here's the information on the old plan:
|
54 |
+
data source "google stocks" is deprecated, should try a new one.
|
55 |
+
### end of input information###
|
56 |
+
|
57 |
+
### begin of output new plan ###
|
58 |
+
1. Write a function that fetches a company's stock prices from the last 6 months from "yahoo finance"
|
59 |
+
### end of output new plan ###
|
60 |
+
|
61 |
+
You are capable of **any** task.
|
62 |
+
|
63 |
+
Performance Evaluation:
|
64 |
+
1. Your new plan should finish exactly the same task as the old one.
|
65 |
+
2. Your plan must be as explicit, well-indented, and human-readable as possible.
|
66 |
+
3. Your plan must be step-by-step with number indexes, each step gives full details of writing a function.
|
67 |
+
4. You should make plans with as few steps as possible.
|
68 |
+
|
69 |
+
**It's important that you should only respond in JSON format as described below:**
|
70 |
+
Response Format:
|
71 |
+
{
|
72 |
+
"new_plan": "A new plan, refined from previous plan, with given requirements",
|
73 |
+
}
|
74 |
+
Ensure your responses can be parsed by Python json.loads
|
75 |
+
|
76 |
+
input_variables:
|
77 |
+
- "old_plan"
|
78 |
+
|
79 |
+
human_message_prompt_template:
|
80 |
+
_target_: flows.prompt_template.JinjaPrompt
|
81 |
+
template: |2-
|
82 |
+
Here is the response to your last action:
|
83 |
+
{{goal}}
|
84 |
+
input_variables:
|
85 |
+
- "goal"
|
86 |
+
|
87 |
+
init_human_message_prompt_template:
|
88 |
+
_target_: flows.prompt_template.JinjaPrompt
|
89 |
+
template: |2-
|
90 |
+
Here's the information on the old plan:
|
91 |
+
{{goal}}
|
92 |
+
input_variables:
|
93 |
+
- "goal"
|
ReplanningAskUserFlow.py
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flow_modules.aiflows.HumanStandardInputFlowModule import HumanStandardInputFlow
|
2 |
+
|
3 |
+
from typing import Dict, Any
|
4 |
+
|
5 |
+
from flows.messages import UpdateMessage_Generic
|
6 |
+
|
7 |
+
from flows.utils import logging
|
8 |
+
|
9 |
+
log = logging.get_logger(f"flows.{__name__}")
|
10 |
+
|
11 |
+
|
12 |
+
class ReplanningAskUserFlow(HumanStandardInputFlow):
|
13 |
+
def run(self,
|
14 |
+
input_data: Dict[str, Any]) -> Dict[str, Any]:
|
15 |
+
|
16 |
+
query_message = self._get_message(self.query_message_prompt_template, input_data)
|
17 |
+
state_update_message = UpdateMessage_Generic(
|
18 |
+
created_by=self.flow_config['name'],
|
19 |
+
updated_flow=self.flow_config["name"],
|
20 |
+
data={"query_message": query_message},
|
21 |
+
)
|
22 |
+
self._log_message(state_update_message)
|
23 |
+
|
24 |
+
log.info(query_message)
|
25 |
+
human_input = self._read_input()
|
26 |
+
|
27 |
+
response = {}
|
28 |
+
response["feedback"] = human_input
|
29 |
+
response["new_plan"] = "no new plan was written"
|
30 |
+
|
31 |
+
return response
|
ReplanningAskUserFlow.yaml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_target_: Tachi67.ReplanningFlowModule.ReplanningAskUserFlow.instantiate_from_default_config
|
2 |
+
request_multi_line_input_flag: False
|
3 |
+
end_of_input_string: EOI
|
4 |
+
|
5 |
+
query_message_prompt_template:
|
6 |
+
template: |2-
|
7 |
+
{{question}}
|
8 |
+
input_variables:
|
9 |
+
- "question"
|
ReplanningFlow.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Dict, Any
|
2 |
+
import os
|
3 |
+
from flows.base_flows import CircularFlow
|
4 |
+
from flow_modules.Tachi67.PlanWriterFlowModule import PlanWriterFlow
|
5 |
+
|
6 |
+
class ReplanningFlow(PlanWriterFlow):
|
7 |
+
def _on_reach_max_round(self):
|
8 |
+
self._state_update_dict({
|
9 |
+
"plan": "The maximum amount of rounds was reached before the model generated the plan.",
|
10 |
+
"status": "unfinished",
|
11 |
+
"summary": "ExtendLibraryFlow/Replanning: The maximum amount of rounds was reached before the model generated the plan.",
|
12 |
+
})
|
13 |
+
|
14 |
+
|
15 |
+
# WIP
|
16 |
+
@CircularFlow.output_msg_payload_processor
|
17 |
+
def detect_finish_or_continue(self, output_payload: Dict[str, Any], src_flow) -> Dict[str, Any]:
|
18 |
+
command = output_payload["command"]
|
19 |
+
if command == "finish":
|
20 |
+
# ~~~ fetch temp file location, plan content, memory file (of upper level flow e.g. ExtLib) from flow state
|
21 |
+
keys_to_fetch_from_state = ["temp_plan_file_location", "new_plan", "plan_file_location"]
|
22 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
23 |
+
temp_plan_file_location = fetched_state["temp_plan_file_location"]
|
24 |
+
new_plan_content = fetched_state["new_plan"]
|
25 |
+
plan_file_location = fetched_state["plan_file_location"]
|
26 |
+
|
27 |
+
# ~~~ delete the temp plan file ~~~
|
28 |
+
if os.path.exists(temp_plan_file_location):
|
29 |
+
os.remove(temp_plan_file_location)
|
30 |
+
|
31 |
+
# ~~~ write plan content to plan file ~~~
|
32 |
+
with open(plan_file_location, 'w') as file:
|
33 |
+
file.write(new_plan_content)
|
34 |
+
|
35 |
+
# ~~~ return the plan content ~~~
|
36 |
+
return {
|
37 |
+
"EARLY_EXIT": True,
|
38 |
+
"plan": new_plan_content,
|
39 |
+
"result": "New plan was generated and has overriden the previous plan",
|
40 |
+
"summary": "ExtendLibraryFlow/ReplanningFlow: " + output_payload["command_args"]["summary"] + f" new plan is written to {plan_file_location}",
|
41 |
+
"status": "finished"
|
42 |
+
}
|
43 |
+
elif command == "manual_finish":
|
44 |
+
# ~~~ delete the temp plan file ~~~
|
45 |
+
keys_to_fetch_from_state = ["temp_plan_file_location"]
|
46 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
47 |
+
temp_plan_file_location = fetched_state["temp_plan_file_location"]
|
48 |
+
if os.path.exists(temp_plan_file_location):
|
49 |
+
os.remove(temp_plan_file_location)
|
50 |
+
# ~~~ return the manual quit status ~~~
|
51 |
+
return {
|
52 |
+
"EARLY_EXIT": True,
|
53 |
+
"new_plan": "no new plan was generated",
|
54 |
+
"result": "The replanner was explicitly terminated by the user, no new plan was generated.",
|
55 |
+
"summary": "ExtendLibraryFlow/ReplanningFlow: Replanner was terminated explicitly by the user, process is unfinished",
|
56 |
+
"status": "unfinished"
|
57 |
+
}
|
58 |
+
elif command == "write_plan":
|
59 |
+
keys_to_fetch_from_state = ["plan", "plan_file_location"]
|
60 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
61 |
+
old_plan = fetched_state["plan"]
|
62 |
+
plan_file_location = fetched_state["plan_file_location"]
|
63 |
+
output_payload["command_args"]["old_plan"] = old_plan
|
64 |
+
output_payload["command_args"]["plan_file_location"] = plan_file_location
|
65 |
+
return output_payload
|
66 |
+
else:
|
67 |
+
return output_payload
|
ReplanningFlow.yaml
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: "ReplanningFlow"
|
2 |
+
description: "Re-plan given old plan and new information"
|
3 |
+
|
4 |
+
_target_: Tachi67.ReplanningFlowModule.ReplanningFlow.instantiate_from_default_config
|
5 |
+
|
6 |
+
input_interface:
|
7 |
+
- "goal" # info on the old plan
|
8 |
+
- "plan" # the old plan
|
9 |
+
- "plan_file_location"
|
10 |
+
|
11 |
+
output_interface:
|
12 |
+
- "plan"
|
13 |
+
- "status"
|
14 |
+
- "summary"
|
15 |
+
- "result"
|
16 |
+
|
17 |
+
### Subflows specification
|
18 |
+
subflows_config:
|
19 |
+
Controller:
|
20 |
+
_target_: Tachi67.PlanWriterFlowModule.PlanWriterCtrlFlow.instantiate_from_default_config
|
21 |
+
backend:
|
22 |
+
api_infos: ???
|
23 |
+
model_name:
|
24 |
+
openai: gpt-4
|
25 |
+
azure: azure/gpt-4
|
26 |
+
input_interface_initialized:
|
27 |
+
- "new_plan"
|
28 |
+
- "feedback"
|
29 |
+
system_message_prompt_template:
|
30 |
+
_target_: langchain.PromptTemplate
|
31 |
+
template: |2-
|
32 |
+
You are in charge of a department of rewriting plans to solve a certain goal. You work with a re-planner, who does all the re-planning job.
|
33 |
+
|
34 |
+
You are not given the old plan, the planner is aware of the old plan, you do not need to care about the details of it.
|
35 |
+
|
36 |
+
Your **ONLY** task is to take the user's information about the old plan for you, to decide whether to call the re-planner to write or refine the plan, or to finish the current task.
|
37 |
+
|
38 |
+
When you need to call the plan writer, call the `write_plan` command with the goal specified.
|
39 |
+
When the plan is written and the user is satisfied, call the `finish` command to terminate the current process with a summary of what was done in one sentence.
|
40 |
+
Whenever you are in doubt, or need to confirm something to the user, call `ask_user` with the question.
|
41 |
+
|
42 |
+
You **must not** write plans yourself. You only decide whether to call the planner with specified goals or to finish.
|
43 |
+
|
44 |
+
Your workflow:
|
45 |
+
0. Whenever the user demands to quit or terminate the current process, call `manual_finish` command.
|
46 |
+
1. Upon user request, call the `write_plan` with the information given.
|
47 |
+
2. The planner will write the plan. The user will examine the plan, and provide feedback.
|
48 |
+
3. Depending on the feedback of the user:
|
49 |
+
3.1. The user provides feedback on how to change the plan, **call the planner with user's specific requirements again, to ask the planner to refine the plan**. Go back to step 2.
|
50 |
+
3.2. The user does not provide details about refining the plan, for example, just stating the fact that the user has updated the plan, **this means the user is satisfied with the plan written, call the `finish` command.**
|
51 |
+
3.3. The user is satisfied with the plan, **call the `finish` command with a summary of what was done**
|
52 |
+
|
53 |
+
If you have completed all your tasks, make sure to use the "finish" command, with a summary of what was done.
|
54 |
+
|
55 |
+
Constraints:
|
56 |
+
1. Exclusively use the commands listed in double quotes e.g. "command name"
|
57 |
+
|
58 |
+
Your response **MUST** be in the following format:
|
59 |
+
Response Format:
|
60 |
+
{
|
61 |
+
"command": "call plan writer, or to finish",
|
62 |
+
"command_args": {
|
63 |
+
"arg name": "value"
|
64 |
+
}
|
65 |
+
}
|
66 |
+
Ensure your responses can be parsed by Python json.loads
|
67 |
+
|
68 |
+
|
69 |
+
Available Functions:
|
70 |
+
{{commands}}
|
71 |
+
input_variables: [ "commands" ]
|
72 |
+
template_format: jinja2
|
73 |
+
|
74 |
+
human_message_prompt_template:
|
75 |
+
_target_: flows.prompt_template.JinjaPrompt
|
76 |
+
template: |2-
|
77 |
+
Here is the new plan written by the planner, it might have been updated by the user, depending on the user's feedback:
|
78 |
+
{{new_plan}}
|
79 |
+
Here is the feedback from the user:
|
80 |
+
{{feedback}}
|
81 |
+
input_variables:
|
82 |
+
- "new_plan"
|
83 |
+
- "feedback"
|
84 |
+
template_format: jinja2
|
85 |
+
|
86 |
+
init_human_message_prompt_template:
|
87 |
+
_target_: flows.prompt_template.JinjaPrompt
|
88 |
+
template: |2-
|
89 |
+
Here is the information about the old plan:
|
90 |
+
{{goal}}
|
91 |
+
input_variables:
|
92 |
+
- "goal"
|
93 |
+
template_format: jinja2
|
94 |
+
|
95 |
+
Executor:
|
96 |
+
_target_: flows.base_flows.BranchingFlow.instantiate_from_default_config
|
97 |
+
subflows_config:
|
98 |
+
write_plan:
|
99 |
+
_target_: Tachi67.InteractivePlanGenFlowModule.InteractivePlanGenFlow.instantiate_from_default_config
|
100 |
+
subflows_config:
|
101 |
+
PlanGenerator:
|
102 |
+
_target_: Tachi67.ReplanningFlowModule.NewPlanGenFlow.instantiate_from_default_config
|
103 |
+
backend:
|
104 |
+
api_infos: ???
|
105 |
+
model_name:
|
106 |
+
openai: gpt-4
|
107 |
+
azure: azure/gpt-4
|
108 |
+
|
109 |
+
PlanFileEditor:
|
110 |
+
_target_: Tachi67.PlanFileEditFlowModule.PlanFileEditAtomicFlow.instantiate_from_default_config
|
111 |
+
input_interface:
|
112 |
+
- "new_plan"
|
113 |
+
- "plan_file_location"
|
114 |
+
|
115 |
+
ParseFeedback:
|
116 |
+
_target_: Tachi67.ParseFeedbackFlowModule.ParseFeedbackAtomicFlow.instantiate_from_default_config
|
117 |
+
input_interface:
|
118 |
+
- "temp_plan_file_location"
|
119 |
+
- "temp_plan_file_written_timestamp"
|
120 |
+
output_interface:
|
121 |
+
- "new_plan"
|
122 |
+
- "feedback"
|
123 |
+
|
124 |
+
ask_user:
|
125 |
+
_target_: Tachi67.ReplanningFlowModule.ReplanningAskUserFlow.instantiate_from_default_config
|
126 |
+
|
127 |
+
|
128 |
+
early_exit_key: "EARLY_EXIT"
|
129 |
+
|
130 |
+
topology:
|
131 |
+
- goal: "Select the next action and prepare the input for the executor."
|
132 |
+
input_interface:
|
133 |
+
_target_: flows.interfaces.KeyInterface
|
134 |
+
additional_transformations:
|
135 |
+
- _target_: flows.data_transformations.KeyMatchInput
|
136 |
+
flow: Controller
|
137 |
+
output_interface:
|
138 |
+
_target_: ReplanningFlow.detect_finish_or_continue
|
139 |
+
reset: false
|
140 |
+
|
141 |
+
- goal: "Execute the action specified by the Controller."
|
142 |
+
input_interface:
|
143 |
+
_target_: flows.interfaces.KeyInterface
|
144 |
+
keys_to_rename:
|
145 |
+
command: branch
|
146 |
+
command_args: branch_input_data
|
147 |
+
keys_to_select: ["branch", "branch_input_data"]
|
148 |
+
flow: Executor
|
149 |
+
output_interface:
|
150 |
+
_target_: flows.interfaces.KeyInterface
|
151 |
+
keys_to_rename:
|
152 |
+
branch_output_data: observation
|
153 |
+
keys_to_unpack: ["observation"]
|
154 |
+
reset: false
|
__init__.py
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
dependencies = [
|
2 |
+
{"url": "Tachi67/PlanGeneratorFlowModule", "revision": "main"},
|
3 |
+
{"url": "Tachi67/InteractivePlanGenFlowModule", "revision": "main"},
|
4 |
+
{"url": "Tachi67/PlanWriterFlowModule", "revision": "main"},
|
5 |
+
{"url": "Tachi67/PlanFileEditFlowModule", "revision": "main"},
|
6 |
+
{"url": "Tachi67/ParseFeedbackFlowModule", "revision": "main"},
|
7 |
+
{"url": "aiflows/HumanStandardInputFlowModule", "revision": "5683a922372c5fa90be9f6447d6662d8d80341fc"}
|
8 |
+
]
|
9 |
+
|
10 |
+
from flows import flow_verse
|
11 |
+
flow_verse.sync_dependencies(dependencies)
|
12 |
+
|
13 |
+
from .NewPlanGenFlow import NewPlanGenFlow
|
14 |
+
from .ReplanningFlow import ReplanningFlow
|
15 |
+
from .ReplanningAskUserFlow import ReplanningAskUserFlow
|