fabricatio 0.2.6__cp39-cp39-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 +43 -0
- fabricatio/_rust.cp39-win_amd64.pyd +0 -0
- fabricatio/_rust.pyi +115 -0
- fabricatio/_rust_instances.py +10 -0
- fabricatio/actions/article.py +128 -0
- fabricatio/actions/output.py +19 -0
- fabricatio/actions/rag.py +71 -0
- fabricatio/capabilities/correct.py +115 -0
- fabricatio/capabilities/propose.py +49 -0
- fabricatio/capabilities/rag.py +384 -0
- fabricatio/capabilities/rating.py +339 -0
- fabricatio/capabilities/review.py +278 -0
- fabricatio/capabilities/task.py +113 -0
- fabricatio/config.py +405 -0
- fabricatio/core.py +181 -0
- fabricatio/decorators.py +179 -0
- fabricatio/fs/__init__.py +29 -0
- fabricatio/fs/curd.py +149 -0
- fabricatio/fs/readers.py +46 -0
- fabricatio/journal.py +21 -0
- fabricatio/models/action.py +230 -0
- fabricatio/models/events.py +120 -0
- fabricatio/models/extra.py +655 -0
- fabricatio/models/generic.py +406 -0
- fabricatio/models/kwargs_types.py +169 -0
- fabricatio/models/role.py +72 -0
- fabricatio/models/task.py +299 -0
- fabricatio/models/tool.py +189 -0
- fabricatio/models/usages.py +718 -0
- fabricatio/models/utils.py +192 -0
- fabricatio/parser.py +151 -0
- fabricatio/py.typed +0 -0
- fabricatio/toolboxes/__init__.py +15 -0
- fabricatio/toolboxes/arithmetic.py +62 -0
- fabricatio/toolboxes/fs.py +31 -0
- fabricatio/workflows/articles.py +26 -0
- fabricatio/workflows/rag.py +11 -0
- fabricatio-0.2.6.data/scripts/tdown.exe +0 -0
- fabricatio-0.2.6.dist-info/METADATA +432 -0
- fabricatio-0.2.6.dist-info/RECORD +42 -0
- fabricatio-0.2.6.dist-info/WHEEL +4 -0
- fabricatio-0.2.6.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,406 @@
|
|
1
|
+
"""This module defines generic classes for models in the Fabricatio library."""
|
2
|
+
|
3
|
+
from abc import abstractmethod
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import Any, Callable, Dict, Iterable, List, Optional, Self, Union, final, overload
|
6
|
+
|
7
|
+
import orjson
|
8
|
+
from fabricatio._rust import blake3_hash
|
9
|
+
from fabricatio._rust_instances import TEMPLATE_MANAGER
|
10
|
+
from fabricatio.config import configs
|
11
|
+
from fabricatio.fs.readers import MAGIKA, safe_text_read
|
12
|
+
from fabricatio.journal import logger
|
13
|
+
from fabricatio.parser import JsonCapture
|
14
|
+
from pydantic import (
|
15
|
+
BaseModel,
|
16
|
+
ConfigDict,
|
17
|
+
Field,
|
18
|
+
HttpUrl,
|
19
|
+
NonNegativeFloat,
|
20
|
+
PositiveFloat,
|
21
|
+
PositiveInt,
|
22
|
+
SecretStr,
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
class Base(BaseModel):
|
27
|
+
"""Base class for all models with Pydantic configuration."""
|
28
|
+
|
29
|
+
model_config = ConfigDict(use_attribute_docstrings=True)
|
30
|
+
|
31
|
+
|
32
|
+
class Display(Base):
|
33
|
+
"""Class that provides a method to display the model in a formatted JSON string."""
|
34
|
+
|
35
|
+
def display(self) -> str:
|
36
|
+
"""Display the model in a formatted JSON string.
|
37
|
+
|
38
|
+
Returns:
|
39
|
+
str: The formatted JSON string of the model.
|
40
|
+
"""
|
41
|
+
return self.model_dump_json(indent=1)
|
42
|
+
|
43
|
+
def compact(self) -> str:
|
44
|
+
"""Display the model in a compact JSON string.
|
45
|
+
|
46
|
+
Returns:
|
47
|
+
str: The compact JSON string of the model.
|
48
|
+
"""
|
49
|
+
return self.model_dump_json()
|
50
|
+
|
51
|
+
|
52
|
+
class Named(Base):
|
53
|
+
"""Class that includes a name attribute."""
|
54
|
+
|
55
|
+
name: str = Field(frozen=True)
|
56
|
+
"""The name of the object."""
|
57
|
+
|
58
|
+
|
59
|
+
class Described(Base):
|
60
|
+
"""Class that includes a description attribute."""
|
61
|
+
|
62
|
+
description: str = Field(default="", frozen=True)
|
63
|
+
"""The description of the object."""
|
64
|
+
|
65
|
+
|
66
|
+
class WithBriefing(Named, Described):
|
67
|
+
"""Class that provides a briefing based on the name and description."""
|
68
|
+
|
69
|
+
@property
|
70
|
+
def briefing(self) -> str:
|
71
|
+
"""Get the briefing of the object.
|
72
|
+
|
73
|
+
Returns:
|
74
|
+
str: The briefing of the object.
|
75
|
+
"""
|
76
|
+
return f"{self.name}: {self.description}" if self.description else self.name
|
77
|
+
|
78
|
+
def prepend[D: Dict[str, Any]](self, kwargs: D) -> D:
|
79
|
+
"""Prepend the briefing to the system message in the kwargs.
|
80
|
+
|
81
|
+
Args:
|
82
|
+
kwargs (Dict[str, Any]): The keyword arguments to modify.
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
Dict[str, Any]: The modified keyword arguments.
|
86
|
+
"""
|
87
|
+
kwargs["system_message"] = f"# your personal briefing: \n{self.briefing}\n" + kwargs.get("system_message", "")
|
88
|
+
return kwargs
|
89
|
+
|
90
|
+
|
91
|
+
class WithFormatedJsonSchema(Base):
|
92
|
+
"""Class that provides a formatted JSON schema of the model."""
|
93
|
+
|
94
|
+
@classmethod
|
95
|
+
def formated_json_schema(cls) -> str:
|
96
|
+
"""Get the JSON schema of the model in a formatted string.
|
97
|
+
|
98
|
+
Returns:
|
99
|
+
str: The JSON schema of the model in a formatted string.
|
100
|
+
"""
|
101
|
+
return orjson.dumps(
|
102
|
+
cls.model_json_schema(),
|
103
|
+
option=orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS,
|
104
|
+
).decode()
|
105
|
+
|
106
|
+
|
107
|
+
class CreateJsonObjPrompt(WithFormatedJsonSchema):
|
108
|
+
"""Class that provides a prompt for creating a JSON object."""
|
109
|
+
|
110
|
+
@classmethod
|
111
|
+
@overload
|
112
|
+
def create_json_prompt(cls, requirement: List[str]) -> List[str]: ...
|
113
|
+
|
114
|
+
@classmethod
|
115
|
+
@overload
|
116
|
+
def create_json_prompt(cls, requirement: str) -> str: ...
|
117
|
+
|
118
|
+
@classmethod
|
119
|
+
def create_json_prompt(cls, requirement: str | List[str]) -> str | List[str]:
|
120
|
+
"""Create the prompt for creating a JSON object with given requirement.
|
121
|
+
|
122
|
+
Args:
|
123
|
+
requirement (str): The requirement for the JSON object.
|
124
|
+
|
125
|
+
Returns:
|
126
|
+
str: The prompt for creating a JSON object with given requirement.
|
127
|
+
"""
|
128
|
+
if isinstance(requirement, str):
|
129
|
+
return TEMPLATE_MANAGER.render_template(
|
130
|
+
configs.templates.create_json_obj_template,
|
131
|
+
{"requirement": requirement, "json_schema": cls.formated_json_schema()},
|
132
|
+
)
|
133
|
+
return [
|
134
|
+
TEMPLATE_MANAGER.render_template(
|
135
|
+
configs.templates.create_json_obj_template,
|
136
|
+
{"requirement": r, "json_schema": cls.formated_json_schema()},
|
137
|
+
)
|
138
|
+
for r in requirement
|
139
|
+
]
|
140
|
+
|
141
|
+
|
142
|
+
class InstantiateFromString(Base):
|
143
|
+
"""Class that provides a method to instantiate the class from a string."""
|
144
|
+
|
145
|
+
@classmethod
|
146
|
+
def instantiate_from_string(cls, string: str) -> Self | None:
|
147
|
+
"""Instantiate the class from a string.
|
148
|
+
|
149
|
+
Args:
|
150
|
+
string (str): The string to instantiate the class from.
|
151
|
+
|
152
|
+
Returns:
|
153
|
+
Self | None: The instance of the class or None if the string is not valid.
|
154
|
+
"""
|
155
|
+
return JsonCapture.convert_with(string, cls.model_validate_json)
|
156
|
+
|
157
|
+
|
158
|
+
class ProposedAble(CreateJsonObjPrompt, InstantiateFromString):
|
159
|
+
"""Class that provides a method to propose a JSON object based on the requirement."""
|
160
|
+
|
161
|
+
pass
|
162
|
+
|
163
|
+
|
164
|
+
class FinalizedDumpAble(Base):
|
165
|
+
"""Class that provides a method to finalize the dump of the object."""
|
166
|
+
|
167
|
+
@abstractmethod
|
168
|
+
def finalized_dump(self) -> str:
|
169
|
+
"""Finalize the dump of the object.
|
170
|
+
|
171
|
+
Returns:
|
172
|
+
str: The finalized dump of the object.
|
173
|
+
"""
|
174
|
+
|
175
|
+
def finalized_dump_to(self, path: str | Path) -> Self:
|
176
|
+
"""Finalize the dump of the object to a file.
|
177
|
+
|
178
|
+
Args:
|
179
|
+
path (str | Path): The path to save the finalized dump.
|
180
|
+
|
181
|
+
Returns:
|
182
|
+
Self: The current instance of the object.
|
183
|
+
"""
|
184
|
+
Path(path).write_text(self.finalized_dump(), encoding="utf-8")
|
185
|
+
return self
|
186
|
+
|
187
|
+
|
188
|
+
class WithDependency(Base):
|
189
|
+
"""Class that manages file dependencies."""
|
190
|
+
|
191
|
+
dependencies: List[str] = Field(default_factory=list)
|
192
|
+
"""The file dependencies which is needed to read or write to meet a specific requirement, a list of file paths."""
|
193
|
+
|
194
|
+
def add_dependency[P: str | Path](self, dependency: P | List[P]) -> Self:
|
195
|
+
"""Add a file dependency to the task.
|
196
|
+
|
197
|
+
Args:
|
198
|
+
dependency (str | Path | List[str | Path]): The file dependency to add to the task.
|
199
|
+
|
200
|
+
Returns:
|
201
|
+
Self: The current instance of the task.
|
202
|
+
"""
|
203
|
+
if not isinstance(dependency, list):
|
204
|
+
dependency = [dependency]
|
205
|
+
self.dependencies.extend(Path(d).as_posix() for d in dependency)
|
206
|
+
return self
|
207
|
+
|
208
|
+
def remove_dependency[P: str | Path](self, dependency: P | List[P]) -> Self:
|
209
|
+
"""Remove a file dependency from the task.
|
210
|
+
|
211
|
+
Args:
|
212
|
+
dependency (str | Path | List[str | Path]): The file dependency to remove from the task.
|
213
|
+
|
214
|
+
Returns:
|
215
|
+
Self: The current instance of the task.
|
216
|
+
"""
|
217
|
+
if not isinstance(dependency, list):
|
218
|
+
dependency = [dependency]
|
219
|
+
for d in dependency:
|
220
|
+
self.dependencies.remove(Path(d).as_posix())
|
221
|
+
return self
|
222
|
+
|
223
|
+
def clear_dependencies(self) -> Self:
|
224
|
+
"""Clear all file dependencies from the task.
|
225
|
+
|
226
|
+
Returns:
|
227
|
+
Self: The current instance of the task.
|
228
|
+
"""
|
229
|
+
self.dependencies.clear()
|
230
|
+
return self
|
231
|
+
|
232
|
+
def override_dependencies[P: str | Path](self, dependencies: List[P] | P) -> Self:
|
233
|
+
"""Override the file dependencies of the task.
|
234
|
+
|
235
|
+
Args:
|
236
|
+
dependencies (List[str | Path] | str | Path): The file dependencies to override the task's dependencies.
|
237
|
+
|
238
|
+
Returns:
|
239
|
+
Self: The current instance of the task.
|
240
|
+
"""
|
241
|
+
return self.clear_dependencies().add_dependency(dependencies)
|
242
|
+
|
243
|
+
def pop_dependence[T](self, idx: int = -1, reader: Callable[[str], T] = safe_text_read) -> T:
|
244
|
+
"""Pop the file dependencies from the task.
|
245
|
+
|
246
|
+
Returns:
|
247
|
+
str: The popped file dependency
|
248
|
+
"""
|
249
|
+
return reader(self.dependencies.pop(idx))
|
250
|
+
|
251
|
+
@property
|
252
|
+
def dependencies_prompt(self) -> str:
|
253
|
+
"""Generate a prompt for the task based on the file dependencies.
|
254
|
+
|
255
|
+
Returns:
|
256
|
+
str: The generated prompt for the task.
|
257
|
+
"""
|
258
|
+
return TEMPLATE_MANAGER.render_template(
|
259
|
+
configs.templates.dependencies_template,
|
260
|
+
{
|
261
|
+
(pth := Path(p)).name: {
|
262
|
+
"path": pth.as_posix(),
|
263
|
+
"exists": pth.exists(),
|
264
|
+
"description": (identity := MAGIKA.identify_path(pth)).output.description,
|
265
|
+
"size": f"{pth.stat().st_size / (1024 * 1024) if pth.exists() and pth.is_file() else 0:.3f} MB",
|
266
|
+
"content": (text := safe_text_read(pth)),
|
267
|
+
"lines": len(text.splitlines()),
|
268
|
+
"language": identity.output.ct_label,
|
269
|
+
"checksum": blake3_hash(pth.read_bytes()) if pth.exists() and pth.is_file() else "unknown",
|
270
|
+
}
|
271
|
+
for p in self.dependencies
|
272
|
+
},
|
273
|
+
)
|
274
|
+
|
275
|
+
|
276
|
+
class PrepareVectorization(Base):
|
277
|
+
"""Class that prepares the vectorization of the model."""
|
278
|
+
|
279
|
+
@abstractmethod
|
280
|
+
def _prepare_vectorization_inner(self) -> str:
|
281
|
+
"""Prepare the vectorization of the model."""
|
282
|
+
|
283
|
+
def prepare_vectorization(self, max_length: Optional[int] = None) -> str:
|
284
|
+
"""Prepare the vectorization of the model.
|
285
|
+
|
286
|
+
Returns:
|
287
|
+
str: The prepared vectorization of the model.
|
288
|
+
"""
|
289
|
+
max_length = max_length or configs.embedding.max_sequence_length
|
290
|
+
chunk = self._prepare_vectorization_inner()
|
291
|
+
if len(chunk) > max_length:
|
292
|
+
logger.error(err := f"Chunk exceeds maximum sequence length {max_length}.")
|
293
|
+
raise ValueError(err)
|
294
|
+
|
295
|
+
return chunk
|
296
|
+
|
297
|
+
|
298
|
+
class ScopedConfig(Base):
|
299
|
+
"""Class that manages a scoped configuration."""
|
300
|
+
|
301
|
+
llm_api_endpoint: Optional[HttpUrl] = None
|
302
|
+
"""The OpenAI API endpoint."""
|
303
|
+
|
304
|
+
llm_api_key: Optional[SecretStr] = None
|
305
|
+
"""The OpenAI API key."""
|
306
|
+
|
307
|
+
llm_timeout: Optional[PositiveInt] = None
|
308
|
+
"""The timeout of the LLM model."""
|
309
|
+
|
310
|
+
llm_max_retries: Optional[PositiveInt] = None
|
311
|
+
"""The maximum number of retries."""
|
312
|
+
|
313
|
+
llm_model: Optional[str] = None
|
314
|
+
"""The LLM model name."""
|
315
|
+
|
316
|
+
llm_temperature: Optional[NonNegativeFloat] = None
|
317
|
+
"""The temperature of the LLM model."""
|
318
|
+
|
319
|
+
llm_stop_sign: Optional[str | List[str]] = None
|
320
|
+
"""The stop sign of the LLM model."""
|
321
|
+
|
322
|
+
llm_top_p: Optional[NonNegativeFloat] = None
|
323
|
+
"""The top p of the LLM model."""
|
324
|
+
|
325
|
+
llm_generation_count: Optional[PositiveInt] = None
|
326
|
+
"""The number of generations to generate."""
|
327
|
+
|
328
|
+
llm_stream: Optional[bool] = None
|
329
|
+
"""Whether to stream the LLM model's response."""
|
330
|
+
|
331
|
+
llm_max_tokens: Optional[PositiveInt] = None
|
332
|
+
"""The maximum number of tokens to generate."""
|
333
|
+
|
334
|
+
llm_tpm: Optional[PositiveInt] = None
|
335
|
+
"""The tokens per minute of the LLM model."""
|
336
|
+
|
337
|
+
llm_rpm: Optional[PositiveInt] = None
|
338
|
+
"""The requests per minute of the LLM model."""
|
339
|
+
|
340
|
+
embedding_api_endpoint: Optional[HttpUrl] = None
|
341
|
+
"""The OpenAI API endpoint."""
|
342
|
+
|
343
|
+
embedding_api_key: Optional[SecretStr] = None
|
344
|
+
"""The OpenAI API key."""
|
345
|
+
|
346
|
+
embedding_timeout: Optional[PositiveInt] = None
|
347
|
+
"""The timeout of the LLM model."""
|
348
|
+
|
349
|
+
embedding_model: Optional[str] = None
|
350
|
+
"""The LLM model name."""
|
351
|
+
|
352
|
+
embedding_max_sequence_length: Optional[PositiveInt] = None
|
353
|
+
"""The maximum sequence length."""
|
354
|
+
|
355
|
+
embedding_dimensions: Optional[PositiveInt] = None
|
356
|
+
"""The dimensions of the embedding."""
|
357
|
+
embedding_caching: Optional[bool] = False
|
358
|
+
"""Whether to cache the embedding result."""
|
359
|
+
|
360
|
+
milvus_uri: Optional[HttpUrl] = Field(default=None)
|
361
|
+
"""The URI of the Milvus server."""
|
362
|
+
milvus_token: Optional[SecretStr] = Field(default=None)
|
363
|
+
"""The token for the Milvus server."""
|
364
|
+
milvus_timeout: Optional[PositiveFloat] = Field(default=None)
|
365
|
+
"""The timeout for the Milvus server."""
|
366
|
+
milvus_dimensions: Optional[PositiveInt] = Field(default=None)
|
367
|
+
"""The dimensions of the Milvus server."""
|
368
|
+
|
369
|
+
@final
|
370
|
+
def fallback_to(self, other: "ScopedConfig") -> Self:
|
371
|
+
"""Fallback to another instance's attribute values if the current instance's attributes are None.
|
372
|
+
|
373
|
+
Args:
|
374
|
+
other (LLMUsage): Another instance from which to copy attribute values.
|
375
|
+
|
376
|
+
Returns:
|
377
|
+
Self: The current instance, allowing for method chaining.
|
378
|
+
"""
|
379
|
+
# Iterate over the attribute names and copy values from 'other' to 'self' where applicable
|
380
|
+
# noinspection PydanticTypeChecker,PyTypeChecker
|
381
|
+
for attr_name in ScopedConfig.model_fields:
|
382
|
+
# Copy the attribute value from 'other' to 'self' only if 'self' has None and 'other' has a non-None value
|
383
|
+
if getattr(self, attr_name) is None and (attr := getattr(other, attr_name)) is not None:
|
384
|
+
setattr(self, attr_name, attr)
|
385
|
+
|
386
|
+
# Return the current instance to allow for method chaining
|
387
|
+
return self
|
388
|
+
|
389
|
+
@final
|
390
|
+
def hold_to(self, others: Union["ScopedConfig", Iterable["ScopedConfig"]]) -> Self:
|
391
|
+
"""Hold to another instance's attribute values if the current instance's attributes are None.
|
392
|
+
|
393
|
+
Args:
|
394
|
+
others (LLMUsage | Iterable[LLMUsage]): Another instance or iterable of instances from which to copy attribute values.
|
395
|
+
|
396
|
+
Returns:
|
397
|
+
Self: The current instance, allowing for method chaining.
|
398
|
+
"""
|
399
|
+
if not isinstance(others, Iterable):
|
400
|
+
others = [others]
|
401
|
+
for other in others:
|
402
|
+
# noinspection PyTypeChecker,PydanticTypeChecker
|
403
|
+
for attr_name in ScopedConfig.model_fields:
|
404
|
+
if (attr := getattr(self, attr_name)) is not None and getattr(other, attr_name) is None:
|
405
|
+
setattr(other, attr_name, attr)
|
406
|
+
return self
|
@@ -0,0 +1,169 @@
|
|
1
|
+
"""This module contains the types for the keyword arguments of the methods in the models module."""
|
2
|
+
|
3
|
+
from importlib.util import find_spec
|
4
|
+
from typing import Any, Required, TypedDict
|
5
|
+
|
6
|
+
from litellm.caching.caching import CacheMode
|
7
|
+
from litellm.types.caching import CachingSupportedCallTypes
|
8
|
+
|
9
|
+
if find_spec("pymilvus"):
|
10
|
+
from pymilvus import CollectionSchema
|
11
|
+
from pymilvus.milvus_client import IndexParams
|
12
|
+
|
13
|
+
class CollectionConfigKwargs(TypedDict, total=False):
|
14
|
+
"""Configuration parameters for a vector collection.
|
15
|
+
|
16
|
+
These arguments are typically used when configuring connections to vector databases.
|
17
|
+
"""
|
18
|
+
|
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
|
27
|
+
|
28
|
+
|
29
|
+
class FetchKwargs(TypedDict, total=False):
|
30
|
+
"""Arguments for fetching data from vector collections.
|
31
|
+
|
32
|
+
Controls how data is retrieved from vector databases, including filtering
|
33
|
+
and result limiting parameters.
|
34
|
+
"""
|
35
|
+
|
36
|
+
collection_name: str | None
|
37
|
+
similarity_threshold: float
|
38
|
+
result_per_query: int
|
39
|
+
|
40
|
+
|
41
|
+
class EmbeddingKwargs(TypedDict, total=False):
|
42
|
+
"""Configuration parameters for text embedding operations.
|
43
|
+
|
44
|
+
These settings control the behavior of embedding models that convert text
|
45
|
+
to vector representations.
|
46
|
+
"""
|
47
|
+
|
48
|
+
model: str
|
49
|
+
dimensions: int
|
50
|
+
timeout: int
|
51
|
+
caching: bool
|
52
|
+
|
53
|
+
|
54
|
+
class LLMKwargs(TypedDict, total=False):
|
55
|
+
"""Configuration parameters for language model inference.
|
56
|
+
|
57
|
+
These arguments control the behavior of large language model calls,
|
58
|
+
including generation parameters and caching options.
|
59
|
+
"""
|
60
|
+
|
61
|
+
model: str
|
62
|
+
temperature: float
|
63
|
+
stop: str | list[str]
|
64
|
+
top_p: float
|
65
|
+
max_tokens: int
|
66
|
+
stream: bool
|
67
|
+
timeout: int
|
68
|
+
max_retries: int
|
69
|
+
no_cache: bool # if the req uses cache in this call
|
70
|
+
no_store: bool # If store the response of this call to cache
|
71
|
+
cache_ttl: int # how long the stored cache is alive, in seconds
|
72
|
+
s_maxage: int # max accepted age of cached response, in seconds
|
73
|
+
|
74
|
+
|
75
|
+
class GenerateKwargs(LLMKwargs, total=False):
|
76
|
+
"""Arguments for content generation operations.
|
77
|
+
|
78
|
+
Extends LLMKwargs with additional parameters specific to generation tasks,
|
79
|
+
such as the number of generated items and the system message.
|
80
|
+
"""
|
81
|
+
|
82
|
+
system_message: str
|
83
|
+
|
84
|
+
|
85
|
+
class ValidateKwargs[T](GenerateKwargs, total=False):
|
86
|
+
"""Arguments for content validation operations.
|
87
|
+
|
88
|
+
Extends LLMKwargs with additional parameters specific to validation tasks,
|
89
|
+
such as limiting the number of validation attempts.
|
90
|
+
"""
|
91
|
+
|
92
|
+
default: T
|
93
|
+
max_validations: int
|
94
|
+
co_extractor: GenerateKwargs
|
95
|
+
|
96
|
+
|
97
|
+
# noinspection PyTypedDict
|
98
|
+
class ReviewKwargs[T](ValidateKwargs[T], total=False):
|
99
|
+
"""Arguments for content review operations.
|
100
|
+
|
101
|
+
Extends GenerateKwargs with parameters for evaluating content against
|
102
|
+
specific topics and review criteria.
|
103
|
+
"""
|
104
|
+
|
105
|
+
topic: Required[str]
|
106
|
+
criteria: set[str]
|
107
|
+
|
108
|
+
|
109
|
+
class CorrectKwargs[T](ReviewKwargs[T], total=False):
|
110
|
+
"""Arguments for content correction operations.
|
111
|
+
|
112
|
+
Extends GenerateKwargs with parameters for correcting content based on
|
113
|
+
specific criteria and templates.
|
114
|
+
"""
|
115
|
+
|
116
|
+
reference: str
|
117
|
+
supervisor_check: bool
|
118
|
+
|
119
|
+
|
120
|
+
# noinspection PyTypedDict
|
121
|
+
class ChooseKwargs[T](ValidateKwargs[T], total=False):
|
122
|
+
"""Arguments for selection operations.
|
123
|
+
|
124
|
+
Extends GenerateKwargs with parameters for selecting among options,
|
125
|
+
such as the number of items to choose.
|
126
|
+
"""
|
127
|
+
|
128
|
+
k: int
|
129
|
+
|
130
|
+
|
131
|
+
class CacheKwargs(TypedDict, total=False):
|
132
|
+
"""Configuration parameters for the caching system.
|
133
|
+
|
134
|
+
These arguments control the behavior of various caching backends,
|
135
|
+
including in-memory, Redis, S3, and vector database caching options.
|
136
|
+
"""
|
137
|
+
|
138
|
+
mode: CacheMode # when default_on cache is always on, when default_off cache is opt in
|
139
|
+
host: str
|
140
|
+
port: str
|
141
|
+
password: str
|
142
|
+
namespace: str
|
143
|
+
ttl: float
|
144
|
+
default_in_memory_ttl: float
|
145
|
+
default_in_redis_ttl: float
|
146
|
+
similarity_threshold: float
|
147
|
+
supported_call_types: list[CachingSupportedCallTypes]
|
148
|
+
# s3 Bucket, boto3 configuration
|
149
|
+
s3_bucket_name: str
|
150
|
+
s3_region_name: str
|
151
|
+
s3_api_version: str
|
152
|
+
s3_use_ssl: bool
|
153
|
+
s3_verify: bool | str
|
154
|
+
s3_endpoint_url: str
|
155
|
+
s3_aws_access_key_id: str
|
156
|
+
s3_aws_secret_access_key: str
|
157
|
+
s3_aws_session_token: str
|
158
|
+
s3_config: Any
|
159
|
+
s3_path: str
|
160
|
+
redis_semantic_cache_use_async: bool
|
161
|
+
redis_semantic_cache_embedding_model: str
|
162
|
+
redis_flush_size: int
|
163
|
+
redis_startup_nodes: list
|
164
|
+
disk_cache_dir: Any
|
165
|
+
qdrant_api_base: str
|
166
|
+
qdrant_api_key: str
|
167
|
+
qdrant_collection_name: str
|
168
|
+
qdrant_quantization_config: str
|
169
|
+
qdrant_semantic_cache_embedding_model: str
|
@@ -0,0 +1,72 @@
|
|
1
|
+
"""Module that contains the Role class for managing workflows and their event registrations."""
|
2
|
+
|
3
|
+
from typing import Any, Self, Set
|
4
|
+
|
5
|
+
from fabricatio.capabilities.correct import Correct
|
6
|
+
from fabricatio.capabilities.task import HandleTask, ProposeTask
|
7
|
+
from fabricatio.core import env
|
8
|
+
from fabricatio.journal import logger
|
9
|
+
from fabricatio.models.action import WorkFlow
|
10
|
+
from fabricatio.models.events import Event
|
11
|
+
from fabricatio.models.tool import ToolBox
|
12
|
+
from pydantic import Field
|
13
|
+
|
14
|
+
|
15
|
+
class Role(ProposeTask, HandleTask, Correct):
|
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
|
+
"""
|
25
|
+
|
26
|
+
registry: dict[Event | str, WorkFlow] = Field(default_factory=dict)
|
27
|
+
"""The registry of events and workflows."""
|
28
|
+
|
29
|
+
toolboxes: Set[ToolBox] = Field(default_factory=set)
|
30
|
+
"""Collection of tools available to this role."""
|
31
|
+
|
32
|
+
def model_post_init(self, __context: Any) -> None:
|
33
|
+
"""Initialize the role by resolving configurations and registering workflows.
|
34
|
+
|
35
|
+
Args:
|
36
|
+
__context: The context used for initialization
|
37
|
+
"""
|
38
|
+
self.resolve_configuration().register_workflows()
|
39
|
+
|
40
|
+
def register_workflows(self) -> Self:
|
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
|
+
"""
|
46
|
+
for event, workflow in self.registry.items():
|
47
|
+
logger.debug(
|
48
|
+
f"Registering workflow: `{workflow.name}` for event: `{Event.instantiate_from(event).collapse()}`"
|
49
|
+
)
|
50
|
+
env.on(event, workflow.serve)
|
51
|
+
return self
|
52
|
+
|
53
|
+
def resolve_configuration(self) -> Self:
|
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
|
+
"""
|
62
|
+
for workflow in self.registry.values():
|
63
|
+
logger.debug(f"Resolving config for workflow: `{workflow.name}`")
|
64
|
+
(
|
65
|
+
workflow.fallback_to(self)
|
66
|
+
.steps_fallback_to_self()
|
67
|
+
.inject_personality(self.briefing)
|
68
|
+
.supply_tools_from(self)
|
69
|
+
.steps_supply_tools_from_self()
|
70
|
+
)
|
71
|
+
|
72
|
+
return self
|