fabricatio 0.1.3__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.
- fabricatio/actions/__init__.py +2 -2
- fabricatio/actions/transmission.py +9 -5
- fabricatio/config.py +61 -61
- fabricatio/decorators.py +56 -0
- fabricatio/fs/__init__.py +1 -0
- fabricatio/fs/readers.py +5 -0
- fabricatio/models/action.py +18 -7
- fabricatio/models/events.py +23 -12
- fabricatio/models/generic.py +51 -0
- fabricatio/models/task.py +38 -26
- fabricatio/parser.py +1 -0
- fabricatio-0.2.0.dev1.dist-info/METADATA +246 -0
- fabricatio-0.2.0.dev1.dist-info/RECORD +24 -0
- fabricatio-0.1.3.dist-info/METADATA +0 -127
- fabricatio-0.1.3.dist-info/RECORD +0 -21
- {fabricatio-0.1.3.dist-info → fabricatio-0.2.0.dev1.dist-info}/WHEEL +0 -0
- {fabricatio-0.1.3.dist-info → fabricatio-0.2.0.dev1.dist-info}/licenses/LICENSE +0 -0
fabricatio/actions/__init__.py
CHANGED
@@ -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
|
9
|
-
"""
|
9
|
+
class PublishTask(Action):
|
10
|
+
"""An action that publishes a task to a list of targets."""
|
10
11
|
|
11
|
-
name: str = "
|
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[
|
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.
|
20
|
+
await send_task.move_to(target).publish()
|
fabricatio/config.py
CHANGED
@@ -1,7 +1,17 @@
|
|
1
|
-
from typing import List, Literal
|
1
|
+
from typing import List, Literal, Optional
|
2
2
|
|
3
3
|
from appdirs import user_config_dir
|
4
|
-
from pydantic import
|
4
|
+
from pydantic import (
|
5
|
+
BaseModel,
|
6
|
+
ConfigDict,
|
7
|
+
DirectoryPath,
|
8
|
+
Field,
|
9
|
+
FilePath,
|
10
|
+
HttpUrl,
|
11
|
+
NonNegativeFloat,
|
12
|
+
PositiveInt,
|
13
|
+
SecretStr,
|
14
|
+
)
|
5
15
|
from pydantic_settings import (
|
6
16
|
BaseSettings,
|
7
17
|
DotEnvSettingsSource,
|
@@ -12,6 +22,8 @@ from pydantic_settings import (
|
|
12
22
|
TomlConfigSettingsSource,
|
13
23
|
)
|
14
24
|
|
25
|
+
ROAMING_DIR = user_config_dir("fabricatio", "", roaming=True)
|
26
|
+
|
15
27
|
|
16
28
|
class LLMConfig(BaseModel):
|
17
29
|
"""LLM configuration class.
|
@@ -32,59 +44,37 @@ class LLMConfig(BaseModel):
|
|
32
44
|
|
33
45
|
model_config = ConfigDict(use_attribute_docstrings=True)
|
34
46
|
api_endpoint: HttpUrl = Field(default=HttpUrl("https://api.openai.com"))
|
35
|
-
"""
|
36
|
-
OpenAI API Endpoint.
|
37
|
-
"""
|
47
|
+
"""OpenAI API Endpoint."""
|
38
48
|
|
39
49
|
api_key: SecretStr = Field(default=SecretStr(""))
|
40
|
-
"""
|
41
|
-
OpenAI API key. Empty by default for security reasons, should be set before use.
|
42
|
-
"""
|
50
|
+
"""OpenAI API key. Empty by default for security reasons, should be set before use."""
|
43
51
|
|
44
52
|
timeout: PositiveInt = Field(default=300)
|
45
|
-
"""
|
46
|
-
The timeout of the LLM model in seconds. Default is 300 seconds as per request.
|
47
|
-
"""
|
53
|
+
"""The timeout of the LLM model in seconds. Default is 300 seconds as per request."""
|
48
54
|
|
49
55
|
max_retries: PositiveInt = Field(default=3)
|
50
|
-
"""
|
51
|
-
The maximum number of retries. Default is 3 retries.
|
52
|
-
"""
|
56
|
+
"""The maximum number of retries. Default is 3 retries."""
|
53
57
|
|
54
58
|
model: str = Field(default="gpt-3.5-turbo")
|
55
|
-
"""
|
56
|
-
The LLM model name. Set to 'gpt-3.5-turbo' as per request.
|
57
|
-
"""
|
59
|
+
"""The LLM model name. Set to 'gpt-3.5-turbo' as per request."""
|
58
60
|
|
59
61
|
temperature: NonNegativeFloat = Field(default=1.0)
|
60
|
-
"""
|
61
|
-
The temperature of the LLM model. Controls randomness in generation. Set to 1.0 as per request.
|
62
|
-
"""
|
62
|
+
"""The temperature of the LLM model. Controls randomness in generation. Set to 1.0 as per request."""
|
63
63
|
|
64
64
|
stop_sign: str | List[str] = Field(default=("\n\n", "User:"))
|
65
|
-
"""
|
66
|
-
The stop sign of the LLM model. No default stop sign specified.
|
67
|
-
"""
|
65
|
+
"""The stop sign of the LLM model. No default stop sign specified."""
|
68
66
|
|
69
67
|
top_p: NonNegativeFloat = Field(default=0.35)
|
70
|
-
"""
|
71
|
-
The top p of the LLM model. Controls diversity via nucleus sampling. Set to 0.35 as per request.
|
72
|
-
"""
|
68
|
+
"""The top p of the LLM model. Controls diversity via nucleus sampling. Set to 0.35 as per request."""
|
73
69
|
|
74
70
|
generation_count: PositiveInt = Field(default=1)
|
75
|
-
"""
|
76
|
-
The number of generations to generate. Default is 1.
|
77
|
-
"""
|
71
|
+
"""The number of generations to generate. Default is 1."""
|
78
72
|
|
79
73
|
stream: bool = Field(default=False)
|
80
|
-
"""
|
81
|
-
Whether to stream the LLM model's response. Default is False.
|
82
|
-
"""
|
74
|
+
"""Whether to stream the LLM model's response. Default is False."""
|
83
75
|
|
84
76
|
max_tokens: PositiveInt = Field(default=8192)
|
85
|
-
"""
|
86
|
-
The maximum number of tokens to generate. Set to 8192 as per request.
|
87
|
-
"""
|
77
|
+
"""The maximum number of tokens to generate. Set to 8192 as per request."""
|
88
78
|
|
89
79
|
|
90
80
|
class PymitterConfig(BaseModel):
|
@@ -98,19 +88,13 @@ class PymitterConfig(BaseModel):
|
|
98
88
|
|
99
89
|
model_config = ConfigDict(use_attribute_docstrings=True)
|
100
90
|
delimiter: str = Field(default=".", frozen=True)
|
101
|
-
"""
|
102
|
-
The delimiter used to separate the event name into segments.
|
103
|
-
"""
|
91
|
+
"""The delimiter used to separate the event name into segments."""
|
104
92
|
|
105
93
|
new_listener_event: bool = Field(default=False, frozen=True)
|
106
|
-
"""
|
107
|
-
If set, a newListener event is emitted when a new listener is added.
|
108
|
-
"""
|
94
|
+
"""If set, a newListener event is emitted when a new listener is added."""
|
109
95
|
|
110
96
|
max_listeners: int = Field(default=-1, frozen=True)
|
111
|
-
"""
|
112
|
-
The maximum number of listeners per event.
|
113
|
-
"""
|
97
|
+
"""The maximum number of listeners per event."""
|
114
98
|
|
115
99
|
|
116
100
|
class DebugConfig(BaseModel):
|
@@ -124,14 +108,28 @@ class DebugConfig(BaseModel):
|
|
124
108
|
model_config = ConfigDict(use_attribute_docstrings=True)
|
125
109
|
|
126
110
|
log_level: Literal["DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL"] = Field(default="INFO")
|
127
|
-
"""
|
128
|
-
The log level of the application.
|
129
|
-
"""
|
111
|
+
"""The log level of the application."""
|
130
112
|
|
131
|
-
log_file: FilePath = Field(default=
|
132
|
-
"""
|
133
|
-
|
134
|
-
|
113
|
+
log_file: FilePath = Field(default=rf"{ROAMING_DIR}\fabricatio.log")
|
114
|
+
"""The log file of the application."""
|
115
|
+
|
116
|
+
|
117
|
+
class Code2PromptConfig(BaseModel):
|
118
|
+
"""Code2Prompt configuration class."""
|
119
|
+
|
120
|
+
model_config = ConfigDict(use_attribute_docstrings=True)
|
121
|
+
template_dir: List[DirectoryPath] = Field(
|
122
|
+
default_factory=lambda: [r".\c2p_templates", rf"{ROAMING_DIR}\c2p_templates"]
|
123
|
+
)
|
124
|
+
"""The directory containing the templates for code2prompt."""
|
125
|
+
|
126
|
+
|
127
|
+
class MagikaConfig(BaseModel):
|
128
|
+
"""Magika configuration class."""
|
129
|
+
|
130
|
+
model_config = ConfigDict(use_attribute_docstrings=True)
|
131
|
+
model_dir: Optional[DirectoryPath] = Field(default=None)
|
132
|
+
"""The directory containing the models for magika."""
|
135
133
|
|
136
134
|
|
137
135
|
class Settings(BaseSettings):
|
@@ -141,6 +139,8 @@ class Settings(BaseSettings):
|
|
141
139
|
llm (LLMConfig): LLM Configuration
|
142
140
|
debug (DebugConfig): Debug Configuration
|
143
141
|
pymitter (PymitterConfig): Pymitter Configuration
|
142
|
+
code2prompt (Code2PromptConfig): Code2Prompt Configuration
|
143
|
+
magika (MagikaConfig): Magika Configuration
|
144
144
|
"""
|
145
145
|
|
146
146
|
model_config = SettingsConfigDict(
|
@@ -148,25 +148,25 @@ class Settings(BaseSettings):
|
|
148
148
|
env_nested_delimiter="__",
|
149
149
|
pyproject_toml_depth=1,
|
150
150
|
pyproject_toml_table_header=("tool", "fabricatio"),
|
151
|
-
toml_file=["fabricatio.toml",
|
151
|
+
toml_file=["fabricatio.toml", rf"{ROAMING_DIR}\fabricatio.toml"],
|
152
152
|
env_file=[".env", ".envrc"],
|
153
153
|
use_attribute_docstrings=True,
|
154
154
|
)
|
155
155
|
|
156
156
|
llm: LLMConfig = Field(default_factory=LLMConfig)
|
157
|
-
"""
|
158
|
-
LLM Configuration
|
159
|
-
"""
|
157
|
+
"""LLM Configuration"""
|
160
158
|
|
161
159
|
debug: DebugConfig = Field(default_factory=DebugConfig)
|
162
|
-
"""
|
163
|
-
Debug Configuration
|
164
|
-
"""
|
160
|
+
"""Debug Configuration"""
|
165
161
|
|
166
162
|
pymitter: PymitterConfig = Field(default_factory=PymitterConfig)
|
167
|
-
"""
|
168
|
-
|
169
|
-
|
163
|
+
"""Pymitter Configuration"""
|
164
|
+
|
165
|
+
code2prompt: Code2PromptConfig = Field(default_factory=Code2PromptConfig)
|
166
|
+
"""Code2Prompt Configuration"""
|
167
|
+
|
168
|
+
magika: MagikaConfig = Field(default_factory=MagikaConfig)
|
169
|
+
"""Magika Configuration"""
|
170
170
|
|
171
171
|
@classmethod
|
172
172
|
def settings_customise_sources(
|
fabricatio/decorators.py
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
from functools import wraps
|
2
|
+
from shutil import which
|
3
|
+
from typing import Callable
|
4
|
+
|
5
|
+
from fabricatio.journal import logger
|
6
|
+
|
7
|
+
|
8
|
+
def depend_on_external_cmd[**P, R](bin_name: str, install_tip: str) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
9
|
+
"""Decorator to check for the presence of an external command.
|
10
|
+
|
11
|
+
Args:
|
12
|
+
bin_name (str): The name of the required binary.
|
13
|
+
install_tip (str): Installation instructions for the required binary.
|
14
|
+
|
15
|
+
Returns:
|
16
|
+
Callable[[Callable[P, R]], Callable[P, R]]: A decorator that wraps the function to check for the binary.
|
17
|
+
|
18
|
+
Raises:
|
19
|
+
RuntimeError: If the required binary is not found.
|
20
|
+
"""
|
21
|
+
|
22
|
+
def decorator(func: Callable[P, R]) -> Callable[P, R]:
|
23
|
+
"""Decorator to wrap the function with binary presence check.
|
24
|
+
|
25
|
+
Args:
|
26
|
+
func (Callable[P, R]): The function to be decorated.
|
27
|
+
|
28
|
+
Returns:
|
29
|
+
Callable[P, R]: The wrapped function.
|
30
|
+
"""
|
31
|
+
|
32
|
+
@wraps(func)
|
33
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
34
|
+
"""Wrapper function to check for the presence of the required binary.
|
35
|
+
|
36
|
+
Args:
|
37
|
+
*args: Positional arguments for the function.
|
38
|
+
**kwargs: Keyword arguments for the function.
|
39
|
+
|
40
|
+
Returns:
|
41
|
+
R: The result of the function call.
|
42
|
+
|
43
|
+
Raises:
|
44
|
+
RuntimeError: If the required binary is not found.
|
45
|
+
"""
|
46
|
+
if which(bin_name) is None:
|
47
|
+
err = (
|
48
|
+
f"{bin_name} is required to run function: {func.__name__}, please install it first.\n{install_tip}"
|
49
|
+
)
|
50
|
+
logger.critical(err)
|
51
|
+
raise RuntimeError(err)
|
52
|
+
return func(*args, **kwargs)
|
53
|
+
|
54
|
+
return wrapper
|
55
|
+
|
56
|
+
return decorator
|
@@ -0,0 +1 @@
|
|
1
|
+
"""FileSystem manipulation module for Fabricatio."""
|
fabricatio/fs/readers.py
ADDED
fabricatio/models/action.py
CHANGED
@@ -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[
|
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
|
-
|
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.
|
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
|
-
|
82
|
-
modified_ctx = await step.act(
|
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/events.py
CHANGED
@@ -4,6 +4,8 @@ from pydantic import BaseModel, ConfigDict, Field
|
|
4
4
|
|
5
5
|
from fabricatio.config import configs
|
6
6
|
|
7
|
+
type EventLike = str | List[str] | Self
|
8
|
+
|
7
9
|
|
8
10
|
class Event(BaseModel):
|
9
11
|
"""A class representing an event."""
|
@@ -14,16 +16,25 @@ class Event(BaseModel):
|
|
14
16
|
""" The segments of the namespaces."""
|
15
17
|
|
16
18
|
@classmethod
|
17
|
-
def
|
18
|
-
"""Create an Event instance from a string.
|
19
|
+
def instantiate_from(cls, event: EventLike) -> Self:
|
20
|
+
"""Create an Event instance from a string or list of strings or an Event instance.
|
19
21
|
|
20
22
|
Args:
|
21
|
-
event (
|
23
|
+
event (EventLike): The event to instantiate from.
|
22
24
|
|
23
25
|
Returns:
|
24
26
|
Event: The Event instance.
|
25
27
|
"""
|
26
|
-
|
28
|
+
if isinstance(event, Event):
|
29
|
+
return event.clone()
|
30
|
+
if isinstance(event, str):
|
31
|
+
event = event.split(configs.pymitter.delimiter)
|
32
|
+
|
33
|
+
return cls(segments=event)
|
34
|
+
|
35
|
+
def derive(self, event: EventLike) -> Self:
|
36
|
+
"""Derive a new event from this event and another event or a string."""
|
37
|
+
return self.clone().concat(event)
|
27
38
|
|
28
39
|
def collapse(self) -> str:
|
29
40
|
"""Collapse the event into a string."""
|
@@ -41,6 +52,10 @@ class Event(BaseModel):
|
|
41
52
|
self.segments.append(segment)
|
42
53
|
return self
|
43
54
|
|
55
|
+
def push_wildcard(self) -> Self:
|
56
|
+
"""Push a wildcard segment to the event."""
|
57
|
+
return self.push("*")
|
58
|
+
|
44
59
|
def pop(self) -> str:
|
45
60
|
"""Pop a segment from the event."""
|
46
61
|
return self.segments.pop()
|
@@ -50,19 +65,15 @@ class Event(BaseModel):
|
|
50
65
|
self.segments.clear()
|
51
66
|
return self
|
52
67
|
|
53
|
-
def concat(self, event:
|
68
|
+
def concat(self, event: EventLike) -> Self:
|
54
69
|
"""Concatenate another event to this event."""
|
55
|
-
|
56
|
-
event = Event.from_string(event)
|
57
|
-
self.segments.extend(event.segments)
|
70
|
+
self.segments.extend(Event.instantiate_from(event).segments)
|
58
71
|
return self
|
59
72
|
|
60
73
|
def __hash__(self) -> int:
|
61
74
|
"""Return the hash of the event, using the collapsed string."""
|
62
75
|
return hash(self.collapse())
|
63
76
|
|
64
|
-
def __eq__(self, other:
|
77
|
+
def __eq__(self, other: str | List[str] | Self) -> bool:
|
65
78
|
"""Check if the event is equal to another event or a string."""
|
66
|
-
|
67
|
-
other = other.collapse()
|
68
|
-
return self.collapse() == other
|
79
|
+
return self.collapse() == Event.instantiate_from(other).collapse()
|
fabricatio/models/generic.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from asyncio import Queue
|
2
|
+
from pathlib import Path
|
2
3
|
from typing import Callable, Dict, Iterable, List, Optional, Self
|
3
4
|
|
4
5
|
import litellm
|
@@ -17,6 +18,7 @@ from pydantic import (
|
|
17
18
|
)
|
18
19
|
|
19
20
|
from fabricatio.config import configs
|
21
|
+
from fabricatio.fs.readers import magika
|
20
22
|
from fabricatio.models.utils import Messages
|
21
23
|
|
22
24
|
|
@@ -464,3 +466,52 @@ class WithJsonExample(Base):
|
|
464
466
|
{field_name: field_info.description for field_name, field_info in cls.model_fields.items()},
|
465
467
|
option=orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS,
|
466
468
|
).decode()
|
469
|
+
|
470
|
+
|
471
|
+
class WithDependency(Base):
|
472
|
+
"""Class that manages file dependencies."""
|
473
|
+
|
474
|
+
dependencies: List[str] = Field(default_factory=list)
|
475
|
+
"""The file dependencies of the task, a list of file paths."""
|
476
|
+
|
477
|
+
def add_dependency[P: str | Path](self, dependency: P | List[P]) -> Self:
|
478
|
+
"""Add a file dependency to the task.
|
479
|
+
|
480
|
+
Args:
|
481
|
+
dependency (str | Path | List[str | Path]): The file dependency to add to the task.
|
482
|
+
|
483
|
+
Returns:
|
484
|
+
Self: The current instance of the task.
|
485
|
+
"""
|
486
|
+
if not isinstance(dependency, list):
|
487
|
+
dependency = [dependency]
|
488
|
+
self.dependencies.extend(Path(d).as_posix() for d in dependency)
|
489
|
+
return self
|
490
|
+
|
491
|
+
def remove_dependency[P: str | Path](self, dependency: P | List[P]) -> Self:
|
492
|
+
"""Remove a file dependency from the task.
|
493
|
+
|
494
|
+
Args:
|
495
|
+
dependency (str | Path | List[str | Path]): The file dependency to remove from the task.
|
496
|
+
|
497
|
+
Returns:
|
498
|
+
Self: The current instance of the task.
|
499
|
+
"""
|
500
|
+
if not isinstance(dependency, list):
|
501
|
+
dependency = [dependency]
|
502
|
+
for d in dependency:
|
503
|
+
self.dependencies.remove(Path(d).as_posix())
|
504
|
+
return self
|
505
|
+
|
506
|
+
def generate_prompt(self) -> str:
|
507
|
+
"""Generate a prompt for the task based on the file dependencies.
|
508
|
+
|
509
|
+
Returns:
|
510
|
+
str: The generated prompt for the task.
|
511
|
+
"""
|
512
|
+
contents = [Path(d).read_text("utf-8") for d in self.dependencies]
|
513
|
+
recognized = [magika.identify_path(c) for c in contents]
|
514
|
+
out = ""
|
515
|
+
for r, p, c in zip(recognized, self.dependencies, contents, strict=False):
|
516
|
+
out += f"---\n\n> {p}\n```{r.dl.ct_label}\n{c}\n```\n\n"
|
517
|
+
return out
|
fabricatio/models/task.py
CHANGED
@@ -5,15 +5,14 @@ It includes methods to manage the task's lifecycle, such as starting, finishing,
|
|
5
5
|
|
6
6
|
from asyncio import Queue
|
7
7
|
from enum import Enum
|
8
|
-
from typing import Optional, Self
|
8
|
+
from typing import Any, List, Optional, Self
|
9
9
|
|
10
10
|
from pydantic import Field, PrivateAttr
|
11
11
|
|
12
|
-
from fabricatio.config import configs
|
13
12
|
from fabricatio.core import env
|
14
13
|
from fabricatio.journal import logger
|
15
|
-
from fabricatio.models.events import Event
|
16
|
-
from fabricatio.models.generic import WithBriefing, WithJsonExample
|
14
|
+
from fabricatio.models.events import Event, EventLike
|
15
|
+
from fabricatio.models.generic import WithBriefing, WithDependency, WithJsonExample
|
17
16
|
|
18
17
|
|
19
18
|
class TaskStatus(Enum):
|
@@ -34,13 +33,15 @@ class TaskStatus(Enum):
|
|
34
33
|
Cancelled = "cancelled"
|
35
34
|
|
36
35
|
|
37
|
-
class Task[T](WithBriefing, WithJsonExample):
|
36
|
+
class Task[T](WithBriefing, WithJsonExample, WithDependency):
|
38
37
|
"""A class representing a task with a status and output.
|
39
38
|
|
40
39
|
Attributes:
|
41
40
|
name (str): The name of the task.
|
42
41
|
description (str): The description of the task.
|
43
42
|
goal (str): The goal of the task.
|
43
|
+
dependencies (List[str]): The file dependencies of the task, a list of file paths.
|
44
|
+
namespace (List[str]): The namespace of the task, a list of namespace segment, as string.
|
44
45
|
"""
|
45
46
|
|
46
47
|
name: str = Field(...)
|
@@ -52,12 +53,35 @@ class Task[T](WithBriefing, WithJsonExample):
|
|
52
53
|
goal: str = Field(default="")
|
53
54
|
"""The goal of the task."""
|
54
55
|
|
56
|
+
namespace: List[str] = Field(default_factory=list)
|
57
|
+
"""The namespace of the task, a list of namespace segment, as string."""
|
58
|
+
|
55
59
|
_output: Queue = PrivateAttr(default_factory=lambda: Queue(maxsize=1))
|
56
60
|
"""The output queue of the task."""
|
57
61
|
|
58
62
|
_status: TaskStatus = PrivateAttr(default=TaskStatus.Pending)
|
59
63
|
"""The status of the task."""
|
60
64
|
|
65
|
+
_namespace: Event = PrivateAttr(default_factory=Event)
|
66
|
+
"""The namespace of the task as an event, which is generated from the namespace list."""
|
67
|
+
|
68
|
+
def model_post_init(self, __context: Any) -> None:
|
69
|
+
"""Initialize the task with a namespace event."""
|
70
|
+
self._namespace.segments.extend(self.namespace)
|
71
|
+
|
72
|
+
def move_to(self, new_namespace: EventLike) -> Self:
|
73
|
+
"""Move the task to a new namespace.
|
74
|
+
|
75
|
+
Args:
|
76
|
+
new_namespace (List[str]): The new namespace to move the task to.
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
Task: The moved instance of the `Task` class.
|
80
|
+
"""
|
81
|
+
self.namespace = new_namespace
|
82
|
+
self._namespace.clear().concat(new_namespace)
|
83
|
+
return self
|
84
|
+
|
61
85
|
@classmethod
|
62
86
|
def simple_task(cls, name: str, goal: str, description: str) -> Self:
|
63
87
|
"""Create a simple task with a name, goal, and description.
|
@@ -106,7 +130,7 @@ class Task[T](WithBriefing, WithJsonExample):
|
|
106
130
|
Returns:
|
107
131
|
str: The formatted status label.
|
108
132
|
"""
|
109
|
-
return
|
133
|
+
return self._namespace.derive(self.name).push(status.value).collapse()
|
110
134
|
|
111
135
|
@property
|
112
136
|
def pending_label(self) -> str:
|
@@ -202,36 +226,24 @@ class Task[T](WithBriefing, WithJsonExample):
|
|
202
226
|
await env.emit_async(self.failed_label, self)
|
203
227
|
return self
|
204
228
|
|
205
|
-
async def publish(self
|
206
|
-
"""Publish the task
|
207
|
-
|
208
|
-
Args:
|
209
|
-
event_namespace (Event | str, optional): The event namespace to use. Defaults to an empty string.
|
229
|
+
async def publish(self) -> Self:
|
230
|
+
"""Publish the task to the event bus.
|
210
231
|
|
211
232
|
Returns:
|
212
|
-
Task: The published instance of the `Task` class
|
233
|
+
Task: The published instance of the `Task` class
|
213
234
|
"""
|
214
|
-
if isinstance(event_namespace, str):
|
215
|
-
event_namespace = Event.from_string(event_namespace)
|
216
|
-
|
217
235
|
logger.info(f"Publishing task {self.name}")
|
218
|
-
await env.emit_async(
|
236
|
+
await env.emit_async(self.pending_label, self)
|
219
237
|
return self
|
220
238
|
|
221
|
-
async def delegate(self
|
222
|
-
"""Delegate the task
|
223
|
-
|
224
|
-
Args:
|
225
|
-
event_namespace (Event | str, optional): The event namespace to use. Defaults to an empty string.
|
239
|
+
async def delegate(self) -> T:
|
240
|
+
"""Delegate the task to the event bus and wait for the output.
|
226
241
|
|
227
242
|
Returns:
|
228
|
-
T: The output of the task
|
243
|
+
T: The output of the task
|
229
244
|
"""
|
230
|
-
if isinstance(event_namespace, str):
|
231
|
-
event_namespace = Event.from_string(event_namespace)
|
232
|
-
|
233
245
|
logger.info(f"Delegating task {self.name}")
|
234
|
-
await env.emit_async(
|
246
|
+
await env.emit_async(self.pending_label, self)
|
235
247
|
return await self.get_output()
|
236
248
|
|
237
249
|
@property
|
fabricatio/parser.py
CHANGED
@@ -0,0 +1,246 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: fabricatio
|
3
|
+
Version: 0.2.0.dev1
|
4
|
+
Summary: A LLM multi-agent framework.
|
5
|
+
Author-email: Whth <zettainspector@foxmail.com>
|
6
|
+
License: MIT License
|
7
|
+
|
8
|
+
Copyright (c) 2025 Whth Yotta
|
9
|
+
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
12
|
+
in the Software without restriction, including without limitation the rights
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
15
|
+
furnished to do so, subject to the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
18
|
+
copies or substantial portions of the Software.
|
19
|
+
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
+
SOFTWARE.
|
27
|
+
License-File: LICENSE
|
28
|
+
Keywords: agents,ai,llm,multi-agent
|
29
|
+
Classifier: Framework :: AsyncIO
|
30
|
+
Classifier: Framework :: Pydantic :: 2
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
32
|
+
Classifier: Programming Language :: Python :: 3.12
|
33
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
34
|
+
Classifier: Typing :: Typed
|
35
|
+
Requires-Python: >=3.12
|
36
|
+
Requires-Dist: aiohttp>=3.11.11
|
37
|
+
Requires-Dist: aiomultiprocess>=0.9.1
|
38
|
+
Requires-Dist: appdirs>=1.4.4
|
39
|
+
Requires-Dist: asyncio>=3.4.3
|
40
|
+
Requires-Dist: code2prompt
|
41
|
+
Requires-Dist: gitpython>=3.1.44
|
42
|
+
Requires-Dist: litellm>=1.60.0
|
43
|
+
Requires-Dist: loguru>=0.7.3
|
44
|
+
Requires-Dist: magika>=0.5.1
|
45
|
+
Requires-Dist: orjson>=3.10.15
|
46
|
+
Requires-Dist: pydantic-settings>=2.7.1
|
47
|
+
Requires-Dist: pydantic>=2.10.6
|
48
|
+
Requires-Dist: pymitter>=1.0.0
|
49
|
+
Requires-Dist: questionary>=2.1.0
|
50
|
+
Requires-Dist: regex>=2024.11.6
|
51
|
+
Requires-Dist: rich>=13.9.4
|
52
|
+
Description-Content-Type: text/markdown
|
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
|
+
|
93
|
+
## Usage
|
94
|
+
|
95
|
+
### Defining a Task
|
96
|
+
|
97
|
+
A task in Fabricatio is defined using the `Task` class. You can specify the name, goal, and description of the task.
|
98
|
+
|
99
|
+
```python
|
100
|
+
from fabricatio.models.task import Task
|
101
|
+
|
102
|
+
task = Task(name="say hello", goal="say hello", description="say hello to the world")
|
103
|
+
```
|
104
|
+
|
105
|
+
|
106
|
+
### Creating an Action
|
107
|
+
|
108
|
+
Actions are the building blocks of workflows. They perform specific tasks and can be asynchronous.
|
109
|
+
|
110
|
+
```python
|
111
|
+
from fabricatio import Action, logger
|
112
|
+
from fabricatio.models.task import Task
|
113
|
+
|
114
|
+
class Talk(Action):
|
115
|
+
async def _execute(self, task_input: Task[str], **_) -> str:
|
116
|
+
ret = "Hello fabricatio!"
|
117
|
+
logger.info("executing talk action")
|
118
|
+
return ret
|
119
|
+
```
|
120
|
+
|
121
|
+
|
122
|
+
### Assigning a Role
|
123
|
+
|
124
|
+
Roles in Fabricatio are responsible for executing workflows. You can define a role with a set of actions.
|
125
|
+
|
126
|
+
```python
|
127
|
+
from fabricatio.models.role import Role
|
128
|
+
from fabricatio.models.action import WorkFlow
|
129
|
+
|
130
|
+
class TestWorkflow(WorkFlow):
|
131
|
+
pass
|
132
|
+
|
133
|
+
role = Role(name="Test Role", actions=[TestWorkflow()])
|
134
|
+
```
|
135
|
+
|
136
|
+
|
137
|
+
### Logging
|
138
|
+
|
139
|
+
Fabricatio uses Loguru for logging. You can configure the log level and file in the `config.py` file.
|
140
|
+
|
141
|
+
```python
|
142
|
+
from fabricatio.config import DebugConfig
|
143
|
+
|
144
|
+
debug_config = DebugConfig(log_level="DEBUG", log_file="fabricatio.log")
|
145
|
+
```
|
146
|
+
|
147
|
+
|
148
|
+
## Configuration
|
149
|
+
|
150
|
+
Fabricatio uses Pydantic for configuration management. You can define your settings in the `config.py` file.
|
151
|
+
|
152
|
+
### LLM Configuration
|
153
|
+
|
154
|
+
The Large Language Model (LLM) configuration is managed by the `LLMConfig` class.
|
155
|
+
|
156
|
+
```python
|
157
|
+
from fabricatio.config import LLMConfig
|
158
|
+
|
159
|
+
llm_config = LLMConfig(api_endpoint="https://api.example.com")
|
160
|
+
```
|
161
|
+
|
162
|
+
|
163
|
+
### Debug Configuration
|
164
|
+
|
165
|
+
The debug configuration is managed by the `DebugConfig` class.
|
166
|
+
|
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())
|
237
|
+
```
|
238
|
+
|
239
|
+
|
240
|
+
## Contributing
|
241
|
+
|
242
|
+
Contributions to Fabricatio are welcome! Please submit a pull request with your changes.
|
243
|
+
|
244
|
+
## License
|
245
|
+
|
246
|
+
Fabricatio is licensed under the MIT License. See the [LICENSE](LICENSE) file for more information.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
fabricatio/__init__.py,sha256=nFPtohqceECRYzU-WlVT6o4oSaKN0vGok-w9JIaiJfs,644
|
2
|
+
fabricatio/config.py,sha256=emkIpaXRQykAX_C2ND8tKR2DQUJJEN0mvdMDTklwOXw,7823
|
3
|
+
fabricatio/core.py,sha256=B6KBIfBRF023HF0UUaUprEkQd6sT7G_pexGXQ9btJnE,5788
|
4
|
+
fabricatio/decorators.py,sha256=Qsyb-_cDwtXY5yhyLrYZEAlrHh5ZuEooQ8vEOUAxj8k,1855
|
5
|
+
fabricatio/journal.py,sha256=CW9HePtgTiboOyPTExq9GjG5BseZcbc-S6lxDXrpmv0,667
|
6
|
+
fabricatio/parser.py,sha256=6PNFNNyHNkNG7vTS1ejFc4vCzl1OCy4bqB0e4Ty_-Qs,2365
|
7
|
+
fabricatio/py.typed,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
|
+
fabricatio/fs/readers.py,sha256=mw0VUH3P7Wk0SMlcQm2yOfjEz5C3mQ_kjduAjecaxgY,123
|
12
|
+
fabricatio/models/action.py,sha256=CbGuR9dHnu87MFAzLWj8cVHZtFNyT_VuwT3pWlKJvEk,3925
|
13
|
+
fabricatio/models/events.py,sha256=pW3sfxEFWTafbP4bn4hVFSe8qloYrrzOgi9oMCqAEgw,2604
|
14
|
+
fabricatio/models/generic.py,sha256=noHow8dUjMnNiasl2ZHaZeCMpxzDme9QvxTetoyB45w,19539
|
15
|
+
fabricatio/models/role.py,sha256=jdabuYRXwgvpYoNwvazygDiZHGGQApUIIKltniu78O8,2151
|
16
|
+
fabricatio/models/task.py,sha256=mWIQHdi1mNJlER5ZFeywsZxg4Skm-VnjW2z8ZEMJLNE,8190
|
17
|
+
fabricatio/models/tool.py,sha256=UkEp1Nzbl5wZX21q_Z2VkpiJmVDSdoGDzINQniO8hSY,3536
|
18
|
+
fabricatio/models/utils.py,sha256=2mgXla9_K3dnRrz6hIKzmltTYPmvDk0MBjjEBkCXTdg,2474
|
19
|
+
fabricatio/toolboxes/__init__.py,sha256=bjefmPd7wBaWhbZzdMPXvrjMTeRzlUh_Dev2PUAc124,158
|
20
|
+
fabricatio/toolboxes/task.py,sha256=xgyPetm2R_HlQwpzE8YPnBN7QOYLd0-T8E6QPZG1PPQ,204
|
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,,
|
@@ -1,127 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: fabricatio
|
3
|
-
Version: 0.1.3
|
4
|
-
Summary: A LLM multi-agent framework.
|
5
|
-
Author-email: Whth <zettainspector@foxmail.com>
|
6
|
-
License: MIT License
|
7
|
-
|
8
|
-
Copyright (c) 2025 Whth Yotta
|
9
|
-
|
10
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
-
of this software and associated documentation files (the "Software"), to deal
|
12
|
-
in the Software without restriction, including without limitation the rights
|
13
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
-
copies of the Software, and to permit persons to whom the Software is
|
15
|
-
furnished to do so, subject to the following conditions:
|
16
|
-
|
17
|
-
The above copyright notice and this permission notice shall be included in all
|
18
|
-
copies or substantial portions of the Software.
|
19
|
-
|
20
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
-
SOFTWARE.
|
27
|
-
License-File: LICENSE
|
28
|
-
Keywords: agents,ai,llm,multi-agent
|
29
|
-
Classifier: Framework :: AsyncIO
|
30
|
-
Classifier: Framework :: Pydantic :: 2
|
31
|
-
Classifier: License :: OSI Approved :: MIT License
|
32
|
-
Classifier: Programming Language :: Python :: 3.12
|
33
|
-
Classifier: Programming Language :: Python :: Implementation :: CPython
|
34
|
-
Classifier: Typing :: Typed
|
35
|
-
Requires-Python: >=3.12
|
36
|
-
Requires-Dist: aiohttp>=3.11.11
|
37
|
-
Requires-Dist: aiomultiprocess>=0.9.1
|
38
|
-
Requires-Dist: appdirs>=1.4.4
|
39
|
-
Requires-Dist: asyncio>=3.4.3
|
40
|
-
Requires-Dist: gitpython>=3.1.44
|
41
|
-
Requires-Dist: litellm>=1.60.0
|
42
|
-
Requires-Dist: loguru>=0.7.3
|
43
|
-
Requires-Dist: orjson>=3.10.15
|
44
|
-
Requires-Dist: pydantic-settings>=2.7.1
|
45
|
-
Requires-Dist: pydantic>=2.10.6
|
46
|
-
Requires-Dist: pymitter>=1.0.0
|
47
|
-
Requires-Dist: regex>=2024.11.6
|
48
|
-
Requires-Dist: rich>=13.9.4
|
49
|
-
Requires-Dist: shutilwhich>=1.1.0
|
50
|
-
Description-Content-Type: text/markdown
|
51
|
-
|
52
|
-
## Usage
|
53
|
-
|
54
|
-
### Defining a Task
|
55
|
-
|
56
|
-
```python
|
57
|
-
from fabricatio.models.task import Task
|
58
|
-
|
59
|
-
task = Task(name="say hello", goal="say hello", description="say hello to the world")
|
60
|
-
```
|
61
|
-
|
62
|
-
|
63
|
-
### Creating an Action
|
64
|
-
|
65
|
-
```python
|
66
|
-
from fabricatio import Action, logger
|
67
|
-
from fabricatio.models.task import Task
|
68
|
-
|
69
|
-
class Talk(Action):
|
70
|
-
async def _execute(self, task_input: Task[str], **_) -> Any:
|
71
|
-
ret = "Hello fabricatio!"
|
72
|
-
logger.info("executing talk action")
|
73
|
-
return ret
|
74
|
-
```
|
75
|
-
|
76
|
-
|
77
|
-
### Assigning a Role
|
78
|
-
|
79
|
-
```python
|
80
|
-
from fabricatio.models.role import Role
|
81
|
-
from fabricatio.models.action import WorkFlow
|
82
|
-
|
83
|
-
class TestWorkflow(WorkFlow):
|
84
|
-
pass
|
85
|
-
|
86
|
-
role = Role(name="Test Role", actions=[TestWorkflow()])
|
87
|
-
```
|
88
|
-
|
89
|
-
|
90
|
-
### Logging
|
91
|
-
|
92
|
-
Fabricatio uses Loguru for logging. You can configure the log level and file in the `config.py` file.
|
93
|
-
|
94
|
-
```python
|
95
|
-
from fabricatio.config import DebugConfig
|
96
|
-
|
97
|
-
debug_config = DebugConfig(log_level="DEBUG", log_file="fabricatio.log")
|
98
|
-
```
|
99
|
-
|
100
|
-
|
101
|
-
## Configuration
|
102
|
-
|
103
|
-
Fabricatio uses Pydantic for configuration management. You can define your settings in the `config.py` file.
|
104
|
-
|
105
|
-
```python
|
106
|
-
from fabricatio.config import Settings
|
107
|
-
|
108
|
-
settings = Settings(llm=LLMConfig(api_endpoint="https://api.example.com"))
|
109
|
-
```
|
110
|
-
|
111
|
-
|
112
|
-
## Testing
|
113
|
-
|
114
|
-
Fabricatio includes a set of tests to ensure the framework works as expected. You can run the tests using `pytest`.
|
115
|
-
|
116
|
-
```bash
|
117
|
-
pytest
|
118
|
-
```
|
119
|
-
|
120
|
-
|
121
|
-
## Contributing
|
122
|
-
|
123
|
-
Contributions to Fabricatio are welcome! Please submit a pull request with your changes.
|
124
|
-
|
125
|
-
## License
|
126
|
-
|
127
|
-
Fabricatio is licensed under the MIT License. See the [LICENSE](LICENSE) file for more information.
|
@@ -1,21 +0,0 @@
|
|
1
|
-
fabricatio/__init__.py,sha256=nFPtohqceECRYzU-WlVT6o4oSaKN0vGok-w9JIaiJfs,644
|
2
|
-
fabricatio/config.py,sha256=EOlVkuEBAHESAlrGtolGwEG2YrTaJPhEGPKS7QDxrx0,6995
|
3
|
-
fabricatio/core.py,sha256=B6KBIfBRF023HF0UUaUprEkQd6sT7G_pexGXQ9btJnE,5788
|
4
|
-
fabricatio/journal.py,sha256=CW9HePtgTiboOyPTExq9GjG5BseZcbc-S6lxDXrpmv0,667
|
5
|
-
fabricatio/parser.py,sha256=On_YUCvOuA0FA_NtDVNJqKp7KEO_sUE89oO_WnkEhQ4,2314
|
6
|
-
fabricatio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
-
fabricatio/actions/__init__.py,sha256=n3lwq9FPNtvfLu2L1pX4UkwiPITU7luk-b4aMJyjIC8,109
|
8
|
-
fabricatio/actions/transmission.py,sha256=Azog4ItVk7aASdYzTwzyckzYG2hDFSXctnA7qp-Qlq0,502
|
9
|
-
fabricatio/models/action.py,sha256=M-12dc-nQiNJU6Y9j-dr4Ef3642vRvzHlzxekBepzaU,3358
|
10
|
-
fabricatio/models/events.py,sha256=PlavKOD94Q9Q9iPoQPkf9HJdznBtzuSUrPtUoVtkQxU,2143
|
11
|
-
fabricatio/models/generic.py,sha256=Sxpx0BO0t85YF5Lwks6F165N6TJsDe7xym28dQG5Mqs,17681
|
12
|
-
fabricatio/models/role.py,sha256=jdabuYRXwgvpYoNwvazygDiZHGGQApUIIKltniu78O8,2151
|
13
|
-
fabricatio/models/task.py,sha256=8IXT192t5EXVHAdHj45DJNdBhdA2xmh36S_vKyEw6y0,7757
|
14
|
-
fabricatio/models/tool.py,sha256=UkEp1Nzbl5wZX21q_Z2VkpiJmVDSdoGDzINQniO8hSY,3536
|
15
|
-
fabricatio/models/utils.py,sha256=2mgXla9_K3dnRrz6hIKzmltTYPmvDk0MBjjEBkCXTdg,2474
|
16
|
-
fabricatio/toolboxes/__init__.py,sha256=bjefmPd7wBaWhbZzdMPXvrjMTeRzlUh_Dev2PUAc124,158
|
17
|
-
fabricatio/toolboxes/task.py,sha256=xgyPetm2R_HlQwpzE8YPnBN7QOYLd0-T8E6QPZG1PPQ,204
|
18
|
-
fabricatio-0.1.3.dist-info/METADATA,sha256=pDZPikewIva_s6riDaxhlOmvd92ls_JoS_VqETPwDdM,3797
|
19
|
-
fabricatio-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
20
|
-
fabricatio-0.1.3.dist-info/licenses/LICENSE,sha256=do7J7EiCGbq0QPbMAL_FqLYufXpHnCnXBOuqVPwSV8Y,1088
|
21
|
-
fabricatio-0.1.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|