fabricatio 0.2.0.dev0__py3-none-any.whl → 0.2.0.dev1__py3-none-any.whl

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.
@@ -1,5 +1,5 @@
1
1
  """module for actions."""
2
2
 
3
- from fabricatio.actions.transmission import SendTask
3
+ from fabricatio.actions.transmission import PublishTask
4
4
 
5
- __all__ = ["SendTask"]
5
+ __all__ = ["PublishTask"]
@@ -2,15 +2,19 @@ from typing import List
2
2
 
3
3
  from fabricatio.journal import logger
4
4
  from fabricatio.models.action import Action
5
+ from fabricatio.models.events import EventLike
5
6
  from fabricatio.models.task import Task
6
7
 
7
8
 
8
- class SendTask(Action):
9
- """Action that sends a task to a user."""
9
+ class PublishTask(Action):
10
+ """An action that publishes a task to a list of targets."""
10
11
 
11
- name: str = "send_task"
12
+ name: str = "publish_task"
13
+ """The name of the action."""
14
+ description: str = "Publish a task to a list of targets."
12
15
 
13
- async def _execute(self, send_targets: List[str], send_task: Task, **_) -> None:
16
+ async def _execute(self, send_targets: List[EventLike], send_task: Task, **_) -> None:
17
+ """Execute the action by sending the task to the specified targets."""
14
18
  logger.info(f"Sending task {send_task.name} to {send_targets}")
15
19
  for target in send_targets:
16
- await send_task.publish(target)
20
+ await send_task.move_to(target).publish()
fabricatio/fs/__init__.py CHANGED
@@ -0,0 +1 @@
1
+ """FileSystem manipulation module for Fabricatio."""
@@ -41,7 +41,7 @@ class Action(WithBriefing, LLMUsage):
41
41
  return cxt
42
42
 
43
43
 
44
- class WorkFlow(WithBriefing, LLMUsage):
44
+ class WorkFlow[A: Type[Action] | Action](WithBriefing, LLMUsage):
45
45
  """Class that represents a workflow to be executed in a task."""
46
46
 
47
47
  _context: Queue[Dict[str, Any]] = PrivateAttr(default_factory=lambda: Queue(maxsize=1))
@@ -49,12 +49,14 @@ class WorkFlow(WithBriefing, LLMUsage):
49
49
 
50
50
  _instances: Tuple[Action, ...] = PrivateAttr(...)
51
51
 
52
- steps: Tuple[Type[Action], ...] = Field(...)
53
- """ The steps to be executed in the workflow."""
52
+ steps: Tuple[A, ...] = Field(...)
53
+ """ The steps to be executed in the workflow, actions or action classes."""
54
54
  task_input_key: str = Field(default="task_input")
55
55
  """ The key of the task input data."""
56
56
  task_output_key: str = Field(default="task_output")
57
57
  """ The key of the task output data."""
58
+ extra_init_context: Dict[str, Any] = Field(default_factory=dict, frozen=True)
59
+ """ The extra context dictionary to be used for workflow initialization."""
58
60
 
59
61
  def model_post_init(self, __context: Any) -> None:
60
62
  """Initialize the workflow by setting fallbacks for each step.
@@ -62,7 +64,11 @@ class WorkFlow(WithBriefing, LLMUsage):
62
64
  Args:
63
65
  __context: The context to be used for initialization.
64
66
  """
65
- self._instances = tuple(step() for step in self.steps)
67
+ temp = []
68
+ for step in self.steps:
69
+ temp.append(step if isinstance(step, Action) else step())
70
+ self._instances = tuple(temp)
71
+
66
72
  for step in self._instances:
67
73
  step.fallback_to(self)
68
74
 
@@ -73,13 +79,13 @@ class WorkFlow(WithBriefing, LLMUsage):
73
79
  task: The task to be served.
