enact 0.4.0.dev0__tar.gz → 0.4.0.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. enact-0.4.0.dev1/PKG-INFO +254 -0
  2. enact-0.4.0.dev1/README.md +243 -0
  3. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/pyproject.toml +1 -1
  4. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/__init__.py +8 -3
  5. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/contexts.py +5 -6
  6. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/digests.py +41 -40
  7. enact-0.4.0.dev1/src/enact/gradio/__init__.py +17 -0
  8. enact-0.4.0.dev0/src/enact/guis.py → enact-0.4.0.dev1/src/enact/gradio/gradio.py +30 -14
  9. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/interfaces.py +13 -8
  10. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/invocations.py +199 -21
  11. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/pretty_print.py +1 -1
  12. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/references.py +22 -11
  13. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/resource_registry.py +2 -1
  14. enact-0.4.0.dev1/src/enact.egg-info/PKG-INFO +254 -0
  15. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact.egg-info/SOURCES.txt +2 -1
  16. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/tests/test_invocations.py +205 -106
  17. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/tests/test_references.py +12 -11
  18. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/tests/test_resource_types.py +2 -2
  19. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/tests/test_resources.py +1 -1
  20. enact-0.4.0.dev0/PKG-INFO +0 -152
  21. enact-0.4.0.dev0/README.md +0 -141
  22. enact-0.4.0.dev0/src/enact.egg-info/PKG-INFO +0 -152
  23. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/LICENSE +0 -0
  24. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/setup.cfg +0 -0
  25. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/resource_types.py +0 -0
  26. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/resources.py +0 -0
  27. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact/serialization.py +0 -0
  28. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact.egg-info/dependency_links.txt +0 -0
  29. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact.egg-info/requires.txt +0 -0
  30. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/src/enact.egg-info/top_level.txt +0 -0
  31. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/tests/test_contexts.py +0 -0
  32. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/tests/test_digest.py +0 -0
  33. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/tests/test_resource_registry.py +0 -0
  34. {enact-0.4.0.dev0 → enact-0.4.0.dev1}/tests/test_serialize.py +0 -0
