fabricatio 0.1.0__py3-none-any.whl → 0.1.1__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.
- fabricatio/__init__.py +24 -18
- fabricatio/config.py +87 -13
- fabricatio/core.py +165 -148
- fabricatio/{logger.py → journal.py} +7 -2
- fabricatio/models/action.py +77 -9
- fabricatio/models/events.py +26 -28
- fabricatio/models/generic.py +208 -119
- fabricatio/models/role.py +22 -7
- fabricatio/models/task.py +220 -0
- fabricatio/models/tool.py +101 -80
- fabricatio/models/utils.py +10 -15
- fabricatio/parser.py +63 -0
- fabricatio/toolboxes/__init__.py +7 -0
- fabricatio/toolboxes/task.py +4 -0
- {fabricatio-0.1.0.dist-info → fabricatio-0.1.1.dist-info}/METADATA +83 -3
- fabricatio-0.1.1.dist-info/RECORD +19 -0
- fabricatio/fs.py +0 -1
- fabricatio-0.1.0.dist-info/RECORD +0 -16
- {fabricatio-0.1.0.dist-info → fabricatio-0.1.1.dist-info}/WHEEL +0 -0
- {fabricatio-0.1.0.dist-info → fabricatio-0.1.1.dist-info}/licenses/LICENSE +0 -0
fabricatio/__init__.py
CHANGED
@@ -1,18 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
from fabricatio.
|
4
|
-
from fabricatio.
|
5
|
-
from fabricatio.models.
|
6
|
-
from fabricatio.models.
|
7
|
-
from fabricatio.models.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
"
|
15
|
-
"
|
16
|
-
"
|
17
|
-
"
|
18
|
-
|
1
|
+
"""Fabricatio is a Python library for building llm app using event-based agent structure."""
|
2
|
+
|
3
|
+
from fabricatio.core import env
|
4
|
+
from fabricatio.journal import logger
|
5
|
+
from fabricatio.models.action import Action, WorkFlow
|
6
|
+
from fabricatio.models.events import Event
|
7
|
+
from fabricatio.models.role import Role
|
8
|
+
from fabricatio.models.task import Task
|
9
|
+
from fabricatio.models.tool import ToolBox
|
10
|
+
from fabricatio.models.utils import Messages
|
11
|
+
from fabricatio.parser import Capture
|
12
|
+
|
13
|
+
__all__ = [
|
14
|
+
"Action",
|
15
|
+
"Capture",
|
16
|
+
"Event",
|
17
|
+
"Messages",
|
18
|
+
"Role",
|
19
|
+
"Task",
|
20
|
+
"ToolBox",
|
21
|
+
"WorkFlow",
|
22
|
+
"env",
|
23
|
+
"logger",
|
24
|
+
]
|
fabricatio/config.py
CHANGED
@@ -1,19 +1,35 @@
|
|
1
1
|
from typing import Literal
|
2
2
|
|
3
3
|
from appdirs import user_config_dir
|
4
|
-
from pydantic import BaseModel,
|
4
|
+
from pydantic import BaseModel, ConfigDict, Field, FilePath, HttpUrl, NonNegativeFloat, PositiveInt, SecretStr
|
5
5
|
from pydantic_settings import (
|
6
6
|
BaseSettings,
|
7
|
-
|
7
|
+
DotEnvSettingsSource,
|
8
|
+
EnvSettingsSource,
|
8
9
|
PydanticBaseSettingsSource,
|
9
|
-
TomlConfigSettingsSource,
|
10
10
|
PyprojectTomlConfigSettingsSource,
|
11
|
-
|
12
|
-
|
11
|
+
SettingsConfigDict,
|
12
|
+
TomlConfigSettingsSource,
|
13
13
|
)
|
14
14
|
|
15
15
|
|
16
16
|
class LLMConfig(BaseModel):
|
17
|
+
"""LLM configuration class.
|
18
|
+
|
19
|
+
Attributes:
|
20
|
+
api_endpoint (HttpUrl): OpenAI API Endpoint.
|
21
|
+
api_key (SecretStr): OpenAI API key. Empty by default for security reasons, should be set before use.
|
22
|
+
timeout (PositiveInt): The timeout of the LLM model in seconds. Default is 300 seconds as per request.
|
23
|
+
max_retries (PositiveInt): The maximum number of retries. Default is 3 retries.
|
24
|
+
model (str): The LLM model name. Set to 'gpt-3.5-turbo' as per request.
|
25
|
+
temperature (NonNegativeFloat): The temperature of the LLM model. Controls randomness in generation. Set to 1.0 as per request.
|
26
|
+
stop_sign (str): The stop sign of the LLM model. No default stop sign specified.
|
27
|
+
top_p (NonNegativeFloat): The top p of the LLM model. Controls diversity via nucleus sampling. Set to 0.35 as per request.
|
28
|
+
generation_count (PositiveInt): The number of generations to generate. Default is 1.
|
29
|
+
stream (bool): Whether to stream the LLM model's response. Default is False.
|
30
|
+
max_tokens (PositiveInt): The maximum number of tokens to generate. Set to 8192 as per request.
|
31
|
+
"""
|
32
|
+
model_config = ConfigDict(use_attribute_docstrings=True)
|
17
33
|
api_endpoint: HttpUrl = Field(default=HttpUrl("https://api.openai.com"))
|
18
34
|
"""
|
19
35
|
OpenAI API Endpoint.
|
@@ -70,24 +86,65 @@ class LLMConfig(BaseModel):
|
|
70
86
|
"""
|
71
87
|
|
72
88
|
|
89
|
+
class PymitterConfig(BaseModel):
|
90
|
+
"""Pymitter configuration class.
|
91
|
+
|
92
|
+
Attributes:
|
93
|
+
delimiter (str): The delimiter used to separate the event name into segments.
|
94
|
+
new_listener_event (bool): If set, a newListener event is emitted when a new listener is added.
|
95
|
+
max_listeners (int): The maximum number of listeners per event.
|
96
|
+
"""
|
97
|
+
model_config = ConfigDict(use_attribute_docstrings=True)
|
98
|
+
delimiter: str = Field(default=".", frozen=True)
|
99
|
+
"""
|
100
|
+
The delimiter used to separate the event name into segments.
|
101
|
+
"""
|
102
|
+
|
103
|
+
new_listener_event: bool = Field(default=False, frozen=True)
|
104
|
+
"""
|
105
|
+
If set, a newListener event is emitted when a new listener is added.
|
106
|
+
"""
|
107
|
+
|
108
|
+
max_listeners: int = Field(default=-1, frozen=True)
|
109
|
+
"""
|
110
|
+
The maximum number of listeners per event.
|
111
|
+
"""
|
112
|
+
|
113
|
+
|
73
114
|
class DebugConfig(BaseModel):
|
115
|
+
"""Debug configuration class.
|
116
|
+
|
117
|
+
Attributes:
|
118
|
+
log_level (Literal["DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL"]): The log level of the application.
|
119
|
+
log_file (FilePath): The log file of the application.
|
120
|
+
"""
|
121
|
+
model_config = ConfigDict(use_attribute_docstrings=True)
|
122
|
+
|
74
123
|
log_level: Literal["DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL"] = Field(default="INFO")
|
75
124
|
"""
|
76
125
|
The log level of the application.
|
77
126
|
"""
|
78
127
|
|
79
|
-
log_file: FilePath = Field(default=f"{user_config_dir(
|
128
|
+
log_file: FilePath = Field(default=f"{user_config_dir('fabricatio', roaming=True)}.log")
|
80
129
|
"""
|
81
130
|
The log file of the application.
|
82
131
|
"""
|
83
132
|
|
84
133
|
|
85
134
|
class Settings(BaseSettings):
|
135
|
+
"""Application settings class.
|
136
|
+
|
137
|
+
Attributes:
|
138
|
+
llm (LLMConfig): LLM Configuration
|
139
|
+
debug (DebugConfig): Debug Configuration
|
140
|
+
pymitter (PymitterConfig): Pymitter Configuration
|
141
|
+
"""
|
86
142
|
model_config = SettingsConfigDict(
|
87
143
|
env_prefix="FABRIK_",
|
88
144
|
env_nested_delimiter="__",
|
89
145
|
pyproject_toml_depth=1,
|
90
|
-
|
146
|
+
pyproject_toml_table_header=("tool", "fabricatio"),
|
147
|
+
toml_file=["fabricatio.toml", f"{user_config_dir('fabricatio', roaming=True)}.toml"],
|
91
148
|
env_file=[".env", ".envrc"],
|
92
149
|
use_attribute_docstrings=True,
|
93
150
|
)
|
@@ -102,15 +159,32 @@ class Settings(BaseSettings):
|
|
102
159
|
Debug Configuration
|
103
160
|
"""
|
104
161
|
|
162
|
+
pymitter: PymitterConfig = Field(default_factory=PymitterConfig)
|
163
|
+
"""
|
164
|
+
Pymitter Configuration
|
165
|
+
"""
|
166
|
+
|
105
167
|
@classmethod
|
106
168
|
def settings_customise_sources(
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
169
|
+
cls,
|
170
|
+
settings_cls: type[BaseSettings],
|
171
|
+
init_settings: PydanticBaseSettingsSource,
|
172
|
+
env_settings: PydanticBaseSettingsSource,
|
173
|
+
dotenv_settings: PydanticBaseSettingsSource,
|
174
|
+
file_secret_settings: PydanticBaseSettingsSource,
|
113
175
|
) -> tuple[PydanticBaseSettingsSource, ...]:
|
176
|
+
"""Customize settings sources.
|
177
|
+
|
178
|
+
Args:
|
179
|
+
settings_cls (type[BaseSettings]): The settings class.
|
180
|
+
init_settings (PydanticBaseSettingsSource): Initial settings source.
|
181
|
+
env_settings (PydanticBaseSettingsSource): Environment settings source.
|
182
|
+
dotenv_settings (PydanticBaseSettingsSource): Dotenv settings source.
|
183
|
+
file_secret_settings (PydanticBaseSettingsSource): File secret settings source.
|
184
|
+
|
185
|
+
Returns:
|
186
|
+
tuple[PydanticBaseSettingsSource, ...]: A tuple of settings sources.
|
187
|
+
"""
|
114
188
|
return (
|
115
189
|
DotEnvSettingsSource(settings_cls),
|
116
190
|
EnvSettingsSource(settings_cls),
|
fabricatio/core.py
CHANGED
@@ -1,148 +1,165 @@
|
|
1
|
-
from typing import Callable, Self, overload
|
2
|
-
|
3
|
-
from pydantic import BaseModel, ConfigDict, PrivateAttr
|
4
|
-
from pymitter import EventEmitter
|
5
|
-
|
6
|
-
from fabricatio.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
Environment class that manages event handling using EventEmitter.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
event
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
self
|
138
|
-
|
139
|
-
|
140
|
-
"""
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
1
|
+
from typing import Callable, Optional, Self, overload
|
2
|
+
|
3
|
+
from pydantic import BaseModel, ConfigDict, PrivateAttr
|
4
|
+
from pymitter import EventEmitter
|
5
|
+
|
6
|
+
from fabricatio.config import configs
|
7
|
+
from fabricatio.models.events import Event
|
8
|
+
|
9
|
+
|
10
|
+
class Env(BaseModel):
|
11
|
+
"""Environment class that manages event handling using EventEmitter."""
|
12
|
+
|
13
|
+
model_config = ConfigDict(use_attribute_docstrings=True)
|
14
|
+
_ee: EventEmitter = PrivateAttr(
|
15
|
+
default_factory=lambda: EventEmitter(
|
16
|
+
delimiter=configs.pymitter.delimiter,
|
17
|
+
new_listener=configs.pymitter.new_listener_event,
|
18
|
+
max_listeners=configs.pymitter.max_listeners,
|
19
|
+
wildcard=True,
|
20
|
+
)
|
21
|
+
)
|
22
|
+
|
23
|
+
@overload
|
24
|
+
def on(self, event: str | Event, /, ttl: int = -1) -> Self:
|
25
|
+
"""
|
26
|
+
Registers an event listener that listens indefinitely or for a specified number of times.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
event (str | Event): The event to listen for.
|
30
|
+
ttl (int): Time-to-live for the listener. If -1, the listener will listen indefinitely.
|
31
|
+
|
32
|
+
Returns:
|
33
|
+
Self: The current instance of Env.
|
34
|
+
"""
|
35
|
+
...
|
36
|
+
|
37
|
+
@overload
|
38
|
+
def on[**P, R](
|
39
|
+
self,
|
40
|
+
event: str | Event,
|
41
|
+
func: Optional[Callable[P, R]] = None,
|
42
|
+
/,
|
43
|
+
ttl: int = -1,
|
44
|
+
) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
45
|
+
"""
|
46
|
+
Registers an event listener with a specific function that listens indefinitely or for a specified number of times.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
event (str | Event): The event to listen for.
|
50
|
+
func (Callable[P, R]): The function to be called when the event is emitted.
|
51
|
+
ttl (int): Time-to-live for the listener. If -1, the listener will listen indefinitely.
|
52
|
+
|
53
|
+
Returns:
|
54
|
+
Callable[[Callable[P, R]], Callable[P, R]]: A decorator that registers the function as an event listener.
|
55
|
+
"""
|
56
|
+
...
|
57
|
+
|
58
|
+
def on[**P, R](
|
59
|
+
self,
|
60
|
+
event: str | Event,
|
61
|
+
func: Optional[Callable[P, R]] = None,
|
62
|
+
/,
|
63
|
+
ttl=-1,
|
64
|
+
) -> Callable[[Callable[P, R]], Callable[P, R]] | Self:
|
65
|
+
"""Registers an event listener with a specific function that listens indefinitely or for a specified number of times.
|
66
|
+
|
67
|
+
Args:
|
68
|
+
event (str | Event): The event to listen for.
|
69
|
+
func (Callable[P, R]): The function to be called when the event is emitted.
|
70
|
+
ttl (int): Time-to-live for the listener. If -1, the listener will listen indefinitely.
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
Callable[[Callable[P, R]], Callable[P, R]] | Self: A decorator that registers the function as an event listener or the current instance of Env.
|
74
|
+
"""
|
75
|
+
if isinstance(event, Event):
|
76
|
+
event = event.collapse()
|
77
|
+
if func is None:
|
78
|
+
return self._ee.on(event, ttl=ttl)
|
79
|
+
|
80
|
+
self._ee.on(event, func, ttl=ttl)
|
81
|
+
return self
|
82
|
+
|
83
|
+
@overload
|
84
|
+
def once[**P, R](
|
85
|
+
self,
|
86
|
+
event: str | Event,
|
87
|
+
) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
88
|
+
"""
|
89
|
+
Registers an event listener that listens only once.
|
90
|
+
|
91
|
+
Args:
|
92
|
+
event (str | Event): The event to listen for.
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
Callable[[Callable[P, R]], Callable[P, R]]: A decorator that registers the function as an event listener.
|
96
|
+
"""
|
97
|
+
...
|
98
|
+
|
99
|
+
@overload
|
100
|
+
def once[**P, R](
|
101
|
+
self,
|
102
|
+
event: str | Event,
|
103
|
+
func: Callable[[Callable[P, R]], Callable[P, R]],
|
104
|
+
) -> Self:
|
105
|
+
"""
|
106
|
+
Registers an event listener with a specific function that listens only once.
|
107
|
+
|
108
|
+
Args:
|
109
|
+
event (str | Event): The event to listen for.
|
110
|
+
func (Callable[P, R]): The function to be called when the event is emitted.
|
111
|
+
|
112
|
+
Returns:
|
113
|
+
Self: The current instance of Env.
|
114
|
+
"""
|
115
|
+
...
|
116
|
+
|
117
|
+
def once[**P, R](
|
118
|
+
self,
|
119
|
+
event: str | Event,
|
120
|
+
func: Optional[Callable[P, R]] = None,
|
121
|
+
) -> Callable[[Callable[P, R]], Callable[P, R]] | Self:
|
122
|
+
"""Registers an event listener with a specific function that listens only once.
|
123
|
+
|
124
|
+
Args:
|
125
|
+
event (str | Event): The event to listen for.
|
126
|
+
func (Callable[P, R]): The function to be called when the event is emitted.
|
127
|
+
|
128
|
+
Returns:
|
129
|
+
Callable[[Callable[P, R]], Callable[P, R]] | Self: A decorator that registers the function as an event listener or the current instance
|
130
|
+
"""
|
131
|
+
if isinstance(event, Event):
|
132
|
+
event = event.collapse()
|
133
|
+
if func is None:
|
134
|
+
return self._ee.once(event)
|
135
|
+
|
136
|
+
self._ee.once(event, func)
|
137
|
+
return self
|
138
|
+
|
139
|
+
def emit[**P](self, event: str | Event, *args: P.args, **kwargs: P.kwargs) -> None:
|
140
|
+
"""Emits an event to all registered listeners.
|
141
|
+
|
142
|
+
Args:
|
143
|
+
event (str | Event): The event to emit.
|
144
|
+
*args: Positional arguments to pass to the listeners.
|
145
|
+
**kwargs: Keyword arguments to pass to the listeners.
|
146
|
+
"""
|
147
|
+
if isinstance(event, Event):
|
148
|
+
event = event.collapse()
|
149
|
+
|
150
|
+
self._ee.emit(event, *args, **kwargs)
|
151
|
+
|
152
|
+
async def emit_async[**P](self, event: str | Event, *args: P.args, **kwargs: P.kwargs) -> None:
|
153
|
+
"""Asynchronously emits an event to all registered listeners.
|
154
|
+
|
155
|
+
Args:
|
156
|
+
event (str | Event): The event to emit.
|
157
|
+
*args: Positional arguments to pass to the listeners.
|
158
|
+
**kwargs: Keyword arguments to pass to the listeners.
|
159
|
+
"""
|
160
|
+
if isinstance(event, Event):
|
161
|
+
event = event.collapse()
|
162
|
+
return await self._ee.emit_async(event, *args, **kwargs)
|
163
|
+
|
164
|
+
|
165
|
+
env = Env()
|
@@ -1,11 +1,16 @@
|
|
1
|
+
import sys
|
2
|
+
|
1
3
|
from loguru import logger
|
2
4
|
from rich import traceback
|
3
5
|
|
4
6
|
from fabricatio.config import configs
|
5
7
|
|
6
8
|
traceback.install()
|
7
|
-
logger.
|
8
|
-
logger.add(
|
9
|
+
logger.remove()
|
10
|
+
logger.add(
|
11
|
+
configs.debug.log_file, level=configs.debug.log_level, rotation="1 weeks", retention="1 month", compression="zip"
|
12
|
+
)
|
13
|
+
logger.add(sys.stderr, level=configs.debug.log_level)
|
9
14
|
|
10
15
|
if __name__ == "__main__":
|
11
16
|
logger.debug("This is a trace message.")
|
fabricatio/models/action.py
CHANGED
@@ -1,22 +1,90 @@
|
|
1
|
+
import traceback
|
1
2
|
from abc import abstractmethod
|
2
|
-
from
|
3
|
+
from asyncio import Queue
|
4
|
+
from typing import Any, Dict, Tuple, Type, Unpack
|
3
5
|
|
4
|
-
from pydantic import Field
|
6
|
+
from pydantic import Field, PrivateAttr
|
5
7
|
|
6
|
-
from fabricatio.
|
8
|
+
from fabricatio.journal import logger
|
9
|
+
from fabricatio.models.generic import LLMUsage, WithBriefing
|
10
|
+
from fabricatio.models.task import Task
|
7
11
|
|
8
12
|
|
9
13
|
class Action(WithBriefing, LLMUsage):
|
14
|
+
"""Class that represents an action to be executed in a workflow."""
|
15
|
+
|
16
|
+
output_key: str = Field(default="")
|
17
|
+
""" The key of the output data."""
|
10
18
|
|
11
19
|
@abstractmethod
|
12
|
-
async def
|
20
|
+
async def _execute(self, **cxt: Unpack) -> Any:
|
21
|
+
"""Execute the action with the provided arguments.
|
22
|
+
|
23
|
+
Args:
|
24
|
+
**cxt: The context dictionary containing input and output data.
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
The result of the action execution.
|
28
|
+
"""
|
13
29
|
pass
|
14
30
|
|
31
|
+
async def act(self, cxt: Dict[str, Any]) -> Dict[str, Any]:
|
32
|
+
"""Perform the action by executing it and setting the output data.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
cxt: The context dictionary containing input and output data.
|
36
|
+
"""
|
37
|
+
ret = await self._execute(**cxt)
|
38
|
+
if self.output_key:
|
39
|
+
logger.debug(f"Setting output: {self.output_key}")
|
40
|
+
cxt[self.output_key] = ret
|
41
|
+
return cxt
|
42
|
+
|
15
43
|
|
16
44
|
class WorkFlow(WithBriefing, LLMUsage):
|
17
|
-
|
45
|
+
"""Class that represents a workflow to be executed in a task."""
|
46
|
+
|
47
|
+
_context: Queue[Dict[str, Any]] = PrivateAttr(default_factory=lambda: Queue(maxsize=1))
|
48
|
+
""" The context dictionary to be used for workflow execution."""
|
49
|
+
|
50
|
+
_instances: Tuple[Action, ...] = PrivateAttr(...)
|
51
|
+
|
52
|
+
steps: Tuple[Type[Action], ...] = Field(...)
|
53
|
+
""" The steps to be executed in the workflow."""
|
54
|
+
task_input_key: str = Field(default="task_input")
|
55
|
+
""" The key of the task input data."""
|
56
|
+
task_output_key: str = Field(default="task_output")
|
57
|
+
""" The key of the task output data."""
|
58
|
+
|
59
|
+
def model_post_init(self, __context: Any) -> None:
|
60
|
+
"""Initialize the workflow by setting fallbacks for each step.
|
61
|
+
|
62
|
+
Args:
|
63
|
+
__context: The context to be used for initialization.
|
64
|
+
"""
|
65
|
+
self._instances = tuple(step() for step in self.steps)
|
66
|
+
for step in self._instances:
|
67
|
+
step.fallback_to(self)
|
68
|
+
|
69
|
+
async def serve(self, task: Task) -> None:
|
70
|
+
"""Serve the task by executing the workflow steps.
|
18
71
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
72
|
+
Args:
|
73
|
+
task: The task to be served.
|
74
|
+
"""
|
75
|
+
await task.start()
|
76
|
+
await self._context.put({self.task_input_key: task})
|
77
|
+
current_action = None
|
78
|
+
try:
|
79
|
+
for step in self._instances:
|
80
|
+
logger.debug(f"Executing step: {step.name}")
|
81
|
+
ctx = await self._context.get()
|
82
|
+
modified_ctx = await step.act(ctx)
|
83
|
+
await self._context.put(modified_ctx)
|
84
|
+
current_action = step.name
|
85
|
+
logger.info(f"Finished executing workflow: {self.name}")
|
86
|
+
await task.finish((await self._context.get()).get(self.task_output_key, None))
|
87
|
+
except RuntimeError as e:
|
88
|
+
logger.error(f"Error during task: {current_action} execution: {e}") # Log the exception
|
89
|
+
logger.error(traceback.format_exc()) # Add this line to log the traceback
|
90
|
+
await task.fail() # Mark the task as failed
|