Upload 15 files
Browse files- Controller_JarvisFlow.py +111 -0
- Controller_JarvisFlow.yaml +148 -0
- CtrlExMem_JarvisFlow.py +47 -0
- CtrlExMem_JarvisFlow.yaml +219 -0
- FinalAns_Jarvis.py +32 -0
- FinalAns_Jarvis.yaml +9 -0
- IntermediateAns_Jarvis.py +32 -0
- IntermediateAns_Jarvis.yaml +9 -0
- JarvisFlow.py +4 -0
- JarvisFlow.yaml +182 -0
- Planner_JarvisFlow.py +54 -0
- Planner_JarvisFlow.yaml +115 -0
- UpdatePlanAtomicFlow.py +30 -0
- UpdatePlanAtomicFlow.yaml +9 -0
- __init__.py +0 -0
Controller_JarvisFlow.py
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
from copy import deepcopy
|
3 |
+
from typing import Any, Dict, List
|
4 |
+
|
5 |
+
from flow_modules.aiflows.ChatFlowModule import ChatAtomicFlow
|
6 |
+
|
7 |
+
|
8 |
+
from dataclasses import dataclass
|
9 |
+
|
10 |
+
|
11 |
+
@dataclass
|
12 |
+
class Command:
|
13 |
+
name: str
|
14 |
+
description: str
|
15 |
+
input_args: List[str]
|
16 |
+
|
17 |
+
# TODO: controller should be generalized
|
18 |
+
class Controller_JarvisFlow(ChatAtomicFlow):
|
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),
|
26 |
+
plan="no plans yet",
|
27 |
+
plan_file_location="no plan file location yet",
|
28 |
+
logs="no logs yet",
|
29 |
+
)
|
30 |
+
self.hint_for_model = """
|
31 |
+
Make sure your response is in the following format:
|
32 |
+
Response Format:
|
33 |
+
{
|
34 |
+
"command": "call one of the subordinates",
|
35 |
+
"command_args": {
|
36 |
+
"arg name": "value"
|
37 |
+
}
|
38 |
+
}
|
39 |
+
"""
|
40 |
+
|
41 |
+
def _get_content_file_location(self, input_data, content_name):
|
42 |
+
# get the location of the file that contains the content: plan, logs, code_library
|
43 |
+
assert "memory_files" in input_data, "memory_files not passed to Jarvis/Controller"
|
44 |
+
assert content_name in input_data["memory_files"], f"{content_name} not in memory files"
|
45 |
+
return input_data["memory_files"][content_name]
|
46 |
+
|
47 |
+
def _get_content(self, input_data, content_name):
|
48 |
+
# get the content of the file that contains the content: plan, logs, code_library
|
49 |
+
assert content_name in input_data, f"{content_name} not passed to Jarvis/Controller"
|
50 |
+
content = input_data[content_name]
|
51 |
+
if len(content) == 0:
|
52 |
+
content = f'No {content_name} yet'
|
53 |
+
return content
|
54 |
+
@staticmethod
|
55 |
+
def _build_commands_manual(commands: List[Command]) -> str:
|
56 |
+
ret = ""
|
57 |
+
for i, command in enumerate(commands):
|
58 |
+
command_input_json_schema = json.dumps(
|
59 |
+
{input_arg: f"YOUR_{input_arg.upper()}" for input_arg in command.input_args})
|
60 |
+
ret += f"{i + 1}. {command.name}: {command.description} Input arguments (given in the JSON schema): {command_input_json_schema}\n"
|
61 |
+
return ret
|
62 |
+
|
63 |
+
|
64 |
+
@classmethod
|
65 |
+
def instantiate_from_config(cls, config):
|
66 |
+
flow_config = deepcopy(config)
|
67 |
+
|
68 |
+
kwargs = {"flow_config": flow_config}
|
69 |
+
|
70 |
+
# ~~~ Set up prompts ~~~
|
71 |
+
kwargs.update(cls._set_up_prompts(flow_config))
|
72 |
+
|
73 |
+
# ~~~Set up backend ~~~
|
74 |
+
kwargs.update(cls._set_up_backend(flow_config))
|
75 |
+
|
76 |
+
# ~~~ Set up commands ~~~
|
77 |
+
commands = flow_config["commands"]
|
78 |
+
commands = [
|
79 |
+
Command(name, command_conf["description"], command_conf["input_args"]) for name, command_conf in
|
80 |
+
commands.items()
|
81 |
+
]
|
82 |
+
kwargs.update({"commands": commands})
|
83 |
+
|
84 |
+
# ~~~ Instantiate flow ~~~
|
85 |
+
return cls(**kwargs)
|
86 |
+
|
87 |
+
def _update_prompts_and_input(self, input_data: Dict[str, Any]):
|
88 |
+
if 'goal' in input_data:
|
89 |
+
input_data['goal'] += self.hint_for_model
|
90 |
+
if 'result' in input_data:
|
91 |
+
input_data['result'] += self.hint_for_model
|
92 |
+
plan_file_location = self._get_content_file_location(input_data, "plan")
|
93 |
+
plan_content = self._get_content(input_data, "plan")
|
94 |
+
logs_content = self._get_content(input_data, "logs")
|
95 |
+
self.system_message_prompt_template = self.system_message_prompt_template.partial(
|
96 |
+
plan_file_location=plan_file_location,
|
97 |
+
plan=plan_content,
|
98 |
+
logs=logs_content
|
99 |
+
)
|
100 |
+
|
101 |
+
def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
|
102 |
+
self._update_prompts_and_input(input_data)
|
103 |
+
api_output = super().run(input_data)["api_output"].strip()
|
104 |
+
try:
|
105 |
+
response = json.loads(api_output)
|
106 |
+
return response
|
107 |
+
except json.decoder.JSONDecodeError:
|
108 |
+
new_input_data = input_data.copy()
|
109 |
+
new_input_data['result'] = "The previous respond cannot be parsed with json.loads. Make sure your next response is in JSON format."
|
110 |
+
new_api_output = super().run(new_input_data)["api_output"].strip()
|
111 |
+
return json.loads(new_api_output)
|
Controller_JarvisFlow.yaml
ADDED
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_target_: Tachi67.JarvisFlowModule.Controller_JarvisFlow.instantiate_from_default_config
|
2 |
+
name: "ControllerFlow_JarvisFlow"
|
3 |
+
description: "Proposes the next action to take towards achieving the goal, and prepares the input for the branching flow"
|
4 |
+
enable_cache: True
|
5 |
+
|
6 |
+
#######################################################
|
7 |
+
# Input keys
|
8 |
+
#######################################################
|
9 |
+
|
10 |
+
input_interface_non_initialized: # initial input keys
|
11 |
+
- "goal"
|
12 |
+
- "memory_files"
|
13 |
+
- "plan"
|
14 |
+
- "logs"
|
15 |
+
|
16 |
+
input_interface_initialized:
|
17 |
+
- "result"
|
18 |
+
- "memory_files"
|
19 |
+
- "plan"
|
20 |
+
- "logs"
|
21 |
+
|
22 |
+
#######################################################
|
23 |
+
# Output keys
|
24 |
+
#######################################################
|
25 |
+
|
26 |
+
output_interface:
|
27 |
+
- 'command'
|
28 |
+
- 'command_args'
|
29 |
+
|
30 |
+
backend:
|
31 |
+
api_infos: ???
|
32 |
+
model_name:
|
33 |
+
openai: gpt-4
|
34 |
+
azure: azure/gpt-4
|
35 |
+
|
36 |
+
commands:
|
37 |
+
call_coder:
|
38 |
+
description: "Instruct the coder to write and run code to finish your given goal."
|
39 |
+
input_args: [ "goal" ]
|
40 |
+
re_plan:
|
41 |
+
description: "When something is wrong with current plan, draft another plan based on the old plan and information about why it's bad or how to refine it."
|
42 |
+
input_args: [ "goal" ]
|
43 |
+
finish:
|
44 |
+
description: "Signal that the objective has been satisfied, return the summary of what was done"
|
45 |
+
input_args: [ "summary" ]
|
46 |
+
manual_finish:
|
47 |
+
description: "The user demands to quit and terminate the current process"
|
48 |
+
input_args: [ ]
|
49 |
+
ask_user:
|
50 |
+
description: "Ask user a question for confirmation or assistance"
|
51 |
+
input_args: [ "question" ]
|
52 |
+
update_plan:
|
53 |
+
description: "When one step of the plan is done, pass the updated plan to edit plan file and override current plan"
|
54 |
+
input_args: [ "updated_plan" ]
|
55 |
+
intermediate_answer:
|
56 |
+
description: "When one step of the plan is done, pass the result from the step as an intermediate answer to the user"
|
57 |
+
input_args: [ "answer" ]
|
58 |
+
final_answer:
|
59 |
+
description: "When the goal is achieved, pass the result from the goal as a final answer to the user"
|
60 |
+
input_args: [ "answer" ]
|
61 |
+
|
62 |
+
|
63 |
+
system_message_prompt_template:
|
64 |
+
_target_: langchain.PromptTemplate
|
65 |
+
template: |2-
|
66 |
+
Your department is in charge of achieving a particular goal by writing and running code. You are the leader of the department.
|
67 |
+
|
68 |
+
You work with several subordinated, they will be in charge of the specific tasks, including writing and running code to achieve a goal given specifically by you, re-planning, etc.
|
69 |
+
|
70 |
+
To call one of the subordinates, you need to call the corresponding command with necessary arguments, here are the commands and their descriptions:
|
71 |
+
{{commands}}
|
72 |
+
|
73 |
+
You are given a step-by-step plan to finish the goal, **make sure you follow the plan**, **notice that, if you are informed that the plan is overriden, this plan is the new plan you should stick to.** The plan is stored at {{plan_file_location}}. Here is the plan:
|
74 |
+
{{plan}}
|
75 |
+
|
76 |
+
You should execute the plan step-by-step, for each step, you should do the following workflows:
|
77 |
+
0.1 Whenever the user demands to quit or terminate the current process, call `manual_finish` command.
|
78 |
+
0.2 Whenever in doubt, or you have something to ask, or confirm to the user, call `ask_user` with your question.
|
79 |
+
0.3 During the execution of the plan, if something goes wrong, call the `re_plan` with detailed information about what was wrong.
|
80 |
+
1. If the current step of plan can be achieved by writing and running code, call `call_coder` with the goal of the current step of plan.
|
81 |
+
2. Whenever you have done one step of the plan, do the following:
|
82 |
+
2.1 Reflect on what plan you are having right now.
|
83 |
+
2.2 Reflect on which step of the plan you just finished.
|
84 |
+
2.3 Generate a plan, **it is exactly the same as the plan you have now, but with the current step of plan marked as done**
|
85 |
+
2.4 Call `update_plan` with the plan you just generated.
|
86 |
+
3. After you finish one step of the plan and have called `update_plan`, call `intermediate_answer` with the result of the step you just finished.
|
87 |
+
4. The user will provide you with feedback on the last step executed, react accordingly.
|
88 |
+
5. If the user is happy with the intermediate result, proceed to the next step of the plan, go back to workflow 1.
|
89 |
+
5. When every step of the plan is done:
|
90 |
+
5.1 Call `final_answer` with the result of the goal.
|
91 |
+
5.2 React to the user's feedback, if the user is not happy, you may want to re-plan or give new instructions to the coder.
|
92 |
+
5.3 If the user is happy, call `finish` with a summary of what was done throughout the process.
|
93 |
+
|
94 |
+
**You MUST call `update_plan` whenever you realize one step of the plan is done.**
|
95 |
+
**You MUST call `finish` whenever everything is done and the user is happy.**
|
96 |
+
|
97 |
+
Here is an example of execution:
|
98 |
+
### Beginning of an example execution: ###
|
99 |
+
Plan: 1. Download the weather data from Paris on 19. Dec. 2021. 2. Send the weather data to an email address. 3. Give a final answer.
|
100 |
+
Your actions:
|
101 |
+
1. Call `call_coder` with the goal of the first step of the plan. Code is written and run, the weather data is downloaded.
|
102 |
+
2. You call `update_plan` with the plan you just generated, it is exactly the same as the plan you have now, but with the current step of plan marked as done.
|
103 |
+
3. You call `intermediate_answer` with the result of the step you just finished.
|
104 |
+
4. The user is happy with the intermediate result, you proceed to the next step of the plan.
|
105 |
+
5. Call `call_coder` with the goal of the second step of the plan. Code is written and run, the weather data is sent to an email address.
|
106 |
+
6. You call `update_plan` with the plan you just generated, it is exactly the same as the plan you have now, but with the current step of plan marked as done.
|
107 |
+
7. You call `intermediate_answer` with the result of the step you just finished.
|
108 |
+
8. The user is happy with the intermediate result, you proceed to the next step of the plan.
|
109 |
+
9. Call `final_answer` with the result of the goal.
|
110 |
+
10. The user is happy with the final result, you call `finish` with a summary of what was done throughout the process.
|
111 |
+
### End of an example of execution ###
|
112 |
+
|
113 |
+
Here is a list of history actions you have taken, for your reference:
|
114 |
+
{{logs}}
|
115 |
+
|
116 |
+
Constraints:
|
117 |
+
1. Exclusively use the commands listed in double quotes e.g. "command name"
|
118 |
+
|
119 |
+
Your response **MUST** be in the following format:
|
120 |
+
Response Format:
|
121 |
+
{
|
122 |
+
"command": "call one of the subordinates",
|
123 |
+
"command_args": {
|
124 |
+
"arg name": "value"
|
125 |
+
}
|
126 |
+
}
|
127 |
+
Ensure your responses can be parsed by Python json.loads
|
128 |
+
|
129 |
+
input_variables: ["commands", "plan", "logs", "plan_file_location"]
|
130 |
+
template_format: jinja2
|
131 |
+
|
132 |
+
human_message_prompt_template:
|
133 |
+
_target_: flows.prompt_template.JinjaPrompt
|
134 |
+
template: |2-
|
135 |
+
Here is the result of your previous action:
|
136 |
+
{{result}}
|
137 |
+
input_variables:
|
138 |
+
- "result"
|
139 |
+
template_format: jinja2
|
140 |
+
|
141 |
+
init_human_message_prompt_template:
|
142 |
+
_target_: flows.prompt_template.JinjaPrompt
|
143 |
+
template: |2-
|
144 |
+
Here is the goal you need to achieve, follow your plan to finish the goal:
|
145 |
+
{{goal}}
|
146 |
+
input_variables:
|
147 |
+
- "goal"
|
148 |
+
template_format: jinja2
|
CtrlExMem_JarvisFlow.py
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Dict, Any
|
2 |
+
|
3 |
+
from flow_modules.Tachi67.AbstractBossFlowModule import CtrlExMemFlow
|
4 |
+
from flows.base_flows import CircularFlow
|
5 |
+
|
6 |
+
|
7 |
+
class CtrlExMem_JarvisFlow(CtrlExMemFlow):
|
8 |
+
def _on_reach_max_round(self):
|
9 |
+
self._state_update_dict({
|
10 |
+
"result": "the maximum amount of rounds was reached before the Jarvis flow has done the job",
|
11 |
+
"summary": "JarvisFlow: the maximum amount of rounds was reached before the flow has done the job",
|
12 |
+
"status": "unfinished"
|
13 |
+
})
|
14 |
+
|
15 |
+
@CircularFlow.output_msg_payload_processor
|
16 |
+
def detect_finish_or_continue(self, output_payload: Dict[str, Any], src_flow) -> Dict[str, Any]:
|
17 |
+
command = output_payload["command"]
|
18 |
+
if command == "finish":
|
19 |
+
return {
|
20 |
+
"EARLY_EXIT": True,
|
21 |
+
"result": output_payload["command_args"]["summary"],
|
22 |
+
"summary": "Jarvis: " + output_payload["command_args"]["summary"],
|
23 |
+
"status": "finished"
|
24 |
+
}
|
25 |
+
elif command == "manual_finish":
|
26 |
+
# ~~~ return the manual quit status ~~~
|
27 |
+
return {
|
28 |
+
"EARLY_EXIT": True,
|
29 |
+
"result": "JarvisFlow was terminated explicitly by the user, process is unfinished",
|
30 |
+
"summary": "Jarvis: process terminated by the user explicitly, nothing generated",
|
31 |
+
"status": "unfinished"
|
32 |
+
}
|
33 |
+
elif command == "update_plan":
|
34 |
+
keys_to_fetch_from_state = ["memory_files"]
|
35 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
36 |
+
output_payload["command_args"]["memory_files"] = fetched_state["memory_files"]
|
37 |
+
return output_payload
|
38 |
+
|
39 |
+
elif command == "re_plan":
|
40 |
+
keys_to_fetch_from_state = ["plan", "memory_files"]
|
41 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
42 |
+
output_payload["command_args"]["plan_file_location"] = fetched_state["memory_files"]["plan"]
|
43 |
+
output_payload["command_args"]["plan"] = fetched_state["plan"]
|
44 |
+
return output_payload
|
45 |
+
|
46 |
+
else:
|
47 |
+
return output_payload
|
CtrlExMem_JarvisFlow.yaml
ADDED
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_target_: Tachi67.JarvisFlowModule.CtrlExMem_JarvisFlow.instantiate_from_default_config
|
2 |
+
name: "CtrlExMem_JarvisFlow"
|
3 |
+
description: "MemorizedControllerExecutor flow for Jarvis flow"
|
4 |
+
|
5 |
+
input_interface:
|
6 |
+
- "plan"
|
7 |
+
- "logs"
|
8 |
+
- "memory_files"
|
9 |
+
- "goal"
|
10 |
+
|
11 |
+
subflows_config:
|
12 |
+
Controller:
|
13 |
+
_target_: Tachi67.JarvisFlowModule.Controller_JarvisFlow.instantiate_from_default_config
|
14 |
+
backend:
|
15 |
+
api_infos: ???
|
16 |
+
model_name:
|
17 |
+
openai: gpt-4
|
18 |
+
azure: azure/gpt-4
|
19 |
+
Executor:
|
20 |
+
_target_: flows.base_flows.BranchingFlow.instantiate_from_default_config
|
21 |
+
subflows_config:
|
22 |
+
call_coder:
|
23 |
+
_target_: Tachi67.CoderFlowModule.CoderFlow.instantiate_from_default_config
|
24 |
+
memory_files: ???
|
25 |
+
subflows_config:
|
26 |
+
Planner:
|
27 |
+
_target_: Tachi67.CoderFlowModule.Planner_CoderFlow.instantiate_from_default_config
|
28 |
+
subflows_config:
|
29 |
+
Controller:
|
30 |
+
backend:
|
31 |
+
api_infos: ???
|
32 |
+
model_name:
|
33 |
+
openai: gpt-4
|
34 |
+
azure: azure/gpt-4
|
35 |
+
Executor:
|
36 |
+
subflows_config:
|
37 |
+
write_plan:
|
38 |
+
subflows_config:
|
39 |
+
PlanGenerator:
|
40 |
+
backend:
|
41 |
+
api_infos: ???
|
42 |
+
model_name:
|
43 |
+
openai: gpt-4
|
44 |
+
azure: azure/gpt-4
|
45 |
+
|
46 |
+
CtrlExMem:
|
47 |
+
subflows_config:
|
48 |
+
Controller:
|
49 |
+
backend:
|
50 |
+
api_infos: ???
|
51 |
+
model_name:
|
52 |
+
openai: gpt-4
|
53 |
+
azure: azure/gpt-4
|
54 |
+
Executor:
|
55 |
+
subflows_config:
|
56 |
+
extend_library:
|
57 |
+
memory_files: ???
|
58 |
+
subflows_config:
|
59 |
+
Planner:
|
60 |
+
subflows_config:
|
61 |
+
Controller:
|
62 |
+
backend:
|
63 |
+
api_infos: ???
|
64 |
+
model_name:
|
65 |
+
openai: gpt-4
|
66 |
+
azure: azure/gpt-4
|
67 |
+
Executor:
|
68 |
+
subflows_config:
|
69 |
+
write_plan:
|
70 |
+
subflows_config:
|
71 |
+
PlanGenerator:
|
72 |
+
backend:
|
73 |
+
api_infos: ???
|
74 |
+
model_name:
|
75 |
+
openai: gpt-4
|
76 |
+
azure: azure/gpt-4
|
77 |
+
CtrlExMem:
|
78 |
+
subflows_config:
|
79 |
+
Controller:
|
80 |
+
backend:
|
81 |
+
api_infos: ???
|
82 |
+
model_name:
|
83 |
+
openai: gpt-4
|
84 |
+
azure: azure/gpt-4
|
85 |
+
Executor:
|
86 |
+
subflows_config:
|
87 |
+
write_code:
|
88 |
+
subflows_config:
|
89 |
+
Controller:
|
90 |
+
backend:
|
91 |
+
api_infos: ???
|
92 |
+
model_name:
|
93 |
+
openai: gpt-4
|
94 |
+
azure: azure/gpt-4
|
95 |
+
Executor:
|
96 |
+
subflows_config:
|
97 |
+
write_code:
|
98 |
+
memory_files: ???
|
99 |
+
subflows_config:
|
100 |
+
CodeGenerator:
|
101 |
+
backend:
|
102 |
+
api_infos: ???
|
103 |
+
model_name:
|
104 |
+
openai: gpt-4
|
105 |
+
azure: azure/gpt-4
|
106 |
+
test:
|
107 |
+
memory_files: ???
|
108 |
+
re_plan:
|
109 |
+
subflows_config:
|
110 |
+
Controller:
|
111 |
+
backend:
|
112 |
+
api_infos: ???
|
113 |
+
model_name:
|
114 |
+
openai: gpt-4
|
115 |
+
azure: azure/gpt-4
|
116 |
+
Executor:
|
117 |
+
subflows_config:
|
118 |
+
write_plan:
|
119 |
+
subflows_config:
|
120 |
+
PlanGenerator:
|
121 |
+
backend:
|
122 |
+
api_infos: ???
|
123 |
+
model_name:
|
124 |
+
openai: gpt-4
|
125 |
+
azure: azure/gpt-4
|
126 |
+
re_plan:
|
127 |
+
subflows_config:
|
128 |
+
Controller:
|
129 |
+
backend:
|
130 |
+
api_infos: ???
|
131 |
+
model_name:
|
132 |
+
openai: gpt-4
|
133 |
+
azure: azure/gpt-4
|
134 |
+
Executor:
|
135 |
+
subflows_config:
|
136 |
+
write_plan:
|
137 |
+
subflows_config:
|
138 |
+
PlanGenerator:
|
139 |
+
backend:
|
140 |
+
api_infos: ???
|
141 |
+
model_name:
|
142 |
+
openai: gpt-4
|
143 |
+
azure: azure/gpt-4
|
144 |
+
ask_user:
|
145 |
+
_target_: Tachi67.ExtendLibraryFlowModule.ExtLibAskUserFlow.instantiate_from_default_config
|
146 |
+
re_plan:
|
147 |
+
_target_: Tachi67.ReplanningFlowModule.ReplanningFlow.instantiate_from_default_config
|
148 |
+
subflows_config:
|
149 |
+
Controller:
|
150 |
+
backend:
|
151 |
+
api_infos: ???
|
152 |
+
model_name:
|
153 |
+
openai: gpt-4
|
154 |
+
azure: azure/gpt-4
|
155 |
+
Executor:
|
156 |
+
subflows_config:
|
157 |
+
write_plan:
|
158 |
+
subflows_config:
|
159 |
+
PlanGenerator:
|
160 |
+
backend:
|
161 |
+
api_infos: ???
|
162 |
+
model_name:
|
163 |
+
openai: gpt-4
|
164 |
+
azure: azure/gpt-4
|
165 |
+
update_plan:
|
166 |
+
_target_: Tachi67.JarvisFlowModule.UpdatePlanAtomicFlow.instantiate_from_default_config
|
167 |
+
intermediate_answer:
|
168 |
+
_target_: Tachi67.JarvisFlowModule.IntermediateAns_Jarvis.instantiate_from_default_config
|
169 |
+
final_answer:
|
170 |
+
_target_: Tachi67.JarvisFlowModule.FinalAns_Jarvis.instantiate_from_default_config
|
171 |
+
|
172 |
+
|
173 |
+
MemoryReading:
|
174 |
+
_target_: Tachi67.MemoryReadingFlowModule.MemoryReadingAtomicFlow.instantiate_from_default_config
|
175 |
+
output_interface:
|
176 |
+
- "plan"
|
177 |
+
- "logs"
|
178 |
+
|
179 |
+
topology:
|
180 |
+
- goal: "Select the next action and prepare the input for the executor."
|
181 |
+
input_interface:
|
182 |
+
_target_: flows.interfaces.KeyInterface
|
183 |
+
additional_transformations:
|
184 |
+
- _target_: flows.data_transformations.KeyMatchInput
|
185 |
+
flow: Controller
|
186 |
+
output_interface:
|
187 |
+
_target_: CtrlExMem_JarvisFlow.detect_finish_or_continue
|
188 |
+
reset: false
|
189 |
+
|
190 |
+
- goal: "Execute the action specified by the Controller."
|
191 |
+
input_interface:
|
192 |
+
_target_: flows.interfaces.KeyInterface
|
193 |
+
keys_to_rename:
|
194 |
+
command: branch
|
195 |
+
command_args: branch_input_data
|
196 |
+
keys_to_select: ["branch", "branch_input_data"]
|
197 |
+
flow: Executor
|
198 |
+
output_interface:
|
199 |
+
_target_: flows.interfaces.KeyInterface
|
200 |
+
keys_to_rename:
|
201 |
+
branch_output_data: observation
|
202 |
+
keys_to_unpack: ["observation"]
|
203 |
+
reset: false
|
204 |
+
|
205 |
+
- goal: "Write memory to memory files"
|
206 |
+
input_interface:
|
207 |
+
_target_: flows.interfaces.KeyInterface
|
208 |
+
additional_transformations:
|
209 |
+
- _target_: flows.data_transformations.KeyMatchInput
|
210 |
+
flow: MemoryWriting
|
211 |
+
reset: false
|
212 |
+
|
213 |
+
- goal: "Read memory from memory files (flow_state)"
|
214 |
+
input_interface:
|
215 |
+
_target_: flows.interfaces.KeyInterface
|
216 |
+
additional_transformations:
|
217 |
+
- _target_: flows.data_transformations.KeyMatchInput
|
218 |
+
flow: MemoryReading
|
219 |
+
reset: false
|
FinalAns_Jarvis.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 FinalAns_Jarvis(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 |
+
answer = input_data["answer"]
|
28 |
+
response = {}
|
29 |
+
response["result"] = human_input
|
30 |
+
response["summary"] = f"Final answer provided: {answer}; feedback of user: {human_input}"
|
31 |
+
|
32 |
+
return response
|
FinalAns_Jarvis.yaml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_target_: Tachi67.JarvisFlowModule.FinalAns_Jarvis.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 |
+
Jarvis has just achieved the goal, here is the final answer: {{answer}}
|
8 |
+
input_variables:
|
9 |
+
- "answer"
|
IntermediateAns_Jarvis.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 IntermediateAns_Jarvis(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 |
+
answer = input_data["answer"]
|
28 |
+
response = {}
|
29 |
+
response["result"] = human_input
|
30 |
+
response["summary"] = f"Intermediate Answer provided: {answer}; feedback of user: {human_input}"
|
31 |
+
|
32 |
+
return response
|
IntermediateAns_Jarvis.yaml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_target_: Tachi67.JarvisFlowModule.IntermediateAns_Jarvis.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 |
+
Jarvis has just finished an intermediate step of execution: {{answer}}
|
8 |
+
input_variables:
|
9 |
+
- "answer"
|
JarvisFlow.py
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flow_modules.Tachi67.AbstractBossFlowModule import AbstractBossFlow
|
2 |
+
|
3 |
+
class JarvisFlow(AbstractBossFlow):
|
4 |
+
pass
|
JarvisFlow.yaml
ADDED
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: JarvisFlow
|
2 |
+
description: Jarvis, an agent with structured llms and tools able to process user requests, write and execute code, with external memory mechanisms.
|
3 |
+
|
4 |
+
target_: Tachi67.JarvisFlowModule.JarvisFlow.instantiate_from_default_config
|
5 |
+
|
6 |
+
memory_files: ???
|
7 |
+
|
8 |
+
subflows_config:
|
9 |
+
MemoryReading:
|
10 |
+
_target_: Tachi67.MemoryReadingFlowModule.MemoryReadingAtomicFlow.instantiate_from_default_config
|
11 |
+
output_interface:
|
12 |
+
- "plan"
|
13 |
+
- "logs"
|
14 |
+
|
15 |
+
Planner:
|
16 |
+
_target_: Tachi67.JarvisFlowModule.Planner_JarvisFlow.instantiate_from_default_config
|
17 |
+
subflows_config:
|
18 |
+
Controller:
|
19 |
+
backend:
|
20 |
+
api_infos: ???
|
21 |
+
model_name:
|
22 |
+
openai: gpt-4
|
23 |
+
azure: azure/gpt-4
|
24 |
+
Executor:
|
25 |
+
subflows_config:
|
26 |
+
write_plan:
|
27 |
+
subflows_config:
|
28 |
+
PlanGenerator:
|
29 |
+
backend:
|
30 |
+
api_infos: ???
|
31 |
+
model_name:
|
32 |
+
openai: gpt-4
|
33 |
+
azure: azure/gpt-4
|
34 |
+
|
35 |
+
CtrlExMem:
|
36 |
+
_target_: Tachi67.JarvisFlowModule.CtrlExMem_JarvisFlow.instantiate_from_default_config
|
37 |
+
subflows_config:
|
38 |
+
Controller:
|
39 |
+
backend:
|
40 |
+
api_infos: ???
|
41 |
+
model_name:
|
42 |
+
openai: gpt-4
|
43 |
+
azure: azure/gpt-4
|
44 |
+
Executor:
|
45 |
+
subflows_config:
|
46 |
+
re_plan:
|
47 |
+
subflows_config:
|
48 |
+
Controller:
|
49 |
+
backend:
|
50 |
+
api_infos: ???
|
51 |
+
model_name:
|
52 |
+
openai: gpt-4
|
53 |
+
azure: azure/gpt-4
|
54 |
+
Executor:
|
55 |
+
subflows_config:
|
56 |
+
write_plan:
|
57 |
+
subflows_config:
|
58 |
+
PlanGenerator:
|
59 |
+
backend:
|
60 |
+
api_infos: ???
|
61 |
+
model_name:
|
62 |
+
openai: gpt-4
|
63 |
+
azure: azure/gpt-4
|
64 |
+
Coder:
|
65 |
+
memory_files: ???
|
66 |
+
subflows_config:
|
67 |
+
Planner:
|
68 |
+
subflows_config:
|
69 |
+
Controller:
|
70 |
+
backend:
|
71 |
+
api_infos: ???
|
72 |
+
model_name:
|
73 |
+
openai: gpt-4
|
74 |
+
azure: azure/gpt-4
|
75 |
+
Executor:
|
76 |
+
subflows_config:
|
77 |
+
write_plan:
|
78 |
+
subflows_config:
|
79 |
+
PlanGenerator:
|
80 |
+
backend:
|
81 |
+
api_infos: ???
|
82 |
+
model_name:
|
83 |
+
openai: gpt-4
|
84 |
+
azure: azure/gpt-4
|
85 |
+
CtrlExMem:
|
86 |
+
subflows_config:
|
87 |
+
Controller:
|
88 |
+
backend:
|
89 |
+
api_infos: ???
|
90 |
+
model_name:
|
91 |
+
openai: gpt-4
|
92 |
+
azure: azure/gpt-4
|
93 |
+
Executor:
|
94 |
+
subflows_config:
|
95 |
+
extend_library:
|
96 |
+
memory_files: ???
|
97 |
+
subflows_config:
|
98 |
+
Planner:
|
99 |
+
subflows_config:
|
100 |
+
Controller:
|
101 |
+
backend:
|
102 |
+
api_infos: ???
|
103 |
+
model_name:
|
104 |
+
openai: gpt-4
|
105 |
+
azure: azure/gpt-4
|
106 |
+
Executor:
|
107 |
+
subflows_config:
|
108 |
+
write_plan:
|
109 |
+
subflows_config:
|
110 |
+
PlanGenerator:
|
111 |
+
backend:
|
112 |
+
api_infos: ???
|
113 |
+
model_name:
|
114 |
+
openai: gpt-4
|
115 |
+
azure: azure/gpt-4
|
116 |
+
CtrlExMem:
|
117 |
+
subflows_config:
|
118 |
+
Controller:
|
119 |
+
backend:
|
120 |
+
api_infos: ???
|
121 |
+
model_name:
|
122 |
+
openai: gpt-4
|
123 |
+
azure: azure/gpt-4
|
124 |
+
Executor:
|
125 |
+
subflows_config:
|
126 |
+
write_code:
|
127 |
+
subflows_config:
|
128 |
+
Controller:
|
129 |
+
backend:
|
130 |
+
api_infos: ???
|
131 |
+
model_name:
|
132 |
+
openai: gpt-4
|
133 |
+
azure: azure/gpt-4
|
134 |
+
Executor:
|
135 |
+
subflows_config:
|
136 |
+
write_code:
|
137 |
+
memory_files: ???
|
138 |
+
subflows_config:
|
139 |
+
CodeGenerator:
|
140 |
+
backend:
|
141 |
+
api_infos: ???
|
142 |
+
model_name:
|
143 |
+
openai: gpt-4
|
144 |
+
azure: azure/gpt-4
|
145 |
+
test:
|
146 |
+
memory_files: ???
|
147 |
+
re_plan:
|
148 |
+
subflows_config:
|
149 |
+
Controller:
|
150 |
+
backend:
|
151 |
+
api_infos: ???
|
152 |
+
model_name:
|
153 |
+
openai: gpt-4
|
154 |
+
azure: azure/gpt-4
|
155 |
+
Executor:
|
156 |
+
subflows_config:
|
157 |
+
write_plan:
|
158 |
+
subflows_config:
|
159 |
+
PlanGenerator:
|
160 |
+
backend:
|
161 |
+
api_infos: ???
|
162 |
+
model_name:
|
163 |
+
openai: gpt-4
|
164 |
+
azure: azure/gpt-4
|
165 |
+
re_plan:
|
166 |
+
subflows_config:
|
167 |
+
Controller:
|
168 |
+
backend:
|
169 |
+
api_infos: ???
|
170 |
+
model_name:
|
171 |
+
openai: gpt-4
|
172 |
+
azure: azure/gpt-4
|
173 |
+
Executor:
|
174 |
+
subflows_config:
|
175 |
+
write_plan:
|
176 |
+
subflows_config:
|
177 |
+
PlanGenerator:
|
178 |
+
backend:
|
179 |
+
api_infos: ???
|
180 |
+
model_name:
|
181 |
+
openai: gpt-4
|
182 |
+
azure: azure/gpt-4
|
Planner_JarvisFlow.py
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Dict, Any
|
2 |
+
import os
|
3 |
+
from flow_modules.Tachi67.PlanWriterFlowModule import PlanWriterFlow
|
4 |
+
from flows.base_flows import CircularFlow
|
5 |
+
|
6 |
+
class Planner_JarvisFlow(PlanWriterFlow):
|
7 |
+
# TODO: generalize this flow to avoid code duplication
|
8 |
+
@CircularFlow.output_msg_payload_processor
|
9 |
+
def detect_finish_or_continue(self, output_payload: Dict[str, Any], src_flow) -> Dict[str, Any]:
|
10 |
+
command = output_payload["command"]
|
11 |
+
if command == "finish":
|
12 |
+
# ~~~ fetch temp file location, plan content, memory file (of upper level flow e.g. ExtLib) from flow state
|
13 |
+
keys_to_fetch_from_state = ["temp_plan_file_location", "plan", "memory_files"]
|
14 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
15 |
+
temp_plan_file_location = fetched_state["temp_plan_file_location"]
|
16 |
+
plan_content = fetched_state["plan"]
|
17 |
+
plan_file_location = fetched_state["memory_files"]["plan"]
|
18 |
+
|
19 |
+
# ~~~ delete the temp plan file ~~~
|
20 |
+
if os.path.exists(temp_plan_file_location):
|
21 |
+
os.remove(temp_plan_file_location)
|
22 |
+
|
23 |
+
# ~~~ write plan content to plan file ~~~
|
24 |
+
with open(plan_file_location, 'w') as file:
|
25 |
+
file.write(plan_content)
|
26 |
+
|
27 |
+
# ~~~ return the plan content ~~~
|
28 |
+
return {
|
29 |
+
"EARLY_EXIT": True,
|
30 |
+
"plan": plan_content,
|
31 |
+
"summary": "Jarvis/PlanWriter: " + output_payload["command_args"]["summary"],
|
32 |
+
"status": "finished"
|
33 |
+
}
|
34 |
+
elif command == "manual_finish":
|
35 |
+
# ~~~ delete the temp plan file ~~~
|
36 |
+
keys_to_fetch_from_state = ["temp_plan_file_location"]
|
37 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
38 |
+
temp_plan_file_location = fetched_state["temp_plan_file_location"]
|
39 |
+
if os.path.exists(temp_plan_file_location):
|
40 |
+
os.remove(temp_plan_file_location)
|
41 |
+
# ~~~ return the manual quit status ~~~
|
42 |
+
return {
|
43 |
+
"EARLY_EXIT": True,
|
44 |
+
"plan": "no plan was generated",
|
45 |
+
"summary": "Jarvis/PlanWriter: PlanWriter was terminated explicitly by the user, process is unfinished",
|
46 |
+
"status": "unfinished"
|
47 |
+
}
|
48 |
+
elif command == "write_plan":
|
49 |
+
keys_to_fetch_from_state = ["memory_files"]
|
50 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
51 |
+
output_payload["command_args"]["plan_file_location"] = fetched_state["memory_files"]["plan"]
|
52 |
+
return output_payload
|
53 |
+
else:
|
54 |
+
return output_payload
|
Planner_JarvisFlow.yaml
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: "Planner/Jarvis"
|
2 |
+
description: "Generates plan with interactions with the user, used for the coder class"
|
3 |
+
|
4 |
+
_target_: Tachi67.JarvisFlowModule.Planner_JarvisFlow.instantiate_from_default_config
|
5 |
+
|
6 |
+
input_interface:
|
7 |
+
- "goal"
|
8 |
+
- "memory_files"
|
9 |
+
|
10 |
+
output_interface:
|
11 |
+
- "plan"
|
12 |
+
- "status"
|
13 |
+
- "summary"
|
14 |
+
|
15 |
+
### Subflows specification
|
16 |
+
subflows_config:
|
17 |
+
Controller:
|
18 |
+
_target_: Tachi67.PlanWriterFlowModule.PlanWriterCtrlFlow.instantiate_from_default_config
|
19 |
+
backend:
|
20 |
+
api_infos: ???
|
21 |
+
model_name:
|
22 |
+
openai: gpt-4
|
23 |
+
azure: azure/gpt-4
|
24 |
+
|
25 |
+
Executor:
|
26 |
+
_target_: flows.base_flows.BranchingFlow.instantiate_from_default_config
|
27 |
+
subflows_config:
|
28 |
+
write_plan:
|
29 |
+
subflows_config:
|
30 |
+
PlanGenerator:
|
31 |
+
backend:
|
32 |
+
api_infos: ???
|
33 |
+
model_name:
|
34 |
+
openai: gpt-4
|
35 |
+
azure: azure/gpt-4
|
36 |
+
system_message_prompt_template:
|
37 |
+
_target_: flows.prompt_template.JinjaPrompt
|
38 |
+
template: |2-
|
39 |
+
You are the planner for Jarvis, an intelligent agent able to achieve goals by writing and running code, you write step-by-step plans for Jarvis to follow and execute.
|
40 |
+
|
41 |
+
Jarvis is capable of:
|
42 |
+
1. Generating and running code, given a goal.
|
43 |
+
2. Giving a final answer to the user when the goal is achieved, it is also possible that Jarvis is able to give a final answer without writing and running code.
|
44 |
+
|
45 |
+
**Your task is: given a goal to achieve, decompose the goal into step-by-step plans for Jarvis, each step of your plan should involve one of the following:
|
46 |
+
1. Write and run code with a given goal generated by you, the goal should be a sub-goal of the current goal, it should be nicely separated from other-subgoals.
|
47 |
+
2. Give a final answer.**
|
48 |
+
|
49 |
+
Here are some criteria you should consider in order to write a good plan:
|
50 |
+
1. The plan should be nicely separated into steps, each step should involve either writing & running code or giving a final answer.
|
51 |
+
2. Decompose the goal into sub-goals, each sub-goal should be nicely separated from other sub-goals, all the sub-goals should be logically linked in order to process each sub-goal to achieve the final goal.
|
52 |
+
|
53 |
+
Performance Evaluation:
|
54 |
+
1. Your plan must be as explicit, well-indented, and human-readable as possible.
|
55 |
+
2. Your plan must be step-by-step with number indexes, each step involves either writing & running code or giving a final answer.
|
56 |
+
3. You should make plans with as few steps as possible.
|
57 |
+
|
58 |
+
|
59 |
+
**Here is an example of a good plan:**
|
60 |
+
Goal: Send an email with the data of the weather in Paris of 19. Dec. 2021 to my friend.
|
61 |
+
Plan:
|
62 |
+
1. Write and run code to get the data of the weather in Paris of 19. Dec. 2021.
|
63 |
+
2. Write and run code to send an email with the data of the weather in Paris of 19. Dec. 2021 to my friend.
|
64 |
+
3. Give a final answer to the user.
|
65 |
+
|
66 |
+
**It's important that you should only respond in JSON format as described below:**
|
67 |
+
Response Format:
|
68 |
+
{
|
69 |
+
"plan": "A well indented string, containing a step-by-step plan to finish the given goal",
|
70 |
+
}
|
71 |
+
Ensure your responses can be parsed by Python json.loads
|
72 |
+
**Make sure that the plan you generate is a well-indented human readable string, with numbered indexes for each step.**
|
73 |
+
|
74 |
+
PlanFileEditor:
|
75 |
+
_target_: Tachi67.PlanFileEditFlowModule.PlanFileEditAtomicFlow.instantiate_from_default_config
|
76 |
+
|
77 |
+
ParseFeedback:
|
78 |
+
_target_: Tachi67.ParseFeedbackFlowModule.ParseFeedbackAtomicFlow.instantiate_from_default_config
|
79 |
+
input_interface:
|
80 |
+
- "temp_plan_file_location"
|
81 |
+
output_interface:
|
82 |
+
- "plan"
|
83 |
+
- "feedback"
|
84 |
+
|
85 |
+
ask_user:
|
86 |
+
_target_: Tachi67.PlanWriterFlowModule.PlanWriterAskUserFlow.instantiate_from_default_config
|
87 |
+
|
88 |
+
|
89 |
+
early_exit_key: "EARLY_EXIT"
|
90 |
+
|
91 |
+
topology:
|
92 |
+
- goal: "Select the next action and prepare the input for the executor."
|
93 |
+
input_interface:
|
94 |
+
_target_: flows.interfaces.KeyInterface
|
95 |
+
additional_transformations:
|
96 |
+
- _target_: flows.data_transformations.KeyMatchInput
|
97 |
+
flow: Controller
|
98 |
+
output_interface:
|
99 |
+
_target_: Planner_JarvisFlow.detect_finish_or_continue
|
100 |
+
reset: false
|
101 |
+
|
102 |
+
- goal: "Execute the action specified by the Controller."
|
103 |
+
input_interface:
|
104 |
+
_target_: flows.interfaces.KeyInterface
|
105 |
+
keys_to_rename:
|
106 |
+
command: branch
|
107 |
+
command_args: branch_input_data
|
108 |
+
keys_to_select: ["branch", "branch_input_data"]
|
109 |
+
flow: Executor
|
110 |
+
output_interface:
|
111 |
+
_target_: flows.interfaces.KeyInterface
|
112 |
+
keys_to_rename:
|
113 |
+
branch_output_data: observation
|
114 |
+
keys_to_unpack: ["observation"]
|
115 |
+
reset: false
|
UpdatePlanAtomicFlow.py
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#TODO: generalize updateplanatomicflow with the one in extendlibrary
|
2 |
+
from typing import Dict, Any
|
3 |
+
from flows.base_flows.atomic import AtomicFlow
|
4 |
+
class UpdatePlanAtomicFlow(AtomicFlow):
|
5 |
+
def _check_input(self, input_data: Dict[str, Any]):
|
6 |
+
assert "memory_files" in input_data, "memory_files not passed to UpdatePlanAtomicFlow.yaml"
|
7 |
+
assert "plan" in input_data["memory_files"], "plan not in memory_files"
|
8 |
+
|
9 |
+
def _call(self, input_data: Dict[str, Any]):
|
10 |
+
try:
|
11 |
+
plan_file_location = input_data["memory_files"]["plan"]
|
12 |
+
plan_to_write = input_data["updated_plan"]
|
13 |
+
with open(plan_file_location, 'w') as file:
|
14 |
+
file.write(plan_to_write + "\n")
|
15 |
+
return {
|
16 |
+
"result": "updated plan saved to the plan file and has overriden the previous plan",
|
17 |
+
"summary": f"Jarvis/UpdatePlanFlow: updated plan saved to {plan_file_location}"
|
18 |
+
}
|
19 |
+
except Exception as e:
|
20 |
+
return {
|
21 |
+
"result": f"Error occurred: {str(e)}",
|
22 |
+
"summary": f"Jarvis/UpdatePlanFlow: error occurred while writing updated plan: {str(e)}"
|
23 |
+
}
|
24 |
+
|
25 |
+
def run(
|
26 |
+
self,
|
27 |
+
input_data: Dict[str, Any]
|
28 |
+
):
|
29 |
+
self._check_input(input_data)
|
30 |
+
return self._call(input_data)
|
UpdatePlanAtomicFlow.yaml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_target_: Tachi67.JarvisFlowModule.UpdatePlanAtomicFlow.instantiate_from_default_config
|
2 |
+
name: "UpdatePlanAtomicFlow"
|
3 |
+
description: "Writes new plan to plan file"
|
4 |
+
|
5 |
+
input_interface:
|
6 |
+
- "updated_plan"
|
7 |
+
|
8 |
+
output_interface:
|
9 |
+
- "result"
|
__init__.py
ADDED
File without changes
|