@@ -0,0 +1,254 @@
1
+ Metadata-Version: 2.1
2
+ Name: enact
3
+ Version: 0.4.0.dev1
4
+ Summary: A framework for generative software.
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: License :: OSI Approved :: Apache Software License
7
+ Classifier: Operating System :: OS Independent
8
+ Requires-Python: >=3.8
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+
12
+ # enact - A Framework for Generative Software.
13
+
14
+ Enact is a python framework for building generative software, specifically
15
+ software that integrates with machine learning models or APIs that generate
16
+ distributions of outputs.
17
+
18
+ The advent of generative AI is driving changes in the way software is built.
19
+ The unique challenges of implementing, maintaining and improving generative
20
+ systems indicate a need to rethink the software stack from a first-principles
21
+ perspective. See [why-enact](#why-enact) for a more in-depth discussion.
22
+
23
+ The design philosophy of enact is to provide an easy-to-use python framework
24
+ that addresses the needs of emerging AI-based systems in a fundamental manner.
25
+ Enact is designed as a core framework that provides low-level primitives
26
+ required by generative software systems.
27
+
28
+ To this end, enact provides support for the following features:
29
+ * The ability to commit data, generative components and executions to
30
+ persistent storage in a versioned manner.
31
+ * Journaled executions of generative python components.
32
+ * The ability to rewind and replay past executions.
33
+ * Easy interchangeability of human and AI-driven subsystems.
34
+ * Support for all of the above features in higher-order generative flows, i.e.,
35
+ generative programs that generate and execute other generative flows.
36
+ * A simple hash-based storage model that simplifies distributed and
37
+ asynchronous generative flows.
38
+
39
+ ## Installation and overview
40
+
41
+ Enact is available as a [pypi package](https://pypi.org/project/enact/) and can
42
+ be installed via:
43
+
44
+ ```bash
45
+ pip install enact
46
+ ```
47
+
48
+ Enact defines generative components as python classes with annotated input and
49
+ output types:
50
+
51
+ ```python
52
+ import enact
53
+
54
+ import dataclasses
55
+ import random
56
+
57
+ @enact.typed_invokable(
58
+ input_type=enact.NoneResource,
59
+ output_type=enact.Int)
60
+ @dataclasses.dataclass
61
+ class RollDie(enact.Invokable):
62
+ """An enact invokable that rolls a die."""
63
+ sides: int
64
+
65
+ def call(self):
66
+ return enact.Int(random.randint(1, self.sides))
67
+
68
+
69
+ @enact.typed_invokable(
70
+ input_type=enact.Int,
71
+ output_type=enact.Int)
72
+ @dataclasses.dataclass
73
+ class RollDice(enact.Invokable):
74
+ """An enact invokable that rolls a specified number of dice."""
75
+ roll: enact.Invokable
76
+ def call(self, num_dice: enact.Int):
77
+ return enact.Int(sum(self.roll() for _ in range(num_dice)))
78
+
79
+ roll_dice = RollDice(RollDie(6))
80
+ print(roll_dice(enact.Int(3))) # Print sum of 3 rolls.
81
+ ```
82
+
83
+ Executions can be journaled and committed to persistent storage. A journaled
84
+ execution supports rewinding and replaying.
85
+
86
+ ```python
87
+ with enact.FileStore('/tmp/my_store') as store:
88
+ num_rolls = enact.commit(enact.Int(3)) # commit input to store.
89
+ invocation = roll_dice.invoke(num_rolls) # create journaled execution.
90
+
91
+ print(invocation.get_output()) # Print sum of 3 rolls
92
+ for i in range(3):
93
+ print(invocation.get_child(i).get_output()) # Print each die roll.
94
+
95
+ invocation = invocation.rewind() # Rewind by one dice roll.
96
+ invocation = invocation.replay() # Replay dice roll 1 & 2, resample roll 3.
97
+ print(invocation.get_output())
98
+ ```
99
+
100
+ Human input can be flexibly swapped in for generative components:
101
+
102
+ ```python
103
+ @enact.typed_invokable(enact.NoneResource, enact.Int)
104
+ class HumanRollsDie(enact.Invokable):
105
+ def call(self):
106
+ return enact.request_input(
107
+ enact.Int, context='Please roll a six-sided die')
108
+
109
+ with store:
110
+ roll_dice = RollDice(HumanRollsDie())
111
+ inv_gen = enact.InvocationGenerator(roll_dice, num_rolls)
112
+ for input_request in inv_gen:
113
+ inv_gen.set_input(enact.Int(6)) # Provide a roll of 6.
114
+
115
+ print(inv_gen.invocation.get_output()) # Prints '18'.
116
+ ```
117
+
118
+ ## Documentation
119
+
120
+ Full documentation is work in progress. A quickstart tutorial, explanation of
121
+ enact concepts and examples can be found in the
122
+ [examples directory](https://github.com/agentic-ai/enact/tree/main/examples).
123
+
124
+ ## Why enact?
125
+
126
+ The rise of generative AI models is transforming the software development
127
+ process.
128
+
129
+ Traditional software relies primarily on functional buildings blocks in which
130
+ inputs and system state directly determine outputs. In contrast, modern software
131
+ increasingly utilizes generative AI elements, in which each input is associated
132
+ with a range of possible outputs.
133
+
134
+ This seemingly small change in emphasis - from functions to conditional
135
+ distributions - implies a shift across multiple dimensions of the engineering
136
+ process, summarized in the table below.
137
+
138
+ | | Traditional | Generative |
139
+ | :----: | :-----------: | :----------: |
140
+ | Building block | Deterministic functions | Conditional distributions |
141
+ | Engineering | Add features, debug errors | Improve output distributions |
142
+ | Subsystems | Interchangeable | Unique |
143
+ | Code sharing | Frameworks | Components |
144
+ | Executions | Logged for metrics/debugging | Training data |
145
+ | Interactivity | At system boundaries | Within system components |
146
+ | Code vs data | Distinct | Overlapping |
147
+
148
+ ### Building generative software means fitting distributions
149
+
150
+ In traditional software, a large part of engineering effort revolves around
151
+ implementing features and debugging errors. In contrast, a generative software
152
+ system may be feature-complete and bug-free, but still not suitable for
153
+ deployment. Consider the following examples:
154
+
155
+ * A search chatbot that is sometimes rude and unhelpful
156
+ * An autonomous agent that recursively sets itself goals and accomplishes tasks,
157
+ but has a tendency to drift off into behavioral loops.
158
+ * An AI avatar generator that produces accurate but unattractive portrait
159
+ images.
160
+
161
+ System correctness is no longer merely a question of specific inputs leading
162
+ to outputs that are either correct or incorrect, but of the _distribution of
163
+ outputs_ satisfying some implicitly or explicitly defined quality target.
164
+
165
+ In cases where generativity is localized, e.g., when the software is a thin
166
+ wrapper around a large language model (LLM) or image generator, machine-learning
167
+ tools and techniques can directly be used to improve the system, but in cases
168
+ where multiple generative components work together to produce an output the
169
+ system must be fitted to the target distribution as a whole.
170
+
171
+ ### Generative software requires recursively swapping subsystems
172
+
173
+ In traditional software engineering, the choice between two API-identical
174
+ implementations primarily revolves around practicalities such as performance or
175
+ maintainability. However, in generative software, individual components produce
176
+ distributions that may be more or less well-fitted to the system's overall goal,
177
+ for example:
178
+
179
+ * A foundation text-to-image model may perform well on a wide range of
180
+ prompts, whereas an API-identical fine-tuned version may be less general but
181
+ produce better results for images of a particular style.
182
+ * An instruction-tuned LLM and an LLM trained as a chatbot both autoregressively
183
+ extend token sequences, but one may be better suited towards data processing
184
+ applications, while another will make a better math tutor.
185
+ * Different components may have vastly different execution costs.
186
+
187
+ Generative system outputs are distributions that optimized towards some - often
188
+ implicitly specified - target. Data selection, training parameters, model
189
+ composition, sampling of feedback and self-improvement flows produce systems
190
+ whose conditional output distributions represent a unique, opinionated take on
191
+ the problem they were trained to solve. Therefore the development of generative
192
+ systems motivates ongoing reevaluation, tuning and replacement of subsystems,
193
+ more so than in traditional engineering applications.
194
+
195
+ ### Generative software should be shareable
196
+
197
+ There are large numbers of generative AI components that are mutually
198
+ API-compatible (e.g., text-to-image generation, LLMs) but cannot be directly
199
+ ranked in terms of quality since they represent a unique take on the problem
200
+ domain. The combination of API compatibility and variation lends itself to a
201
+ more evolutionary collaborative style than traditional software, where
202
+ shared effort tends to centralize into fewer, lower-level frameworks.
203
+
204
+ This new collaborative approach is already evidenced by widespread sharing of
205
+ prompt templates and the existence of public databases of fine-tuned models.
206
+
207
+ ### Generative software reflects on its executions.
208
+
209
+ In conventional software, executions are typically tracked at a low level
210
+ of resolution, since their primary use is to track metrics and debug errors.
211
+ A generative system represents an implicitly specified distribution, and
212
+ its execution history provides valuable information that may be used for
213
+ analysis or training.
214
+
215
+ * System outputs can be corrected, scored or critiqued by humans or AI
216
+ models to produce data for fine-tuning.
217
+ * Data from one generative model can be distilled into another.
218
+ * Complex orchestrations of different ML models can be replaced by end-to-end
219
+ trained models once sufficient data is available.
220
+ * Failed executions are potential input data for generative systems, e.g., in
221
+ the case of program synthesis and 'self-healing programs'.
222
+
223
+ ### Humans are in the loop
224
+
225
+ Unlike traditional systems, where user interactions happen at system boundaries,
226
+ AI and humans are often equal participants in generative computations. An
227
+ example is Reinforcement Learning from Human Feedback (RLHF), where humans
228
+ provide feedback on AI output, only to be replaced by an AI model that mimics
229
+ their feedback behavior during the training process. Critical generative flows
230
+ (e.g., the drafting of legal documents) may require a human verification step.
231
+
232
+ The choice between sampling human input and sampling a generative model is
233
+ one of cost, quality and timing constraints, and may be subject to change during
234
+ the development of a system. Therefore, ideally, a generative system will be able
235
+ to sample output from a human in the same way that it would call into an API or
236
+ subsystem.
237
+
238
+ ### Data is code, code is data
239
+
240
+ Traditional software systems tend to allow a clear distinction between code
241
+ (written by developers) and data (generated by the user and the system). In
242
+ generative systems this distinction breaks down: Approaches such as AutoGPT or
243
+ Voyager use generative AI to generate programs (specified in code or plain
244
+ text), which in turn may be interpreted by generative AI systems; prompts for
245
+ chat-based generative AI could equally be considered code or data.
246
+
247
+ ## Development and Contributing
248
+
249
+ Enact is currently in alpha release. The framework is open source and Apache
250
+ licensed. We are actively looking for contributors that are excited about the
251
+ vision.
252
+
253
+ You can download the source code, report issues and create pull requests at
254
+ https://github.com/agentic-ai/enact.
@@ -0,0 +1,243 @@
1
+ # enact - A Framework for Generative Software.
2
+
3
+ Enact is a python framework for building generative software, specifically
4
+ software that integrates with machine learning models or APIs that generate
5
+ distributions of outputs.
6
+
7
+ The advent of generative AI is driving changes in the way software is built.
8
+ The unique challenges of implementing, maintaining and improving generative
9
+ systems indicate a need to rethink the software stack from a first-principles
10
+ perspective. See [why-enact](#why-enact) for a more in-depth discussion.
11
+
12
+ The design philosophy of enact is to provide an easy-to-use python framework
13
+ that addresses the needs of emerging AI-based systems in a fundamental manner.
14
+ Enact is designed as a core framework that provides low-level primitives
15
+ required by generative software systems.
16
+
17
+ To this end, enact provides support for the following features:
18
+ * The ability to commit data, generative components and executions to
19
+ persistent storage in a versioned manner.
20
+ * Journaled executions of generative python components.
21
+ * The ability to rewind and replay past executions.
22
+ * Easy interchangeability of human and AI-driven subsystems.
23
+ * Support for all of the above features in higher-order generative flows, i.e.,
24
+ generative programs that generate and execute other generative flows.
25
+ * A simple hash-based storage model that simplifies distributed and
26
+ asynchronous generative flows.
27
+
28
+ ## Installation and overview
29
+
30
+ Enact is available as a [pypi package](https://pypi.org/project/enact/) and can
31
+ be installed via:
32
+
33
+ ```bash
34
+ pip install enact
35
+ ```
36
+
37
+ Enact defines generative components as python classes with annotated input and
38
+ output types:
39
+
40
+ ```python
41
+ import enact
42
+
43
+ import dataclasses
44
+ import random
45
+
46
+ @enact.typed_invokable(
47
+ input_type=enact.NoneResource,
48
+ output_type=enact.Int)
49
+ @dataclasses.dataclass
50
+ class RollDie(enact.Invokable):
51
+ """An enact invokable that rolls a die."""
52
+ sides: int
53
+
54
+ def call(self):
55
+ return enact.Int(random.randint(1, self.sides))
56
+
57
+
58
+ @enact.typed_invokable(
59
+ input_type=enact.Int,
60
+ output_type=enact.Int)
61
+ @dataclasses.dataclass
62
+ class RollDice(enact.Invokable):
63
+ """An enact invokable that rolls a specified number of dice."""
64
+ roll: enact.Invokable
65
+ def call(self, num_dice: enact.Int):
66
+ return enact.Int(sum(self.roll() for _ in range(num_dice)))
67
+
68
+ roll_dice = RollDice(RollDie(6))
69
+ print(roll_dice(enact.Int(3))) # Print sum of 3 rolls.
70
+ ```
71
+
72
+ Executions can be journaled and committed to persistent storage. A journaled
73
+ execution supports rewinding and replaying.
74
+
75
+ ```python
76
+ with enact.FileStore('/tmp/my_store') as store:
77
+ num_rolls = enact.commit(enact.Int(3)) # commit input to store.
78
+ invocation = roll_dice.invoke(num_rolls) # create journaled execution.
79
+
80
+ print(invocation.get_output()) # Print sum of 3 rolls
81
+ for i in range(3):
82
+ print(invocation.get_child(i).get_output()) # Print each die roll.
83
+
84
+ invocation = invocation.rewind() # Rewind by one dice roll.
85
+ invocation = invocation.replay() # Replay dice roll 1 & 2, resample roll 3.
86
+ print(invocation.get_output())
87
+ ```
88
+
89
+ Human input can be flexibly swapped in for generative components:
90
+
91
+ ```python
92
+ @enact.typed_invokable(enact.NoneResource, enact.Int)
93
+ class HumanRollsDie(enact.Invokable):
94
+ def call(self):
95
+ return enact.request_input(
96
+ enact.Int, context='Please roll a six-sided die')
97
+
98
+ with store:
99
+ roll_dice = RollDice(HumanRollsDie())
100
+ inv_gen = enact.InvocationGenerator(roll_dice, num_rolls)
101
+ for input_request in inv_gen:
102
+ inv_gen.set_input(enact.Int(6)) # Provide a roll of 6.
103
+
104
+ print(inv_gen.invocation.get_output()) # Prints '18'.
105
+ ```
106
+
107
+ ## Documentation
108
+
109
+ Full documentation is work in progress. A quickstart tutorial, explanation of
110
+ enact concepts and examples can be found in the
111
+ [examples directory](https://github.com/agentic-ai/enact/tree/main/examples).
112
+
113
+ ## Why enact?
114
+
115
+ The rise of generative AI models is transforming the software development
116
+ process.
117
+
118
+ Traditional software relies primarily on functional buildings blocks in which
119
+ inputs and system state directly determine outputs. In contrast, modern software
120
+ increasingly utilizes generative AI elements, in which each input is associated
121
+ with a range of possible outputs.
122
+
123
+ This seemingly small change in emphasis - from functions to conditional
124
+ distributions - implies a shift across multiple dimensions of the engineering
125
+ process, summarized in the table below.
126
+
127
+ | | Traditional | Generative |
128
+ | :----: | :-----------: | :----------: |
129
+ | Building block | Deterministic functions | Conditional distributions |
130
+ | Engineering | Add features, debug errors | Improve output distributions |
131
+ | Subsystems | Interchangeable | Unique |
132
+ | Code sharing | Frameworks | Components |
133
+ | Executions | Logged for metrics/debugging | Training data |
134
+ | Interactivity | At system boundaries | Within system components |
135
+ | Code vs data | Distinct | Overlapping |
136
+
137
+ ### Building generative software means fitting distributions
138
+
139
+ In traditional software, a large part of engineering effort revolves around
140
+ implementing features and debugging errors. In contrast, a generative software
141
+ system may be feature-complete and bug-free, but still not suitable for
142
+ deployment. Consider the following examples:
143
+
144
+ * A search chatbot that is sometimes rude and unhelpful
145
+ * An autonomous agent that recursively sets itself goals and accomplishes tasks,
146
+ but has a tendency to drift off into behavioral loops.
147
+ * An AI avatar generator that produces accurate but unattractive portrait
148
+ images.
149
+
150
+ System correctness is no longer merely a question of specific inputs leading
151
+ to outputs that are either correct or incorrect, but of the _distribution of
152
+ outputs_ satisfying some implicitly or explicitly defined quality target.
153
+
154
+ In cases where generativity is localized, e.g., when the software is a thin
155
+ wrapper around a large language model (LLM) or image generator, machine-learning
156
+ tools and techniques can directly be used to improve the system, but in cases
157
+ where multiple generative components work together to produce an output the
158
+ system must be fitted to the target distribution as a whole.
159
+
160
+ ### Generative software requires recursively swapping subsystems
161
+
162
+ In traditional software engineering, the choice between two API-identical
163
+ implementations primarily revolves around practicalities such as performance or
164
+ maintainability. However, in generative software, individual components produce
165
+ distributions that may be more or less well-fitted to the system's overall goal,
166
+ for example:
167
+
168
+ * A foundation text-to-image model may perform well on a wide range of
169
+ prompts, whereas an API-identical fine-tuned version may be less general but
170
+ produce better results for images of a particular style.
171
+ * An instruction-tuned LLM and an LLM trained as a chatbot both autoregressively
172
+ extend token sequences, but one may be better suited towards data processing
173
+ applications, while another will make a better math tutor.
174
+ * Different components may have vastly different execution costs.
175
+
176
+ Generative system outputs are distributions that optimized towards some - often
177
+ implicitly specified - target. Data selection, training parameters, model
178
+ composition, sampling of feedback and self-improvement flows produce systems
179
+ whose conditional output distributions represent a unique, opinionated take on
180
+ the problem they were trained to solve. Therefore the development of generative
181
+ systems motivates ongoing reevaluation, tuning and replacement of subsystems,
182
+ more so than in traditional engineering applications.
183
+
184
+ ### Generative software should be shareable
185
+
186
+ There are large numbers of generative AI components that are mutually
187
+ API-compatible (e.g., text-to-image generation, LLMs) but cannot be directly
188
+ ranked in terms of quality since they represent a unique take on the problem
189
+ domain. The combination of API compatibility and variation lends itself to a
190
+ more evolutionary collaborative style than traditional software, where
191
+ shared effort tends to centralize into fewer, lower-level frameworks.
192
+
193
+ This new collaborative approach is already evidenced by widespread sharing of
194
+ prompt templates and the existence of public databases of fine-tuned models.
195
+
196
+ ### Generative software reflects on its executions.
197
+
198
+ In conventional software, executions are typically tracked at a low level
199
+ of resolution, since their primary use is to track metrics and debug errors.
200
+ A generative system represents an implicitly specified distribution, and
201
+ its execution history provides valuable information that may be used for
202
+ analysis or training.
203
+
204
+ * System outputs can be corrected, scored or critiqued by humans or AI
205
+ models to produce data for fine-tuning.
206
+ * Data from one generative model can be distilled into another.
207
+ * Complex orchestrations of different ML models can be replaced by end-to-end
208
+ trained models once sufficient data is available.
209
+ * Failed executions are potential input data for generative systems, e.g., in
210
+ the case of program synthesis and 'self-healing programs'.
211
+
212
+ ### Humans are in the loop
213
+
214
+ Unlike traditional systems, where user interactions happen at system boundaries,
215
+ AI and humans are often equal participants in generative computations. An
216
+ example is Reinforcement Learning from Human Feedback (RLHF), where humans
217
+ provide feedback on AI output, only to be replaced by an AI model that mimics
218
+ their feedback behavior during the training process. Critical generative flows
219
+ (e.g., the drafting of legal documents) may require a human verification step.
220
+
221
+ The choice between sampling human input and sampling a generative model is
222
+ one of cost, quality and timing constraints, and may be subject to change during
223
+ the development of a system. Therefore, ideally, a generative system will be able
224
+ to sample output from a human in the same way that it would call into an API or
225
+ subsystem.
226
+
227
+ ### Data is code, code is data
228
+
229
+ Traditional software systems tend to allow a clear distinction between code
230
+ (written by developers) and data (generated by the user and the system). In
231
+ generative systems this distinction breaks down: Approaches such as AutoGPT or
232
+ Voyager use generative AI to generate programs (specified in code or plain
233
+ text), which in turn may be interpreted by generative AI systems; prompts for
234
+ chat-based generative AI could equally be considered code or data.
235
+
236
+ ## Development and Contributing
237
+
238
+ Enact is currently in alpha release. The framework is open source and Apache
239
+ licensed. We are actively looking for contributors that are excited about the
240
+ vision.
241
+
242
+ You can download the source code, report issues and create pull requests at
243
+ https://github.com/agentic-ai/enact.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "enact"
3
- version = "0.4.0.dev0"
3
+ version = "0.4.0.dev1"
4
4
  dependencies = [
5
5
  "gradio",
6
6
  "numpy",
@@ -26,6 +26,7 @@ from enact.invocations import InputChanged
26
26
  from enact.invocations import InputRequest
27
27
  from enact.invocations import InputRequestOutsideInvocation
28
28
  from enact.invocations import RequestedTypeUndetermined
29
+ from enact.invocations import InvocationGenerator
29
30
  from enact.invocations import Invokable
30
31
  from enact.invocations import InvokableBase
31
32
  from enact.invocations import InvokableBase
@@ -34,8 +35,8 @@ from enact.invocations import ReplayContext
34
35
  from enact.invocations import ReplayError
35
36
  from enact.invocations import Request
36
37
  from enact.invocations import Response
37
- from enact.invocations import request_input
38
38
  from enact.invocations import RequestInput
39
+ from enact.invocations import request_input
39
40
  from enact.invocations import typed_invokable
40
41
  from enact.invocations import WrappedException
41
42
 
@@ -51,6 +52,8 @@ from enact.references import InMemoryBackend
51
52
  from enact.references import Ref
52
53
  from enact.references import RefError
53
54
  from enact.references import Store
55
+ from enact.references import InMemoryStore
56
+ from enact.references import FileStore
54
57
 
55
58
  from enact.resources import Resource
56
59
 
@@ -64,7 +67,9 @@ from enact.resource_types import Str
64
67
  from enact.resource_types import Bytes
65
68
  from enact.resource_types import NPArray
66
69
 
67
-
68
- from enact.guis import GUI
70
+ from enact.serialization import Serializer
71
+ from enact.serialization import JsonSerializer
72
+ from enact.serialization import SerializationError
73
+ from enact.serialization import DeserializationError
69
74
 
70
75
  from enact import contexts
@@ -25,12 +25,10 @@ _context_vars: Dict[Type['Context'],
25
25
 
26
26
  class ContextError(Exception):
27
27
  """Error raised when there is a problem with the context."""
28
- pass
29
28
 
30
29
 
31
30
  class NoActiveContext(ContextError):
32
31
  """Raised when there is no active context."""
33
- pass
34
32
 
35
33
  C = TypeVar('C', bound='Context')
36
34
 
@@ -47,10 +45,10 @@ class Context:
47
45
  """Returns the context var for this type."""
48
46
  try:
49
47
  return cast(contextvars.ContextVar[Optional[C]], _context_vars[cls])
50
- except KeyError:
48
+ except KeyError as key_error:
51
49
  raise ContextError(
52
50
  f'Context {cls} not registered. A context class must be registered '
53
- f'with the "@register" decorator.')
51
+ f'with the "@register" decorator.') from key_error
54
52
 
55
53
  @classmethod
56
54
  @contextlib.contextmanager
@@ -69,11 +67,12 @@ class Context:
69
67
  context_var = cls._get_context_var()
70
68
  try:
71
69
  current_context = context_var.get()
72
- except LookupError:
70
+ except LookupError as lookup_error:
73
71
  raise ContextError(
74
72
  f'Context {cls} not initialized. If running inside a thread, make sure '
75
73
  f'to annotate the thread function with either the '
76
- f'"@with_current_contexts" or "@with_new_contexts" decorator.')
74
+ f'"@with_current_contexts" or "@with_new_contexts" decorator.'
75
+ ) from lookup_error
77
76
  return current_context
78
77
 
79
78
  @classmethod