Upload 16 files
Browse files- ControllerFlow_ExtLib.py +128 -0
- ControllerFlow_ExtLib.yaml +149 -0
- CtrlExMem_ExtLib.py +64 -0
- CtrlExMem_ExtLib.yaml +106 -0
- ExtLibAskUserFlow.py +44 -0
- ExtLibAskUserFlow.yaml +9 -0
- ExtendLibraryFlow.py +43 -0
- ExtendLibraryFlow.yaml +91 -0
- README.md +264 -3
- SaveCodeAtomicFlow.py +58 -0
- SaveCodeAtomicFlow.yaml +11 -0
- UpdatePlanAtomicFlow.py +30 -0
- UpdatePlanAtomicFlow.yaml +9 -0
- __init__.py +18 -0
- pip_requirements.txt +15 -0
- run_ExtendLibrary.py +81 -0
ControllerFlow_ExtLib.py
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
from dataclasses import dataclass
|
8 |
+
|
9 |
+
|
10 |
+
@dataclass
|
11 |
+
class Command:
|
12 |
+
name: str
|
13 |
+
description: str
|
14 |
+
input_args: List[str]
|
15 |
+
|
16 |
+
class ControllerFlow_ExtLib(ChatAtomicFlow):
|
17 |
+
"""Refer to: https://huggingface.co/Tachi67/JarvisFlowModule/blob/main/Controller_JarvisFlow.py"""
|
18 |
+
def __init__(
|
19 |
+
self,
|
20 |
+
commands: List[Command],
|
21 |
+
**kwargs):
|
22 |
+
super().__init__(**kwargs)
|
23 |
+
self.system_message_prompt_template = self.system_message_prompt_template.partial(
|
24 |
+
commands=self._build_commands_manual(commands),
|
25 |
+
plan_file_location="no location yet",
|
26 |
+
plan="no plan yet",
|
27 |
+
logs="no logs yet",
|
28 |
+
)
|
29 |
+
self.hint_for_model = """
|
30 |
+
Make sure your response is in the following format:
|
31 |
+
Response Format:
|
32 |
+
{
|
33 |
+
"command": "call one of the commands you have e.g. `write_code`",
|
34 |
+
"command_args": {
|
35 |
+
"arg name": "value"
|
36 |
+
}
|
37 |
+
}
|
38 |
+
"""
|
39 |
+
|
40 |
+
@staticmethod
|
41 |
+
def _build_commands_manual(commands: List[Command]) -> str:
|
42 |
+
ret = ""
|
43 |
+
for i, command in enumerate(commands):
|
44 |
+
command_input_json_schema = json.dumps(
|
45 |
+
{input_arg: f"YOUR_{input_arg.upper()}" for input_arg in command.input_args})
|
46 |
+
ret += f"{i + 1}. {command.name}: {command.description} Input arguments (given in the JSON schema): {command_input_json_schema}\n"
|
47 |
+
return ret
|
48 |
+
|
49 |
+
def _get_plan_file_location(self, input_data: Dict[str, Any]):
|
50 |
+
assert "memory_files" in input_data, "memory_files not passed to Extlib/Controller"
|
51 |
+
assert "plan" in input_data["memory_files"], "plan not in memory files"
|
52 |
+
return input_data["memory_files"]["plan"]
|
53 |
+
|
54 |
+
def _get_plan_content(self, input_data: Dict[str, Any]):
|
55 |
+
assert "plan" in input_data, "plan not passed to Extlib/Controller"
|
56 |
+
plan_content = input_data["plan"]
|
57 |
+
if len(plan_content) == 0:
|
58 |
+
plan_content = 'No plan yet'
|
59 |
+
return plan_content
|
60 |
+
|
61 |
+
def _get_logs_content(self, input_data: Dict[str, Any]):
|
62 |
+
assert "logs" in input_data, "logs not passed to Extlib/Controller"
|
63 |
+
logs_content = input_data["logs"]
|
64 |
+
if len(logs_content) == 0:
|
65 |
+
logs_content = "No logs yet"
|
66 |
+
return logs_content
|
67 |
+
|
68 |
+
@classmethod
|
69 |
+
def instantiate_from_config(cls, config):
|
70 |
+
flow_config = deepcopy(config)
|
71 |
+
|
72 |
+
kwargs = {"flow_config": flow_config}
|
73 |
+
|
74 |
+
# ~~~ Set up prompts ~~~
|
75 |
+
kwargs.update(cls._set_up_prompts(flow_config))
|
76 |
+
|
77 |
+
# ~~~Set up backend ~~~
|
78 |
+
kwargs.update(cls._set_up_backend(flow_config))
|
79 |
+
|
80 |
+
# ~~~ Set up commands ~~~
|
81 |
+
commands = flow_config["commands"]
|
82 |
+
commands = [
|
83 |
+
Command(name, command_conf["description"], command_conf["input_args"]) for name, command_conf in
|
84 |
+
commands.items()
|
85 |
+
]
|
86 |
+
kwargs.update({"commands": commands})
|
87 |
+
|
88 |
+
# ~~~ Instantiate flow ~~~
|
89 |
+
return cls(**kwargs)
|
90 |
+
|
91 |
+
def _update_prompts_and_input(self, input_data: Dict[str, Any]):
|
92 |
+
if 'goal' in input_data:
|
93 |
+
input_data['goal'] += self.hint_for_model
|
94 |
+
if 'result' in input_data:
|
95 |
+
input_data['result'] += self.hint_for_model
|
96 |
+
plan_file_location = self._get_plan_file_location(input_data)
|
97 |
+
plan_content = self._get_plan_content(input_data)
|
98 |
+
logs_content = self._get_logs_content(input_data)
|
99 |
+
self.system_message_prompt_template = self.system_message_prompt_template.partial(
|
100 |
+
plan_file_location=plan_file_location,
|
101 |
+
plan=plan_content,
|
102 |
+
logs=logs_content
|
103 |
+
)
|
104 |
+
|
105 |
+
def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
|
106 |
+
self._update_prompts_and_input(input_data)
|
107 |
+
|
108 |
+
# ~~~when conversation is initialized, append the updated system prompts to the chat history ~~~
|
109 |
+
if self._is_conversation_initialized():
|
110 |
+
updated_system_message_content = self._get_message(self.system_message_prompt_template, input_data)
|
111 |
+
self._state_update_add_chat_message(content=updated_system_message_content,
|
112 |
+
role=self.flow_config["system_name"])
|
113 |
+
|
114 |
+
while True:
|
115 |
+
api_output = super().run(input_data)["api_output"].strip()
|
116 |
+
try:
|
117 |
+
start = api_output.index("{")
|
118 |
+
end = api_output.rindex("}") + 1
|
119 |
+
json_str = api_output[start:end]
|
120 |
+
return json.loads(json_str)
|
121 |
+
except (json.decoder.JSONDecodeError, json.JSONDecodeError):
|
122 |
+
updated_system_message_content = self._get_message(self.system_message_prompt_template, input_data)
|
123 |
+
self._state_update_add_chat_message(content=updated_system_message_content,
|
124 |
+
role=self.flow_config["system_name"])
|
125 |
+
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."
|
126 |
+
new_input_data = input_data.copy()
|
127 |
+
new_input_data['result'] = new_goal
|
128 |
+
input_data = new_input_data
|
ControllerFlow_ExtLib.yaml
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_target_: flow_modules.aiflows.ExtendLibraryFlowModule.ControllerFlow_ExtLib.instantiate_from_default_config
|
2 |
+
name: "ControllerFlow_ExtendLibrary"
|
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 |
+
- "goal"
|
18 |
+
- "result"
|
19 |
+
- "memory_files"
|
20 |
+
- "plan"
|
21 |
+
- "logs"
|
22 |
+
|
23 |
+
#######################################################
|
24 |
+
# Output keys
|
25 |
+
#######################################################
|
26 |
+
|
27 |
+
output_interface:
|
28 |
+
- 'command'
|
29 |
+
- 'command_args'
|
30 |
+
|
31 |
+
backend:
|
32 |
+
api_infos: ???
|
33 |
+
model_name:
|
34 |
+
openai: gpt-4
|
35 |
+
azure: azure/gpt-4
|
36 |
+
|
37 |
+
commands:
|
38 |
+
write_code:
|
39 |
+
description: "Write code to finish the current step of plan with user interaction"
|
40 |
+
input_args: ["goal"]
|
41 |
+
save_code:
|
42 |
+
description: "When code is written by the coder, save the code to the library"
|
43 |
+
input_args: []
|
44 |
+
re_plan:
|
45 |
+
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."
|
46 |
+
input_args: ["goal"]
|
47 |
+
finish:
|
48 |
+
description: "Signal that the objective has been satisfied, return the summary of what was done"
|
49 |
+
input_args: ["summary"]
|
50 |
+
manual_finish:
|
51 |
+
description: "The user demands to quit and terminate the current process"
|
52 |
+
input_args: []
|
53 |
+
ask_user:
|
54 |
+
description: "Ask user a question for confirmation or assistance"
|
55 |
+
input_args: ["question"]
|
56 |
+
update_plan:
|
57 |
+
description: "Pass the updated plan to edit plan file and override current plan"
|
58 |
+
input_args: ["updated_plan"]
|
59 |
+
|
60 |
+
|
61 |
+
system_message_prompt_template:
|
62 |
+
_target_: langchain.PromptTemplate
|
63 |
+
template: |2-
|
64 |
+
Your department is in charge of writing code and extending the code library with the code written. You are the leader of this department.
|
65 |
+
|
66 |
+
Here is the goal you need to achieve, follow your plan to finish the goal:
|
67 |
+
{{goal}}
|
68 |
+
|
69 |
+
You work with several subordinates, they will be in charge of the specific tasks, including writing code, saving code to the library, etc.
|
70 |
+
|
71 |
+
You are given a step-by-step plan to finish the goal, **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}}:
|
72 |
+
{{plan}}
|
73 |
+
|
74 |
+
Your **ONLY** task is to take the user's goal for you, to decide which command to call.
|
75 |
+
|
76 |
+
You **must not** write code nor write plan yourself. You only decide whether to call the coder with specified goals or to finish.
|
77 |
+
|
78 |
+
Each step of the plan should involve writing one function, **for each step in the plan, your workflow**:
|
79 |
+
0.1 Whenever the user demands to quit or terminate the current process, call `manual_finish` command.
|
80 |
+
0.2 Whenever in doubt, or you have something to ask, or confirm to the user, call `ask_user` with your question.
|
81 |
+
0.3 During the execution of the plan, if something goes wrong, call the `re_plan` with detailed information about what was wrong.
|
82 |
+
1. Based on the current step of plan, call `write_code` with the current goal in the step of plan, the code writer will write some code.
|
83 |
+
2. After code is written, call `save_code` to save the code to the code library, **you do not need to worry about the details of the code nor the library, they will be handled by your subordinates.**
|
84 |
+
3. **When workflow 1 and workflow 2 are successfully executed, that means the current step of plan is done.** Do the following:
|
85 |
+
3.1 Reflect on what plan you are having right now.
|
86 |
+
3.2 Reflect on which step of the plan you just finished.
|
87 |
+
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**
|
88 |
+
3.4 Call `update_plan` with the plan you just generated.
|
89 |
+
4. Proceed to the next step of the plan, go back to workflow 1.
|
90 |
+
5. When every step of the plan is done, call the `finish` command, with a summary of what functions are written and saved.
|
91 |
+
|
92 |
+
**You MUST call `update_plan` whenever you realize one step of the plan is done.**
|
93 |
+
|
94 |
+
### Beginning of an example execution: ###
|
95 |
+
Plan: 1. Write a function that fetches weather data from google; 2. Write a function that prints the weather data in a formatted way.
|
96 |
+
You start from step 1 of the plan, execute workflow 1, code is written.
|
97 |
+
You are informed that code is written, you go to workflow 2 to save the code.
|
98 |
+
You are informed that the code is saved, you go to workflow 3 to update the plan:
|
99 |
+
3.1 You recall the plan you have.
|
100 |
+
3.2 You realize step 1 of the plan is done.
|
101 |
+
3.3 You generate the updated plan: 1. Write a function that fetches weather data from google;(DONE) 2. Write a function that prints the weather data in a formatted way.
|
102 |
+
3.4 You call `update_plan` with the generated plan.
|
103 |
+
The updated plan will override the existing plan, you are informed of the behaviour of override.
|
104 |
+
You go on with the next step of the plan, do the same as above.
|
105 |
+
All steps are done, you call `finish`, with a summary of what functions are written and saved to the library.
|
106 |
+
### End of an example of execution ###
|
107 |
+
|
108 |
+
Here is a list of history actions you have taken, for your reference:
|
109 |
+
{{logs}}
|
110 |
+
|
111 |
+
Constraints:
|
112 |
+
1. Exclusively use the commands listed in double quotes e.g. "command name"
|
113 |
+
|
114 |
+
Your response **MUST** be in the following format:
|
115 |
+
Response Format:
|
116 |
+
{
|
117 |
+
"command": "call code writer, the tester, or to finish",
|
118 |
+
"command_args": {
|
119 |
+
"arg name": "args value"
|
120 |
+
}
|
121 |
+
}
|
122 |
+
Ensure your responses can be parsed by Python json.loads
|
123 |
+
|
124 |
+
|
125 |
+
Available Functions:
|
126 |
+
{{commands}}
|
127 |
+
input_variables: ["commands", "plan_file_location", "plan", "logs", "goal"]
|
128 |
+
template_format: jinja2
|
129 |
+
|
130 |
+
human_message_prompt_template:
|
131 |
+
_target_: aiflows.prompt_template.JinjaPrompt
|
132 |
+
template: |2-
|
133 |
+
Here is the result of your previous action:
|
134 |
+
{{result}}
|
135 |
+
input_variables:
|
136 |
+
- "result"
|
137 |
+
template_format: jinja2
|
138 |
+
|
139 |
+
init_human_message_prompt_template:
|
140 |
+
_target_: aiflows.prompt_template.JinjaPrompt
|
141 |
+
template: |2-
|
142 |
+
Here is the goal you need to achieve, follow your plan to finish the goal:
|
143 |
+
{{goal}}
|
144 |
+
input_variables:
|
145 |
+
- "goal"
|
146 |
+
template_format: jinja2
|
147 |
+
|
148 |
+
previous_messages:
|
149 |
+
last_k: 3
|
CtrlExMem_ExtLib.py
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_ExtLib(CtrlExMemFlow):
|
7 |
+
"""This class inherits from the CtrlExMemFlow class from AbstractBossFlowModule.
|
8 |
+
See: https://huggingface.co/Tachi67/AbstractBossFlowModule/blob/main/CtrlExMemFlow.py
|
9 |
+
*Input Interface*:
|
10 |
+
- `plan`
|
11 |
+
- `logs`
|
12 |
+
- `memory_files`
|
13 |
+
- `goal`
|
14 |
+
*Output Interface*
|
15 |
+
- `result` (str): The result of the flow, the result will be returned to the caller.
|
16 |
+
- `summary` (str): The summary of the flow, the summary will be logged into the logs of the caller flow.
|
17 |
+
"""
|
18 |
+
def _on_reach_max_round(self):
|
19 |
+
self._state_update_dict({
|
20 |
+
"result": "the maximum amount of rounds was reached before the extend library flow has done the job",
|
21 |
+
"summary": "ExtendLibraryFlow: the maximum amount of rounds was reached before the flow has done the job",
|
22 |
+
"status": "unfinished"
|
23 |
+
})
|
24 |
+
|
25 |
+
@CircularFlow.output_msg_payload_processor
|
26 |
+
def detect_finish_or_continue(self, output_payload: Dict[str, Any], src_flow) -> Dict[str, Any]:
|
27 |
+
command = output_payload["command"]
|
28 |
+
if command == "finish":
|
29 |
+
return {
|
30 |
+
"EARLY_EXIT": True,
|
31 |
+
"result": output_payload["command_args"]["summary"],
|
32 |
+
"summary": "ExtendLibrary: " + output_payload["command_args"]["summary"],
|
33 |
+
"status": "finished"
|
34 |
+
}
|
35 |
+
elif command == "manual_finish":
|
36 |
+
# ~~~ return the manual quit status ~~~
|
37 |
+
return {
|
38 |
+
"EARLY_EXIT": True,
|
39 |
+
"result": "ExtendLibraryFlow was terminated explicitly by the user, process is unfinished",
|
40 |
+
"summary": "ExtendLibrary: process terminated by the user explicitly, nothing generated",
|
41 |
+
"status": "unfinished"
|
42 |
+
}
|
43 |
+
elif command == "save_code":
|
44 |
+
keys_to_fetch_from_state = ["code", "memory_files"]
|
45 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
46 |
+
output_payload["command_args"]["code"] = fetched_state["code"]
|
47 |
+
output_payload["command_args"]["memory_files"] = fetched_state["memory_files"]
|
48 |
+
return output_payload
|
49 |
+
|
50 |
+
elif command == "update_plan":
|
51 |
+
keys_to_fetch_from_state = ["memory_files"]
|
52 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
53 |
+
output_payload["command_args"]["memory_files"] = fetched_state["memory_files"]
|
54 |
+
return output_payload
|
55 |
+
|
56 |
+
elif command == "re_plan":
|
57 |
+
keys_to_fetch_from_state = ["plan", "memory_files"]
|
58 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
59 |
+
output_payload["command_args"]["plan_file_location"] = fetched_state["memory_files"]["plan"]
|
60 |
+
output_payload["command_args"]["plan"] = fetched_state["plan"]
|
61 |
+
return output_payload
|
62 |
+
|
63 |
+
else:
|
64 |
+
return output_payload
|
CtrlExMem_ExtLib.yaml
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_target_: flow_modules.aiflows.ExtendLibraryFlowModule.CtrlExMem_ExtLib.instantiate_from_default_config
|
2 |
+
name: "CtrlExMem_ExtLibFlow"
|
3 |
+
description: "MemorizedControllerExecutor flow for ExtendLibrary flow"
|
4 |
+
|
5 |
+
subflows_config:
|
6 |
+
Controller:
|
7 |
+
_target_: flow_modules.aiflows.ExtendLibraryFlowModule.ControllerFlow_ExtLib.instantiate_from_default_config
|
8 |
+
backend:
|
9 |
+
api_infos: ???
|
10 |
+
model_name:
|
11 |
+
openai: gpt-4
|
12 |
+
azure: azure/gpt-4
|
13 |
+
Executor:
|
14 |
+
_target_: aiflows.base_flows.BranchingFlow.instantiate_from_default_config
|
15 |
+
subflows_config:
|
16 |
+
write_code:
|
17 |
+
_target_: flow_modules.aiflows.CodeWriterFlowModule.CodeWriterFlow.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_code:
|
28 |
+
subflows_config:
|
29 |
+
CodeGenerator:
|
30 |
+
backend:
|
31 |
+
api_infos: ???
|
32 |
+
model_name:
|
33 |
+
openai: gpt-4
|
34 |
+
azure: azure/gpt-4
|
35 |
+
save_code:
|
36 |
+
_target_: flow_modules.aiflows.ExtendLibraryFlowModule.SaveCodeAtomicFlow.instantiate_from_default_config
|
37 |
+
ask_user:
|
38 |
+
_target_: flow_modules.aiflows.ExtendLibraryFlowModule.ExtLibAskUserFlow.instantiate_from_default_config
|
39 |
+
re_plan:
|
40 |
+
_target_: flow_modules.aiflows.ReplanningFlowModule.ReplanningFlow.instantiate_from_default_config
|
41 |
+
subflows_config:
|
42 |
+
Controller:
|
43 |
+
backend:
|
44 |
+
api_infos: ???
|
45 |
+
model_name:
|
46 |
+
openai: gpt-4
|
47 |
+
azure: azure/gpt-4
|
48 |
+
Executor:
|
49 |
+
subflows_config:
|
50 |
+
write_plan:
|
51 |
+
subflows_config:
|
52 |
+
PlanGenerator:
|
53 |
+
backend:
|
54 |
+
api_infos: ???
|
55 |
+
model_name:
|
56 |
+
openai: gpt-4
|
57 |
+
azure: azure/gpt-4
|
58 |
+
|
59 |
+
update_plan:
|
60 |
+
_target_: flow_modules.aiflows.ExtendLibraryFlowModule.UpdatePlanAtomicFlow.instantiate_from_default_config
|
61 |
+
|
62 |
+
topology:
|
63 |
+
- goal: "Select the next action and prepare the input for the executor."
|
64 |
+
input_interface:
|
65 |
+
_target_: aiflows.interfaces.KeyInterface
|
66 |
+
additional_transformations:
|
67 |
+
- _target_: aiflows.data_transformations.KeyMatchInput
|
68 |
+
flow: Controller
|
69 |
+
output_interface:
|
70 |
+
_target_: CtrlExMem_ExtLib.detect_finish_or_continue
|
71 |
+
reset: false
|
72 |
+
|
73 |
+
- goal: "Execute the action specified by the Controller."
|
74 |
+
input_interface:
|
75 |
+
_target_: aiflows.interfaces.KeyInterface
|
76 |
+
keys_to_rename:
|
77 |
+
command: branch
|
78 |
+
command_args: branch_input_data
|
79 |
+
keys_to_select: ["branch", "branch_input_data"]
|
80 |
+
flow: Executor
|
81 |
+
output_interface:
|
82 |
+
_target_: aiflows.interfaces.KeyInterface
|
83 |
+
keys_to_rename:
|
84 |
+
branch_output_data.code: code
|
85 |
+
branch_output_data.plan: plan
|
86 |
+
branch_output_data.status: status
|
87 |
+
branch_output_data.summary: summary
|
88 |
+
branch_output_data.result: result
|
89 |
+
keys_to_delete: ["branch_output_data"]
|
90 |
+
reset: false
|
91 |
+
|
92 |
+
- goal: "Write memory to memory files"
|
93 |
+
input_interface:
|
94 |
+
_target_: aiflows.interfaces.KeyInterface
|
95 |
+
additional_transformations:
|
96 |
+
- _target_: aiflows.data_transformations.KeyMatchInput
|
97 |
+
flow: MemoryWriting
|
98 |
+
reset: false
|
99 |
+
|
100 |
+
- goal: "Read memory from memory files (flow_state)"
|
101 |
+
input_interface:
|
102 |
+
_target_: aiflows.interfaces.KeyInterface
|
103 |
+
additional_transformations:
|
104 |
+
- _target_: aiflows.data_transformations.KeyMatchInput
|
105 |
+
flow: MemoryReading
|
106 |
+
reset: false
|
ExtLibAskUserFlow.py
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flow_modules.aiflows.HumanStandardInputFlowModule import HumanStandardInputFlow
|
2 |
+
|
3 |
+
from typing import Dict, Any
|
4 |
+
|
5 |
+
from aiflows.messages import UpdateMessage_Generic
|
6 |
+
|
7 |
+
from aiflows.utils import logging
|
8 |
+
|
9 |
+
log = logging.get_logger(f"aiflows.{__name__}")
|
10 |
+
|
11 |
+
# TODO: extract this flow to a seperate flow module for modularity.
|
12 |
+
class ExtLibAskUserFlow(HumanStandardInputFlow):
|
13 |
+
"""This class is used to ask for user feedback whenever the controller is unsure of something, or need confirmation, etc.
|
14 |
+
|
15 |
+
*Expected Input*:
|
16 |
+
- `question`: The question asked by the controller
|
17 |
+
|
18 |
+
*Expected Behaviour*:
|
19 |
+
- The question is displayed, and the user gives feedback by inputing string.
|
20 |
+
|
21 |
+
*Expected Ouput*:
|
22 |
+
- `result`: The input of the user.
|
23 |
+
- `summary`: The summary that will be written by the caller.
|
24 |
+
"""
|
25 |
+
def run(self,
|
26 |
+
input_data: Dict[str, Any]) -> Dict[str, Any]:
|
27 |
+
|
28 |
+
query_message = self._get_message(self.query_message_prompt_template, input_data)
|
29 |
+
state_update_message = UpdateMessage_Generic(
|
30 |
+
created_by=self.flow_config['name'],
|
31 |
+
updated_flow=self.flow_config["name"],
|
32 |
+
data={"query_message": query_message},
|
33 |
+
)
|
34 |
+
self._log_message(state_update_message)
|
35 |
+
|
36 |
+
log.info(query_message)
|
37 |
+
human_input = self._read_input()
|
38 |
+
|
39 |
+
question = input_data["question"]
|
40 |
+
response = {}
|
41 |
+
response["result"] = human_input
|
42 |
+
response["summary"] = f"Question raised: {question}; answer of user: {human_input}"
|
43 |
+
|
44 |
+
return response
|
ExtLibAskUserFlow.yaml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_target_: aiflows.ExtendLibraryFlowModule.ExtLibAskUserFlow.instantiate_from_default_config
|
2 |
+
request_multi_line_input_flag: False
|
3 |
+
end_of_input_string: EOI
|
4 |
+
|
5 |
+
query_message_prompt_template:
|
6 |
+
template: |2-
|
7 |
+
{{question}}
|
8 |
+
input_variables:
|
9 |
+
- "question"
|
ExtendLibraryFlow.py
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
class ExtendLibraryFlow(AbstractBossFlow):
|
7 |
+
"""ExtendLibraryFlow is one branch executor of CoderFlow. At a higher level, it takes the goal
|
8 |
+
from the Coder, writes functions in an interactive way, test the code and append the newly written function to
|
9 |
+
the code library.
|
10 |
+
|
11 |
+
Workflow of ExtendLibrary:
|
12 |
+
0. Coder calls ExtendLibrary with a goal.
|
13 |
+
1. MemoryReading reads logs, plan, and code library.
|
14 |
+
2. Planner makes a plan based on the goal.
|
15 |
+
3. Write code in an interactive fashion.
|
16 |
+
4. Test code.
|
17 |
+
5. Finish, writes code to the library.
|
18 |
+
Step 3-5 is done via prompting the controller.
|
19 |
+
|
20 |
+
*Input Interface (expected input)*
|
21 |
+
- `goal` (str): The goal from the caller (source flow, i.e. CoderFlow)
|
22 |
+
*Output Interface (expected output)*
|
23 |
+
- `result` (str): The result of the flow, the result will be returned to the caller (i.e. CoderFlow).
|
24 |
+
- `summary` (str): The summary of the flow, the summary will be logged into the logs of the caller flow (i.e. CoderFlow).
|
25 |
+
"""
|
26 |
+
def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
|
27 |
+
# ~~~ sets the input_data in the flow_state dict ~~~
|
28 |
+
self._state_update_dict(update_data=input_data)
|
29 |
+
|
30 |
+
# ~~~ set the memory file to the flow state ~~~
|
31 |
+
self._state_update_dict(update_data={"memory_files": self.memory_files})
|
32 |
+
|
33 |
+
max_rounds = self.flow_config.get("max_rounds", 1)
|
34 |
+
if max_rounds is None:
|
35 |
+
log.info(f"Running {self.flow_config['name']} without `max_rounds` until the early exit condition is met.")
|
36 |
+
|
37 |
+
self._sequential_run(max_rounds=max_rounds)
|
38 |
+
|
39 |
+
output = self._get_output_from_state()
|
40 |
+
|
41 |
+
self.reset(full_reset=True, recursive=True, src_flow=self)
|
42 |
+
|
43 |
+
return output
|
ExtendLibraryFlow.yaml
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: ExtendLibraryFlow
|
2 |
+
description: "A flow used to extend the content in the code library"
|
3 |
+
|
4 |
+
_target_: flow_modules.aiflows.ExtendLibraryFlowModule.ExtendLibraryFlow.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.PlanWriterFlowModule.PlanWriterFlow.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.ExtendLibraryFlowModule.CtrlExMem_ExtLib.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 |
+
write_code:
|
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 |
+
memory_files: ???
|
59 |
+
subflows_config:
|
60 |
+
CodeGenerator:
|
61 |
+
backend:
|
62 |
+
api_infos: ???
|
63 |
+
model_name:
|
64 |
+
openai: gpt-4
|
65 |
+
azure: azure/gpt-4
|
66 |
+
test:
|
67 |
+
memory_files: ???
|
68 |
+
re_plan:
|
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_plan:
|
79 |
+
subflows_config:
|
80 |
+
PlanGenerator:
|
81 |
+
backend:
|
82 |
+
api_infos: ???
|
83 |
+
model_name:
|
84 |
+
openai: gpt-4
|
85 |
+
azure: azure/gpt-4
|
86 |
+
MemoryReading:
|
87 |
+
_target_: flow_modules.aiflows.MemoryReadingFlowModule.MemoryReadingAtomicFlow.instantiate_from_default_config
|
88 |
+
output_interface:
|
89 |
+
- "plan"
|
90 |
+
- "logs"
|
91 |
+
- "code_library"
|
README.md
CHANGED
@@ -1,3 +1,264 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
### Structure of ExtendLibraryFlow
|
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 |
+
write_code ask_user re_plan update_plan save_code
|
78 |
+
|
79 |
+
```
|
80 |
+
|
81 |
+
Memory files of ExtendLibraryFlow:
|
82 |
+
- plan_extlib.txt
|
83 |
+
- logs_extlib.txt
|
84 |
+
- library.py
|
85 |
+
|
86 |
+
About the branches:
|
87 |
+
- [write_code](https://huggingface.co/Tachi67/CodeWriterFlowModule): Generates code in an interactive way, the user is able to edit or provide feedback during the process of writing code.
|
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 |
+
- [save_code](https://huggingface.co/Tachi67/ExtendLibraryFlowModule/blob/main/SaveCodeAtomicFlow.py): Writes the wriiten & tested code to the code library.
|
92 |
+
|
93 |
+
|
94 |
+
# Table of Contents
|
95 |
+
|
96 |
+
* [SaveCodeAtomicFlow](#SaveCodeAtomicFlow)
|
97 |
+
* [SaveCodeAtomicFlow](#SaveCodeAtomicFlow.SaveCodeAtomicFlow)
|
98 |
+
* [run](#SaveCodeAtomicFlow.SaveCodeAtomicFlow.run)
|
99 |
+
* [ExtLibAskUserFlow](#ExtLibAskUserFlow)
|
100 |
+
* [ExtLibAskUserFlow](#ExtLibAskUserFlow.ExtLibAskUserFlow)
|
101 |
+
* [ExtendLibraryFlow](#ExtendLibraryFlow)
|
102 |
+
* [ExtendLibraryFlow](#ExtendLibraryFlow.ExtendLibraryFlow)
|
103 |
+
* [UpdatePlanAtomicFlow](#UpdatePlanAtomicFlow)
|
104 |
+
* [UpdatePlanAtomicFlow](#UpdatePlanAtomicFlow.UpdatePlanAtomicFlow)
|
105 |
+
* [run\_ExtendLibrary](#run_ExtendLibrary)
|
106 |
+
* [CtrlExMem\_ExtLib](#CtrlExMem_ExtLib)
|
107 |
+
* [CtrlExMem\_ExtLib](#CtrlExMem_ExtLib.CtrlExMem_ExtLib)
|
108 |
+
* [ControllerFlow\_ExtLib](#ControllerFlow_ExtLib)
|
109 |
+
* [ControllerFlow\_ExtLib](#ControllerFlow_ExtLib.ControllerFlow_ExtLib)
|
110 |
+
* [\_\_init\_\_](#__init__)
|
111 |
+
|
112 |
+
<a id="SaveCodeAtomicFlow"></a>
|
113 |
+
|
114 |
+
# SaveCodeAtomicFlow
|
115 |
+
|
116 |
+
<a id="SaveCodeAtomicFlow.SaveCodeAtomicFlow"></a>
|
117 |
+
|
118 |
+
## SaveCodeAtomicFlow Objects
|
119 |
+
|
120 |
+
```python
|
121 |
+
class SaveCodeAtomicFlow(AtomicFlow)
|
122 |
+
```
|
123 |
+
|
124 |
+
This flow appends the code to the code library file.
|
125 |
+
*Input Interface*:
|
126 |
+
- `code` (str): the code to be appended to the code library
|
127 |
+
- `memory_files` (dict): the dictionary of memory files
|
128 |
+
|
129 |
+
*Output Interface*:
|
130 |
+
- `result` (str): the result of the flow, to be returned to the controller of the caller
|
131 |
+
- `summary` (str): the summary of the flow, to be appended to logs
|
132 |
+
|
133 |
+
<a id="SaveCodeAtomicFlow.SaveCodeAtomicFlow.run"></a>
|
134 |
+
|
135 |
+
#### run
|
136 |
+
|
137 |
+
```python
|
138 |
+
def run(input_data: Dict[str, Any])
|
139 |
+
```
|
140 |
+
|
141 |
+
Run the flow
|
142 |
+
|
143 |
+
**Arguments**:
|
144 |
+
|
145 |
+
- `input_data`: the input data
|
146 |
+
|
147 |
+
**Returns**:
|
148 |
+
|
149 |
+
the output data
|
150 |
+
|
151 |
+
<a id="ExtLibAskUserFlow"></a>
|
152 |
+
|
153 |
+
# ExtLibAskUserFlow
|
154 |
+
|
155 |
+
<a id="ExtLibAskUserFlow.ExtLibAskUserFlow"></a>
|
156 |
+
|
157 |
+
## ExtLibAskUserFlow Objects
|
158 |
+
|
159 |
+
```python
|
160 |
+
class ExtLibAskUserFlow(HumanStandardInputFlow)
|
161 |
+
```
|
162 |
+
|
163 |
+
This class is used to ask for user feedback whenever the controller is unsure of something, or need confirmation, etc.
|
164 |
+
|
165 |
+
*Expected Input*:
|
166 |
+
- `question`: The question asked by the controller
|
167 |
+
|
168 |
+
*Expected Behaviour*:
|
169 |
+
- The question is displayed, and the user gives feedback by inputing string.
|
170 |
+
|
171 |
+
*Expected Ouput*:
|
172 |
+
- `result`: The input of the user.
|
173 |
+
- `summary`: The summary that will be written by the caller.
|
174 |
+
|
175 |
+
<a id="ExtendLibraryFlow"></a>
|
176 |
+
|
177 |
+
# ExtendLibraryFlow
|
178 |
+
|
179 |
+
<a id="ExtendLibraryFlow.ExtendLibraryFlow"></a>
|
180 |
+
|
181 |
+
## ExtendLibraryFlow Objects
|
182 |
+
|
183 |
+
```python
|
184 |
+
class ExtendLibraryFlow(AbstractBossFlow)
|
185 |
+
```
|
186 |
+
|
187 |
+
ExtendLibraryFlow is one branch executor of CoderFlow. At a higher level, it takes the goal
|
188 |
+
from the Coder, writes functions in an interactive way, test the code and append the newly written function to
|
189 |
+
the code library.
|
190 |
+
|
191 |
+
Workflow of ExtendLibrary:
|
192 |
+
0. Coder calls ExtendLibrary with a goal.
|
193 |
+
1. MemoryReading reads logs, plan, and code library.
|
194 |
+
2. Planner makes a plan based on the goal.
|
195 |
+
3. Write code in an interactive fashion.
|
196 |
+
4. Test code.
|
197 |
+
5. Finish, writes code to the library.
|
198 |
+
Step 3-5 is done via prompting the controller.
|
199 |
+
|
200 |
+
*Input Interface (expected input)*
|
201 |
+
- `goal` (str): The goal from the caller (source flow, i.e. CoderFlow)
|
202 |
+
*Output Interface (expected output)*
|
203 |
+
- `result` (str): The result of the flow, the result will be returned to the caller (i.e. CoderFlow).
|
204 |
+
- `summary` (str): The summary of the flow, the summary will be logged into the logs of the caller flow (i.e. CoderFlow).
|
205 |
+
|
206 |
+
<a id="UpdatePlanAtomicFlow"></a>
|
207 |
+
|
208 |
+
# UpdatePlanAtomicFlow
|
209 |
+
|
210 |
+
<a id="UpdatePlanAtomicFlow.UpdatePlanAtomicFlow"></a>
|
211 |
+
|
212 |
+
## UpdatePlanAtomicFlow Objects
|
213 |
+
|
214 |
+
```python
|
215 |
+
class UpdatePlanAtomicFlow(AtomicFlow)
|
216 |
+
```
|
217 |
+
|
218 |
+
Refer to: https://huggingface.co/Tachi67/CoderFlowModule/blob/main/UpdatePlanAtomicFlow.py
|
219 |
+
|
220 |
+
<a id="run_ExtendLibrary"></a>
|
221 |
+
|
222 |
+
# run\_ExtendLibrary
|
223 |
+
|
224 |
+
<a id="CtrlExMem_ExtLib"></a>
|
225 |
+
|
226 |
+
# CtrlExMem\_ExtLib
|
227 |
+
|
228 |
+
<a id="CtrlExMem_ExtLib.CtrlExMem_ExtLib"></a>
|
229 |
+
|
230 |
+
## CtrlExMem\_ExtLib Objects
|
231 |
+
|
232 |
+
```python
|
233 |
+
class CtrlExMem_ExtLib(CtrlExMemFlow)
|
234 |
+
```
|
235 |
+
|
236 |
+
This class inherits from the CtrlExMemFlow class from AbstractBossFlowModule.
|
237 |
+
See: https://huggingface.co/Tachi67/AbstractBossFlowModule/blob/main/CtrlExMemFlow.py
|
238 |
+
*Input Interface*:
|
239 |
+
- `plan`
|
240 |
+
- `logs`
|
241 |
+
- `memory_files`
|
242 |
+
- `goal`
|
243 |
+
*Output Interface*
|
244 |
+
- `result` (str): The result of the flow, the result will be returned to the caller.
|
245 |
+
- `summary` (str): The summary of the flow, the summary will be logged into the logs of the caller flow.
|
246 |
+
|
247 |
+
<a id="ControllerFlow_ExtLib"></a>
|
248 |
+
|
249 |
+
# ControllerFlow\_ExtLib
|
250 |
+
|
251 |
+
<a id="ControllerFlow_ExtLib.ControllerFlow_ExtLib"></a>
|
252 |
+
|
253 |
+
## ControllerFlow\_ExtLib Objects
|
254 |
+
|
255 |
+
```python
|
256 |
+
class ControllerFlow_ExtLib(ChatAtomicFlow)
|
257 |
+
```
|
258 |
+
|
259 |
+
Refer to: https://huggingface.co/Tachi67/JarvisFlowModule/blob/main/Controller_JarvisFlow.py
|
260 |
+
|
261 |
+
<a id="__init__"></a>
|
262 |
+
|
263 |
+
# \_\_init\_\_
|
264 |
+
|
SaveCodeAtomicFlow.py
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Dict, Any
|
2 |
+
from aiflows.base_flows.atomic import AtomicFlow
|
3 |
+
|
4 |
+
|
5 |
+
class SaveCodeAtomicFlow(AtomicFlow):
|
6 |
+
"""This flow appends the code to the code library file.
|
7 |
+
*Input Interface*:
|
8 |
+
- `code` (str): the code to be appended to the code library
|
9 |
+
- `memory_files` (dict): the dictionary of memory files
|
10 |
+
|
11 |
+
*Output Interface*:
|
12 |
+
- `result` (str): the result of the flow, to be returned to the controller of the caller
|
13 |
+
- `summary` (str): the summary of the flow, to be appended to logs
|
14 |
+
"""
|
15 |
+
def _check_input(self, input_data: Dict[str, Any]):
|
16 |
+
"""Check if the input data is valid
|
17 |
+
:param input_data: the input data
|
18 |
+
:return: None
|
19 |
+
"""
|
20 |
+
assert "code" in input_data, "code is not passed to SaveCodeAtomicFlow"
|
21 |
+
assert "memory_files" in input_data, "memory_files is not passed to SaveCodeFlow"
|
22 |
+
assert "code_library" in input_data["memory_files"], "code_library not in memory_files"
|
23 |
+
# create the code library if it doesn't exist yet
|
24 |
+
code_library_location = input_data["memory_files"]["code_library"]
|
25 |
+
with open(code_library_location, 'a') as file:
|
26 |
+
pass
|
27 |
+
|
28 |
+
def _call(self, input_data: Dict[str, Any]):
|
29 |
+
"""The internal logic of the flow
|
30 |
+
:param input_data: the input data
|
31 |
+
:return: the output data
|
32 |
+
"""
|
33 |
+
try:
|
34 |
+
code_to_append = input_data["code"]
|
35 |
+
code_lib_loc = input_data["memory_files"]["code_library"]
|
36 |
+
with open(code_lib_loc, 'a') as file:
|
37 |
+
file.write(code_to_append + '\n')
|
38 |
+
return {
|
39 |
+
"result": "code successfully written to the library",
|
40 |
+
"summary": f"ExtendLibrayFlow/SaveCodeAtomicFlow: code written to {code_lib_loc}"
|
41 |
+
}
|
42 |
+
except Exception as e:
|
43 |
+
error_msg = str(e)
|
44 |
+
return {
|
45 |
+
"result": f"error occurred: {error_msg}",
|
46 |
+
"summary": f"ExtendLibrayFlow/SaveCodeAtomicFlow: error occurred: {error_msg}"
|
47 |
+
}
|
48 |
+
|
49 |
+
def run(
|
50 |
+
self,
|
51 |
+
input_data: Dict[str, Any]
|
52 |
+
):
|
53 |
+
"""Run the flow
|
54 |
+
:param input_data: the input data
|
55 |
+
:return: the output data
|
56 |
+
"""
|
57 |
+
self._check_input(input_data)
|
58 |
+
return self._call(input_data)
|
SaveCodeAtomicFlow.yaml
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_target_: aiflows.ExtendLibraryFlowModule.SaveCodeAtomicFlow.instantiate_from_default_config
|
2 |
+
name: "SaveCodeAtomicFlow"
|
3 |
+
description: "In extend library flow, once the code is written and tested, the controller calls this flow to save the code to the library."
|
4 |
+
|
5 |
+
input_interface:
|
6 |
+
- "memory_files"
|
7 |
+
- "code"
|
8 |
+
|
9 |
+
output_interface:
|
10 |
+
- "result"
|
11 |
+
- "summary"
|
UpdatePlanAtomicFlow.py
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Dict, Any
|
2 |
+
from aiflows.base_flows.atomic import AtomicFlow
|
3 |
+
class UpdatePlanAtomicFlow(AtomicFlow):
|
4 |
+
"""Refer to: https://huggingface.co/Tachi67/CoderFlowModule/blob/main/UpdatePlanAtomicFlow.py"""
|
5 |
+
def _check_input(self, input_data: Dict[str, Any]):
|
6 |
+
assert "memory_files" in input_data, "memory_files not passed to UpdatePlanAtomicFlow"
|
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"ExtendLibrary/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"ExtendLibrary/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_: flow_modules.aiflows.ExtendLibraryFlowModule.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,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
dependencies = [
|
2 |
+
{"url": "aiflows/AbstractBossFlowModule", "revision": "main"},
|
3 |
+
{"url": "aiflows/MemoryReadingFlowModule", "revision": "main"},
|
4 |
+
{"url": "aiflows/PlanWriterFlowModule", "revision": "main"},
|
5 |
+
{"url": "aiflows/ReplanningFlowModule", "revision": "main"},
|
6 |
+
{"url": "aiflows/CodeWriterFlowModule", "revision": "main"},
|
7 |
+
{"url": "aiflows/HumanStandardInputFlowModule", "revision": "4ff043522c89a964ea3a928ce09811c51a2b5b98"},
|
8 |
+
{"url": "aiflows/ChatFlowModule", "revision": "297c90d08087d9ff3139521f11d1a48d7dc63ed4"},
|
9 |
+
]
|
10 |
+
|
11 |
+
from aiflows import flow_verse
|
12 |
+
flow_verse.sync_dependencies(dependencies)
|
13 |
+
from .ControllerFlow_ExtLib import ControllerFlow_ExtLib
|
14 |
+
from .CtrlExMem_ExtLib import CtrlExMem_ExtLib
|
15 |
+
from .ExtendLibraryFlow import ExtendLibraryFlow
|
16 |
+
from .ExtLibAskUserFlow import ExtLibAskUserFlow
|
17 |
+
from .SaveCodeAtomicFlow import SaveCodeAtomicFlow
|
18 |
+
from .UpdatePlanAtomicFlow import UpdatePlanAtomicFlow
|
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_ExtendLibrary.py
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
9 |
+
from aiflows import logging
|
10 |
+
from aiflows.flow_cache import CACHING_PARAMETERS, clear_cache
|
11 |
+
from aiflows.utils.general_helpers import quick_load
|
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/ExtendLibraryFlowModule", "revision": "main"},
|
23 |
+
{"url": "aiflows/AbstractBossFlowModule", "revision": "main"},
|
24 |
+
{"url": "aiflows/MemoryReadingFlowModule", "revision": "main"},
|
25 |
+
{"url": "aiflows/PlanWriterFlowModule", "revision": "main"},
|
26 |
+
{"url": "aiflows/ReplanningFlowModule", "revision": "main"},
|
27 |
+
{"url": "aiflows/CodeWriterFlowModule", "revision": "main"},
|
28 |
+
]
|
29 |
+
|
30 |
+
from aiflows import flow_verse
|
31 |
+
|
32 |
+
flow_verse.sync_dependencies(dependencies)
|
33 |
+
|
34 |
+
if __name__ == "__main__":
|
35 |
+
# ~~~ make sure to set the openai api key in the envs ~~~
|
36 |
+
key = os.getenv("OPENAI_API_KEY")
|
37 |
+
api_information = [ApiInfo(backend_used="openai", api_key=os.getenv("OPENAI_API_KEY"))]
|
38 |
+
path_to_output_file = None
|
39 |
+
|
40 |
+
current_dir = os.getcwd()
|
41 |
+
cfg_path = os.path.join(current_dir, "ExtendLibraryFlow.yaml")
|
42 |
+
cfg = read_yaml_file(cfg_path)
|
43 |
+
# ~~~ setting api information into config ~~~
|
44 |
+
quick_load(cfg, api_information)
|
45 |
+
|
46 |
+
# ~~~ setting memory files into config ~~~
|
47 |
+
code_lib_file_loc = os.path.join(current_dir, "library.py")
|
48 |
+
plan_file_loc = os.path.join(current_dir, "plan_extlib.txt")
|
49 |
+
logs_file_loc = os.path.join(current_dir, "logs_extlib.txt")
|
50 |
+
with open(code_lib_file_loc, 'w') as file:
|
51 |
+
pass
|
52 |
+
with open(plan_file_loc, 'w') as file:
|
53 |
+
pass
|
54 |
+
with open(logs_file_loc, 'w') as file:
|
55 |
+
pass
|
56 |
+
memfiles_extlib = {}
|
57 |
+
memfiles_writecode_interactivecoder = {}
|
58 |
+
memfiles_writecode_test = {}
|
59 |
+
memfiles_extlib["plan"] = plan_file_loc
|
60 |
+
memfiles_extlib["logs"] = 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_extlib
|
65 |
+
cfg["subflows_config"]["CtrlExMem"]["subflows_config"]["Executor"]["subflows_config"]["write_code"]["subflows_config"]["Executor"]["subflows_config"]["write_code"]["memory_files"] = memfiles_writecode_interactivecoder
|
66 |
+
cfg["subflows_config"]["CtrlExMem"]["subflows_config"]["Executor"]["subflows_config"]["write_code"]["subflows_config"]["Executor"]["subflows_config"]["test"]["memory_files"] = memfiles_writecode_test
|
67 |
+
|
68 |
+
|
69 |
+
# ~~~ instantiating the flow and input data ~~~
|
70 |
+
ExtendLibraryFlow = hydra.utils.instantiate(cfg, _recursive_=False, _convert_="partial")
|
71 |
+
input_data = {
|
72 |
+
"goal": "Write a function that adds up two numbers",
|
73 |
+
}
|
74 |
+
input_message = InputMessage.build(
|
75 |
+
data_dict=input_data,
|
76 |
+
src_flow="Launcher",
|
77 |
+
dst_flow=ExtendLibraryFlow.name
|
78 |
+
)
|
79 |
+
|
80 |
+
# ~~~ calling the flow ~~~
|
81 |
+
output_message = ExtendLibraryFlow(input_message)
|