Upload 13 files
Browse files- ControllerFlow_ExtLib.py +114 -0
- ControllerFlow_ExtLib.yaml +134 -0
- CtrlExMem_ExtLib.py +53 -0
- CtrlExMem_ExtLib.yaml +102 -0
- ExtLibAskUserFlow.py +30 -0
- ExtLibAskUserFlow.yaml +9 -0
- ExtendLibraryFlow.py +4 -0
- ExtendLibraryFlow.yaml +77 -0
- SaveCodeAtomicFlow.py +37 -0
- SaveCodeAtomicFlow.yaml +11 -0
- UpdatePlanAtomicFlow.py +29 -0
- UpdatePlanAtomicFlow.yaml +9 -0
- __init__.py +16 -0
ControllerFlow_ExtLib.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
def __init__(
|
| 18 |
+
self,
|
| 19 |
+
commands: List[Command],
|
| 20 |
+
**kwargs):
|
| 21 |
+
super().__init__(**kwargs)
|
| 22 |
+
self.system_message_prompt_template = self.system_message_prompt_template.partial(
|
| 23 |
+
commands=self._build_commands_manual(commands),
|
| 24 |
+
plan_file_location="no location yet",
|
| 25 |
+
plan="no plan yet",
|
| 26 |
+
logs="no logs yet",
|
| 27 |
+
)
|
| 28 |
+
self.hint_for_model = """
|
| 29 |
+
Make sure your response is in the following format:
|
| 30 |
+
Response Format:
|
| 31 |
+
{
|
| 32 |
+
"command": "call one of the commands you have e.g. `write_code`",
|
| 33 |
+
"command_args": {
|
| 34 |
+
"arg name": "value"
|
| 35 |
+
}
|
| 36 |
+
}
|
| 37 |
+
"""
|
| 38 |
+
|
| 39 |
+
@staticmethod
|
| 40 |
+
def _build_commands_manual(commands: List[Command]) -> str:
|
| 41 |
+
ret = ""
|
| 42 |
+
for i, command in enumerate(commands):
|
| 43 |
+
command_input_json_schema = json.dumps(
|
| 44 |
+
{input_arg: f"YOUR_{input_arg.upper()}" for input_arg in command.input_args})
|
| 45 |
+
ret += f"{i + 1}. {command.name}: {command.description} Input arguments (given in the JSON schema): {command_input_json_schema}\n"
|
| 46 |
+
return ret
|
| 47 |
+
|
| 48 |
+
def _get_plan_file_location(self, input_data: Dict[str, Any]):
|
| 49 |
+
assert "memory_files" in input_data, "memory_files not passed to Extlib/Controller"
|
| 50 |
+
assert "plan" in input_data["memory_files"], "plan not in memory files"
|
| 51 |
+
return input_data["memory_files"]["plan"]
|
| 52 |
+
|
| 53 |
+
def _get_plan_content(self, input_data: Dict[str, Any]):
|
| 54 |
+
assert "plan" in input_data, "plan not passed to Extlib/Controller"
|
| 55 |
+
plan_content = input_data["plan"]
|
| 56 |
+
if len(plan_content) == 0:
|
| 57 |
+
plan_content = 'No plan yet'
|
| 58 |
+
return plan_content
|
| 59 |
+
|
| 60 |
+
def _get_logs_content(self, input_data: Dict[str, Any]):
|
| 61 |
+
assert "logs" in input_data, "logs not passed to Extlib/Controller"
|
| 62 |
+
logs_content = input_data["logs"]
|
| 63 |
+
if len(logs_content) == 0:
|
| 64 |
+
logs_content = "No logs yet"
|
| 65 |
+
return logs_content
|
| 66 |
+
|
| 67 |
+
@classmethod
|
| 68 |
+
def instantiate_from_config(cls, config):
|
| 69 |
+
flow_config = deepcopy(config)
|
| 70 |
+
|
| 71 |
+
kwargs = {"flow_config": flow_config}
|
| 72 |
+
|
| 73 |
+
# ~~~ Set up prompts ~~~
|
| 74 |
+
kwargs.update(cls._set_up_prompts(flow_config))
|
| 75 |
+
|
| 76 |
+
# ~~~Set up backend ~~~
|
| 77 |
+
kwargs.update(cls._set_up_backend(flow_config))
|
| 78 |
+
|
| 79 |
+
# ~~~ Set up commands ~~~
|
| 80 |
+
commands = flow_config["commands"]
|
| 81 |
+
commands = [
|
| 82 |
+
Command(name, command_conf["description"], command_conf["input_args"]) for name, command_conf in
|
| 83 |
+
commands.items()
|
| 84 |
+
]
|
| 85 |
+
kwargs.update({"commands": commands})
|
| 86 |
+
|
| 87 |
+
# ~~~ Instantiate flow ~~~
|
| 88 |
+
return cls(**kwargs)
|
| 89 |
+
|
| 90 |
+
def _update_prompts_and_input(self, input_data: Dict[str, Any]):
|
| 91 |
+
if 'goal' in input_data:
|
| 92 |
+
input_data['goal'] += self.hint_for_model
|
| 93 |
+
if 'result' in input_data:
|
| 94 |
+
input_data['result'] += self.hint_for_model
|
| 95 |
+
plan_file_location = self._get_plan_file_location(input_data)
|
| 96 |
+
plan_content = self._get_plan_content(input_data)
|
| 97 |
+
logs_content = self._get_logs_content(input_data)
|
| 98 |
+
self.system_message_prompt_template = self.system_message_prompt_template.partial(
|
| 99 |
+
plan_file_location=plan_file_location,
|
| 100 |
+
plan=plan_content,
|
| 101 |
+
logs=logs_content
|
| 102 |
+
)
|
| 103 |
+
|
| 104 |
+
def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
|
| 105 |
+
self._update_prompts_and_input(input_data)
|
| 106 |
+
api_output = super().run(input_data)["api_output"].strip()
|
| 107 |
+
try:
|
| 108 |
+
response = json.loads(api_output)
|
| 109 |
+
return response
|
| 110 |
+
except json.decoder.JSONDecodeError:
|
| 111 |
+
new_input_data = input_data.copy()
|
| 112 |
+
new_input_data['result'] = "The previous respond cannot be parsed with json.loads. Make sure your next response is in JSON format."
|
| 113 |
+
new_api_output = super().run(new_input_data)["api_output"].strip()
|
| 114 |
+
return json.loads(new_api_output)
|
ControllerFlow_ExtLib.yaml
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: Tachi67.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 |
+
|
| 13 |
+
input_interface_initialized:
|
| 14 |
+
- "result"
|
| 15 |
+
|
| 16 |
+
#######################################################
|
| 17 |
+
# Output keys
|
| 18 |
+
#######################################################
|
| 19 |
+
|
| 20 |
+
output_interface:
|
| 21 |
+
- 'command'
|
| 22 |
+
- 'command_args'
|
| 23 |
+
|
| 24 |
+
backend:
|
| 25 |
+
api_infos: ???
|
| 26 |
+
model_name:
|
| 27 |
+
openai: gpt-4
|
| 28 |
+
azure: azure/gpt-4
|
| 29 |
+
|
| 30 |
+
commands:
|
| 31 |
+
write_code:
|
| 32 |
+
description: "Write code to finish the current step of plan with user interaction"
|
| 33 |
+
input_args: ["goal"]
|
| 34 |
+
save_code:
|
| 35 |
+
description: "When code is written by the coder, save the code to the library"
|
| 36 |
+
input_args: []
|
| 37 |
+
re_plan:
|
| 38 |
+
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."
|
| 39 |
+
input_args: ["goal"]
|
| 40 |
+
finish:
|
| 41 |
+
description: "Signal that the objective has been satisfied, return the summary of what was done"
|
| 42 |
+
input_args: ["summary"]
|
| 43 |
+
manual_finish:
|
| 44 |
+
description: "The user demands to quit and terminate the current process"
|
| 45 |
+
input_args: []
|
| 46 |
+
ask_user:
|
| 47 |
+
description: "Ask user a question for confirmation or assistance"
|
| 48 |
+
input_args: ["question"]
|
| 49 |
+
update_plan:
|
| 50 |
+
description: "Pass the updated plan to edit plan file and override current plan"
|
| 51 |
+
input_args: ["updated_plan"]
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
system_message_prompt_template:
|
| 55 |
+
_target_: langchain.PromptTemplate
|
| 56 |
+
template: |2-
|
| 57 |
+
Your department is in charge of writing code and extending the code library with the code written. You are the leader of this department.
|
| 58 |
+
|
| 59 |
+
You work with several subordinates, they will be in charge of the specific tasks, including writing code, saving code to the library, etc.
|
| 60 |
+
|
| 61 |
+
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}}:
|
| 62 |
+
{{plan}}
|
| 63 |
+
|
| 64 |
+
Your **ONLY** task is to take the user's goal for you, to decide which command to call.
|
| 65 |
+
|
| 66 |
+
You **must not** write code nor write plan yourself. You only decide whether to call the coder with specified goals or to finish.
|
| 67 |
+
|
| 68 |
+
Each step of the plan should involve writing one function, **for each step in the plan, your workflow**:
|
| 69 |
+
0.1 Whenever the user demands to quit or terminate the current process, call `manual_finish` command.
|
| 70 |
+
0.2 Whenever in double, or you have something to ask, or confirm to the user, call `ask_user` with your question.
|
| 71 |
+
0.3 During the execution of the plan, if something goes wrong, call the `re_plan` with detailed information about what was wrong.
|
| 72 |
+
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.
|
| 73 |
+
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.**
|
| 74 |
+
3. **When workflow 1 and workflow 2 are successfully executed, that means the current step of plan is done.** Do the following:
|
| 75 |
+
3.1 Reflect on what plan you are having right now.
|
| 76 |
+
3.2 Reflect on which step of the plan you just finished.
|
| 77 |
+
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**
|
| 78 |
+
3.4 Call `update_plan` with the plan you just generated.
|
| 79 |
+
4. Proceed to the next step of the plan, go back to workflow 1.
|
| 80 |
+
5. When every step of the plan is done, call the `finish` command, with a summary of what functions are written and saved.
|
| 81 |
+
|
| 82 |
+
### Beginning of an example execution: ###
|
| 83 |
+
Plan: 1. Write a function that fetches weather data from google; 2. Write a function that prints the weather data in a formatted way.
|
| 84 |
+
You start from step 1 of the plan, execute workflow 1, code is written.
|
| 85 |
+
You are informed that code is written, you go to workflow 2 to save the code.
|
| 86 |
+
You are informed that the code is saved, you go to workflow 3 to update the plan:
|
| 87 |
+
3.1 You recall the plan you have.
|
| 88 |
+
3.2 You realize step 1 of the plan is done.
|
| 89 |
+
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.
|
| 90 |
+
3.4 You call `update_plan` with the generated plan.
|
| 91 |
+
The updated plan will override the existing plan, you are informed of the behaviour of override.
|
| 92 |
+
You go on with the next step of the plan, do the same as above.
|
| 93 |
+
All steps are done, you call `finish`, with a summary of what functions are written and saved to the library.
|
| 94 |
+
### End of an example of execution ###
|
| 95 |
+
|
| 96 |
+
Here is a list of history actions you have taken, for your reference:
|
| 97 |
+
{{logs}}
|
| 98 |
+
|
| 99 |
+
Constraints:
|
| 100 |
+
1. Exclusively use the commands listed in double quotes e.g. "command name"
|
| 101 |
+
|
| 102 |
+
Your response **MUST** be in the following format:
|
| 103 |
+
Response Format:
|
| 104 |
+
{
|
| 105 |
+
"command": "call code writer, the tester, or to finish",
|
| 106 |
+
"command_args": {
|
| 107 |
+
"arg name": "value"
|
| 108 |
+
}
|
| 109 |
+
}
|
| 110 |
+
Ensure your responses can be parsed by Python json.loads
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
Available Functions:
|
| 114 |
+
{{commands}}
|
| 115 |
+
input_variables: ["commands", "plan_file_location", "plan", "logs"]
|
| 116 |
+
template_format: jinja2
|
| 117 |
+
|
| 118 |
+
human_message_prompt_template:
|
| 119 |
+
_target_: flows.prompt_template.JinjaPrompt
|
| 120 |
+
template: |2-
|
| 121 |
+
Here is the result of your previous action:
|
| 122 |
+
{{result}}
|
| 123 |
+
input_variables:
|
| 124 |
+
- "result"
|
| 125 |
+
template_format: jinja2
|
| 126 |
+
|
| 127 |
+
init_human_message_prompt_template:
|
| 128 |
+
_target_: flows.prompt_template.JinjaPrompt
|
| 129 |
+
template: |2-
|
| 130 |
+
Here is the goal you need to achieve, follow your plan to finish the goal:
|
| 131 |
+
{{goal}}
|
| 132 |
+
input_variables:
|
| 133 |
+
- "goal"
|
| 134 |
+
template_format: jinja2
|
CtrlExMem_ExtLib.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Dict, Any
|
| 2 |
+
|
| 3 |
+
from flow_modules.Tachi67.AbstractBossFlowModule import CtrlExMemFlow
|
| 4 |
+
from flows.base_flows import CircularFlow
|
| 5 |
+
|
| 6 |
+
class CtrlExMem_ExtLib(CtrlExMemFlow):
|
| 7 |
+
def _on_reach_max_round(self):
|
| 8 |
+
self._state_update_dict({
|
| 9 |
+
"answer": "the maximum amount of rounds was reached before the extend library flow has done the job",
|
| 10 |
+
"summary": "ExtendLibraryFlow: the maximum amount of rounds was reached before the flow has done the job",
|
| 11 |
+
"status": "unfinished"
|
| 12 |
+
})
|
| 13 |
+
|
| 14 |
+
@CircularFlow.output_msg_payload_processor
|
| 15 |
+
def detect_finish_or_continue(self, output_payload: Dict[str, Any], src_flow) -> Dict[str, Any]:
|
| 16 |
+
command = output_payload["command"]
|
| 17 |
+
if command == "finish":
|
| 18 |
+
return {
|
| 19 |
+
"EARLY_EXIT": True,
|
| 20 |
+
"answer": output_payload["command_args"]["summary"],
|
| 21 |
+
"summary": "ExtendLibrary: " + output_payload["command_args"]["summary"],
|
| 22 |
+
"status": "finished"
|
| 23 |
+
}
|
| 24 |
+
elif command == "manual_finish":
|
| 25 |
+
# ~~~ return the manual quit status ~~~
|
| 26 |
+
return {
|
| 27 |
+
"EARLY_EXIT": True,
|
| 28 |
+
"answer": "ExtendLibraryFlow was terminated explicitly by the user, process is unfinished",
|
| 29 |
+
"summary": "ExtendLibrary: process terminated by the user explicitly, nothing generated",
|
| 30 |
+
"status": "unfinished"
|
| 31 |
+
}
|
| 32 |
+
elif command == "save_code":
|
| 33 |
+
keys_to_fetch_from_state = ["code", "memory_files"]
|
| 34 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
| 35 |
+
output_payload["command_args"]["code"] = fetched_state["code"]
|
| 36 |
+
output_payload["command_args"]["memory_files"] = fetched_state["memory_files"]
|
| 37 |
+
return output_payload
|
| 38 |
+
|
| 39 |
+
elif command == "update_plan":
|
| 40 |
+
keys_to_fetch_from_state = ["memory_files"]
|
| 41 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
| 42 |
+
output_payload["command_args"]["memory_files"] = fetched_state["memory_files"]
|
| 43 |
+
return output_payload
|
| 44 |
+
|
| 45 |
+
elif command == "re_plan":
|
| 46 |
+
keys_to_fetch_from_state = ["plan", "memory_files"]
|
| 47 |
+
fetched_state = self._fetch_state_attributes_by_keys(keys=keys_to_fetch_from_state)
|
| 48 |
+
output_payload["command_args"]["plan_file_location"] = fetched_state["memory_files"]["plan"]
|
| 49 |
+
output_payload["command_args"]["plan"] = fetched_state["plan"]
|
| 50 |
+
return output_payload
|
| 51 |
+
|
| 52 |
+
else:
|
| 53 |
+
return output_payload
|
CtrlExMem_ExtLib.yaml
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: Tachi67.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_: Tachi67.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_: flows.base_flows.BranchingFlow.instantiate_from_default_config
|
| 15 |
+
subflows_config:
|
| 16 |
+
write_code:
|
| 17 |
+
_target_: Tachi67.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_: Tachi67.ExtendLibraryFlowModule.SaveCodeAtomicFlow.instantiate_from_default_config
|
| 37 |
+
ask_user:
|
| 38 |
+
_target_: Tachi67.ExtendLibraryFlowModule.ExtLibAskUserFlow.instantiate_from_default_config
|
| 39 |
+
re_plan:
|
| 40 |
+
_target_: Tachi67.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_: Tachi67.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_: flows.interfaces.KeyInterface
|
| 66 |
+
additional_transformations:
|
| 67 |
+
- _target_: flows.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_: flows.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_: flows.interfaces.KeyInterface
|
| 83 |
+
keys_to_rename:
|
| 84 |
+
branch_output_data: observation
|
| 85 |
+
keys_to_unpack: ["observation"]
|
| 86 |
+
reset: false
|
| 87 |
+
|
| 88 |
+
- goal: "Write memory to memory files"
|
| 89 |
+
input_interface:
|
| 90 |
+
_target_: flows.interfaces.KeyInterface
|
| 91 |
+
additional_transformations:
|
| 92 |
+
- _target_: flows.data_transformations.KeyMatchInput
|
| 93 |
+
flow: MemoryWriting
|
| 94 |
+
reset: false
|
| 95 |
+
|
| 96 |
+
- goal: "Read memory from memory files (flow_state)"
|
| 97 |
+
input_interface:
|
| 98 |
+
_target_: flows.interfaces.KeyInterface
|
| 99 |
+
additional_transformations:
|
| 100 |
+
- _target_: flows.data_transformations.KeyMatchInput
|
| 101 |
+
flow: MemoryReading
|
| 102 |
+
reset: false
|
ExtLibAskUserFlow.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from flow_modules.aiflows.HumanStandardInputFlowModule import HumanStandardInputFlow
|
| 2 |
+
|
| 3 |
+
from typing import Dict, Any
|
| 4 |
+
|
| 5 |
+
from flows.messages import UpdateMessage_Generic
|
| 6 |
+
|
| 7 |
+
from flows.utils import logging
|
| 8 |
+
|
| 9 |
+
log = logging.get_logger(f"flows.{__name__}")
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class ExtLibAskUserFlow(HumanStandardInputFlow):
|
| 13 |
+
def run(self,
|
| 14 |
+
input_data: Dict[str, Any]) -> Dict[str, Any]:
|
| 15 |
+
|
| 16 |
+
query_message = self._get_message(self.query_message_prompt_template, input_data)
|
| 17 |
+
state_update_message = UpdateMessage_Generic(
|
| 18 |
+
created_by=self.flow_config['name'],
|
| 19 |
+
updated_flow=self.flow_config["name"],
|
| 20 |
+
data={"query_message": query_message},
|
| 21 |
+
)
|
| 22 |
+
self._log_message(state_update_message)
|
| 23 |
+
|
| 24 |
+
log.info(query_message)
|
| 25 |
+
human_input = self._read_input()
|
| 26 |
+
|
| 27 |
+
response = {}
|
| 28 |
+
response["result"] = human_input
|
| 29 |
+
|
| 30 |
+
return response
|
ExtLibAskUserFlow.yaml
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: Tachi67.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,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from flow_modules.Tachi67.AbstractBossFlowModule import AbstractBossFlow
|
| 2 |
+
|
| 3 |
+
class ExtendLibraryFlow(AbstractBossFlow):
|
| 4 |
+
pass
|
ExtendLibraryFlow.yaml
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: ExtendLibraryFlow
|
| 2 |
+
description: "A flow used to extend the content in the code library"
|
| 3 |
+
|
| 4 |
+
_target_: Tachi67.ExtendLibraryFlowModule.ExtendLibraryFlow.instantiate_from_default_config
|
| 5 |
+
|
| 6 |
+
subflows_config:
|
| 7 |
+
MemoryReading:
|
| 8 |
+
_target_: Tachi67.MemoryReadingFlowModule.MemoryReadingAtomicFlow.instantiate_from_default_config
|
| 9 |
+
|
| 10 |
+
Planner:
|
| 11 |
+
_target_: Tachi67.PlanWriterFlowModule.PlanWriterFlow.instantiate_from_default_config
|
| 12 |
+
subflows_config:
|
| 13 |
+
Controller:
|
| 14 |
+
backend:
|
| 15 |
+
api_infos: ???
|
| 16 |
+
model_name:
|
| 17 |
+
openai: gpt-4
|
| 18 |
+
azure: azure/gpt-4
|
| 19 |
+
Executor:
|
| 20 |
+
subflows_config:
|
| 21 |
+
write_plan:
|
| 22 |
+
subflows_config:
|
| 23 |
+
PlanGenerator:
|
| 24 |
+
backend:
|
| 25 |
+
api_infos: ???
|
| 26 |
+
model_name:
|
| 27 |
+
openai: gpt-4
|
| 28 |
+
azure: azure/gpt-4
|
| 29 |
+
|
| 30 |
+
CtrlExMem:
|
| 31 |
+
_target_: Tachi67.ExtendLibraryFlowModule.CtrlExMem_ExtLib.instantiate_from_default_config
|
| 32 |
+
subflows_config:
|
| 33 |
+
Controller:
|
| 34 |
+
backend:
|
| 35 |
+
api_infos: ???
|
| 36 |
+
model_name:
|
| 37 |
+
openai: gpt-4
|
| 38 |
+
azure: azure/gpt-4
|
| 39 |
+
Executor:
|
| 40 |
+
subflows_config:
|
| 41 |
+
write_code:
|
| 42 |
+
subflows_config:
|
| 43 |
+
Controller:
|
| 44 |
+
backend:
|
| 45 |
+
api_infos: ???
|
| 46 |
+
model_name:
|
| 47 |
+
openai: gpt-4
|
| 48 |
+
azure: azure/gpt-4
|
| 49 |
+
Executor:
|
| 50 |
+
subflows_config:
|
| 51 |
+
write_code:
|
| 52 |
+
subflows_config:
|
| 53 |
+
CodeGenerator:
|
| 54 |
+
backend:
|
| 55 |
+
api_infos: ???
|
| 56 |
+
model_name:
|
| 57 |
+
openai: gpt-4
|
| 58 |
+
azure: azure/gpt-4
|
| 59 |
+
re_plan:
|
| 60 |
+
subflows_config:
|
| 61 |
+
Controller:
|
| 62 |
+
backend:
|
| 63 |
+
api_infos: ???
|
| 64 |
+
model_name:
|
| 65 |
+
openai: gpt-4
|
| 66 |
+
azure: azure/gpt-4
|
| 67 |
+
Executor:
|
| 68 |
+
subflows_config:
|
| 69 |
+
write_plan:
|
| 70 |
+
subflows_config:
|
| 71 |
+
PlanGenerator:
|
| 72 |
+
backend:
|
| 73 |
+
api_infos: ???
|
| 74 |
+
model_name:
|
| 75 |
+
openai: gpt-4
|
| 76 |
+
azure: azure/gpt-4
|
| 77 |
+
|
SaveCodeAtomicFlow.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Dict, Any
|
| 2 |
+
from flows.base_flows.atomic import AtomicFlow
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class SaveCodeAtomicFlow(AtomicFlow):
|
| 6 |
+
def _check_input(self, input_data: Dict[str, Any]):
|
| 7 |
+
assert "code" in input_data, "code is not passed to SaveCodeAtomicFlow"
|
| 8 |
+
assert "memory_files" in input_data, "memory_files is not passed to SaveCodeFlow"
|
| 9 |
+
assert "code_library" in input_data["memory_files"], "code_library not in memory_files"
|
| 10 |
+
# create the code library if it doesn't exist yet
|
| 11 |
+
code_library_location = input_data["memory_files"]["code_library"]
|
| 12 |
+
with open(code_library_location, 'a') as file:
|
| 13 |
+
pass
|
| 14 |
+
|
| 15 |
+
def _call(self, input_data: Dict[str, Any]):
|
| 16 |
+
try:
|
| 17 |
+
code_to_append = input_data["code"]
|
| 18 |
+
code_lib_loc = input_data["memory_files"]["code_library"]
|
| 19 |
+
with open(code_lib_loc, 'a') as file:
|
| 20 |
+
file.write(code_to_append + '\n')
|
| 21 |
+
return {
|
| 22 |
+
"result": "code successfully written to the library",
|
| 23 |
+
"summary": f"ExtendLibrayFlow/SaveCodeAtomicFlow: code written to {code_lib_loc}"
|
| 24 |
+
}
|
| 25 |
+
except Exception as e:
|
| 26 |
+
error_msg = str(e)
|
| 27 |
+
return {
|
| 28 |
+
"result": f"error occurred: {error_msg}",
|
| 29 |
+
"summary": f"ExtendLibrayFlow/SaveCodeAtomicFlow: error occurred: {error_msg}"
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
def run(
|
| 33 |
+
self,
|
| 34 |
+
input_data: Dict[str, Any]
|
| 35 |
+
):
|
| 36 |
+
self._check_input(input_data)
|
| 37 |
+
return self._call(input_data)
|
SaveCodeAtomicFlow.yaml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: Tachi67.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,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Dict, Any
|
| 2 |
+
from flows.base_flows.atomic import AtomicFlow
|
| 3 |
+
class UpdatePlanAtomicFlow(AtomicFlow):
|
| 4 |
+
def _check_input(self, input_data: Dict[str, Any]):
|
| 5 |
+
assert "memory_files" in input_data, "memory_files not passed to UpdatePlanAtomicFlow"
|
| 6 |
+
assert "plan" in input_data["memory_files"], "plan not in memory_files"
|
| 7 |
+
|
| 8 |
+
def _call(self, input_data: Dict[str, Any]):
|
| 9 |
+
try:
|
| 10 |
+
plan_file_location = input_data["memory_files"]["plan"]
|
| 11 |
+
plan_to_write = input_data["updated_plan"]
|
| 12 |
+
with open(plan_file_location, 'w') as file:
|
| 13 |
+
file.write(plan_to_write + "\n")
|
| 14 |
+
return {
|
| 15 |
+
"result": "updated plan saved to the plan file and has overriden the previous plan",
|
| 16 |
+
"summary": f"ExtendLibrary/UpdatePlanFlow: updated plan saved to {plan_file_location}"
|
| 17 |
+
}
|
| 18 |
+
except Exception as e:
|
| 19 |
+
return {
|
| 20 |
+
"result": f"Error occurred: {str(e)}",
|
| 21 |
+
"summary": f"ExtendLibrary/UpdatePlanFlow: error occurred while writing updated plan: {str(e)}"
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
def run(
|
| 25 |
+
self,
|
| 26 |
+
input_data: Dict[str, Any]
|
| 27 |
+
):
|
| 28 |
+
self._check_input(input_data)
|
| 29 |
+
return self._call(input_data)
|
UpdatePlanAtomicFlow.yaml
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: Tachi67.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,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
dependencies = [
|
| 2 |
+
{"url": "Tachi67/AbstractBossFlowModule", "revision": "main"},
|
| 3 |
+
{"url": "Tachi67/MemoryReadingFlowModule", "revision": "main"},
|
| 4 |
+
{"url": "Tachi67/PlanWriterFlowModule", "revision": "main"},
|
| 5 |
+
{"url": "Tachi67/ReplanningFlowModule", "revision": "main"},
|
| 6 |
+
{"url": "Tachi67/CodeWriterFlowModule", "revision": "main"},
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
from flows import flow_verse
|
| 10 |
+
flow_verse.sync_dependencies(dependencies)
|
| 11 |
+
from .ControllerFlow_ExtLib import ControllerFlow_ExtLib
|
| 12 |
+
from .CtrlExMem_ExtLib import CtrlExMem_ExtLib
|
| 13 |
+
from .ExtendLibraryFlow import ExtendLibraryFlow
|
| 14 |
+
from .ExtLibAskUserFlow import ExtLibAskUserFlow
|
| 15 |
+
from .SaveCodeAtomicFlow import SaveCodeAtomicFlow
|
| 16 |
+
from .UpdatePlanAtomicFlow import UpdatePlanAtomicFlow
|