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
|