74
80
  """
75
81
  await task.start()
76
- await self._context.put({self.task_input_key: task})
82
+ await self._init_context()
77
83
  current_action = None
78
84
  try:
79
85
  for step in self._instances:
80
86
  logger.debug(f"Executing step: {step.name}")
81
- ctx = await self._context.get()
82
- modified_ctx = await step.act(ctx)
87
+ cxt = await self._context.get()
88
+ modified_ctx = await step.act(cxt)
83
89
  await self._context.put(modified_ctx)
84
90
  current_action = step.name
85
91
  logger.info(f"Finished executing workflow: {self.name}")
@@ -88,3 +94,8 @@ class WorkFlow(WithBriefing, LLMUsage):
88
94
  logger.error(f"Error during task: {current_action} execution: {e}") # Log the exception
89
95
  logger.error(traceback.format_exc()) # Add this line to log the traceback
90
96
  await task.fail() # Mark the task as failed
97
+
98
+ async def _init_context(self) -> None:
99
+ """Initialize the context dictionary for workflow execution."""
100
+ logger.debug(f"Initializing context for workflow: {self.name}")
101
+ await self._context.put({self.task_input_key: None, **dict(self.extra_init_context)})
fabricatio/models/task.py CHANGED
@@ -11,7 +11,7 @@ from pydantic import Field, PrivateAttr
11
11
 
12
12
  from fabricatio.core import env
13
13
  from fabricatio.journal import logger
14
- from fabricatio.models.events import Event
14
+ from fabricatio.models.events import Event, EventLike
15
15
  from fabricatio.models.generic import WithBriefing, WithDependency, WithJsonExample
16
16
 
17
17
 
@@ -69,7 +69,7 @@ class Task[T](WithBriefing, WithJsonExample, WithDependency):
69
69
  """Initialize the task with a namespace event."""
70
70
  self._namespace.segments.extend(self.namespace)
71
71
 
72
- def move_to(self, new_namespace: List[str]) -> Self:
72
+ def move_to(self, new_namespace: EventLike) -> Self:
73
73
  """Move the task to a new namespace.
74
74
 
75
75
  Args:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fabricatio
3
- Version: 0.2.0.dev0
3
+ Version: 0.2.0.dev1
4
4
  Summary: A LLM multi-agent framework.
5
5
  Author-email: Whth <zettainspector@foxmail.com>
6
6
  License: MIT License
@@ -51,10 +51,51 @@ Requires-Dist: regex>=2024.11.6
51
51
  Requires-Dist: rich>=13.9.4
52
52
  Description-Content-Type: text/markdown
53
53
 
