Tachi67 commited on
Commit
1e4c673
·
1 Parent(s): 935b189

Upload 7 files

Browse files
ParseFeedbackAtomicFlow.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, Any
2
+ from aiflows.base_flows.atomic import AtomicFlow
3
+ import time
4
+ import subprocess
5
+
6
+
7
+ class ParseFeedbackAtomicFlow(AtomicFlow):
8
+ """This flow parses the feedback from the user. The flow is supposed to be called after the CodeFileEdit or PlanFileEdit flow.
9
+ The flow will open the file in VSCode and wait for the user to edit the file. Once the user closes the file, the flow will parse the file and return the content of the file.
10
+
11
+ *Input Interface*:
12
+ - `temp_code_file_location`: Notice that if we are parsing the plan file, this should be changed to `temp_plan_file_location`.
13
+
14
+ *Output Interface*:
15
+ - `code`: The content of the code file.
16
+ - `feedback`: The feedback from the user.
17
+ """
18
+ def _read_content(self, file_location, file_type):
19
+ if file_type == "code":
20
+ header_string = "# Code:\n"
21
+ elif file_type == "plan":
22
+ header_string = "Plan:\n"
23
+ else:
24
+ raise NotImplemented
25
+
26
+ with open(file_location, "r") as file:
27
+ content = file.read()
28
+
29
+ start_index = content.find(header_string)
30
+ if start_index == -1:
31
+ raise ValueError(f"Format error: {header_string} tag not found.")
32
+
33
+ end_index = content.find("\n############\n")
34
+ if end_index == -1 or end_index < start_index:
35
+ raise ValueError(f"Format error: {file_type} section is malformed.")
36
+
37
+ ret = content[start_index + len(header_string):end_index].strip()
38
+
39
+ return ret
40
+
41
+ def _parse_user_thoughts(self, file_location):
42
+ with open(file_location, "r") as file:
43
+ content = file.read()
44
+
45
+ delimiter = "\n############\n"
46
+ parts = content.split(delimiter)
47
+ if len(parts) < 2:
48
+ raise ValueError("Format error: Unable to find the thoughts section.")
49
+
50
+ thoughts_section = parts[1].strip()
51
+
52
+ thoughts_index = thoughts_section.find("Thoughts:")
53
+ if thoughts_index == -1:
54
+ raise ValueError("Format error: 'Thoughts:' tag not found.")
55
+
56
+ thoughts = thoughts_section[thoughts_index + len("Thoughts:"):].strip()
57
+
58
+ if thoughts == '':
59
+ thoughts = 'Looks good, go on.'
60
+
61
+ return thoughts
62
+
63
+ def _check_input(self, input_data: Dict[str, Any]):
64
+ code_file_exists = "temp_code_file_location" in input_data
65
+ plan_file_exists = "temp_plan_file_location" in input_data
66
+ if code_file_exists == False and plan_file_exists == False:
67
+ raise AssertionError("Neither code file nor plan file is passed to ParseFeedbackAtomicFlow")
68
+ elif code_file_exists and plan_file_exists:
69
+ raise AssertionError("Both code file and plan file are passed to ParseFeedbackAtomic, which one to parse?")
70
+
71
+ def _open_file_and_wait_for_file_update(self, file_location, check_interval=1):
72
+ process = subprocess.Popen(["code", "--wait", file_location])
73
+ while True:
74
+ if process.poll() is not None:
75
+ break
76
+ time.sleep(check_interval)
77
+
78
+ def run(
79
+ self,
80
+ input_data: Dict[str, Any]
81
+ ):
82
+ response = {}
83
+ self._check_input(input_data)
84
+ if "temp_code_file_location" in input_data:
85
+ temp_code_file_location = input_data['temp_code_file_location']
86
+ self._open_file_and_wait_for_file_update(temp_code_file_location)
87
+ code_content = self._read_content(temp_code_file_location, "code")
88
+ user_thoughts = self._parse_user_thoughts(temp_code_file_location)
89
+ response = {"code": code_content, "feedback": user_thoughts}
90
+
91
+ elif "temp_plan_file_location" in input_data:
92
+ plan_file_location = input_data["temp_plan_file_location"]
93
+ self._open_file_and_wait_for_file_update(plan_file_location)
94
+ plan_content = self._read_content(plan_file_location, "plan")
95
+ user_thoughts = self._parse_user_thoughts(plan_file_location)
96
+ response = {"plan": plan_content, "feedback": user_thoughts}
97
+
98
+ return response
ParseFeedbackAtomicFlow.yaml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: "ParseFeedbackAtomicFlow"
2
+ description: "A flow used to parse user feedback from a plan file or a code file"
3
+ _target_: flow_modules.aiflows.ParseFeedbackFlowModule.ParseFeedbackAtomicFlow.instantiate_from_default_config
4
+
5
+
6
+ # Should be changed when the ParseFeedbackAtomicFlow is used to parse a plan file.
7
+ input_interface:
8
+ - "temp_code_file_location"
9
+
10
+ # Should be changed when the ParseFeedbackAtomicFlow is used to parse a plan file.
11
+ output_interface:
12
+ - "code"
13
+ - "feedback"
README.md CHANGED
@@ -1,3 +1,32 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Table of Contents
2
+
3
+ * [ParseFeedbackAtomicFlow](#ParseFeedbackAtomicFlow)
4
+ * [ParseFeedbackAtomicFlow](#ParseFeedbackAtomicFlow.ParseFeedbackAtomicFlow)
5
+ * [\_\_init\_\_](#__init__)
6
+
7
+ <a id="ParseFeedbackAtomicFlow"></a>
8
+
9
+ # ParseFeedbackAtomicFlow
10
+
11
+ <a id="ParseFeedbackAtomicFlow.ParseFeedbackAtomicFlow"></a>
12
+
13
+ ## ParseFeedbackAtomicFlow Objects
14
+
15
+ ```python
16
+ class ParseFeedbackAtomicFlow(AtomicFlow)
17
+ ```
18
+
19
+ This flow parses the feedback from the user. The flow is supposed to be called after the CodeFileEdit or PlanFileEdit flow.
20
+ The flow will open the file in VSCode and wait for the user to edit the file. Once the user closes the file, the flow will parse the file and return the content of the file.
21
+
22
+ *Input Interface*:
23
+ - `temp_code_file_location`: Notice that if we are parsing the plan file, this should be changed to `temp_plan_file_location`.
24
+
25
+ *Output Interface*:
26
+ - `code`: The content of the code file.
27
+ - `feedback`: The feedback from the user.
28
+
29
+ <a id="__init__"></a>
30
+
31
+ # \_\_init\_\_
32
+
__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .ParseFeedbackAtomicFlow import ParseFeedbackAtomicFlow
example_code_file.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ # Code:
2
+ # This is the initial code that needs review or modification.
3
+ # For example, a simple Python function:
4
+ def example_function(x):
5
+ return x * x
6
+
7
+ ############
8
+
9
+ # Thoughts: lgtm
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.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import hydra
4
+
5
+ from aiflows.messages import InputMessage
6
+ from aiflows.utils.general_helpers import read_yaml_file
7
+
8
+ from aiflows import logging
9
+ from aiflows.flow_cache import CACHING_PARAMETERS, clear_cache
10
+
11
+ CACHING_PARAMETERS.do_caching = False # Set to True in order to disable caching
12
+ # clear_cache() # Uncomment this line to clear the cache
13
+
14
+ logging.set_verbosity_debug()
15
+ logging.auto_set_dir()
16
+
17
+ dependencies = [
18
+ {"url": "aiflows/ParseFeedbackFlowModule", "revision": "main"},
19
+ ]
20
+
21
+ from aiflows import flow_verse
22
+
23
+ flow_verse.sync_dependencies(dependencies)
24
+
25
+ if __name__ == "__main__":
26
+ current_dir = os.getcwd()
27
+ cfg_path = os.path.join(current_dir, "ParseFeedbackAtomicFlow.yaml")
28
+ cfg = read_yaml_file(cfg_path)
29
+
30
+
31
+ # ~~~ instantiating the flow and input data ~~~
32
+ ParseFeedbackFlow = hydra.utils.instantiate(cfg, _recursive_=False, _convert_="partial")
33
+ input_data = {
34
+ "temp_code_file_location": os.path.join(current_dir, "example_code_file.py")
35
+ }
36
+ input_message = InputMessage.build(
37
+ data_dict=input_data,
38
+ src_flow="Launcher",
39
+ dst_flow=ParseFeedbackFlow.name
40
+ )
41
+
42
+ # ~~~ calling the flow ~~~
43
+ output_message = ParseFeedbackFlow(input_message)
44
+
45
+ print(output_message.data)