Tachi67 commited on
Commit
e9cd8d3
·
1 Parent(s): b881bd2

Upload 14 files

Browse files
CoderFlow.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, Any
2
+ from aiflows.utils import logging
3
+ log = logging.get_logger(__name__)
4
+
5
+ from flow_modules.aiflows.AbstractBossFlowModule import AbstractBossFlow
6
+
7
+ class CoderFlow(AbstractBossFlow):
8
+ """Coder flow is one executor branch of the Jarvis flow. At a higher level, it is a flow that
9
+ writes and runs code given a goal. In the Jarvis flow, the Coder flow in invoked by the controller,
10
+ The Coder flow receives the goal generated by the controller, writes and runs code in an interactive fashion.
11
+
12
+ The Coder flow has the similar structure as the Jarvis flow (inherited from AbstractBossFlow).
13
+
14
+
15
+ *Input Interface (expected input)*
16
+ - `goal` (str): The goal from the caller (source flow, i.e. JarvisFlow)
17
+
18
+
19
+ *Output Interface (expected output)*
20
+ - `result` (str): The result of the flow, the result will be returned to the caller (i.e. JarvisFlow).
21
+ - `summary` (str): The summary of the flow, the summary will be logged into the logs of the caller flow (i.e. JarvisFlow).
22
+
23
+ Typical workflow of Coder:
24
+ 0. JarvisFlow calls Coder with a goal.
25
+ 1. MemoryReading reads plans, logs and code library.
26
+ 2. Planner makes plan based on goal.
27
+ 3. Extend library with the goal given by the controller.
28
+ 4. Run code with code (possibly calls the newly written function) given by the controller.
29
+ 5. Finish and give an answer.
30
+ """
31
+ def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
32
+ """The run function of the Coder flow.
33
+ :param input_data: The input data of the flow.
34
+ :type input_data: Dict[str, Any]
35
+ :return: The output data of the flow.
36
+ :rtype: Dict[str, Any]
37
+ """
38
+ # ~~~ sets the input_data in the flow_state dict ~~~
39
+ self._state_update_dict(update_data=input_data)
40
+
41
+ # ~~~ set the memory file to the flow state ~~~
42
+ self._state_update_dict(update_data={"memory_files": self.memory_files})
43
+
44
+ max_rounds = self.flow_config.get("max_rounds", 1)
45
+ if max_rounds is None:
46
+ log.info(f"Running {self.flow_config['name']} without `max_rounds` until the early exit condition is met.")
47
+
48
+ self._sequential_run(max_rounds=max_rounds)
49
+
50
+ output = self._get_output_from_state()
51
+
52
+ self.reset(full_reset=True, recursive=True, src_flow=self)
53
+
54
+ return output
CoderFlow.yaml ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: CoderFlow
2
+ description: "A flow used to tackle goals with coding in a step-by-step fashion"
3
+
4
+ _target_: flow_modules.aiflows.CoderFlowModule.CoderFlow.instantiate_from_default_config
5
+
6
+ memory_files: ???
7
+
8
+ subflows_config:
9
+ MemoryReading:
10
+ _target_: flow_modules.aiflows.MemoryReadingFlowModule.MemoryReadingAtomicFlow.instantiate_from_default_config
11
+ output_interface:
12
+ - "plan"
13
+ - "logs"
14
+ - "code_library"
15
+
16
+ Planner:
17
+ _target_: flow_modules.aiflows.CoderFlowModule.Planner_CoderFlow.instantiate_from_default_config
18
+ subflows_config:
19
+ Controller:
20
+ backend:
21
+ api_infos: ???
22
+ model_name:
23
+ openai: gpt-4
24
+ azure: azure/gpt-4
25
+ Executor:
26
+ subflows_config:
27
+ write_plan:
28
+ subflows_config:
29
+ PlanGenerator:
30
+ backend:
31
+ api_infos: ???
32
+ model_name:
33
+ openai: gpt-4
34
+ azure: azure/gpt-4
35
+
36
+ CtrlExMem:
37
+ _target_: flow_modules.aiflows.CoderFlowModule.CtrlExMem_CoderFlow.instantiate_from_default_config
38
+ subflows_config:
39
+ Controller:
40
+ backend:
41
+ api_infos: ???
42
+ model_name:
43
+ openai: gpt-4
44
+ azure: azure/gpt-4
45
+ Executor:
46
+ subflows_config:
47
+ extend_library:
48
+ memory_files: ???
49
+ subflows_config:
50
+ Planner:
51
+ subflows_config:
52
+ Controller:
53
+ backend:
54
+ api_infos: ???
55
+ model_name:
56
+ openai: gpt-4
57
+ azure: azure/gpt-4
58
+ Executor:
59
+ subflows_config:
60
+ write_plan:
61
+ subflows_config:
62
+ PlanGenerator:
63
+ backend:
64
+ api_infos: ???
65
+ model_name:
66
+ openai: gpt-4
67
+ azure: azure/gpt-4
68
+ CtrlExMem:
69
+ subflows_config:
70
+ Controller:
71
+ backend:
72
+ api_infos: ???
73
+ model_name:
74
+ openai: gpt-4
75
+ azure: azure/gpt-4
76
+ Executor:
77
+ subflows_config:
78
+ write_code:
79
+ subflows_config:
80
+ Controller:
81
+ backend:
82
+ api_infos: ???
83
+ model_name:
84
+ openai: gpt-4
85
+ azure: azure/gpt-4
86
+ Executor:
87
+ subflows_config:
88
+ write_code:
89
+ memory_files: ???
90
+ subflows_config:
91
+ CodeGenerator:
92
+ backend:
93
+ api_infos: ???
94
+ model_name:
95
+ openai: gpt-4
96
+ azure: azure/gpt-4
97
+ test:
98
+ memory_files: ???
99
+ re_plan:
100
+ subflows_config:
101
+ Controller:
102
+ backend:
103
+ api_infos: ???
104
+ model_name:
105
+ openai: gpt-4
106
+ azure: azure/gpt-4
107
+ Executor:
108
+ subflows_config:
109
+ write_plan:
110
+ subflows_config:
111
+ PlanGenerator:
112
+ backend:
113
+ api_infos: ???
114
+ model_name:
115
+ openai: gpt-4
116
+ azure: azure/gpt-4
117
+ re_plan:
118
+ subflows_config:
119
+ Controller:
120
+ backend:
121
+ api_infos: ???
122
+ model_name:
123
+ openai: gpt-4
124
+ azure: azure/gpt-4
125
+ Executor:
126
+ subflows_config:
127
+ write_plan:
128
+ subflows_config:
129
+ PlanGenerator:
130
+ backend:
131
+ api_infos: ???
132
+ model_name:
133
+ openai: gpt-4
134
+ azure: azure/gpt-4
Controller_CoderFlow.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ class Controller_CoderFlow(ChatAtomicFlow):
18
+ """Refer to: https://huggingface.co/Tachi67/JarvisFlowModule/blob/main/Controller_JarvisFlow.py"""
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 location yet",
28
+ code_library="no code library yet",
29
+ code_library_location="no location yet",
30
+ logs="no logs yet",
31
+ )
32
+ self.hint_for_model = """
33
+ Make sure your response is in the following format:
34
+ Response Format:
35
+ {
36
+ "command": "call one of the subordinates",
37
+ "command_args": {
38
+ "arg name": "value"
39
+ }
40
+ }
41
+ """
42
+
43
+ @staticmethod
44
+ def _build_commands_manual(commands: List[Command]) -> str:
45
+ ret = ""
46
+ for i, command in enumerate(commands):
47
+ command_input_json_schema = json.dumps(
48
+ {input_arg: f"YOUR_{input_arg.upper()}" for input_arg in command.input_args})
49
+ ret += f"{i + 1}. {command.name}: {command.description} Input arguments (given in the JSON schema): {command_input_json_schema}\n"
50
+ return ret
51
+
52
+ def _get_content_file_location(self, input_data, content_name):
53
+ # get the location of the file that contains the content: plan, logs, code_library
54
+ assert "memory_files" in input_data, "memory_files not passed to Coder/Controller"
55
+ assert content_name in input_data["memory_files"], f"{content_name} not in memory files"
56
+ return input_data["memory_files"][content_name]
57
+
58
+ def _get_content(self, input_data, content_name):
59
+ # get the content of the file that contains the content: plan, logs, code_library
60
+ assert content_name in input_data, f"{content_name} not passed to Coder/Controller"
61
+ content = input_data[content_name]
62
+ if len(content) == 0:
63
+ content = f'No {content_name} yet'
64
+ return content
65
+
66
+ @classmethod
67
+ def instantiate_from_config(cls, config):
68
+ flow_config = deepcopy(config)
69
+
70
+ kwargs = {"flow_config": flow_config}
71
+
72
+ # ~~~ Set up prompts ~~~
73
+ kwargs.update(cls._set_up_prompts(flow_config))
74
+
75
+ # ~~~Set up backend ~~~
76
+ kwargs.update(cls._set_up_backend(flow_config))
77
+
78
+ # ~~~ Set up commands ~~~
79
+ commands = flow_config["commands"]
80
+ commands = [
81
+ Command(name, command_conf["description"], command_conf["input_args"]) for name, command_conf in
82
+ commands.items()
83
+ ]
84
+ kwargs.update({"commands": commands})
85
+
86
+ # ~~~ Instantiate flow ~~~
87
+ return cls(**kwargs)
88
+
89
+ def _update_prompts_and_input(self, input_data: Dict[str, Any]):
90
+ if 'goal' in input_data:
91
+ input_data['goal'] += self.hint_for_model
92
+ if 'result' in input_data:
93
+ input_data['result'] += self.hint_for_model
94
+ plan_file_location = self._get_content_file_location(input_data, "plan")
95
+ plan_content = self._get_content(input_data, "plan")
96
+ code_library_location = self._get_content_file_location(input_data, "code_library")
97
+ code_library_content = self._get_content(input_data, "code_library")
98
+ logs_content = self._get_content(input_data, "logs")
99
+ self.system_message_prompt_template = self.system_message_prompt_template.partial(
100
+ plan_file_location=plan_file_location,
101
+ plan=plan_content,
102
+ code_library_location=code_library_location,
103
+ code_library=code_library_content,
104
+ logs=logs_content
105
+ )
106
+
107
+ def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
108
+ self._update_prompts_and_input(input_data)
109
+
110
+ # ~~~when conversation is initialized, append the updated system prompts to the chat history ~~~
111
+ if self._is_conversation_initialized():
112
+ updated_system_message_content = self._get_message(self.system_message_prompt_template, input_data)
113
+ self._state_update_add_chat_message(content=updated_system_message_content,
114
+ role=self.flow_config["system_name"])
115
+
116
+ while True:
117
+ api_output = super().run(input_data)["api_output"].strip()
118
+ try:
119
+ start = api_output.index("{")
120
+ end = api_output.rindex("}") + 1
121
+ json_str = api_output[start:end]
122
+ return json.loads(json_str)
123
+ except (ValueError, json.decoder.JSONDecodeError, json.JSONDecodeError):
124
+ updated_system_message_content = self._get_message(self.system_message_prompt_template, input_data)
125
+ self._state_update_add_chat_message(content=updated_system_message_content,
126
+ role=self.flow_config["system_name"])
127
+ new_goal = "The previous respond cannot be parsed with json.loads. Next time, do not provide any comments or code blocks. Make sure your next response is purely json parsable."
128
+ new_input_data = input_data.copy()
129
+ new_input_data['result'] = new_goal
130
+ input_data = new_input_data
131
+
Controller_CoderFlow.yaml ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _target_: flow_modules.aiflows.CoderFlowModule.Controller_CoderFlow.instantiate_from_default_config
2
+ name: "ControllerFlow_Coder"
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
+ - "code_library"
16
+
17
+ input_interface_initialized:
18
+ - "goal"
19
+ - "result"
20
+ - "memory_files"
21
+ - "plan"
22
+ - "logs"
23
+ - "code_library"
24
+
25
+ #######################################################
26
+ # Output keys
27
+ #######################################################
28
+
29
+ output_interface:
30
+ - 'command'
31
+ - 'command_args'
32
+
33
+ backend:
34
+ api_infos: ???
35
+ model_name:
36
+ openai: gpt-4
37
+ azure: azure/gpt-4
38
+
39
+ commands:
40
+ extend_library:
41
+ description: "Given goal, write functions to achieve the goal, and then extend the library with the functions"
42
+ input_args: [ "goal" ]
43
+ re_plan:
44
+ 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."
45
+ input_args: [ "goal" ]
46
+ finish:
47
+ description: "Signal that the objective has been satisfied, return the summary of what was done"
48
+ input_args: [ "summary" ]
49
+ manual_finish:
50
+ description: "The user demands to quit and terminate the current process"
51
+ input_args: [ ]
52
+ ask_user:
53
+ description: "Ask user a question for confirmation or assistance"
54
+ input_args: [ "question" ]
55
+ update_plan:
56
+ description: "When one step of the plan is done, pass the updated plan to edit plan file and override current plan"
57
+ input_args: [ "updated_plan" ]
58
+ run_code:
59
+ description: "Run a code script written by yourself, e.g. downloading a package to the current environment, importing and calling a function from the code library"
60
+ input_args: [ "code", "language" ]
61
+
62
+
63
+ system_message_prompt_template:
64
+ _target_: langchain.PromptTemplate
65
+ template: |2-
66
+ Your department is in charge of achieving goals with writing and executing code. You are the leader of this department.
67
+
68
+ Here is the goal you need to achieve:
69
+ {{goal}}
70
+
71
+ You have a code library located at {{code_library_location}}, which contains functions that are already written and saved by your subordinates.
72
+ Here are the functions in the library:
73
+ {{code_library}}
74
+
75
+ You work with several subordinates, they will be in charge of the specific tasks, including extending the code library, running a code script (you need to write the code script yourself, e.g. importing and calling a function from the code library), re-planning, etc.
76
+
77
+ To call one of the subordinates, you need to call the corresponding command with necessary arguments, here are the commands and their descriptions:
78
+ {{commands}}
79
+
80
+ 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 located in a plan file {{plan_file_location}}:
81
+ {{plan}}
82
+
83
+ You should execute the plan step-by-step, for each step, you should do the following workflows:
84
+ 0.1 Whenever the user demands to quit or terminate the current process, call `manual_finish` command.
85
+ 0.2 Whenever in doubt, or you have something to ask, or confirm to the user, call `ask_user` with your question.
86
+ 0.3 During the execution of the plan, if something goes wrong, call the `re_plan` with detailed information about what was wrong.
87
+ 1. If the current step of plan asks to extend the library, call `extend_library` with the goal of the current step of plan.
88
+ 2. In one of the following situations, call `run_code` with the code script you write:
89
+ 2.1. The current step of plan does not require to extend the library, but requires to run a code script.
90
+ 2.2. The current step of plan requires to import and run some functions from the library. In this case you **MUST** make sure you import the library, something like `from LIBRARY_NAME import FUNCTION_NAME` should suffice.
91
+ 2.3. You need to download a package to the current environment, e.g. `pip install PACKAGE_NAME`, in this case the language of code should be `shell`.
92
+ After the code is run, the user will provide feedback about the execution, react to the feedback accordingly.
93
+ 3. Whenever you have done one step of the plan, **it could be either extending the library or running the code**, do the following:
94
+ 3.1 Reflect on what plan you are having right now.
95
+ 3.2 Reflect on which step of the plan you just finished.
96
+ 3.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**
97
+ 3.4 Call `update_plan` with the plan you just generated.
98
+ 4. Proceed to the next step of the plan, go back to workflow 1 or 2.
99
+ 5. When every step of the plan is done, call the `finish` command, with a summary of what was done.
100
+
101
+ **You MUST call `update_plan` whenever you realize one step of the plan, for example, extending the library or running the code is done.**
102
+
103
+ Here is an example of execution:
104
+ ### Beginning of an example execution: ###
105
+ Plan: 1. Extend the library with a function that reads the stock prices from yahoo finance for the last `k` months for a company given its `company_code` 2. Call this function for `company_code`=TSLA and `k`=6.
106
+ You start from step 1 of the plan, execute workflow 1, the extend_library command is called with the goal of step 1 of the plan.
107
+ You are informed of what functions are written and saved to the library.
108
+ You realize that step 1 is done, you go to workflow 3 to update the plan:
109
+ 3.1 You recall the plan you have.
110
+ 3.2 You realize step 1 of the plan is done.
111
+ 3.3 You generate the updated plan: 1. Extend the library with a function that reads the stock prices for the last k months for a company given its `company_code` (DONE) 2. Call this function for `company_code`=TSLA and k=6.
112
+ 3.4 You call `update_plan` with the generated plan.
113
+ The updated plan will override the existing plan, you are informed of the behaviour of override.
114
+ You enter step 2 of the plan.
115
+ You go to workflow 2 to run a code script, you write a code script that imports the function you just wrote and call it with the arguments specified in the plan.
116
+ You are informed that package yahoo finance is not installed, the user instructs to install the yahoo finance package, you go to workflow 2 to run a code script, you write a code script that installs the package.
117
+ You are informed that the package is installed, you go to workflow 2 to run a code script, you write a code script that imports the function you just wrote and call it with the arguments specified in the plan.
118
+ You are informed that the code has been successfully ran, the user is satisfied with the result.
119
+ You realize that step 2 is done, you go to workflow 3 to update the plan:
120
+ 3.1 You recall the plan you have.
121
+ 3.2 You realize step 2 of the plan is done.
122
+ 3.3 You generate the updated plan: 1. Extend the library with a function that reads the stock prices for the last k months for a company given its `company_code` (DONE) 2. Call this function for `company_code`=TSLA and k=6. (DONE)
123
+ 3.4 You call `update_plan` with the generated plan.
124
+ The updated plan will override the existing plan, you are informed of the behaviour of override.
125
+ All steps are done, you call `finish`, with a summary of what functions are written and saved to the library.
126
+ ### End of an example of execution ###
127
+
128
+ Here is a list of history actions you have taken, for your reference:
129
+ {{logs}}
130
+
131
+ Constraints:
132
+ 1. Exclusively use the commands listed in double quotes e.g. "command name"
133
+
134
+ Your response **MUST** be in the following format:
135
+ Response Format:
136
+ {
137
+ "command": "call one of the subordinates",
138
+ "command_args": {
139
+ "arg name": "value"
140
+ }
141
+ }
142
+ Ensure your responses can be parsed by Python json.loads
143
+
144
+ input_variables: ["commands", "plan_file_location", "plan", "logs", "code_library_location", "code_library", "goal"]
145
+ template_format: jinja2
146
+
147
+ human_message_prompt_template:
148
+ _target_: aiflows.prompt_template.JinjaPrompt
149
+ template: |2-
150
+ Here is the result of your previous action:
151
+ {{result}}
152
+ input_variables:
153
+ - "result"
154
+ template_format: jinja2
155
+
156
+ init_human_message_prompt_template:
157
+ _target_: aiflows.prompt_template.JinjaPrompt
158
+ template: |2-
159
+ Here is the goal you need to achieve, follow your plan to finish the goal:
160
+ {{goal}}
161
+ input_variables:
162
+ - "goal"
163
+ template_format: jinja2
164
+
165
+
166
+ previous_messages:
167
+ last_k: 3
CtrlExMem_CoderFlow.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, Any
2
+
3
+ from flow_modules.aiflows.AbstractBossFlowModule import CtrlExMemFlow
4
+ from aiflows.base_flows import CircularFlow
5
+
6
+ class CtrlExMem_CoderFlow(CtrlExMemFlow):
7
+ """This class inherits from the CtrlExMemFlow class from AbstractBossFlowModule.
8
+ See: https://huggingface.co/Tachi67/AbstractBossFlowModule/blob/main/CtrlExMemFlow.py
9
+
10
+ *Input Interface*:
11
+ - `plan`
12
+ - `logs`
13
+ - `code_library`: the signatures and docstring of the functions in the code library.
14
+ - `memory_files`
15
+ - `goal`
16
+
17
+ *Output Interface*
18
+ - `result` (str): The result of the flow, the result will be returned to the caller.
19
+ - `summary` (str): The summary of the flow, the summary will be logged into the logs of the caller flow.
20
+
21
+ """
22
+ def _on_reach_max_round(self):
23
+ self._state_update_dict({
24
+ "result": "the maximum amount of rounds was reached before the coder flow has done the job",
25
+ "summary": "CoderFlow: the maximum amount of rounds was reached before the flow has done the job",
26
+ "status": "unfinished"
27
+ })
28
+
29
+ @CircularFlow.output_msg_payload_processor
30
+ def detect_finish_or_continue(self, output_payload: Dict[str, Any], src_flow) -> Dict[str, Any]:
31
+ command = output_payload["command"]
32
+ if command == "finish":
33
+ return {
34
+ "EARLY_EXIT": True,
35
+ "result": output_payload["command_args"]["summary"],
36
+ "summary": "Coder: " + output_payload["command_args"]["summary"],
37
+ "status": "finished"
38
+ }
39
+ elif command == "manual_finish":
40
+ # ~~~ return the manual quit status ~~~
41
+ return {
42
+ "EARLY_EXIT": True,
43
+ "result": "CoderFlow was terminated explicitly by the user, process is unfinished",
44
+ "summary": "Coder: process terminated by the user explicitly, nothing generated",
45
+ "status": "unfinished"
46
+ }
47
+ elif command == "update_plan":
48
+ keys_to_fetch_from_state = ["memory_files"]
49
+ fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
50
+ output_payload["command_args"]["memory_files"] = fetched_state["memory_files"]
51
+ return output_payload
52
+
53
+ elif command == "re_plan":
54
+ keys_to_fetch_from_state = ["plan", "memory_files"]
55
+ fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
56
+ output_payload["command_args"]["plan_file_location"] = fetched_state["memory_files"]["plan"]
57
+ output_payload["command_args"]["plan"] = fetched_state["plan"]
58
+ return output_payload
59
+
60
+ elif command == "run_code":
61
+ keys_to_fetch_from_state = ["memory_files"]
62
+ fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
63
+ output_payload["command_args"]["memory_files"] = fetched_state["memory_files"]
64
+ return output_payload
65
+
66
+ else:
67
+ return output_payload
CtrlExMem_CoderFlow.yaml ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _target_: flow_modules.aiflows.CoderFlowModule.CtrlExMem_CoderFlow.instantiate_from_default_config
2
+ name: "CtrlExMem_CoderFlow"
3
+ description: "MemorizedControllerExecutor flow for Coder flow"
4
+
5
+ input_interface:
6
+ - "plan"
7
+ - "logs"
8
+ - "code_library"
9
+ - "memory_files"
10
+ - "goal"
11
+
12
+ subflows_config:
13
+ Controller:
14
+ _target_: flow_modules.aiflows.CoderFlowModule.Controller_CoderFlow.instantiate_from_default_config
15
+ backend:
16
+ api_infos: ???
17
+ model_name:
18
+ openai: gpt-4
19
+ azure: azure/gpt-4
20
+ Executor:
21
+ _target_: aiflows.base_flows.BranchingFlow.instantiate_from_default_config
22
+ subflows_config:
23
+ extend_library:
24
+ _target_: flow_modules.aiflows.ExtendLibraryFlowModule.ExtendLibraryFlow.instantiate_from_default_config
25
+ memory_files: ???
26
+ subflows_config:
27
+ Planner:
28
+ _target_: flow_modules.aiflows.PlanWriterFlowModule.PlanWriterFlow.instantiate_from_default_config
29
+ subflows_config:
30
+ Controller:
31
+ backend:
32
+ api_infos: ???
33
+ model_name:
34
+ openai: gpt-4
35
+ azure: azure/gpt-4
36
+ Executor:
37
+ subflows_config:
38
+ write_plan:
39
+ subflows_config:
40
+ PlanGenerator:
41
+ backend:
42
+ api_infos: ???
43
+ model_name:
44
+ openai: gpt-4
45
+ azure: azure/gpt-4
46
+ CtrlExMem:
47
+ _target_: flow_modules.aiflows.ExtendLibraryFlowModule.CtrlExMem_ExtLib.instantiate_from_default_config
48
+ subflows_config:
49
+ Controller:
50
+ backend:
51
+ api_infos: ???
52
+ model_name:
53
+ openai: gpt-4
54
+ azure: azure/gpt-4
55
+ Executor:
56
+ subflows_config:
57
+ write_code:
58
+ subflows_config:
59
+ Controller:
60
+ backend:
61
+ api_infos: ???
62
+ model_name:
63
+ openai: gpt-4
64
+ azure: azure/gpt-4
65
+ Executor:
66
+ subflows_config:
67
+ write_code:
68
+ memory_files: ???
69
+ subflows_config:
70
+ CodeGenerator:
71
+ backend:
72
+ api_infos: ???
73
+ model_name:
74
+ openai: gpt-4
75
+ azure: azure/gpt-4
76
+ test:
77
+ memory_files: ???
78
+ re_plan:
79
+ subflows_config:
80
+ Controller:
81
+ backend:
82
+ api_infos: ???
83
+ model_name:
84
+ openai: gpt-4
85
+ azure: azure/gpt-4
86
+ Executor:
87
+ subflows_config:
88
+ write_plan:
89
+ subflows_config:
90
+ PlanGenerator:
91
+ backend:
92
+ api_infos: ???
93
+ model_name:
94
+ openai: gpt-4
95
+ azure: azure/gpt-4
96
+ ask_user:
97
+ _target_: flow_modules.aiflows.ExtendLibraryFlowModule.ExtLibAskUserFlow.instantiate_from_default_config
98
+ re_plan:
99
+ _target_: flow_modules.aiflows.ReplanningFlowModule.ReplanningFlow.instantiate_from_default_config
100
+ subflows_config:
101
+ Controller:
102
+ backend:
103
+ api_infos: ???
104
+ model_name:
105
+ openai: gpt-4
106
+ azure: azure/gpt-4
107
+ Executor:
108
+ subflows_config:
109
+ write_plan:
110
+ subflows_config:
111
+ PlanGenerator:
112
+ backend:
113
+ api_infos: ???
114
+ model_name:
115
+ openai: gpt-4
116
+ azure: azure/gpt-4
117
+ run_code:
118
+ _target_: flow_modules.aiflows.RunCodeFlowModule.RunCodeFlow.instantiate_from_default_config
119
+ update_plan:
120
+ _target_: flow_modules.aiflows.CoderFlowModule.UpdatePlanAtomicFlow.instantiate_from_default_config
121
+ MemoryReading:
122
+ _target_: flow_modules.aiflows.MemoryReadingFlowModule.MemoryReadingAtomicFlow.instantiate_from_default_config
123
+ output_interface:
124
+ - "plan"
125
+ - "logs"
126
+ - "code_library"
127
+
128
+ topology:
129
+ - goal: "Select the next action and prepare the input for the executor."
130
+ input_interface:
131
+ _target_: aiflows.interfaces.KeyInterface
132
+ additional_transformations:
133
+ - _target_: aiflows.data_transformations.KeyMatchInput
134
+ flow: Controller
135
+ output_interface:
136
+ _target_: CtrlExMem_CoderFlow.detect_finish_or_continue
137
+ reset: false
138
+
139
+ - goal: "Execute the action specified by the Controller."
140
+ input_interface:
141
+ _target_: aiflows.interfaces.KeyInterface
142
+ keys_to_rename:
143
+ command: branch
144
+ command_args: branch_input_data
145
+ keys_to_select: ["branch", "branch_input_data"]
146
+ flow: Executor
147
+ output_interface:
148
+ _target_: aiflows.interfaces.KeyInterface
149
+ keys_to_rename:
150
+ branch_output_data.code_ran: code_ran
151
+ branch_output_data.interpreter_output: interpreter_output
152
+ branch_output_data.plan: plan
153
+ branch_output_data.status: status
154
+ branch_output_data.summary: summary
155
+ branch_output_data.result: result
156
+ keys_to_delete: ["branch_output_data"]
157
+ reset: false
158
+
159
+ - goal: "Write memory to memory files"
160
+ input_interface:
161
+ _target_: aiflows.interfaces.KeyInterface
162
+ additional_transformations:
163
+ - _target_: aiflows.data_transformations.KeyMatchInput
164
+ flow: MemoryWriting
165
+ reset: false
166
+
167
+ - goal: "Read memory from memory files (flow_state)"
168
+ input_interface:
169
+ _target_: aiflows.interfaces.KeyInterface
170
+ additional_transformations:
171
+ - _target_: aiflows.data_transformations.KeyMatchInput
172
+ flow: MemoryReading
173
+ reset: false
Planner_CoderFlow.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, Any
2
+ import os
3
+ from flow_modules.aiflows.PlanWriterFlowModule import PlanWriterFlow
4
+ from aiflows.base_flows import CircularFlow
5
+
6
+
7
+
8
+ class Planner_CoderFlow(PlanWriterFlow):
9
+ """Planner of the coder flow, it inherits from PlanWriterFlow, see: https://huggingface.co/Tachi67/PlanWriterFlowModule
10
+ """
11
+ def _on_reach_max_round(self):
12
+ self._state_update_dict({
13
+ "plan": "The maximum amount of rounds was reached before the model generated the plan.",
14
+ "status": "unfinished"
15
+ })
16
+
17
+ @CircularFlow.output_msg_payload_processor
18
+ def detect_finish_or_continue(self, output_payload: Dict[str, Any], src_flow) -> Dict[str, Any]:
19
+ command = output_payload["command"]
20
+ if command == "finish":
21
+ # ~~~ fetch temp file location, plan content, memory file (of upper level flow e.g. ExtLib) from flow state
22
+ keys_to_fetch_from_state = ["temp_plan_file_location", "plan", "memory_files"]
23
+ fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
24
+ temp_plan_file_location = fetched_state["temp_plan_file_location"]
25
+ plan_content = fetched_state["plan"]
26
+ plan_file_location = fetched_state["memory_files"]["plan"]
27
+
28
+ # ~~~ delete the temp plan file ~~~
29
+ if os.path.exists(temp_plan_file_location):
30
+ os.remove(temp_plan_file_location)
31
+
32
+ # ~~~ write plan content to plan file ~~~
33
+ with open(plan_file_location, 'w') as file:
34
+ file.write(plan_content)
35
+
36
+ # ~~~ return the plan content ~~~
37
+ return {
38
+ "EARLY_EXIT": True,
39
+ "plan": plan_content,
40
+ "summary": "Coder/PlanWriter: " + output_payload["command_args"]["summary"],
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
+ "plan": "no plan was generated",
54
+ "summary": "Coder/PlanWriter: PlanWriter was terminated explicitly by the user, process is unfinished",
55
+ "status": "unfinished"
56
+ }
57
+ elif command == "write_plan":
58
+ keys_to_fetch_from_state = ["memory_files", "code_library"]
59
+ fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
60
+ output_payload["command_args"]["plan_file_location"] = fetched_state["memory_files"]["plan"]
61
+ output_payload["command_args"]["code_library_location"] = fetched_state["memory_files"]["code_library"]
62
+ output_payload["command_args"]["code_library"] = fetched_state["code_library"]
63
+ return output_payload
64
+ else:
65
+ return output_payload
Planner_CoderFlow.yaml ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: "Planner/Coder"
2
+ description: "Generates plan with interactions with the user, used for the coder class"
3
+
4
+ _target_: flow_modules.aiflows.CoderFlowModule.Planner_CoderFlow.instantiate_from_default_config
5
+
6
+ input_interface:
7
+ - "goal"
8
+ - "code_library"
9
+ - "memory_files"
10
+
11
+ output_interface:
12
+ - "plan"
13
+ - "status"
14
+ - "summary"
15
+
16
+ ### Subflows specification
17
+ subflows_config:
18
+ Controller:
19
+ _target_: flow_modules.aiflows.PlanWriterFlowModule.PlanWriterCtrlFlow.instantiate_from_default_config
20
+ backend:
21
+ api_infos: ???
22
+ model_name:
23
+ openai: gpt-4
24
+ azure: azure/gpt-4
25
+
26
+ Executor:
27
+ _target_: aiflows.base_flows.BranchingFlow.instantiate_from_default_config
28
+ subflows_config:
29
+ write_plan:
30
+ _target_: flow_modules.aiflows.InteractivePlanGenFlowModule.InteractivePlanGenFlow.instantiate_from_default_config
31
+ input_interface:
32
+ - "goal"
33
+ - "plan_file_location"
34
+ - "code_library_location"
35
+ - "code_library"
36
+ subflows_config:
37
+ PlanGenerator:
38
+ _target_: flow_modules.aiflows.PlanGeneratorFlowModule.PlanGeneratorAtomicFlow.instantiate_from_default_config
39
+ backend:
40
+ api_infos: ???
41
+ model_name:
42
+ openai: gpt-4
43
+ azure: azure/gpt-4
44
+ input_interface_non_initialized:
45
+ - "goal"
46
+ - "code_library"
47
+ - "code_library_location"
48
+ input_interface_initialized:
49
+ - "goal"
50
+ - "code_library"
51
+ - "code_library_location"
52
+ system_message_prompt_template:
53
+ _target_: aiflows.prompt_template.JinjaPrompt
54
+ template: |2-
55
+ You are a planner for a coding department, you write step-by-step plans for the coders to follow and execute.
56
+
57
+ You and the coders work with a code library located at {{code_library_location}}, **it is important that when you make plans, make the best use of the functions in the library.** Here are the contents in the library:
58
+ {{code_library}}
59
+
60
+ The coders are able to read and write the code library, namely, they can import and use the functions in the library, and they are also able to extend the library.
61
+
62
+ Apart from reading and writing code, the coders are also able to execute a code script written by themselves.
63
+
64
+ **You task is: given a goal to achieve, write step-by-step plans for the coders, each step of your plan should involve one of the three actions:
65
+ 1. Extend the code library with a function, describe the purpose, input and output of this function so that the coders understand what you mean and write appropriate functions.
66
+ 2. Run a code script, for example, downloading a package after you realize the current environment lacks it; import and call one function from the code library with specific inputs.
67
+ 3. Give a final answer**
68
+
69
+ Here are some criteria you should consider in order to write a good plan:
70
+ 1. The plan should be nicely separated into steps, each step should involve extending the library, or running code, or giving a final answer.
71
+ 2. Always try to use the functions already existent in the code library. To use them, instruct the coders to import and run the function from the code library.
72
+ 3. If the current milestone cannot be solved by the functions in the library, generalize the problem and instruct the coders to extend the library with a function to deal with this problem.
73
+ For example, suppose the goal you need to achieve is "Download Google's stock prices from the last 6 months from Yahoo finance", there is no function available to solve this in the library.
74
+ In this case, your step of plan is: "Extend the library with a function that reads the stock prices for the last k months for a company given its `company_code`"
75
+ 4. On top of criterion 3, when you instruct the coders to extend the library, make sure that:
76
+ 4.1. Each time you instruct to extend the library, ask for only one function.
77
+ 4.2. If the problem you generalize involves several separated steps and should not be done in one function, decompose the problem into several sub-problems and instruct the coders to extend the library with a function for each sub-problem, this should be done in several steps of plan.
78
+
79
+ Performance Evaluation:
80
+ 1. Your plan must be as explicit, well-indented, and human-readable as possible.
81
+ 2. Your plan must be step-by-step with number indexes, each step involves extending the library, or running code, or answering.
82
+ 3. You should make plans with as few steps as possible.
83
+
84
+ **It's important that you should only respond in JSON format as described below:**
85
+ Response Format:
86
+ {
87
+ "plan": "A well indented string, containing a step-by-step plan to finish the given goal",
88
+ }
89
+ Ensure your responses can be parsed by Python json.loads
90
+ **Make sure that the plan you generate is a well-indented human readable string, with numbered indexes for each step.**
91
+ input_variables:
92
+ - "code_library_location"
93
+ - "code_library"
94
+
95
+ PlanFileEditor:
96
+ _target_: flow_modules.aiflows.PlanFileEditFlowModule.PlanFileEditAtomicFlow.instantiate_from_default_config
97
+
98
+ ParseFeedback:
99
+ _target_: flow_modules.aiflows.ParseFeedbackFlowModule.ParseFeedbackAtomicFlow.instantiate_from_default_config
100
+ input_interface:
101
+ - "temp_plan_file_location"
102
+ output_interface:
103
+ - "plan"
104
+ - "feedback"
105
+
106
+ ask_user:
107
+ _target_: flow_modules.aiflows.PlanWriterFlowModule.PlanWriterAskUserFlow.instantiate_from_default_config
108
+
109
+
110
+ early_exit_key: "EARLY_EXIT"
111
+
112
+ topology:
113
+ - goal: "Select the next action and prepare the input for the executor."
114
+ input_interface:
115
+ _target_: aiflows.interfaces.KeyInterface
116
+ additional_transformations:
117
+ - _target_: aiflows.data_transformations.KeyMatchInput
118
+ flow: Controller
119
+ output_interface:
120
+ _target_: Planner_CoderFlow.detect_finish_or_continue
121
+ reset: false
122
+
123
+ - goal: "Execute the action specified by the Controller."
124
+ input_interface:
125
+ _target_: aiflows.interfaces.KeyInterface
126
+ keys_to_rename:
127
+ command: branch
128
+ command_args: branch_input_data
129
+ keys_to_select: ["branch", "branch_input_data"]
130
+ flow: Executor
131
+ output_interface:
132
+ _target_: aiflows.interfaces.KeyInterface
133
+ keys_to_rename:
134
+ branch_output_data.plan: plan
135
+ branch_output_data.feedback: feedback
136
+ branch_output_data.temp_plan_file_location: temp_plan_file_location
137
+ keys_to_delete: ["branch_output_data"]
138
+ reset: false
README.md CHANGED
@@ -1,3 +1,248 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Structure of Coder
2
+
3
+ ```
4
+ goal, memory_files (dict)
5
+ |
6
+ v
7
+ +-------------------+
8
+ | MemoryReading | Reads in the content of the memory files
9
+ | Flow |
10
+ +-------------------+
11
+ |
12
+ | (memory_content)
13
+ |
14
+ v
15
+ +-------------------+
16
+ | PlanWriter | Writes a step-by-step plan to achieve the goal
17
+ +-------------------+
18
+ |
19
+ | (plan)
20
+ |
21
+ v
22
+ +-------------------+
23
+ | CtrlExMemFlow | Illustrated below. Carries out the plan in an controller-executor fashion,
24
+ | | with memory management mechanisms.
25
+ +-------------------+
26
+ |
27
+ (summary, result)
28
+
29
+ ```
30
+
31
+ Here is the structure of the `CtrlExMemFlow`:
32
+ ```
33
+ plan, memory_files, memory_content, goal
34
+ |
35
+ v
36
+ +---------------+
37
+ | Controller | --------<<<<-----------+
38
+ +---------------+ |
39
+ | |
40
+ | (command, command args) |
41
+ | |
42
+ v |
43
+ +------------------+ |
44
+ | Executor | Each branch is an |
45
+ | (Tree Structure) | executor |
46
+ +------------------+ |
47
+ | ^
48
+ | (execution results) ^
49
+ | ^
50
+ v ^
51
+ +---------------+ ^
52
+ | MemWriteFlow | Updates memory files ^
53
+ +---------------+ ^
54
+ | ^
55
+ | (summary) |
56
+ | |
57
+ v |
58
+ +---------------+ |
59
+ | MemReadFlow | Reads updated memory |
60
+ +---------------+ |
61
+ | |
62
+ | (updated memory content) |
63
+ | |
64
+ +-> goes back to the Controller>-+
65
+
66
+ ```
67
+ Structure of the Executors:
68
+ ```
69
+ +-------------------+
70
+ | Branching |
71
+ | Executor |
72
+ +-------------------+
73
+ / | | | \
74
+ / | | | \
75
+ / | | | \
76
+ / | | | \
77
+ Extend_library ask_user re_plan update_plan run_code
78
+
79
+ ```
80
+
81
+ Memory files of Coder:
82
+ - plan_coder.txt
83
+ - logs_coder.txt
84
+ - library.py
85
+
86
+ About the branches:
87
+ - [ExtendLibrary](https://huggingface.co/Tachi67/ExtendLibraryFlowModule): Writes and tests code functions in an interactive fashion, finally saves the written function to the code library.
88
+ - [ask_user](https://huggingface.co/Tachi67/ExtendLibraryFlowModule/blob/main/ExtLibAskUserFlow.py): Ask user for info / confirmation, etc.
89
+ - [re_plan](https://huggingface.co/Tachi67/ReplanningFlowModule): One branch of the executors, when something goes wrong, re-draft the plan.
90
+ - [update_plan](https://huggingface.co/Tachi67/JarvisFlowModule/blob/main/UpdatePlanAtomicFlow.py): One branch of the executors, when the controller realizes that one (or some, depending on the LLM's response) step of the plan is (are) done, it generates a new plan that marks the step(s) as done.
91
+ - [run_code](https://huggingface.co/Tachi67/RunCodeFlowModule): Runs the code written by the Controller, will first open up a temp file with the code for user confirmation and editing, then the code is passed to the [InterpreterFlow](https://huggingface.co/Tachi67/InterpreterFlowModule).
92
+
93
+
94
+
95
+
96
+ # Table of Contents
97
+
98
+ * [CtrlExMem\_CoderFlow](#CtrlExMem_CoderFlow)
99
+ * [CtrlExMem\_CoderFlow](#CtrlExMem_CoderFlow.CtrlExMem_CoderFlow)
100
+ * [run\_coder](#run_coder)
101
+ * [Planner\_CoderFlow](#Planner_CoderFlow)
102
+ * [Planner\_CoderFlow](#Planner_CoderFlow.Planner_CoderFlow)
103
+ * [Controller\_CoderFlow](#Controller_CoderFlow)
104
+ * [Controller\_CoderFlow](#Controller_CoderFlow.Controller_CoderFlow)
105
+ * [UpdatePlanAtomicFlow](#UpdatePlanAtomicFlow)
106
+ * [UpdatePlanAtomicFlow](#UpdatePlanAtomicFlow.UpdatePlanAtomicFlow)
107
+ * [CoderFlow](#CoderFlow)
108
+ * [CoderFlow](#CoderFlow.CoderFlow)
109
+ * [run](#CoderFlow.CoderFlow.run)
110
+ * [\_\_init\_\_](#__init__)
111
+
112
+ <a id="CtrlExMem_CoderFlow"></a>
113
+
114
+ # CtrlExMem\_CoderFlow
115
+
116
+ <a id="CtrlExMem_CoderFlow.CtrlExMem_CoderFlow"></a>
117
+
118
+ ## CtrlExMem\_CoderFlow Objects
119
+
120
+ ```python
121
+ class CtrlExMem_CoderFlow(CtrlExMemFlow)
122
+ ```
123
+
124
+ This class inherits from the CtrlExMemFlow class from AbstractBossFlowModule.
125
+ See: https://huggingface.co/Tachi67/AbstractBossFlowModule/blob/main/CtrlExMemFlow.py
126
+
127
+ *Input Interface*:
128
+ - `plan`
129
+ - `logs`
130
+ - `code_library`: the signatures and docstring of the functions in the code library.
131
+ - `memory_files`
132
+ - `goal`
133
+
134
+ *Output Interface*
135
+ - `result` (str): The result of the flow, the result will be returned to the caller.
136
+ - `summary` (str): The summary of the flow, the summary will be logged into the logs of the caller flow.
137
+
138
+ <a id="run_coder"></a>
139
+
140
+ # run\_coder
141
+
142
+ <a id="Planner_CoderFlow"></a>
143
+
144
+ # Planner\_CoderFlow
145
+
146
+ <a id="Planner_CoderFlow.Planner_CoderFlow"></a>
147
+
148
+ ## Planner\_CoderFlow Objects
149
+
150
+ ```python
151
+ class Planner_CoderFlow(PlanWriterFlow)
152
+ ```
153
+
154
+ Planner of the coder flow, it inherits from PlanWriterFlow, see: https://huggingface.co/Tachi67/PlanWriterFlowModule
155
+
156
+ <a id="Controller_CoderFlow"></a>
157
+
158
+ # Controller\_CoderFlow
159
+
160
+ <a id="Controller_CoderFlow.Controller_CoderFlow"></a>
161
+
162
+ ## Controller\_CoderFlow Objects
163
+
164
+ ```python
165
+ class Controller_CoderFlow(ChatAtomicFlow)
166
+ ```
167
+
168
+ Refer to: https://huggingface.co/Tachi67/JarvisFlowModule/blob/main/Controller_JarvisFlow.py
169
+
170
+ <a id="UpdatePlanAtomicFlow"></a>
171
+
172
+ # UpdatePlanAtomicFlow
173
+
174
+ <a id="UpdatePlanAtomicFlow.UpdatePlanAtomicFlow"></a>
175
+
176
+ ## UpdatePlanAtomicFlow Objects
177
+
178
+ ```python
179
+ class UpdatePlanAtomicFlow(AtomicFlow)
180
+ ```
181
+
182
+ This flow updates the plan file with the updated plan. The controller should pass the updated plan to this flow.
183
+ This design (controller reflect on the existing plan--update plan) is intended to let the controller more aware of the
184
+ plan it has. However one setback is that this process in then not deterministic.
185
+
186
+ *Input Interface*
187
+ - `updated_plan`: the updated plan in string format
188
+
189
+ *Output Interface*
190
+ - `result`: the result of the update plan operation
191
+
192
+ <a id="CoderFlow"></a>
193
+
194
+ # CoderFlow
195
+
196
+ <a id="CoderFlow.CoderFlow"></a>
197
+
198
+ ## CoderFlow Objects
199
+
200
+ ```python
201
+ class CoderFlow(AbstractBossFlow)
202
+ ```
203
+
204
+ Coder flow is one executor branch of the Jarvis flow. At a higher level, it is a flow that
205
+ writes and runs code given a goal. In the Jarvis flow, the Coder flow in invoked by the controller,
206
+ The Coder flow receives the goal generated by the controller, writes and runs code in an interactive fashion.
207
+
208
+ The Coder flow has the similar structure as the Jarvis flow (inherited from AbstractBossFlow).
209
+
210
+
211
+ *Input Interface (expected input)*
212
+ - `goal` (str): The goal from the caller (source flow, i.e. JarvisFlow)
213
+
214
+
215
+ *Output Interface (expected output)*
216
+ - `result` (str): The result of the flow, the result will be returned to the caller (i.e. JarvisFlow).
217
+ - `summary` (str): The summary of the flow, the summary will be logged into the logs of the caller flow (i.e. JarvisFlow).
218
+
219
+ Typical workflow of Coder:
220
+ 0. JarvisFlow calls Coder with a goal.
221
+ 1. MemoryReading reads plans, logs and code library.
222
+ 2. Planner makes plan based on goal.
223
+ 3. Extend library with the goal given by the controller.
224
+ 4. Run code with code (possibly calls the newly written function) given by the controller.
225
+ 5. Finish and give an answer.
226
+
227
+ <a id="CoderFlow.CoderFlow.run"></a>
228
+
229
+ #### run
230
+
231
+ ```python
232
+ def run(input_data: Dict[str, Any]) -> Dict[str, Any]
233
+ ```
234
+
235
+ The run function of the Coder flow.
236
+
237
+ **Arguments**:
238
+
239
+ - `input_data` (`Dict[str, Any]`): The input data of the flow.
240
+
241
+ **Returns**:
242
+
243
+ `Dict[str, Any]`: The output data of the flow.
244
+
245
+ <a id="__init__"></a>
246
+
247
+ # \_\_init\_\_
248
+
UpdatePlanAtomicFlow.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #TODO: generalize updateplanatomicflow with the one in extendlibrary
2
+ from typing import Dict, Any
3
+ from aiflows.base_flows.atomic import AtomicFlow
4
+ class UpdatePlanAtomicFlow(AtomicFlow):
5
+ """This flow updates the plan file with the updated plan. The controller should pass the updated plan to this flow.
6
+ This design (controller reflect on the existing plan--update plan) is intended to let the controller more aware of the
7
+ plan it has. However one setback is that this process in then not deterministic.
8
+
9
+ *Input Interface*
10
+ - `updated_plan`: the updated plan in string format
11
+
12
+ *Output Interface*
13
+ - `result`: the result of the update plan operation
14
+ """
15
+ def _check_input(self, input_data: Dict[str, Any]):
16
+ assert "memory_files" in input_data, "memory_files not passed to UpdatePlanAtomicFlow.yaml"
17
+ assert "plan" in input_data["memory_files"], "plan not in memory_files"
18
+
19
+ def _call(self, input_data: Dict[str, Any]):
20
+ try:
21
+ plan_file_location = input_data["memory_files"]["plan"]
22
+ plan_to_write = input_data["updated_plan"]
23
+ with open(plan_file_location, 'w') as file:
24
+ file.write(plan_to_write + "\n")
25
+ return {
26
+ "result": "updated plan saved to the plan file and has overriden the previous plan",
27
+ "summary": f"Coder/UpdatePlanFlow: updated plan saved to {plan_file_location}"
28
+ }
29
+ except Exception as e:
30
+ return {
31
+ "result": f"Error occurred: {str(e)}",
32
+ "summary": f"Coder/UpdatePlanFlow: error occurred while writing updated plan: {str(e)}"
33
+ }
34
+
35
+ def run(
36
+ self,
37
+ input_data: Dict[str, Any]
38
+ ):
39
+ self._check_input(input_data)
40
+ return self._call(input_data)
UpdatePlanAtomicFlow.yaml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ _target_: aiflows.CoderFlowModule.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
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ dependencies = [
2
+ {"url": "aiflows/AbstractBossFlowModule", "revision": "main"},
3
+ {"url": "aiflows/MemoryReadingFlowModule", "revision": "main"},
4
+ {"url": "aiflows/PlanWriterFlowModule", "revision": "main"},
5
+ {"url": "aiflows/ExtendLibraryFlowModule", "revision": "main"},
6
+ {"url": "aiflows/RunCodeFlowModule", "revision": "main"},
7
+ {"url": "aiflows/ReplanningFlowModule", "revision": "main"},
8
+ {"url": "aiflows/HumanStandardInputFlowModule", "revision": "4ff043522c89a964ea3a928ce09811c51a2b5b98"},
9
+ {"url": "aiflows/ChatFlowModule", "revision": "297c90d08087d9ff3139521f11d1a48d7dc63ed4"},
10
+ ]
11
+
12
+ from aiflows import flow_verse
13
+ flow_verse.sync_dependencies(dependencies)
14
+
15
+ from .UpdatePlanAtomicFlow import UpdatePlanAtomicFlow
16
+ from .CoderFlow import CoderFlow
17
+ from .Controller_CoderFlow import Controller_CoderFlow
18
+ from .CtrlExMem_CoderFlow import CtrlExMem_CoderFlow
19
+ from .Planner_CoderFlow import Planner_CoderFlow
pip_requirements.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ colorama==0.4.6
2
+ pytest==7.3.1
3
+ pytest-cov==4.1.0
4
+ hydra-core==1.3.2
5
+ hydra-colorlog==1.1.0
6
+ wrapt-timeout-decorator==1.3.12.2
7
+ diskcache==5.6.1
8
+ openai==1.0.0
9
+ huggingface_hub==0.19.4
10
+ jsonlines==3.1.0
11
+ jinja2==3.1.2
12
+ mock==5.0.2
13
+ rich==12.6.0
14
+ litellm==1.0.0
15
+ aiflows
run_coder.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import hydra
4
+
5
+ from aiflows.backends.api_info import ApiInfo
6
+ from aiflows.messages import InputMessage
7
+ from aiflows.utils.general_helpers import read_yaml_file
8
+ from aiflows.utils.general_helpers import quick_load
9
+
10
+ from aiflows import logging
11
+ from aiflows.flow_cache import CACHING_PARAMETERS, clear_cache
12
+
13
+ CACHING_PARAMETERS.do_caching = False # Set to True in order to disable caching
14
+ # clear_cache() # Uncomment this line to clear the cache
15
+
16
+ logging.set_verbosity_debug()
17
+ logging.auto_set_dir()
18
+
19
+ dependencies = [
20
+ {"url": "aiflows/HumanStandardInputFlowModule", "revision": "4ff043522c89a964ea3a928ce09811c51a2b5b98"},
21
+ {"url": "aiflows/ChatFlowModule", "revision": "297c90d08087d9ff3139521f11d1a48d7dc63ed4"},
22
+ {"url": "aiflows/AbstractBossFlowModule", "revision": "main"},
23
+ {"url": "aiflows/MemoryReadingFlowModule", "revision": "main"},
24
+ {"url": "aiflows/PlanWriterFlowModule", "revision": "main"},
25
+ {"url": "aiflows/ExtendLibraryFlowModule", "revision": "main"},
26
+ {"url": "aiflows/RunCodeFlowModule", "revision": "main"},
27
+ {"url": "aiflows/ReplanningFlowModule", "revision": "main"},
28
+ {"url": "aiflows/CoderFlowModule", "revision": "main"},
29
+ ]
30
+
31
+ from aiflows import flow_verse
32
+
33
+ flow_verse.sync_dependencies(dependencies)
34
+
35
+ def set_up_memfiles():
36
+ code_lib_file_loc = os.path.join(current_dir, "library.py")
37
+ coder_plan_file_loc = os.path.join(current_dir, "plan_coder.txt")
38
+ coder_logs_file_loc = os.path.join(current_dir, "logs_coder.txt")
39
+ extlib_plan_file_loc = os.path.join(current_dir, "plan_extlib.txt")
40
+ extlib_logs_file_loc = os.path.join(current_dir, "logs_extlib.txt")
41
+ with open(code_lib_file_loc, 'w') as file:
42
+ pass
43
+ with open(coder_plan_file_loc, 'w') as file:
44
+ pass
45
+ with open(coder_logs_file_loc, 'w') as file:
46
+ pass
47
+ with open(extlib_plan_file_loc, 'w') as file:
48
+ pass
49
+ with open(extlib_logs_file_loc, 'w') as file:
50
+ pass
51
+
52
+ memfiles_coder = {}
53
+ memfiles_extlib = {}
54
+ memfiles_writecode_interactivecoder = {}
55
+ memfiles_writecode_test = {}
56
+ memfiles_coder["plan"] = coder_plan_file_loc
57
+ memfiles_coder["logs"] = coder_logs_file_loc
58
+ memfiles_coder["code_library"] = code_lib_file_loc
59
+ memfiles_extlib["plan"] = extlib_plan_file_loc
60
+ memfiles_extlib["logs"] = extlib_logs_file_loc
61
+ memfiles_extlib["code_library"] = code_lib_file_loc
62
+ memfiles_writecode_interactivecoder["code_library"] = code_lib_file_loc
63
+ memfiles_writecode_test["code_library"] = code_lib_file_loc
64
+ cfg["memory_files"] = memfiles_coder
65
+ cfg["subflows_config"]["CtrlExMem"]["subflows_config"]["Executor"]["subflows_config"]["extend_library"]["memory_files"] = memfiles_extlib
66
+ cfg["subflows_config"]["CtrlExMem"]["subflows_config"]["Executor"]["subflows_config"]["extend_library"]["subflows_config"]["CtrlExMem"]["subflows_config"]["Executor"]["subflows_config"]["write_code"][
67
+ "subflows_config"]["Executor"]["subflows_config"]["write_code"][
68
+ "memory_files"] = memfiles_writecode_interactivecoder
69
+ cfg["subflows_config"]["CtrlExMem"]["subflows_config"]["Executor"]["subflows_config"]["extend_library"]["subflows_config"]["CtrlExMem"]["subflows_config"]["Executor"]["subflows_config"]["write_code"][
70
+ "subflows_config"]["Executor"]["subflows_config"]["test"]["memory_files"] = memfiles_writecode_test
71
+
72
+
73
+ if __name__ == "__main__":
74
+ # ~~~ make sure to set the openai api key in the envs ~~~
75
+ key = os.getenv("OPENAI_API_KEY")
76
+ api_information = [ApiInfo(backend_used="openai", api_key=os.getenv("OPENAI_API_KEY"))]
77
+ path_to_output_file = None
78
+
79
+ current_dir = os.getcwd()
80
+ cfg_path = os.path.join(current_dir, "CoderFlow.yaml")
81
+ cfg = read_yaml_file(cfg_path)
82
+
83
+ # ~~~ setting api information into config ~~~
84
+ quick_load(cfg, api_information)
85
+
86
+ # ~~~ setting memory files into config ~~~
87
+ set_up_memfiles()
88
+
89
+ # ~~~ instantiating the flow and input data ~~~
90
+ CoderFlow = hydra.utils.instantiate(cfg, _recursive_=False, _convert_="partial")
91
+ input_data = {
92
+ #"goal": "define a calculator that supports addition and multiplication on complex numbers",
93
+ #"goal": "define a calculator that supports addition on complex numbers"
94
+ "goal": "fetch google's stock prices using yfinance for the last 6 months and print the first 10 entries"
95
+ }
96
+ input_message = InputMessage.build(
97
+ data_dict=input_data,
98
+ src_flow="Launcher",
99
+ dst_flow=CoderFlow.name
100
+ )
101
+
102
+ # ~~~ calling the flow ~~~
103
+ output_message = CoderFlow(input_message)
104
+
105
+ # ~~~ printing the output ~~~
106
+ print(output_message)