54
+ # Fabricatio
55
+
56
+ ---
57
+
58
+ Fabricatio is a powerful framework designed to facilitate the creation and management of tasks, actions, and workflows. It leverages modern Python features and libraries to provide a robust and flexible environment for building applications that require task automation and orchestration.
59
+
60
+ ## Table of Contents
61
+
62
+ - [Installation](#installation)
63
+ - [Usage](#usage)
64
+ - [Defining a Task](#defining-a-task)
65
+ - [Creating an Action](#creating-an-action)
66
+ - [Assigning a Role](#assigning-a-role)
67
+ - [Logging](#logging)
68
+ - [Configuration](#configuration)
69
+ - [LLM Configuration](#llm-configuration)
70
+ - [Debug Configuration](#debug-configuration)
71
+ - [Examples](#examples)
72
+ - [Simple Task Example](#simple-task-example)
73
+ - [Complex Workflow Example](#complex-workflow-example)
74
+ - [Contributing](#contributing)
75
+ - [License](#license)
76
+
77
+ ## Installation
78
+ To install Fabricatio, you can use pip:
79
+
80
+ ```bash
81
+ pip install fabricatio
82
+ ```
83
+
84
+ Alternatively, you can clone the repository and install it manually:
85
+
86
+ ```bash
87
+ git clone https://github.com/your-repo/fabricatio.git
88
+ cd fabricatio
89
+ pip install .
90
+ ```
91
+
92
+
54
93
  ## Usage
55
94
 
56
95
  ### Defining a Task
57
96
 
97
+ A task in Fabricatio is defined using the `Task` class. You can specify the name, goal, and description of the task.
98
+
58
99
  ```python
59
100
  from fabricatio.models.task import Task
60
101
 
@@ -64,12 +105,14 @@ task = Task(name="say hello", goal="say hello", description="say hello to the wo
64
105
 
65
106
  ### Creating an Action
66
107
 
108
+ Actions are the building blocks of workflows. They perform specific tasks and can be asynchronous.
109
+
67
110
  ```python
68
111
  from fabricatio import Action, logger
69
112
  from fabricatio.models.task import Task
70
113
 
71
114
  class Talk(Action):
72
- async def _execute(self, task_input: Task[str], **_) -> Any:
115
+ async def _execute(self, task_input: Task[str], **_) -> str:
73
116
  ret = "Hello fabricatio!"
74
117
  logger.info("executing talk action")
75
118
  return ret
@@ -78,6 +121,8 @@ class Talk(Action):
78
121
 
79
122
  ### Assigning a Role
80
123
 
124
+ Roles in Fabricatio are responsible for executing workflows. You can define a role with a set of actions.
125
+
81
126
  ```python
82
127
  from fabricatio.models.role import Role
83
128
  from fabricatio.models.action import WorkFlow
@@ -104,19 +149,91 @@ debug_config = DebugConfig(log_level="DEBUG", log_file="fabricatio.log")
104
149
 
105
150
  Fabricatio uses Pydantic for configuration management. You can define your settings in the `config.py` file.
106
151
 
152
+ ### LLM Configuration
153
+
154
+ The Large Language Model (LLM) configuration is managed by the `LLMConfig` class.
155
+
107
156
  ```python
108
- from fabricatio.config import Settings
157
+ from fabricatio.config import LLMConfig
109
158
 
110
- settings = Settings(llm=LLMConfig(api_endpoint="https://api.example.com"))
159
+ llm_config = LLMConfig(api_endpoint="https://api.example.com")
111
160
  ```
112
161
 
113
162
 
114
- ## Testing
163
+ ### Debug Configuration
115
164
 
116
- Fabricatio includes a set of tests to ensure the framework works as expected. You can run the tests using `pytest`.
165
+ The debug configuration is managed by the `DebugConfig` class.
117
166
 
118
- ```bash
119
- pytest
167
+ ```python
168
+ from fabricatio.config import DebugConfig
169
+
170
+ debug_config = DebugConfig(log_level="DEBUG", log_file="fabricatio.log")
171
+ ```
172
+
173
+
174
+ ## Examples
175
+
176
+ ### Simple Task Example
177
+
178
+ Here is a simple example of a task that prints "Hello fabricatio!".
179
+
180
+ ```python
181
+ import asyncio
182
+ from fabricatio import Action, Role, Task, WorkFlow, logger
183
+
184
+ task = Task(name="say hello", goal="say hello", description="say hello to the world")
185
+
186
+ class Talk(Action):
187
+ async def _execute(self, task_input: Task[str], **_) -> Any:
188
+ ret = "Hello fabricatio!"
189
+ logger.info("executing talk action")
190
+ return ret
191
+
192
+ class TestWorkflow(WorkFlow):
193
+ pass
194
+
195
+ role = Role(name="Test Role", actions=[TestWorkflow()])
196
+
197
+ async def main() -> None:
198
+ await role.act(task)
199
+
200
+ if __name__ == "__main__":
201
+ asyncio.run(main())
202
+ ```
203
+
204
+
205
+ ### Complex Workflow Example
206
+
207
+ Here is a more complex example that demonstrates how to create a workflow with multiple actions.
208
+
209
+ ```python
210
+ import asyncio
211
+ from fabricatio import Action, Role, Task, WorkFlow, logger
212
+
213
+ task = Task(name="complex task", goal="perform complex operations", description="a task with multiple actions")
214
+
215
+ class ActionOne(Action):
216
+ async def _execute(self, task_input: Task[str], **_) -> Any:
217
+ ret = "Action One executed"
218
+ logger.info(ret)
219
+ return ret
220
+
221
+ class ActionTwo(Action):
222
+ async def _execute(self, task_input: Task[str], **_) -> Any:
223
+ ret = "Action Two executed"
224
+ logger.info(ret)
225
+ return ret
226
+
227
+ class ComplexWorkflow(WorkFlow):
228
+ actions = [ActionOne(), ActionTwo()]
229
+
230
+ role = Role(name="Complex Role", actions=[ComplexWorkflow()])
231
+
232
+ async def main() -> None:
233
+ await role.act(task)
234
+
235
+ if __name__ == "__main__":
236
+ asyncio.run(main())
120
237
  ```
121
238
 
122
239
 
@@ -5,20 +5,20 @@ fabricatio/decorators.py,sha256=Qsyb-_cDwtXY5yhyLrYZEAlrHh5ZuEooQ8vEOUAxj8k,1855
5
5
  fabricatio/journal.py,sha256=CW9HePtgTiboOyPTExq9GjG5BseZcbc-S6lxDXrpmv0,667
6
6
  fabricatio/parser.py,sha256=6PNFNNyHNkNG7vTS1ejFc4vCzl1OCy4bqB0e4Ty_-Qs,2365
7
7
  fabricatio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- fabricatio/actions/__init__.py,sha256=n3lwq9FPNtvfLu2L1pX4UkwiPITU7luk-b4aMJyjIC8,109
9
- fabricatio/actions/transmission.py,sha256=Azog4ItVk7aASdYzTwzyckzYG2hDFSXctnA7qp-Qlq0,502
10
- fabricatio/fs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ fabricatio/actions/__init__.py,sha256=eFmFVPQvtNgFynIXBVr3eP-vWQDWCPng60YY5LXvZgg,115
9
+ fabricatio/actions/transmission.py,sha256=TABvBB127hC3KYvm7zJp_i-_GF9wXXCR-k8bxfhNYak,768
10
+ fabricatio/fs/__init__.py,sha256=OL9f4jZDYcErSM7Yw7rhy97f8QDE-6wZIoGz1reS3Z0,54
11
11
  fabricatio/fs/readers.py,sha256=mw0VUH3P7Wk0SMlcQm2yOfjEz5C3mQ_kjduAjecaxgY,123
12
- fabricatio/models/action.py,sha256=M-12dc-nQiNJU6Y9j-dr4Ef3642vRvzHlzxekBepzaU,3358
12
+ fabricatio/models/action.py,sha256=CbGuR9dHnu87MFAzLWj8cVHZtFNyT_VuwT3pWlKJvEk,3925
13
13
  fabricatio/models/events.py,sha256=pW3sfxEFWTafbP4bn4hVFSe8qloYrrzOgi9oMCqAEgw,2604
14
14
  fabricatio/models/generic.py,sha256=noHow8dUjMnNiasl2ZHaZeCMpxzDme9QvxTetoyB45w,19539
15
15
  fabricatio/models/role.py,sha256=jdabuYRXwgvpYoNwvazygDiZHGGQApUIIKltniu78O8,2151
16
- fabricatio/models/task.py,sha256=Qc16UeeTMaFjG2-sXafyOrjOS7H_0RluE9sFNwArDlI,8179
16
+ fabricatio/models/task.py,sha256=mWIQHdi1mNJlER5ZFeywsZxg4Skm-VnjW2z8ZEMJLNE,8190
17
17
  fabricatio/models/tool.py,sha256=UkEp1Nzbl5wZX21q_Z2VkpiJmVDSdoGDzINQniO8hSY,3536
18
18
  fabricatio/models/utils.py,sha256=2mgXla9_K3dnRrz6hIKzmltTYPmvDk0MBjjEBkCXTdg,2474
19
19
  fabricatio/toolboxes/__init__.py,sha256=bjefmPd7wBaWhbZzdMPXvrjMTeRzlUh_Dev2PUAc124,158
20
20
  fabricatio/toolboxes/task.py,sha256=xgyPetm2R_HlQwpzE8YPnBN7QOYLd0-T8E6QPZG1PPQ,204
21
- fabricatio-0.2.0.dev0.dist-info/METADATA,sha256=keLz2I0t_VqaU0Xx5rgSIW66aZqSeJLKIsi9Vjw89vc,3858
22
- fabricatio-0.2.0.dev0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
- fabricatio-0.2.0.dev0.dist-info/licenses/LICENSE,sha256=do7J7EiCGbq0QPbMAL_FqLYufXpHnCnXBOuqVPwSV8Y,1088
24
- fabricatio-0.2.0.dev0.dist-info/RECORD,,
21
+ fabricatio-0.2.0.dev1.dist-info/METADATA,sha256=RIwaKlrpJQplobxDYSljYSlUXwC-Ai2F1SPYzBxGG0A,7054
22
+ fabricatio-0.2.0.dev1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ fabricatio-0.2.0.dev1.dist-info/licenses/LICENSE,sha256=do7J7EiCGbq0QPbMAL_FqLYufXpHnCnXBOuqVPwSV8Y,1088
24
+ fabricatio-0.2.0.dev1.dist-info/RECORD,,