fabricatio 0.2.6.dev1__cp312-cp312-win_amd64.whl → 0.2.7__cp312-cp312-win_amd64.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 +7 -24
- fabricatio/_rust.cp312-win_amd64.pyd +0 -0
- fabricatio/_rust.pyi +22 -0
- fabricatio/actions/article.py +168 -19
- fabricatio/actions/article_rag.py +35 -0
- fabricatio/actions/output.py +21 -6
- fabricatio/actions/rag.py +51 -3
- fabricatio/capabilities/correct.py +55 -11
- fabricatio/capabilities/rag.py +67 -16
- fabricatio/capabilities/rating.py +15 -6
- fabricatio/capabilities/review.py +7 -4
- fabricatio/capabilities/task.py +5 -5
- fabricatio/config.py +29 -21
- fabricatio/decorators.py +32 -0
- fabricatio/models/action.py +117 -43
- fabricatio/models/extra/article_base.py +378 -0
- fabricatio/models/extra/article_essence.py +226 -0
- fabricatio/models/extra/article_main.py +196 -0
- fabricatio/models/extra/article_outline.py +32 -0
- fabricatio/models/extra/article_proposal.py +35 -0
- fabricatio/models/generic.py +164 -14
- fabricatio/models/kwargs_types.py +51 -10
- fabricatio/models/role.py +30 -6
- fabricatio/models/tool.py +6 -2
- fabricatio/models/usages.py +94 -47
- fabricatio/models/utils.py +29 -2
- fabricatio/parser.py +2 -0
- fabricatio/workflows/articles.py +12 -1
- fabricatio-0.2.7.data/scripts/tdown.exe +0 -0
- fabricatio-0.2.7.dist-info/METADATA +181 -0
- fabricatio-0.2.7.dist-info/RECORD +47 -0
- {fabricatio-0.2.6.dev1.dist-info → fabricatio-0.2.7.dist-info}/WHEEL +1 -1
- fabricatio/models/extra.py +0 -171
- fabricatio-0.2.6.dev1.data/scripts/tdown.exe +0 -0
- fabricatio-0.2.6.dev1.dist-info/METADATA +0 -312
- fabricatio-0.2.6.dev1.dist-info/RECORD +0 -42
- {fabricatio-0.2.6.dev1.dist-info → fabricatio-0.2.7.dist-info}/licenses/LICENSE +0 -0
fabricatio/models/generic.py
CHANGED
@@ -10,6 +10,7 @@ from fabricatio._rust_instances import TEMPLATE_MANAGER
|
|
10
10
|
from fabricatio.config import configs
|
11
11
|
from fabricatio.fs.readers import MAGIKA, safe_text_read
|
12
12
|
from fabricatio.journal import logger
|
13
|
+
from fabricatio.models.utils import ok
|
13
14
|
from fabricatio.parser import JsonCapture
|
14
15
|
from pydantic import (
|
15
16
|
BaseModel,
|
@@ -19,8 +20,10 @@ from pydantic import (
|
|
19
20
|
NonNegativeFloat,
|
20
21
|
PositiveFloat,
|
21
22
|
PositiveInt,
|
23
|
+
PrivateAttr,
|
22
24
|
SecretStr,
|
23
25
|
)
|
26
|
+
from pydantic.json_schema import GenerateJsonSchema, JsonSchemaValue
|
24
27
|
|
25
28
|
|
26
29
|
class Base(BaseModel):
|
@@ -63,6 +66,134 @@ class Described(Base):
|
|
63
66
|
"""The description of the object."""
|
64
67
|
|
65
68
|
|
69
|
+
class AsPrompt(Base):
|
70
|
+
"""Class that provides a method to generate a prompt from the model."""
|
71
|
+
|
72
|
+
@final
|
73
|
+
def as_prompt(self) -> str:
|
74
|
+
"""Generate a prompt from the model.
|
75
|
+
|
76
|
+
Returns:
|
77
|
+
str: The generated prompt.
|
78
|
+
"""
|
79
|
+
return TEMPLATE_MANAGER.render_template(
|
80
|
+
configs.templates.as_prompt_template,
|
81
|
+
self._as_prompt_inner(),
|
82
|
+
)
|
83
|
+
|
84
|
+
@abstractmethod
|
85
|
+
def _as_prompt_inner(self) -> Dict[str, str]: ...
|
86
|
+
|
87
|
+
|
88
|
+
class WithRef[T](Base):
|
89
|
+
"""Class that provides a reference to another object."""
|
90
|
+
|
91
|
+
_reference: Optional[T] = PrivateAttr(None)
|
92
|
+
|
93
|
+
@property
|
94
|
+
def referenced(self) -> T:
|
95
|
+
"""Get the referenced object."""
|
96
|
+
return ok(self._reference, "_reference is None")
|
97
|
+
|
98
|
+
def update_ref[S: "WithRef"](self: S, reference: T | S) -> S: # noqa: PYI019
|
99
|
+
"""Update the reference of the object."""
|
100
|
+
if isinstance(reference, self.__class__):
|
101
|
+
self._reference = reference.referenced
|
102
|
+
else:
|
103
|
+
self._reference = reference
|
104
|
+
return self
|
105
|
+
|
106
|
+
|
107
|
+
class PersistentAble(Base):
|
108
|
+
"""Class that provides a method to persist the object."""
|
109
|
+
|
110
|
+
def persist(self, path: str | Path) -> Self:
|
111
|
+
"""Persist the object to a file.
|
112
|
+
|
113
|
+
Args:
|
114
|
+
path (str | Path): The path to save the object.
|
115
|
+
|
116
|
+
Returns:
|
117
|
+
Self: The current instance of the object.
|
118
|
+
"""
|
119
|
+
p = Path(path)
|
120
|
+
out = self.model_dump_json()
|
121
|
+
if p.is_dir():
|
122
|
+
p.joinpath(f"{self.__class__.__name__}_{blake3_hash(out.encode())[:6]}.json").write_text(
|
123
|
+
out, encoding="utf-8"
|
124
|
+
)
|
125
|
+
return self
|
126
|
+
p.mkdir(exist_ok=True, parents=True)
|
127
|
+
p.write_text(out, encoding="utf-8")
|
128
|
+
return self
|
129
|
+
|
130
|
+
def from_persistent(self, path: str | Path) -> Self:
|
131
|
+
"""Load the object from a file.
|
132
|
+
|
133
|
+
Args:
|
134
|
+
path (str | Path): The path to load the object from.
|
135
|
+
|
136
|
+
Returns:
|
137
|
+
Self: The current instance of the object.
|
138
|
+
"""
|
139
|
+
return self.model_validate_json(Path(path).read_text(encoding="utf-8"))
|
140
|
+
|
141
|
+
|
142
|
+
class ModelHash(Base):
|
143
|
+
"""Class that provides a hash value for the object."""
|
144
|
+
|
145
|
+
def __hash__(self) -> int:
|
146
|
+
"""Calculates a hash value for the ArticleBase object based on its model_dump_json representation."""
|
147
|
+
return hash(self.model_dump_json())
|
148
|
+
|
149
|
+
|
150
|
+
class UpdateFrom(Base):
|
151
|
+
"""Class that provides a method to update the object from another object."""
|
152
|
+
|
153
|
+
def update_pre_check(self, other: Self) -> Self:
|
154
|
+
"""Pre-check for updating the object from another object."""
|
155
|
+
if not isinstance(other, self.__class__):
|
156
|
+
raise TypeError(f"Cannot update from a non-{self.__class__.__name__} instance.")
|
157
|
+
|
158
|
+
return self
|
159
|
+
|
160
|
+
@abstractmethod
|
161
|
+
def update_from_inner(self, other: Self) -> Self:
|
162
|
+
"""Updates the current instance with the attributes of another instance."""
|
163
|
+
|
164
|
+
@final
|
165
|
+
def update_from(self, other: Self) -> Self:
|
166
|
+
"""Updates the current instance with the attributes of another instance."""
|
167
|
+
return self.update_pre_check(other).update_from_inner(other)
|
168
|
+
|
169
|
+
|
170
|
+
class ResolveUpdateConflict(Base):
|
171
|
+
"""Class that provides a method to update the object from another object."""
|
172
|
+
|
173
|
+
@abstractmethod
|
174
|
+
def resolve_update_conflict(self, other: Self) -> str:
|
175
|
+
"""Resolve the update conflict between two objects.
|
176
|
+
|
177
|
+
Args:
|
178
|
+
other (Self): The other object to resolve the update conflict with.
|
179
|
+
|
180
|
+
Returns:
|
181
|
+
str: The resolved update conflict.
|
182
|
+
"""
|
183
|
+
|
184
|
+
|
185
|
+
class Introspect(Base):
|
186
|
+
"""Class that provides a method to introspect the object."""
|
187
|
+
|
188
|
+
@abstractmethod
|
189
|
+
def introspect(self) -> str:
|
190
|
+
"""Internal introspection of the object.
|
191
|
+
|
192
|
+
Returns:
|
193
|
+
str: The internal introspection of the object.
|
194
|
+
"""
|
195
|
+
|
196
|
+
|
66
197
|
class WithBriefing(Named, Described):
|
67
198
|
"""Class that provides a briefing based on the name and description."""
|
68
199
|
|
@@ -75,17 +206,34 @@ class WithBriefing(Named, Described):
|
|
75
206
|
"""
|
76
207
|
return f"{self.name}: {self.description}" if self.description else self.name
|
77
208
|
|
78
|
-
def
|
79
|
-
"
|
209
|
+
def _prepend_inner(self, input_text: str) -> str:
|
210
|
+
return f"# your personal briefing: \n{self.briefing}\n{input_text}"
|
211
|
+
|
212
|
+
def prepend_sys_msg[D: (Dict[str, Any], str)](self, system_msg_like: D = "") -> Dict[str, Any]:
|
213
|
+
"""Prepend the system message with the briefing.
|
80
214
|
|
81
215
|
Args:
|
82
|
-
|
216
|
+
system_msg_like (str | dict): The system message or a dictionary containing the system message.
|
83
217
|
|
84
218
|
Returns:
|
85
|
-
|
219
|
+
dict: The system message with the briefing prepended.
|
86
220
|
"""
|
87
|
-
|
88
|
-
|
221
|
+
match system_msg_like:
|
222
|
+
case dict(d):
|
223
|
+
d["system_message"] = self._prepend_inner(d.get("system_message", ""))
|
224
|
+
return d
|
225
|
+
case str(s):
|
226
|
+
return {"system_message": self._prepend_inner(s)}
|
227
|
+
case _:
|
228
|
+
raise TypeError(f"{system_msg_like} is not a dict or str")
|
229
|
+
|
230
|
+
|
231
|
+
class UnsortGenerate(GenerateJsonSchema):
|
232
|
+
"""Class that provides a reverse JSON schema of the model."""
|
233
|
+
|
234
|
+
def sort(self, value: JsonSchemaValue, parent_key: str | None = None) -> JsonSchemaValue:
|
235
|
+
"""Not sort."""
|
236
|
+
return value
|
89
237
|
|
90
238
|
|
91
239
|
class WithFormatedJsonSchema(Base):
|
@@ -99,8 +247,8 @@ class WithFormatedJsonSchema(Base):
|
|
99
247
|
str: The JSON schema of the model in a formatted string.
|
100
248
|
"""
|
101
249
|
return orjson.dumps(
|
102
|
-
cls.model_json_schema(),
|
103
|
-
option=orjson.OPT_INDENT_2
|
250
|
+
cls.model_json_schema(schema_generator=UnsortGenerate),
|
251
|
+
option=orjson.OPT_INDENT_2,
|
104
252
|
).decode()
|
105
253
|
|
106
254
|
|
@@ -158,19 +306,17 @@ class InstantiateFromString(Base):
|
|
158
306
|
class ProposedAble(CreateJsonObjPrompt, InstantiateFromString):
|
159
307
|
"""Class that provides a method to propose a JSON object based on the requirement."""
|
160
308
|
|
161
|
-
pass
|
162
|
-
|
163
309
|
|
164
310
|
class FinalizedDumpAble(Base):
|
165
311
|
"""Class that provides a method to finalize the dump of the object."""
|
166
312
|
|
167
|
-
@abstractmethod
|
168
313
|
def finalized_dump(self) -> str:
|
169
314
|
"""Finalize the dump of the object.
|
170
315
|
|
171
316
|
Returns:
|
172
317
|
str: The finalized dump of the object.
|
173
318
|
"""
|
319
|
+
return self.model_dump_json()
|
174
320
|
|
175
321
|
def finalized_dump_to(self, path: str | Path) -> Self:
|
176
322
|
"""Finalize the dump of the object to a file.
|
@@ -185,6 +331,10 @@ class FinalizedDumpAble(Base):
|
|
185
331
|
return self
|
186
332
|
|
187
333
|
|
334
|
+
class CensoredAble(ProposedAble, FinalizedDumpAble):
|
335
|
+
"""Class that provides a method to censor the object."""
|
336
|
+
|
337
|
+
|
188
338
|
class WithDependency(Base):
|
189
339
|
"""Class that manages file dependencies."""
|
190
340
|
|
@@ -288,7 +438,7 @@ class PrepareVectorization(Base):
|
|
288
438
|
"""
|
289
439
|
max_length = max_length or configs.embedding.max_sequence_length
|
290
440
|
chunk = self._prepare_vectorization_inner()
|
291
|
-
if len(chunk) > max_length:
|
441
|
+
if max_length and len(chunk) > max_length:
|
292
442
|
logger.error(err := f"Chunk exceeds maximum sequence length {max_length}.")
|
293
443
|
raise ValueError(err)
|
294
444
|
|
@@ -371,7 +521,7 @@ class ScopedConfig(Base):
|
|
371
521
|
"""Fallback to another instance's attribute values if the current instance's attributes are None.
|
372
522
|
|
373
523
|
Args:
|
374
|
-
other (
|
524
|
+
other (ScopedConfig): Another instance from which to copy attribute values.
|
375
525
|
|
376
526
|
Returns:
|
377
527
|
Self: The current instance, allowing for method chaining.
|
@@ -391,7 +541,7 @@ class ScopedConfig(Base):
|
|
391
541
|
"""Hold to another instance's attribute values if the current instance's attributes are None.
|
392
542
|
|
393
543
|
Args:
|
394
|
-
others (
|
544
|
+
others (Union[ScopedConfig, Iterable[ScopedConfig]]): Another instance or iterable of instances from which to copy attribute values.
|
395
545
|
|
396
546
|
Returns:
|
397
547
|
Self: The current instance, allowing for method chaining.
|
@@ -1,19 +1,29 @@
|
|
1
1
|
"""This module contains the types for the keyword arguments of the methods in the models module."""
|
2
2
|
|
3
|
-
from
|
3
|
+
from importlib.util import find_spec
|
4
|
+
from typing import Any, Dict, Required, TypedDict
|
4
5
|
|
5
6
|
from litellm.caching.caching import CacheMode
|
6
7
|
from litellm.types.caching import CachingSupportedCallTypes
|
7
8
|
|
9
|
+
if find_spec("pymilvus"):
|
10
|
+
from pymilvus import CollectionSchema
|
11
|
+
from pymilvus.milvus_client import IndexParams
|
8
12
|
|
9
|
-
class
|
10
|
-
|
13
|
+
class CollectionConfigKwargs(TypedDict, total=False):
|
14
|
+
"""Configuration parameters for a vector collection.
|
11
15
|
|
12
|
-
|
13
|
-
|
16
|
+
These arguments are typically used when configuring connections to vector databases.
|
17
|
+
"""
|
14
18
|
|
15
|
-
|
16
|
-
|
19
|
+
dimension: int | None
|
20
|
+
primary_field_name: str
|
21
|
+
id_type: str
|
22
|
+
vector_field_name: str
|
23
|
+
metric_type: str
|
24
|
+
timeout: float | None
|
25
|
+
schema: CollectionSchema | None
|
26
|
+
index_params: IndexParams | None
|
17
27
|
|
18
28
|
|
19
29
|
class FetchKwargs(TypedDict, total=False):
|
@@ -28,6 +38,12 @@ class FetchKwargs(TypedDict, total=False):
|
|
28
38
|
result_per_query: int
|
29
39
|
|
30
40
|
|
41
|
+
class RetrievalKwargs(FetchKwargs, total=False):
|
42
|
+
"""Arguments for retrieval operations."""
|
43
|
+
|
44
|
+
final_limit: int
|
45
|
+
|
46
|
+
|
31
47
|
class EmbeddingKwargs(TypedDict, total=False):
|
32
48
|
"""Configuration parameters for text embedding operations.
|
33
49
|
|
@@ -81,18 +97,43 @@ class ValidateKwargs[T](GenerateKwargs, total=False):
|
|
81
97
|
|
82
98
|
default: T
|
83
99
|
max_validations: int
|
100
|
+
co_extractor: GenerateKwargs
|
101
|
+
|
102
|
+
|
103
|
+
class ReviewInnerKwargs[T](ValidateKwargs[T], total=False):
|
104
|
+
"""Arguments for content review operations."""
|
105
|
+
|
106
|
+
criteria: set[str]
|
84
107
|
|
85
108
|
|
86
109
|
# noinspection PyTypedDict
|
87
|
-
class ReviewKwargs[T](
|
110
|
+
class ReviewKwargs[T](ReviewInnerKwargs[T], total=False):
|
88
111
|
"""Arguments for content review operations.
|
89
112
|
|
90
113
|
Extends GenerateKwargs with parameters for evaluating content against
|
91
114
|
specific topics and review criteria.
|
92
115
|
"""
|
93
116
|
|
94
|
-
|
95
|
-
|
117
|
+
rating_manual: Dict[str, str]
|
118
|
+
topic: Required[str]
|
119
|
+
|
120
|
+
|
121
|
+
class CorrectKwargs[T](ReviewKwargs[T], total=False):
|
122
|
+
"""Arguments for content correction operations.
|
123
|
+
|
124
|
+
Extends GenerateKwargs with parameters for correcting content based on
|
125
|
+
specific criteria and templates.
|
126
|
+
"""
|
127
|
+
|
128
|
+
reference: str
|
129
|
+
supervisor_check: bool
|
130
|
+
|
131
|
+
|
132
|
+
class CensoredCorrectKwargs[T](ReviewInnerKwargs[T], total=False):
|
133
|
+
"""Arguments for content censorship operations."""
|
134
|
+
|
135
|
+
reference: str
|
136
|
+
supervisor_check: bool
|
96
137
|
|
97
138
|
|
98
139
|
# noinspection PyTypedDict
|
fabricatio/models/role.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""Module that contains the Role class."""
|
1
|
+
"""Module that contains the Role class for managing workflows and their event registrations."""
|
2
2
|
|
3
3
|
from typing import Any, Self, Set
|
4
4
|
|
@@ -13,19 +13,36 @@ from pydantic import Field
|
|
13
13
|
|
14
14
|
|
15
15
|
class Role(ProposeTask, HandleTask, Correct):
|
16
|
-
"""Class that represents a role with a registry of events and workflows.
|
16
|
+
"""Class that represents a role with a registry of events and workflows.
|
17
|
+
|
18
|
+
A Role serves as a container for workflows, managing their registration to events
|
19
|
+
and providing them with shared configuration like tools and personality.
|
20
|
+
|
21
|
+
Attributes:
|
22
|
+
registry: Mapping of events to workflows that handle them
|
23
|
+
toolboxes: Set of toolboxes available to this role and its workflows
|
24
|
+
"""
|
17
25
|
|
18
26
|
registry: dict[Event | str, WorkFlow] = Field(default_factory=dict)
|
19
|
-
"""
|
27
|
+
"""The registry of events and workflows."""
|
20
28
|
|
21
29
|
toolboxes: Set[ToolBox] = Field(default_factory=set)
|
30
|
+
"""Collection of tools available to this role."""
|
22
31
|
|
23
32
|
def model_post_init(self, __context: Any) -> None:
|
24
|
-
"""
|
33
|
+
"""Initialize the role by resolving configurations and registering workflows.
|
34
|
+
|
35
|
+
Args:
|
36
|
+
__context: The context used for initialization
|
37
|
+
"""
|
25
38
|
self.resolve_configuration().register_workflows()
|
26
39
|
|
27
40
|
def register_workflows(self) -> Self:
|
28
|
-
"""Register
|
41
|
+
"""Register each workflow in the registry to its corresponding event in the event bus.
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
Self: The role instance for method chaining
|
45
|
+
"""
|
29
46
|
for event, workflow in self.registry.items():
|
30
47
|
logger.debug(
|
31
48
|
f"Registering workflow: `{workflow.name}` for event: `{Event.instantiate_from(event).collapse()}`"
|
@@ -34,7 +51,14 @@ class Role(ProposeTask, HandleTask, Correct):
|
|
34
51
|
return self
|
35
52
|
|
36
53
|
def resolve_configuration(self) -> Self:
|
37
|
-
"""
|
54
|
+
"""Apply role-level configuration to all workflows in the registry.
|
55
|
+
|
56
|
+
This includes setting up fallback configurations, injecting personality traits,
|
57
|
+
and providing tool access to workflows and their steps.
|
58
|
+
|
59
|
+
Returns:
|
60
|
+
Self: The role instance for method chaining
|
61
|
+
"""
|
38
62
|
for workflow in self.registry.values():
|
39
63
|
logger.debug(f"Resolving config for workflow: `{workflow.name}`")
|
40
64
|
(
|
fabricatio/models/tool.py
CHANGED
@@ -136,7 +136,9 @@ class ToolExecutor(BaseModel):
|
|
136
136
|
|
137
137
|
def inject_tools[M: ModuleType](self, module: Optional[M] = None) -> M:
|
138
138
|
"""Inject the tools into the provided module or default."""
|
139
|
-
module = module or cast(
|
139
|
+
module = module or cast(
|
140
|
+
"M", module_from_spec(spec=ModuleSpec(name=configs.toolbox.tool_module_name, loader=None))
|
141
|
+
)
|
140
142
|
for tool in self.candidates:
|
141
143
|
logger.debug(f"Injecting tool: {tool.name}")
|
142
144
|
setattr(module, tool.name, tool.invoke)
|
@@ -144,7 +146,9 @@ class ToolExecutor(BaseModel):
|
|
144
146
|
|
145
147
|
def inject_data[M: ModuleType](self, module: Optional[M] = None) -> M:
|
146
148
|
"""Inject the data into the provided module or default."""
|
147
|
-
module = module or cast(
|
149
|
+
module = module or cast(
|
150
|
+
'M', module_from_spec(spec=ModuleSpec(name=configs.toolbox.data_module_name, loader=None))
|
151
|
+
)
|
148
152
|
for key, value in self.data.items():
|
149
153
|
logger.debug(f"Injecting data: {key}")
|
150
154
|
setattr(module, key, value)
|