Tachi67 commited on
Commit
67ebb93
·
1 Parent(s): b9becf6

Upload 9 files

Browse files
MemoryReadingAtomicFlow.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, Any
2
+ import os
3
+ import ast
4
+ import importlib
5
+ import inspect
6
+ from aiflows.base_flows import AtomicFlow
7
+
8
+
9
+ class MemoryReadingAtomicFlow(AtomicFlow):
10
+ """A flow to read memory from given files.
11
+
12
+ Any composite flow that uses this flow should have
13
+ memory_files: Dict[str, str] which maps memory name to its memory file location in the flow_state
14
+
15
+ *Input Interface*:
16
+ - `memory_files` : name of the Dict which maps the memory name to its file location e.g.
17
+ {"plan": "examples/JARVIS/plan.txt"}
18
+
19
+ *Output_Interface*:
20
+ - corresponding memory content, for example, `code_library`. There could be multiple memory content returned.
21
+ """
22
+
23
+ def __init__(self, **kwargs):
24
+ super().__init__(**kwargs)
25
+ self.supported_mem_name = ["plan", "logs", "code_library"]
26
+
27
+ def _check_input_data(self, input_data: Dict[str, Any]):
28
+ """input data sanity check"""
29
+ assert "memory_files" in input_data, "memory_files not passed to MemoryReadingAtomicFlow"
30
+
31
+ for mem_name, mem_path in input_data["memory_files"].items():
32
+ assert mem_name in self.supported_mem_name, (f"{mem_name} is not supported in MemoryReadingAtomicFlow, "
33
+ f"supported names are: {self.supported_mem_name}")
34
+ assert os.path.exists(mem_path), f"{mem_path} does not exist."
35
+ assert os.path.isfile(mem_path), f"{mem_path} is not a file."
36
+
37
+ def _read_text(self, file_location):
38
+ with open(file_location, 'r', encoding='utf-8') as file:
39
+ content = file.read()
40
+ return content
41
+
42
+ def _get_pyfile_functions_metadata_from_file(self, file_location):
43
+ def python_file_path_to_module_name(file_path):
44
+ return os.path.basename(file_path).replace('.py', '')
45
+
46
+ def extract_top_level_function_names(python_file_path):
47
+ with open(python_file_path, 'r') as file:
48
+ file_content = file.read()
49
+ tree = ast.parse(file_content)
50
+ functions = filter(lambda node: isinstance(node, ast.FunctionDef), ast.iter_child_nodes(tree))
51
+ return [node.name for node in functions]
52
+
53
+ def load_module_from_file(file_path):
54
+ module_name = python_file_path_to_module_name(file_path)
55
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
56
+ module = importlib.util.module_from_spec(spec)
57
+ spec.loader.exec_module(module)
58
+ return module
59
+
60
+ def get_function_from_name(function_name, module):
61
+ return getattr(module, function_name)
62
+
63
+ def function_to_dict(function):
64
+ if not callable(function):
65
+ raise ValueError("Provided object is not a function.")
66
+
67
+ function_dict = {
68
+ "name": function.__name__,
69
+ "doc": function.__doc__,
70
+ "args": []
71
+ }
72
+
73
+ signature = inspect.signature(function)
74
+ for name, param in signature.parameters.items():
75
+ arg_info = {
76
+ "name": name,
77
+ "default": param.default if param.default is not inspect.Parameter.empty else None,
78
+ "type": str(param.annotation) if param.annotation is not inspect.Parameter.empty else "unknown"
79
+ }
80
+ function_dict["args"].append(arg_info)
81
+
82
+ return function_dict
83
+
84
+ function_names = extract_top_level_function_names(file_location)
85
+ module = load_module_from_file(file_location)
86
+ functions = [get_function_from_name(name, module) for name in function_names]
87
+ return [function_to_dict(function) for function in functions]
88
+
89
+ def _format_metadata(self, metadata):
90
+ lines = []
91
+ for function_data in metadata:
92
+ lines.append(f"Function: {function_data['name']}")
93
+ lines.append(f"Documentation: {function_data['doc']}")
94
+
95
+ args = function_data.get('args', [])
96
+ if args:
97
+ lines.append("Arguments:")
98
+ for arg in args:
99
+ default = f" (default: {arg['default']})" if arg['default'] is not None else ""
100
+ lines.append(f" - {arg['name']} (type: {arg['type']}){default}")
101
+ else:
102
+ lines.append("Arguments: None")
103
+
104
+ lines.append("#########")
105
+
106
+ return '\n'.join(lines)
107
+ def _read_py_code_library(self, file_location):
108
+ metadata = self._get_pyfile_functions_metadata_from_file(file_location)
109
+ if len(metadata) == 0:
110
+ return "No functions yet."
111
+ formatted_metadata = self._format_metadata(metadata)
112
+ return formatted_metadata
113
+
114
+ def run(
115
+ self,
116
+ input_data: Dict[str, Any]):
117
+ self._check_input_data(input_data)
118
+ response = {}
119
+ for mem_name, mem_path in input_data["memory_files"].items():
120
+ if mem_name in ['plan', 'logs']:
121
+ response[mem_name] = self._read_text(mem_path)
122
+ elif mem_name == 'code_library' and mem_path.endswith('.py'):
123
+ response[mem_name] = self._read_py_code_library(mem_path)
124
+ return response
MemoryReadingAtomicFlow.yaml ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: "MemoryReadingAtomicFlow"
2
+ description: "A flow that reads memory from given file locations"
3
+ _target_: flow_modules.aiflows.MemoryReadingFlowModule.MemoryReadingAtomicFlow.instantiate_from_default_config
4
+
5
+ input_interface:
6
+ - "memory_files"
7
+
8
+
9
+ # should be overriden if the memory reading is to read other memories
10
+ output_interface:
11
+ - "code_library"
README.md CHANGED
@@ -1,3 +1,34 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Table of Contents
2
+
3
+ * [MemoryReadingAtomicFlow](#MemoryReadingAtomicFlow)
4
+ * [MemoryReadingAtomicFlow](#MemoryReadingAtomicFlow.MemoryReadingAtomicFlow)
5
+ * [\_\_init\_\_](#__init__)
6
+
7
+ <a id="MemoryReadingAtomicFlow"></a>
8
+
9
+ # MemoryReadingAtomicFlow
10
+
11
+ <a id="MemoryReadingAtomicFlow.MemoryReadingAtomicFlow"></a>
12
+
13
+ ## MemoryReadingAtomicFlow Objects
14
+
15
+ ```python
16
+ class MemoryReadingAtomicFlow(AtomicFlow)
17
+ ```
18
+
19
+ A flow to read memory from given files.
20
+
21
+ Any composite flow that uses this flow should have
22
+ memory_files: Dict[str, str] which maps memory name to its memory file location in the flow_state
23
+
24
+ *Input Interface*:
25
+ - `memory_files` : name of the Dict which maps the memory name to its file location e.g.
26
+ {"plan": "examples/JARVIS/plan.txt"}
27
+
28
+ *Output_Interface*:
29
+ - corresponding memory content, for example, `code_library`. There could be multiple memory content returned.
30
+
31
+ <a id="__init__"></a>
32
+
33
+ # \_\_init\_\_
34
+
__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .MemoryReadingAtomicFlow import MemoryReadingAtomicFlow
example_library.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ def add_two_numbers(a, b):
2
+ """Add two numbers together and return the result
3
+ :param a: first number
4
+ :param b: second number
5
+ :return: sum of a and b
6
+ """
7
+ return a + b
example_logs.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ some logs
example_plan.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ 1. step1
2
+ 2. step2
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,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
12
+ CACHING_PARAMETERS.do_caching = False # Set to True in order to disable caching
13
+
14
+ logging.set_verbosity_debug()
15
+ logging.auto_set_dir()
16
+
17
+ dependencies = [
18
+ {"url": "aiflows/MemoryReadingFlowModule", "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, "MemoryReadingAtomicFlow.yaml")
28
+ cfg = read_yaml_file(cfg_path)
29
+
30
+ MemReadFlow = hydra.utils.instantiate(cfg, _recursive_=False, _convert_="partial")
31
+
32
+ input_data = {
33
+ "memory_files": {
34
+ "plan": os.path.join(current_dir, "example_plan.txt"),
35
+ "logs": os.path.join(current_dir, "example_logs.txt"),
36
+ "code_library": os.path.join(current_dir, "example_library.txt")
37
+ }
38
+ }
39
+ input_message = InputMessage.build(
40
+ data_dict=input_data,
41
+ src_flow="Launcher",
42
+ dst_flow=MemReadFlow.name
43
+ )
44
+
45
+ # ~~~ calling the flow ~~~
46
+ output_message = MemReadFlow(input_message)
47
+
48
+ print(output_message.data)