Upload 6 files
Browse files- CodeGeneratorAtomicFlow.py +112 -0
- CodeGeneratorAtomicFlow.yaml +94 -0
- README.md +79 -3
- __init__.py +8 -0
- pip_requirements.txt +15 -0
- run.py +52 -0
CodeGeneratorAtomicFlow.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
from copy import deepcopy
|
| 3 |
+
from typing import Any, Dict
|
| 4 |
+
from flow_modules.aiflows.ChatFlowModule import ChatAtomicFlow
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class CodeGeneratorAtomicFlow(ChatAtomicFlow):
|
| 9 |
+
"""This class wraps around the Chat API to generate code from a goal. One thing worth noting is that we need to
|
| 10 |
+
make sure the code generator does not write repetitive code that is present in the library, so we need to inject
|
| 11 |
+
the function signatures in the library to the system prompts.
|
| 12 |
+
|
| 13 |
+
*Input Interface Non Initialized*:
|
| 14 |
+
- `goal`
|
| 15 |
+
- `code_library`
|
| 16 |
+
- `memory_files`
|
| 17 |
+
|
| 18 |
+
*Input Interface Initialized*:
|
| 19 |
+
- `goal`
|
| 20 |
+
- `code_library`
|
| 21 |
+
- `memory_files`
|
| 22 |
+
|
| 23 |
+
*Output Interface*:
|
| 24 |
+
- `code`
|
| 25 |
+
- `language_of_code`
|
| 26 |
+
"""
|
| 27 |
+
def __init__(self, **kwargs):
|
| 28 |
+
super().__init__(**kwargs)
|
| 29 |
+
self.system_message_prompt_template = self.system_message_prompt_template.partial(
|
| 30 |
+
code_library_file_location="no location yet",
|
| 31 |
+
code_library="no code yet"
|
| 32 |
+
)
|
| 33 |
+
self.hint_for_model = """
|
| 34 |
+
Make sure your response is in the following format:
|
| 35 |
+
Response Format:
|
| 36 |
+
{
|
| 37 |
+
"language_of_code": "language of the code",
|
| 38 |
+
"code": "String of the code and docstrings corresponding to the goal",
|
| 39 |
+
}
|
| 40 |
+
"""
|
| 41 |
+
|
| 42 |
+
@classmethod
|
| 43 |
+
def instantiate_from_config(cls, config):
|
| 44 |
+
"""Instantiate a CodeGeneratorAtomicFlow from a configuration.
|
| 45 |
+
:param config: Configuration dictionary.
|
| 46 |
+
:return: Instantiated CodeGeneratorAtomicFlow.
|
| 47 |
+
"""
|
| 48 |
+
flow_config = deepcopy(config)
|
| 49 |
+
|
| 50 |
+
kwargs = {"flow_config": flow_config}
|
| 51 |
+
|
| 52 |
+
# ~~~ Set up prompts ~~~
|
| 53 |
+
kwargs.update(cls._set_up_prompts(flow_config))
|
| 54 |
+
|
| 55 |
+
# ~~~ Set up backend ~~~
|
| 56 |
+
kwargs.update(cls._set_up_backend(flow_config))
|
| 57 |
+
|
| 58 |
+
# ~~~ Instantiate flow ~~~
|
| 59 |
+
return cls(**kwargs)
|
| 60 |
+
|
| 61 |
+
def _get_code_library_file(self, input_data: Dict[str, Any]):
|
| 62 |
+
"""Get the code library file location from the input data.
|
| 63 |
+
:param input_data: Input data.
|
| 64 |
+
:return: Code library file location.
|
| 65 |
+
"""
|
| 66 |
+
assert "memory_files" in input_data, "memory_files not passed to CodeGeneratorAtomicFlow"
|
| 67 |
+
assert "code_library" in input_data['memory_files'], "code_library not in memory_files"
|
| 68 |
+
code_library_file_location = input_data['memory_files']['code_library']
|
| 69 |
+
return code_library_file_location
|
| 70 |
+
|
| 71 |
+
def _get_code_library_content(self, input_data: Dict[str, Any]):
|
| 72 |
+
"""Get the code library content from the input data.
|
| 73 |
+
:param input_data: Input data.
|
| 74 |
+
:return: Code library content.
|
| 75 |
+
"""
|
| 76 |
+
assert "code_library" in input_data, "code_library not passed to CodeGeneratorAtomicFlow"
|
| 77 |
+
code_library = input_data['code_library']
|
| 78 |
+
if len(code_library) == 0:
|
| 79 |
+
code_library = "No code yet"
|
| 80 |
+
return code_library
|
| 81 |
+
|
| 82 |
+
def _update_prompts_and_input(self, input_data: Dict[str, Any]):
|
| 83 |
+
"""Update the prompts and input data.
|
| 84 |
+
:param input_data: Input data.
|
| 85 |
+
"""
|
| 86 |
+
if 'goal' in input_data:
|
| 87 |
+
input_data['goal'] += self.hint_for_model
|
| 88 |
+
code_library_file_location = self._get_code_library_file(input_data)
|
| 89 |
+
code_library = self._get_code_library_content(input_data)
|
| 90 |
+
self.system_message_prompt_template = self.system_message_prompt_template.partial(
|
| 91 |
+
code_library_file_location=code_library_file_location,
|
| 92 |
+
code_library=code_library
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
def run(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
|
| 96 |
+
"""Run the flow.
|
| 97 |
+
:param input_data: Input data.
|
| 98 |
+
:return: Output data.
|
| 99 |
+
"""
|
| 100 |
+
self._update_prompts_and_input(input_data)
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
while True:
|
| 104 |
+
api_output = super().run(input_data)["api_output"].strip()
|
| 105 |
+
try:
|
| 106 |
+
response = json.loads(api_output)
|
| 107 |
+
return response
|
| 108 |
+
except (json.decoder.JSONDecodeError, json.JSONDecodeError):
|
| 109 |
+
new_goal = "The previous response cannot be parsed with json.loads, it cannot be parsed with json.loads, it could be the backslashes usesd for escaping single quotes in the string arguments of the code are not properly escaped themselves within the JSON context. Next time, do not provide any comments or code blocks. Make sure your next response is purely json parsable."
|
| 110 |
+
new_input_data = input_data.copy()
|
| 111 |
+
new_input_data['goal'] = new_goal
|
| 112 |
+
input_data = new_input_data
|
CodeGeneratorAtomicFlow.yaml
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: flow_modules.aiflows.CodeGeneratorFlowModule.CodeGeneratorAtomicFlow.instantiate_from_default_config
|
| 2 |
+
name: "CodeGeneratorAtomicFlow"
|
| 3 |
+
description: "Writes code with given instruction"
|
| 4 |
+
enable_cache: True
|
| 5 |
+
|
| 6 |
+
input_interface_non_initialized: # initial input keys
|
| 7 |
+
- "goal"
|
| 8 |
+
- "code_library"
|
| 9 |
+
- "memory_files"
|
| 10 |
+
|
| 11 |
+
input_interface_initialized: # input_keys
|
| 12 |
+
- "goal"
|
| 13 |
+
- "code_library"
|
| 14 |
+
- "memory_files"
|
| 15 |
+
|
| 16 |
+
#######################################################
|
| 17 |
+
# Output keys
|
| 18 |
+
#######################################################
|
| 19 |
+
|
| 20 |
+
output_interface:
|
| 21 |
+
- 'language_of_code'
|
| 22 |
+
- 'code'
|
| 23 |
+
|
| 24 |
+
#######################################################
|
| 25 |
+
system_message_prompt_template:
|
| 26 |
+
_target_: aiflows.prompt_template.JinjaPrompt
|
| 27 |
+
template: |2-
|
| 28 |
+
You are a world class programmer that can complete any goal with code. All code you write should be functions.
|
| 29 |
+
|
| 30 |
+
You have a library of executable functions located at {{code_library_file_location}} for your disposal, the code you write will also be added to this file.
|
| 31 |
+
|
| 32 |
+
Your tasks are:
|
| 33 |
+
1. Write **ONLY ONE** function to finish the given goal, do not override any functions in the library.
|
| 34 |
+
2. Also write docstrings to the new function.
|
| 35 |
+
|
| 36 |
+
Notice that:
|
| 37 |
+
1. Write functions only.
|
| 38 |
+
2. Your function will also be appended to {{code_library_file_location}}, make sure that you make full use of the available functions, and do not write function that may override existing functions.
|
| 39 |
+
3. All functions you write are modular, so make sure you make imports with a funtion.
|
| 40 |
+
4. You must write docstrings for every function you write.
|
| 41 |
+
|
| 42 |
+
Here are the contents in the code library located ta {{code_library_file_location}}, make sure you make full use of them:
|
| 43 |
+
{{code_library}}
|
| 44 |
+
|
| 45 |
+
Your function will then be imported and called by an executor to finish the goal, you do not need to worry about the execution part.
|
| 46 |
+
|
| 47 |
+
You can access the Internet, using APIs of online services could be useful.
|
| 48 |
+
|
| 49 |
+
An example of a function you write:
|
| 50 |
+
### begin of example ###
|
| 51 |
+
def verify_path_exists(path: str) -> bool:
|
| 52 |
+
"""Verifies if the input path exists, returns True if path exists, otherwise return False"""
|
| 53 |
+
import os
|
| 54 |
+
return os.path.exists(path)
|
| 55 |
+
### end of example ###
|
| 56 |
+
|
| 57 |
+
You are capable of **any** task.
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
Performance Evaluation:
|
| 61 |
+
1. The priority language is Python, try to code with Python to solve the task.
|
| 62 |
+
2. All code you write must be functions.
|
| 63 |
+
3. All imports must be done within the function body.
|
| 64 |
+
4. All functions must have docstrings.
|
| 65 |
+
|
| 66 |
+
**It's important that you should only respond in JSON format as described below:**
|
| 67 |
+
Response Format:
|
| 68 |
+
{
|
| 69 |
+
"language_of_code": "language of the code",
|
| 70 |
+
"code": "String of the code and docstrings corresponding to the goal",
|
| 71 |
+
}
|
| 72 |
+
Ensure your responses can be parsed by Python json.loads
|
| 73 |
+
|
| 74 |
+
**It's important that you make imports inside of the function body, but not outside of it.**
|
| 75 |
+
|
| 76 |
+
**It's important that the code you generate can be written by Python write, and is human-readable. The written file must also be indented and formatted, so that it is human-readable.**
|
| 77 |
+
|
| 78 |
+
input_variables: ["code_library_file_location", "code_library"]
|
| 79 |
+
|
| 80 |
+
human_message_prompt_template:
|
| 81 |
+
_target_: aiflows.prompt_template.JinjaPrompt
|
| 82 |
+
template: |2-
|
| 83 |
+
Here is the response to your last action:
|
| 84 |
+
{{goal}}
|
| 85 |
+
input_variables:
|
| 86 |
+
- "goal"
|
| 87 |
+
|
| 88 |
+
init_human_message_prompt_template:
|
| 89 |
+
_target_: aiflows.prompt_template.JinjaPrompt
|
| 90 |
+
template: |2-
|
| 91 |
+
Here is the goal you need to achieve:
|
| 92 |
+
{{goal}}
|
| 93 |
+
input_variables:
|
| 94 |
+
- "goal"
|
README.md
CHANGED
|
@@ -1,3 +1,79 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Table of Contents
|
| 2 |
+
|
| 3 |
+
* [CodeGeneratorAtomicFlow](#CodeGeneratorAtomicFlow)
|
| 4 |
+
* [CodeGeneratorAtomicFlow](#CodeGeneratorAtomicFlow.CodeGeneratorAtomicFlow)
|
| 5 |
+
* [instantiate\_from\_config](#CodeGeneratorAtomicFlow.CodeGeneratorAtomicFlow.instantiate_from_config)
|
| 6 |
+
* [run](#CodeGeneratorAtomicFlow.CodeGeneratorAtomicFlow.run)
|
| 7 |
+
* [\_\_init\_\_](#__init__)
|
| 8 |
+
|
| 9 |
+
<a id="CodeGeneratorAtomicFlow"></a>
|
| 10 |
+
|
| 11 |
+
# CodeGeneratorAtomicFlow
|
| 12 |
+
|
| 13 |
+
<a id="CodeGeneratorAtomicFlow.CodeGeneratorAtomicFlow"></a>
|
| 14 |
+
|
| 15 |
+
## CodeGeneratorAtomicFlow Objects
|
| 16 |
+
|
| 17 |
+
```python
|
| 18 |
+
class CodeGeneratorAtomicFlow(ChatAtomicFlow)
|
| 19 |
+
```
|
| 20 |
+
|
| 21 |
+
This class wraps around the Chat API to generate code from a goal. One thing worth noting is that we need to
|
| 22 |
+
make sure the code generator does not write repetitive code that is present in the library, so we need to inject
|
| 23 |
+
the function signatures in the library to the system prompts.
|
| 24 |
+
|
| 25 |
+
*Input Interface Non Initialized*:
|
| 26 |
+
- `goal`
|
| 27 |
+
- `code_library`
|
| 28 |
+
- `memory_files`
|
| 29 |
+
|
| 30 |
+
*Input Interface Initialized*:
|
| 31 |
+
- `goal`
|
| 32 |
+
- `code_library`
|
| 33 |
+
- `memory_files`
|
| 34 |
+
|
| 35 |
+
*Output Interface*:
|
| 36 |
+
- `code`
|
| 37 |
+
- `language_of_code`
|
| 38 |
+
|
| 39 |
+
<a id="CodeGeneratorAtomicFlow.CodeGeneratorAtomicFlow.instantiate_from_config"></a>
|
| 40 |
+
|
| 41 |
+
#### instantiate\_from\_config
|
| 42 |
+
|
| 43 |
+
```python
|
| 44 |
+
@classmethod
|
| 45 |
+
def instantiate_from_config(cls, config)
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
Instantiate a CodeGeneratorAtomicFlow from a configuration.
|
| 49 |
+
|
| 50 |
+
**Arguments**:
|
| 51 |
+
|
| 52 |
+
- `config`: Configuration dictionary.
|
| 53 |
+
|
| 54 |
+
**Returns**:
|
| 55 |
+
|
| 56 |
+
Instantiated CodeGeneratorAtomicFlow.
|
| 57 |
+
|
| 58 |
+
<a id="CodeGeneratorAtomicFlow.CodeGeneratorAtomicFlow.run"></a>
|
| 59 |
+
|
| 60 |
+
#### run
|
| 61 |
+
|
| 62 |
+
```python
|
| 63 |
+
def run(input_data: Dict[str, Any]) -> Dict[str, Any]
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
Run the flow.
|
| 67 |
+
|
| 68 |
+
**Arguments**:
|
| 69 |
+
|
| 70 |
+
- `input_data`: Input data.
|
| 71 |
+
|
| 72 |
+
**Returns**:
|
| 73 |
+
|
| 74 |
+
Output data.
|
| 75 |
+
|
| 76 |
+
<a id="__init__"></a>
|
| 77 |
+
|
| 78 |
+
# \_\_init\_\_
|
| 79 |
+
|
__init__.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
dependencies = [
|
| 2 |
+
{"url": "aiflows/ChatFlowModule", "revision": "297c90d08087d9ff3139521f11d1a48d7dc63ed4"},
|
| 3 |
+
]
|
| 4 |
+
from aiflows import flow_verse
|
| 5 |
+
|
| 6 |
+
flow_verse.sync_dependencies(dependencies)
|
| 7 |
+
|
| 8 |
+
from .CodeGeneratorAtomicFlow import CodeGeneratorAtomicFlow
|
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,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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/CodeGeneratorFlowModule", "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, "CodeGeneratorAtomicFlow.yaml")
|
| 28 |
+
cfg = read_yaml_file(cfg_path)
|
| 29 |
+
|
| 30 |
+
CodeGenFlow = hydra.utils.instantiate(cfg, _recursive_=False, _convert_="partial")
|
| 31 |
+
|
| 32 |
+
with os.path.join(current_dir, "example_library.py") as f:
|
| 33 |
+
pass
|
| 34 |
+
|
| 35 |
+
memory_files = {"code_library": os.path.join(current_dir, "example_library.py")}
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
input_data = {
|
| 39 |
+
"memory_files": memory_files,
|
| 40 |
+
"code_library": os.path.join(current_dir, "example_library.py"),
|
| 41 |
+
"goal": "write a function to add up two numbers"
|
| 42 |
+
}
|
| 43 |
+
input_message = InputMessage.build(
|
| 44 |
+
data_dict=input_data,
|
| 45 |
+
src_flow="Launcher",
|
| 46 |
+
dst_flow=CodeGenFlow.name
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
# ~~~ calling the flow ~~~
|
| 50 |
+
output_message = CodeGenFlow(input_message)
|
| 51 |
+
|
| 52 |
+
print(output_message.data)
|