readme + demo
Browse files- HumanStandardInputFlow.py +66 -1
- README.md +78 -13
- demo.yaml +17 -0
- pip_requirements.py +0 -1
- pip_requirements.txt +0 -0
- run.py +58 -0
HumanStandardInputFlow.py
CHANGED
@@ -14,13 +14,46 @@ log = logging.get_logger(f"flows.{__name__}") # ToDo: Is there a better fix?
|
|
14 |
|
15 |
|
16 |
class HumanStandardInputFlow(AtomicFlow):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
REQUIRED_KEYS_CONFIG = ["request_multi_line_input_flag"]
|
18 |
|
19 |
query_message_prompt_template: JinjaPrompt = None
|
20 |
|
21 |
__default_flow_config = {
|
22 |
"end_of_input_string": "EOI",
|
23 |
-
"input_keys": [],
|
24 |
"description": "Reads input from the user's standard input.",
|
25 |
"query_message_prompt_template": {
|
26 |
"_target_": "flows.prompt_template.JinjaPrompt",
|
@@ -36,6 +69,12 @@ class HumanStandardInputFlow(AtomicFlow):
|
|
36 |
|
37 |
@classmethod
|
38 |
def _set_up_prompts(cls, config):
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
kwargs = {}
|
40 |
|
41 |
kwargs["query_message_prompt_template"] = \
|
@@ -44,6 +83,12 @@ class HumanStandardInputFlow(AtomicFlow):
|
|
44 |
|
45 |
@classmethod
|
46 |
def instantiate_from_config(cls, config):
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
flow_config = deepcopy(config)
|
48 |
|
49 |
kwargs = {"flow_config": flow_config}
|
@@ -56,6 +101,14 @@ class HumanStandardInputFlow(AtomicFlow):
|
|
56 |
|
57 |
@staticmethod
|
58 |
def _get_message(prompt_template, input_data: Dict[str, Any]):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
template_kwargs = {}
|
60 |
for input_variable in prompt_template.input_variables:
|
61 |
template_kwargs[input_variable] = input_data[input_variable]
|
@@ -64,6 +117,11 @@ class HumanStandardInputFlow(AtomicFlow):
|
|
64 |
return msg_content
|
65 |
|
66 |
def _read_input(self):
|
|
|
|
|
|
|
|
|
|
|
67 |
if not self.flow_config["request_multi_line_input_flag"]:
|
68 |
log.info("Please enter you single-line response and press enter.")
|
69 |
human_input = input()
|
@@ -84,6 +142,13 @@ class HumanStandardInputFlow(AtomicFlow):
|
|
84 |
|
85 |
def run(self,
|
86 |
input_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
|
88 |
query_message = self._get_message(self.query_message_prompt_template, input_data)
|
89 |
state_update_message = UpdateMessage_Generic(
|
|
|
14 |
|
15 |
|
16 |
class HumanStandardInputFlow(AtomicFlow):
|
17 |
+
""" This class implements a HumanStandardInputFlow. It's used to read input from the user/human. Typically used to get feedback from the user/human.
|
18 |
+
|
19 |
+
*Configuration Parameters*:
|
20 |
+
|
21 |
+
- `name` (str): The name of the flow.
|
22 |
+
|
23 |
+
- `description` (str): A description of the flow. This description is used to generate the help message of the flow.
|
24 |
+
Default: "Reads input from the user's standard input."
|
25 |
+
|
26 |
+
- `request_multi_line_input_flag` (bool): If True, the user/human is requested to enter a multi-line input.
|
27 |
+
If False, the user/human is requested to enter a single-line input. Default: No defaul, this parameter is required.
|
28 |
+
|
29 |
+
- `end_of_input_string` (str): The string that the user/human should enter to indicate that the input is finished.
|
30 |
+
This parameter is only used if "request_multi_line_input_flag" is True. Default: "EOI"
|
31 |
+
|
32 |
+
- `query_message_prompt_template` (JinjaPrompt): The prompt template used to generate the query message. By default its of type flows.prompt_template.JinjaPrompt.
|
33 |
+
None of the parameters of the prompt are defined by default and therefore need to be defined if one wants to use the init_human_message_prompt_template. Default parameters are defined in
|
34 |
+
flows.prompt_template.jinja2_prompts.JinjaPrompt.
|
35 |
+
|
36 |
+
- The other parameters are inherited from the default configuration of AtomicFlow (see AtomicFlow)
|
37 |
+
|
38 |
+
*input_interface*:
|
39 |
+
|
40 |
+
- No Input Interface. By default, the input interface expects no input. But if inputs are expected from the query_message_prompt_template,then the input interface should contain the keys specified in the input_variables of the query_message_prompt_template.
|
41 |
+
|
42 |
+
*output_interface*:
|
43 |
+
|
44 |
+
- `human_input` (str): The message inputed from the user/human.
|
45 |
+
|
46 |
+
:param query_message_prompt_template: The prompt template used to generate the query message. Expected if the class is instantiated programmatically.
|
47 |
+
:type query_message_prompt_template: JinjaPrompt
|
48 |
+
:param \**kwargs: The keyword arguments passed to the AtomicFlow constructor. Use to create the flow_config. Includes request_multi_line_input_flag, end_of_input_string, input_keys, description of Configuration Parameters.
|
49 |
+
:type \**kwargs: Dict[str, Any]
|
50 |
+
"""
|
51 |
REQUIRED_KEYS_CONFIG = ["request_multi_line_input_flag"]
|
52 |
|
53 |
query_message_prompt_template: JinjaPrompt = None
|
54 |
|
55 |
__default_flow_config = {
|
56 |
"end_of_input_string": "EOI",
|
|
|
57 |
"description": "Reads input from the user's standard input.",
|
58 |
"query_message_prompt_template": {
|
59 |
"_target_": "flows.prompt_template.JinjaPrompt",
|
|
|
69 |
|
70 |
@classmethod
|
71 |
def _set_up_prompts(cls, config):
|
72 |
+
""" Instantiates the prompt templates from the config.
|
73 |
+
|
74 |
+
:param config: The configuration of the flow.
|
75 |
+
:type config: Dict[str, Any]
|
76 |
+
:return: A dictionary of keyword arguments to pass to the constructor of the flow.
|
77 |
+
"""
|
78 |
kwargs = {}
|
79 |
|
80 |
kwargs["query_message_prompt_template"] = \
|
|
|
83 |
|
84 |
@classmethod
|
85 |
def instantiate_from_config(cls, config):
|
86 |
+
""" Instantiates the flow from a config file.
|
87 |
+
|
88 |
+
:param config: The configuration of the flow.
|
89 |
+
:type config: Dict[str, Any]
|
90 |
+
"""
|
91 |
+
|
92 |
flow_config = deepcopy(config)
|
93 |
|
94 |
kwargs = {"flow_config": flow_config}
|
|
|
101 |
|
102 |
@staticmethod
|
103 |
def _get_message(prompt_template, input_data: Dict[str, Any]):
|
104 |
+
""" Returns the message content given the prompt template and the input data.
|
105 |
+
|
106 |
+
:param prompt_template: The prompt template.
|
107 |
+
:type prompt_template: JinjaPrompt
|
108 |
+
:param input_data: The input data.
|
109 |
+
:type input_data: Dict[str, Any]
|
110 |
+
:return: The message content.
|
111 |
+
"""
|
112 |
template_kwargs = {}
|
113 |
for input_variable in prompt_template.input_variables:
|
114 |
template_kwargs[input_variable] = input_data[input_variable]
|
|
|
117 |
return msg_content
|
118 |
|
119 |
def _read_input(self):
|
120 |
+
""" Reads the input from the user/human's standard input.
|
121 |
+
|
122 |
+
:return: The input read from the user/human's standard input.
|
123 |
+
:rtype: str
|
124 |
+
"""
|
125 |
if not self.flow_config["request_multi_line_input_flag"]:
|
126 |
log.info("Please enter you single-line response and press enter.")
|
127 |
human_input = input()
|
|
|
142 |
|
143 |
def run(self,
|
144 |
input_data: Dict[str, Any]) -> Dict[str, Any]:
|
145 |
+
""" Runs the HumanStandardInputFlow. It's used to read input from the user/human's standard input.
|
146 |
+
|
147 |
+
:param input_data: The input data dictionary
|
148 |
+
:type input_data: Dict[str, Any]
|
149 |
+
:return: The output data dictionary
|
150 |
+
:rtype: Dict[str, Any]
|
151 |
+
"""
|
152 |
|
153 |
query_message = self._get_message(self.query_message_prompt_template, input_data)
|
154 |
state_update_message = UpdateMessage_Generic(
|
README.md
CHANGED
@@ -1,25 +1,90 @@
|
|
1 |
---
|
2 |
license: mit
|
3 |
---
|
4 |
-
## Description
|
5 |
|
6 |
-
|
7 |
|
8 |
-
|
|
|
|
|
|
|
9 |
|
10 |
-
|
11 |
|
12 |
-
|
13 |
-
* **template** (String): The template for the message to be presented to the user (e.g., "Hi {{name}}, The last `{{action}}` completed successfully. Do you have any feedback that should be considered before selecting the next action?"). Default value is "".
|
14 |
-
* **input_variables** (Optional)(List): The list of variables to be used in the template (e.g., ["action"]). Default value is [].
|
15 |
-
* **partial_variables** (Optional)(Dict): Dictionary of partial variables to be used in the template (a subset of the required values, as to create a new prompt template which expects only the remaining subset of values)(e.g. {"name": "John"} )
|
16 |
|
17 |
-
|
18 |
|
19 |
-
##
|
20 |
|
21 |
-
|
|
|
|
|
22 |
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
|
25 |
-
* **human_input** (String): The user's input.
|
|
|
1 |
---
|
2 |
license: mit
|
3 |
---
|
|
|
4 |
|
5 |
+
# Table of Contents
|
6 |
|
7 |
+
* [HumanStandardInputFlow](#HumanStandardInputFlow)
|
8 |
+
* [HumanStandardInputFlow](#HumanStandardInputFlow.HumanStandardInputFlow)
|
9 |
+
* [instantiate\_from\_config](#HumanStandardInputFlow.HumanStandardInputFlow.instantiate_from_config)
|
10 |
+
* [run](#HumanStandardInputFlow.HumanStandardInputFlow.run)
|
11 |
|
12 |
+
<a id="HumanStandardInputFlow"></a>
|
13 |
|
14 |
+
# HumanStandardInputFlow
|
|
|
|
|
|
|
15 |
|
16 |
+
<a id="HumanStandardInputFlow.HumanStandardInputFlow"></a>
|
17 |
|
18 |
+
## HumanStandardInputFlow Objects
|
19 |
|
20 |
+
```python
|
21 |
+
class HumanStandardInputFlow(AtomicFlow)
|
22 |
+
```
|
23 |
|
24 |
+
This class implements a HumanStandardInputFlow. It's used to read input from the user/human. Typically used to get feedback from the user/human.
|
25 |
+
|
26 |
+
*Configuration Parameters*:
|
27 |
+
|
28 |
+
- `name` (str): The name of the flow.
|
29 |
+
|
30 |
+
- `description` (str): A description of the flow. This description is used to generate the help message of the flow.
|
31 |
+
Default: "Reads input from the user's standard input."
|
32 |
+
|
33 |
+
- `request_multi_line_input_flag` (bool): If True, the user/human is requested to enter a multi-line input.
|
34 |
+
If False, the user/human is requested to enter a single-line input. Default: No defaul, this parameter is required.
|
35 |
+
|
36 |
+
- `end_of_input_string` (str): The string that the user/human should enter to indicate that the input is finished.
|
37 |
+
This parameter is only used if "request_multi_line_input_flag" is True. Default: "EOI"
|
38 |
+
|
39 |
+
- `query_message_prompt_template` (JinjaPrompt): The prompt template used to generate the query message. By default its of type flows.prompt_template.JinjaPrompt.
|
40 |
+
None of the parameters of the prompt are defined by default and therefore need to be defined if one wants to use the init_human_message_prompt_template. Default parameters are defined in
|
41 |
+
flows.prompt_template.jinja2_prompts.JinjaPrompt.
|
42 |
+
|
43 |
+
- The other parameters are inherited from the default configuration of AtomicFlow (see AtomicFlow)
|
44 |
+
|
45 |
+
*input_interface*:
|
46 |
+
|
47 |
+
- No Input Interface. By default, the input interface expects no input. But if inputs are expected from the query_message_prompt_template,then the input interface should contain the keys specified in the input_variables of the query_message_prompt_template.
|
48 |
+
|
49 |
+
*output_interface*:
|
50 |
+
|
51 |
+
- `human_input` (str): The message inputed from the user/human.
|
52 |
+
|
53 |
+
**Arguments**:
|
54 |
+
|
55 |
+
- `query_message_prompt_template` (`JinjaPrompt`): The prompt template used to generate the query message. Expected if the class is instantiated programmatically.
|
56 |
+
- `\**kwargs` (`Dict[str, Any]`): The keyword arguments passed to the AtomicFlow constructor. Use to create the flow_config. Includes request_multi_line_input_flag, end_of_input_string, input_keys, description of Configuration Parameters.
|
57 |
+
|
58 |
+
<a id="HumanStandardInputFlow.HumanStandardInputFlow.instantiate_from_config"></a>
|
59 |
+
|
60 |
+
#### instantiate\_from\_config
|
61 |
+
|
62 |
+
```python
|
63 |
+
@classmethod
|
64 |
+
def instantiate_from_config(cls, config)
|
65 |
+
```
|
66 |
+
|
67 |
+
Instantiates the flow from a config file.
|
68 |
+
|
69 |
+
**Arguments**:
|
70 |
+
|
71 |
+
- `config` (`Dict[str, Any]`): The configuration of the flow.
|
72 |
+
|
73 |
+
<a id="HumanStandardInputFlow.HumanStandardInputFlow.run"></a>
|
74 |
+
|
75 |
+
#### run
|
76 |
+
|
77 |
+
```python
|
78 |
+
def run(input_data: Dict[str, Any]) -> Dict[str, Any]
|
79 |
+
```
|
80 |
+
|
81 |
+
Runs the HumanStandardInputFlow. It's used to read input from the user/human's standard input.
|
82 |
+
|
83 |
+
**Arguments**:
|
84 |
+
|
85 |
+
- `input_data` (`Dict[str, Any]`): The input data dictionary
|
86 |
+
|
87 |
+
**Returns**:
|
88 |
+
|
89 |
+
`Dict[str, Any]`: The output data dictionary
|
90 |
|
|
demo.yaml
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
input_interface:
|
2 |
+
_target_: flows.interfaces.KeyInterface
|
3 |
+
flow:
|
4 |
+
_target_: aiflows.HumanStandardInputFlowModule.HumanStandardInputFlow.instantiate_from_default_config
|
5 |
+
name: "HumanStandardInputFlow"
|
6 |
+
description: "A demo of the HumanStandardInputFlow."
|
7 |
+
request_multi_line_input_flag: True
|
8 |
+
end_of_input_string: EOI
|
9 |
+
query_message_prompt_template:
|
10 |
+
_target_: flows.prompt_template.JinjaPrompt
|
11 |
+
template: |2-
|
12 |
+
Please enter your input.
|
13 |
+
|
14 |
+
What's opinion on this statement?
|
15 |
+
{{statement}}
|
16 |
+
input_variables: []
|
17 |
+
partial_variables: {"statement": "This Flow works well."}
|
pip_requirements.py
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
# ToDo
|
|
|
|
pip_requirements.txt
ADDED
File without changes
|
run.py
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
import hydra
|
4 |
+
|
5 |
+
|
6 |
+
from flows.flow_launchers import FlowLauncher
|
7 |
+
from flows.utils.general_helpers import read_yaml_file
|
8 |
+
|
9 |
+
from flows import logging
|
10 |
+
from flows.flow_cache import CACHING_PARAMETERS
|
11 |
+
|
12 |
+
CACHING_PARAMETERS.do_caching = False # Set to True to enable caching
|
13 |
+
# clear_cache() # Uncomment this line to clear the cache
|
14 |
+
|
15 |
+
logging.set_verbosity_debug()
|
16 |
+
|
17 |
+
dependencies = [
|
18 |
+
{"url": "aiflows/HumanStandardInputFlowModule", "revision": os.getcwd()},
|
19 |
+
]
|
20 |
+
from flows import flow_verse
|
21 |
+
flow_verse.sync_dependencies(dependencies)
|
22 |
+
|
23 |
+
if __name__ == "__main__":
|
24 |
+
|
25 |
+
root_dir = "."
|
26 |
+
cfg_path = os.path.join(root_dir, "demo.yaml")
|
27 |
+
cfg = read_yaml_file(cfg_path)
|
28 |
+
flow_with_interfaces = {
|
29 |
+
"flow": hydra.utils.instantiate(cfg['flow'], _recursive_=False, _convert_="partial"),
|
30 |
+
"input_interface": (
|
31 |
+
None
|
32 |
+
if getattr(cfg, "input_interface", None) is None
|
33 |
+
else hydra.utils.instantiate(cfg['input_interface'], _recursive_=False)
|
34 |
+
),
|
35 |
+
"output_interface": (
|
36 |
+
None
|
37 |
+
if getattr(cfg, "output_interface", None) is None
|
38 |
+
else hydra.utils.instantiate(cfg['output_interface'], _recursive_=False)
|
39 |
+
),
|
40 |
+
}
|
41 |
+
|
42 |
+
# ~~~ Get the data ~~~
|
43 |
+
# This can be a list of samples
|
44 |
+
data = {"id": 0} # Add your data here
|
45 |
+
|
46 |
+
# ~~~ Run inference ~~~
|
47 |
+
path_to_output_file = None
|
48 |
+
# path_to_output_file = "output.jsonl" # Uncomment this line to save the output to disk
|
49 |
+
|
50 |
+
_, outputs = FlowLauncher.launch(
|
51 |
+
flow_with_interfaces=flow_with_interfaces,
|
52 |
+
data=data,
|
53 |
+
path_to_output_file=path_to_output_file,
|
54 |
+
)
|
55 |
+
|
56 |
+
# ~~~ Print the output ~~~
|
57 |
+
flow_output_data = outputs[0]
|
58 |
+
print(flow_output_data)
|