fabricatio 0.3.13__cp312-cp312-win_amd64.whl → 0.3.14__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.
Files changed (48) hide show
  1. fabricatio/__init__.py +6 -13
  2. fabricatio/actions/article.py +87 -50
  3. fabricatio/actions/article_rag.py +59 -68
  4. fabricatio/actions/output.py +58 -24
  5. fabricatio/actions/rag.py +2 -3
  6. fabricatio/capabilities/advanced_judge.py +4 -7
  7. fabricatio/capabilities/advanced_rag.py +2 -1
  8. fabricatio/capabilities/censor.py +5 -4
  9. fabricatio/capabilities/check.py +27 -27
  10. fabricatio/capabilities/correct.py +22 -22
  11. fabricatio/capabilities/extract.py +33 -33
  12. fabricatio/capabilities/persist.py +103 -0
  13. fabricatio/capabilities/propose.py +2 -2
  14. fabricatio/capabilities/rag.py +11 -10
  15. fabricatio/capabilities/rating.py +66 -70
  16. fabricatio/capabilities/review.py +12 -11
  17. fabricatio/capabilities/task.py +19 -18
  18. fabricatio/decorators.py +11 -9
  19. fabricatio/{core.py → emitter.py} +17 -19
  20. fabricatio/journal.py +2 -4
  21. fabricatio/models/action.py +15 -32
  22. fabricatio/models/extra/aricle_rag.py +13 -8
  23. fabricatio/models/extra/article_base.py +57 -25
  24. fabricatio/models/extra/article_essence.py +2 -1
  25. fabricatio/models/extra/article_main.py +24 -22
  26. fabricatio/models/extra/article_outline.py +2 -1
  27. fabricatio/models/extra/article_proposal.py +1 -1
  28. fabricatio/models/extra/rag.py +2 -2
  29. fabricatio/models/extra/rule.py +2 -1
  30. fabricatio/models/generic.py +55 -137
  31. fabricatio/models/kwargs_types.py +1 -54
  32. fabricatio/models/role.py +49 -28
  33. fabricatio/models/task.py +3 -4
  34. fabricatio/models/tool.py +6 -7
  35. fabricatio/models/usages.py +146 -149
  36. fabricatio/parser.py +59 -99
  37. fabricatio/rust.cp312-win_amd64.pyd +0 -0
  38. fabricatio/rust.pyi +58 -81
  39. fabricatio/utils.py +63 -162
  40. fabricatio-0.3.14.data/scripts/tdown.exe +0 -0
  41. fabricatio-0.3.14.data/scripts/ttm.exe +0 -0
  42. {fabricatio-0.3.13.dist-info → fabricatio-0.3.14.dist-info}/METADATA +10 -13
  43. fabricatio-0.3.14.dist-info/RECORD +64 -0
  44. {fabricatio-0.3.13.dist-info → fabricatio-0.3.14.dist-info}/WHEEL +1 -1
  45. fabricatio-0.3.13.data/scripts/tdown.exe +0 -0
  46. fabricatio-0.3.13.data/scripts/ttm.exe +0 -0
  47. fabricatio-0.3.13.dist-info/RECORD +0 -63
  48. {fabricatio-0.3.13.dist-info → fabricatio-0.3.14.dist-info}/licenses/LICENSE +0 -0
@@ -1,18 +1,19 @@
1
1
  """This module defines generic classes for models in the Fabricatio library, providing a foundation for various model functionalities."""
2
2
 
3
3
  from abc import ABC, abstractmethod
4
- from datetime import datetime
5
4
  from pathlib import Path
6
- from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Self, Type, Union, final, overload
5
+ from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Self, Sequence, Type, Union, final, overload
7
6
 
8
7
  import ujson
8
+ from fabricatio.fs import dump_text
9
+ from fabricatio.fs.readers import safe_text_read
10
+ from fabricatio.journal import logger
9
11
  from fabricatio.rust import CONFIG, TEMPLATE_MANAGER, blake3_hash, detect_language
10
- from litellm.utils import token_counter
12
+ from fabricatio.utils import ok
11
13
  from pydantic import (
12
14
  BaseModel,
13
15
  ConfigDict,
14
16
  Field,
15
- HttpUrl,
16
17
  NonNegativeFloat,
17
18
  PositiveFloat,
18
19
  PositiveInt,
@@ -21,14 +22,8 @@ from pydantic import (
21
22
  )
22
23
  from pydantic.json_schema import GenerateJsonSchema, JsonSchemaValue
23
24
 
24
- from fabricatio.fs import dump_text
25
- from fabricatio.fs.readers import safe_text_read
26
- from fabricatio.journal import logger
27
- from fabricatio.parser import JsonCapture
28
- from fabricatio.utils import ok
29
25
 
30
-
31
- class Base(BaseModel):
26
+ class Base(BaseModel, ABC):
32
27
  """Base class for all models with Pydantic configuration.
33
28
 
34
29
  This class sets up the basic Pydantic configuration for all models in the Fabricatio library.
@@ -39,7 +34,7 @@ class Base(BaseModel):
39
34
  model_config = ConfigDict(use_attribute_docstrings=True)
40
35
 
41
36
 
42
- class Display(Base):
37
+ class Display(Base, ABC):
43
38
  """Class that provides formatted JSON representation utilities.
44
39
 
45
40
  Provides methods to generate both pretty-printed and compact JSON representations of the model.
@@ -74,13 +69,13 @@ class Display(Base):
74
69
  str: Combined display output with boundary markers
75
70
  """
76
71
  return (
77
- "--- Start of Extra Info Sequence ---"
78
- + "\n".join(d.compact() if compact else d.display() for d in seq)
79
- + "--- End of Extra Info Sequence ---"
72
+ "--- Start of Extra Info Sequence ---"
73
+ + "\n".join(d.compact() if compact else d.display() for d in seq)
74
+ + "--- End of Extra Info Sequence ---"
80
75
  )
81
76
 
82
77
 
83
- class Named(Base):
78
+ class Named(Base, ABC):
84
79
  """Class that includes a name attribute.
85
80
 
86
81
  This class adds a name attribute to models, which is intended to be a unique identifier.
@@ -90,7 +85,7 @@ class Named(Base):
90
85
  """The name of this object,briefly and conclusively."""
91
86
 
92
87
 
93
- class Described(Base):
88
+ class Described(Base, ABC):
94
89
  """Class that includes a description attribute.
95
90
 
96
91
  This class adds a description attribute to models, providing additional context or information.
@@ -103,19 +98,24 @@ class Described(Base):
103
98
  this object's intent and application."""
104
99
 
105
100
 
106
- class Titled(Base):
101
+ class Titled(Base, ABC):
107
102
  """Class that includes a title attribute."""
108
103
 
109
104
  title: str
110
105
  """The title of this object, make it professional and concise.No prefixed heading number should be included."""
111
106
 
112
107
 
113
- class WordCount(Base):
108
+ class WordCount(Base, ABC):
114
109
  """Class that includes a word count attribute."""
115
110
 
116
111
  expected_word_count: int
117
112
  """Expected word count of this research component."""
118
113
 
114
+ @property
115
+ def exact_word_count(self) -> int:
116
+ """Get the exact word count of this research component."""
117
+ raise NotImplementedError(f"`exact_word_count` is not implemented for {self.__class__.__name__}")
118
+
119
119
 
120
120
  class FromMapping:
121
121
  """Class that provides a method to generate a list of objects from a mapping."""
@@ -126,6 +126,15 @@ class FromMapping:
126
126
  """Generate a list of objects from a mapping."""
127
127
 
128
128
 
129
+ class FromSequence:
130
+ """Class that provides a method to generate a list of objects from a sequence."""
131
+
132
+ @classmethod
133
+ @abstractmethod
134
+ def from_sequence[S](cls: S, sequence: Sequence[Any], **kwargs: Any) -> List[S]:
135
+ """Generate a list of objects from a sequence."""
136
+
137
+
129
138
  class AsPrompt:
130
139
  """Class that provides a method to generate a prompt from the model.
131
140
 
@@ -155,7 +164,7 @@ class AsPrompt:
155
164
  """
156
165
 
157
166
 
158
- class WithRef[T](Base):
167
+ class WithRef[T](Base, ABC):
159
168
  """Class that provides a reference to another object.
160
169
 
161
170
  This class manages a reference to another object, allowing for easy access and updates.
@@ -178,16 +187,13 @@ class WithRef[T](Base):
178
187
  )
179
188
 
180
189
  @overload
181
- def update_ref[S: WithRef](self: S, reference: T) -> S:
182
- ...
190
+ def update_ref[S: WithRef](self: S, reference: T) -> S: ...
183
191
 
184
192
  @overload
185
- def update_ref[S: WithRef](self: S, reference: "WithRef[T]") -> S:
186
- ...
193
+ def update_ref[S: WithRef](self: S, reference: "WithRef[T]") -> S: ...
187
194
 
188
195
  @overload
189
- def update_ref[S: WithRef](self: S, reference: None = None) -> S:
190
- ...
196
+ def update_ref[S: WithRef](self: S, reference: None = None) -> S: ...
191
197
 
192
198
  def update_ref[S: WithRef](self: S, reference: Union[T, "WithRef[T]", None] = None) -> S:
193
199
  """Update the reference of the object.
@@ -205,97 +211,6 @@ class WithRef[T](Base):
205
211
  return self
206
212
 
207
213
 
208
- class PersistentAble(Base):
209
- """Class providing file persistence capabilities.
210
-
211
- Enables saving model instances to disk with timestamped filenames and loading from persisted files.
212
- Implements basic versioning through filename hashing and timestamping.
213
- """
214
-
215
- def persist(self, path: str | Path) -> Self:
216
- """Save model instance to disk with versioned filename.
217
-
218
- Args:
219
- path (str | Path): Target directory or file path. If directory, filename is auto-generated.
220
-
221
- Returns:
222
- Self: Current instance for method chaining
223
-
224
- Notes:
225
- - Filename format: <ClassName>_<YYYYMMDD_HHMMSS>_<6-char_hash>.json
226
- - Hash generated from JSON content ensures uniqueness
227
- """
228
- p = Path(path)
229
- out = self.model_dump_json(indent=1, by_alias=True)
230
-
231
- # Generate a timestamp in the format YYYYMMDD_HHMMSS
232
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
233
-
234
- # Generate the hash
235
- file_hash = blake3_hash(out.encode())[:6]
236
-
237
- # Construct the file name with timestamp and hash
238
- file_name = f"{self.__class__.__name__}_{timestamp}_{file_hash}.json"
239
-
240
- if p.is_dir():
241
- p.joinpath(file_name).write_text(out, encoding="utf-8")
242
- else:
243
- p.mkdir(exist_ok=True, parents=True)
244
- p.write_text(out, encoding="utf-8")
245
-
246
- logger.info(f"Persisted `{self.__class__.__name__}` to {p.as_posix()}")
247
- return self
248
-
249
- @classmethod
250
- def from_latest_persistent(cls, dir_path: str | Path) -> Optional[Self]:
251
- """Load most recent persisted instance from directory.
252
-
253
- Args:
254
- dir_path (str | Path): Directory containing persisted files
255
-
256
- Returns:
257
- Self: Most recently modified instance
258
-
259
- Raises:
260
- NotADirectoryError: If path is not a valid directory
261
- FileNotFoundError: If no matching files found
262
- """
263
- dir_path = Path(dir_path)
264
- if not dir_path.is_dir():
265
- return None
266
-
267
- pattern = f"{cls.__name__}_*.json"
268
- files = list(dir_path.glob(pattern))
269
-
270
- if not files:
271
- return None
272
-
273
- def _get_timestamp(file_path: Path) -> datetime:
274
- stem = file_path.stem
275
- parts = stem.split("_")
276
- return datetime.strptime(f"{parts[1]}_{parts[2]}", "%Y%m%d_%H%M%S")
277
-
278
- files.sort(key=lambda f: _get_timestamp(f), reverse=True)
279
-
280
- return cls.from_persistent(files.pop(0))
281
-
282
- @classmethod
283
- def from_persistent(cls, path: str | Path) -> Self:
284
- """Load an instance from a specific persisted file.
285
-
286
- Args:
287
- path (str | Path): Path to the JSON file.
288
-
289
- Returns:
290
- Self: The loaded instance from the file.
291
-
292
- Raises:
293
- FileNotFoundError: If the specified file does not exist.
294
- ValueError: If the file content is invalid for the model.
295
- """
296
- return cls.model_validate_json(safe_text_read(path))
297
-
298
-
299
214
  class Language:
300
215
  """Class that provides a language attribute."""
301
216
 
@@ -311,7 +226,7 @@ class Language:
311
226
  raise RuntimeError(f"Cannot determine language! class that not support language: {self.__class__.__name__}")
312
227
 
313
228
 
314
- class ModelHash(Base):
229
+ class ModelHash(Base, ABC):
315
230
  """Class that provides a hash value for the object.
316
231
 
317
232
  This class includes a method to calculate a hash value for the object based on its JSON representation.
@@ -326,7 +241,7 @@ class ModelHash(Base):
326
241
  return hash(self.model_dump_json())
327
242
 
328
243
 
329
- class UpdateFrom:
244
+ class UpdateFrom(ABC):
330
245
  """Class that provides a method to update the object from another object.
331
246
 
332
247
  This class includes methods to update the current object with the attributes of another object.
@@ -375,7 +290,7 @@ class UpdateFrom:
375
290
  return self.update_pre_check(other).update_from_inner(other)
376
291
 
377
292
 
378
- class Introspect:
293
+ class Introspect(ABC):
379
294
  """Class that provides a method to introspect the object.
380
295
 
381
296
  This class includes a method to perform internal introspection of the object.
@@ -390,7 +305,7 @@ class Introspect:
390
305
  """
391
306
 
392
307
 
393
- class WithBriefing(Named, Described):
308
+ class WithBriefing(Named, Described, ABC):
394
309
  """Class that provides a briefing based on the name and description.
395
310
 
396
311
  This class combines the name and description attributes to provide a brief summary of the object.
@@ -425,7 +340,7 @@ class UnsortGenerate(GenerateJsonSchema):
425
340
  return value
426
341
 
427
342
 
428
- class WithFormatedJsonSchema(Base):
343
+ class WithFormatedJsonSchema(Base, ABC):
429
344
  """Class that provides a formatted JSON schema of the model.
430
345
 
431
346
  This class includes a method to generate a formatted JSON schema of the model.
@@ -443,7 +358,7 @@ class WithFormatedJsonSchema(Base):
443
358
  )
444
359
 
445
360
 
446
- class CreateJsonObjPrompt(WithFormatedJsonSchema):
361
+ class CreateJsonObjPrompt(WithFormatedJsonSchema, ABC):
447
362
  """Class that provides a prompt for creating a JSON object.
448
363
 
449
364
  This class includes a method to create a prompt for creating a JSON object based on the model's schema and a requirement.
@@ -481,7 +396,7 @@ class CreateJsonObjPrompt(WithFormatedJsonSchema):
481
396
  ]
482
397
 
483
398
 
484
- class InstantiateFromString(Base):
399
+ class InstantiateFromString(Base, ABC):
485
400
  """Class that provides a method to instantiate the class from a string.
486
401
 
487
402
  This class includes a method to instantiate the class from a JSON string representation.
@@ -497,19 +412,21 @@ class InstantiateFromString(Base):
497
412
  Returns:
498
413
  Self | None: The instance of the class or None if the string is not valid.
499
414
  """
415
+ from fabricatio.parser import JsonCapture
416
+
500
417
  obj = JsonCapture.convert_with(string, cls.model_validate_json)
501
418
  logger.debug(f"Instantiate `{cls.__name__}` from string, {'Failed' if obj is None else 'Success'}.")
502
419
  return obj
503
420
 
504
421
 
505
- class ProposedAble(CreateJsonObjPrompt, InstantiateFromString):
422
+ class ProposedAble(CreateJsonObjPrompt, InstantiateFromString, ABC):
506
423
  """Class that provides a method to propose a JSON object based on the requirement.
507
424
 
508
425
  This class combines the functionality to create a prompt for a JSON object and instantiate it from a string.
509
426
  """
510
427
 
511
428
 
512
- class SketchedAble(ProposedAble, Display):
429
+ class SketchedAble(ProposedAble, Display, ABC):
513
430
  """Class that provides a method to scratch the object.
514
431
 
515
432
  This class combines the functionality to propose a JSON object, instantiate it from a string, and display it.
@@ -523,7 +440,7 @@ class ProposedUpdateAble(SketchedAble, UpdateFrom, ABC):
523
440
  """
524
441
 
525
442
 
526
- class FinalizedDumpAble(Base):
443
+ class FinalizedDumpAble(Base, ABC):
527
444
  """Class that provides a method to finalize the dump of the object.
528
445
 
529
446
  This class includes methods to finalize the JSON representation of the object and dump it to a file.
@@ -550,7 +467,7 @@ class FinalizedDumpAble(Base):
550
467
  return self
551
468
 
552
469
 
553
- class WithDependency(Base):
470
+ class WithDependency(Base, ABC):
554
471
  """Class that manages file dependencies.
555
472
 
556
473
  This class includes methods to manage file dependencies required for reading or writing.
@@ -643,7 +560,7 @@ class WithDependency(Base):
643
560
  )
644
561
 
645
562
 
646
- class Vectorizable:
563
+ class Vectorizable(ABC):
647
564
  """Class that prepares the vectorization of the model.
648
565
 
649
566
  This class includes methods to prepare the model for vectorization, ensuring it fits within a specified token length.
@@ -666,6 +583,8 @@ class Vectorizable:
666
583
  Raises:
667
584
  ValueError: If the chunk exceeds the maximum sequence length.
668
585
  """
586
+ from litellm.utils import token_counter
587
+
669
588
  max_length = max_length or CONFIG.embedding.max_sequence_length
670
589
  chunk = self._prepare_vectorization_inner()
671
590
  if max_length and (length := token_counter(text=chunk)) > max_length:
@@ -674,14 +593,14 @@ class Vectorizable:
674
593
  return chunk
675
594
 
676
595
 
677
- class ScopedConfig(Base):
596
+ class ScopedConfig(Base, ABC):
678
597
  """Configuration holder with hierarchical fallback mechanism.
679
598
 
680
599
  Manages LLM, embedding, and vector database configurations with fallback logic.
681
600
  Allows configuration values to be overridden in a hierarchical manner.
682
601
  """
683
602
 
684
- llm_api_endpoint: Optional[HttpUrl] = None
603
+ llm_api_endpoint: Optional[str] = None
685
604
  """The OpenAI API endpoint."""
686
605
 
687
606
  llm_api_key: Optional[SecretStr] = None
@@ -726,7 +645,7 @@ class ScopedConfig(Base):
726
645
  llm_frequency_penalty: Optional[PositiveFloat] = None
727
646
  """The frequency penalty of the LLM model."""
728
647
 
729
- embedding_api_endpoint: Optional[HttpUrl] = None
648
+ embedding_api_endpoint: Optional[str] = None
730
649
  """The OpenAI API endpoint."""
731
650
 
732
651
  embedding_api_key: Optional[SecretStr] = None
@@ -747,7 +666,7 @@ class ScopedConfig(Base):
747
666
  embedding_caching: Optional[bool] = False
748
667
  """Whether to cache the embedding result."""
749
668
 
750
- milvus_uri: Optional[HttpUrl] = Field(default=None)
669
+ milvus_uri: Optional[str] = Field(default=None)
751
670
  """The URI of the Milvus server."""
752
671
 
753
672
  milvus_token: Optional[SecretStr] = Field(default=None)
@@ -807,7 +726,7 @@ class ScopedConfig(Base):
807
726
  return self
808
727
 
809
728
 
810
- class Patch[T](ProposedAble):
729
+ class Patch[T](ProposedAble, ABC):
811
730
  """Base class for patches.
812
731
 
813
732
  This class provides a base implementation for patches that can be applied to other objects.
@@ -854,15 +773,14 @@ class Patch[T](ProposedAble):
854
773
  # copy the desc info of each corresponding fields from `ref_cls`
855
774
  for field_name in [f for f in cls.model_fields if f in ref_cls.model_fields]:
856
775
  my_schema["properties"][field_name]["description"] = (
857
- ref_cls.model_fields[field_name].description or my_schema["properties"][field_name][
858
- "description"]
776
+ ref_cls.model_fields[field_name].description or my_schema["properties"][field_name]["description"]
859
777
  )
860
778
  my_schema["description"] = ref_cls.__doc__
861
779
 
862
780
  return ujson.dumps(my_schema, indent=2, ensure_ascii=False, sort_keys=False)
863
781
 
864
782
 
865
- class SequencePatch[T](ProposedUpdateAble):
783
+ class SequencePatch[T](ProposedUpdateAble, ABC):
866
784
  """Base class for patches.
867
785
 
868
786
  This class provides a base implementation for patches that can be applied to sequences of objects.
@@ -1,9 +1,6 @@
1
1
  """This module contains the types for the keyword arguments of the methods in the models module."""
2
2
 
3
- from typing import Any, Dict, List, Literal, NotRequired, Optional, Required, TypedDict
4
-
5
- from litellm.caching.caching import CacheMode
6
- from litellm.types.caching import CachingSupportedCallTypes
3
+ from typing import Dict, List, NotRequired, Optional, Required, TypedDict
7
4
 
8
5
 
9
6
  class ChunkKwargs(TypedDict):
@@ -70,7 +67,6 @@ class ValidateKwargs[T](GenerateKwargs, total=False):
70
67
  max_validations: int
71
68
 
72
69
 
73
-
74
70
  class CompositeScoreKwargs(ValidateKwargs[List[Dict[str, float]]], total=False):
75
71
  """Arguments for composite score generation operations.
76
72
 
@@ -123,52 +119,3 @@ class ChooseKwargs[T](ValidateKwargs[T], total=False):
123
119
  """
124
120
 
125
121
  k: int
126
-
127
-
128
- class CacheKwargs(TypedDict, total=False):
129
- """Configuration parameters for the caching system.
130
-
131
- These arguments control the behavior of various caching backends,
132
- including in-memory, Redis, S3, and vector database caching options.
133
- """
134
-
135
- mode: CacheMode # when default_on cache is always on, when default_off cache is opt in
136
- host: str
137
- port: str
138
- password: str
139
- namespace: str
140
- ttl: float
141
- default_in_memory_ttl: float
142
- default_in_redis_ttl: float
143
- similarity_threshold: float
144
- supported_call_types: list[CachingSupportedCallTypes]
145
- # s3 Bucket, boto3 configuration
146
- s3_bucket_name: str
147
- s3_region_name: str
148
- s3_api_version: str
149
- s3_use_ssl: bool
150
- s3_verify: bool | str
151
- s3_endpoint_url: str
152
- s3_aws_access_key_id: str
153
- s3_aws_secret_access_key: str
154
- s3_aws_session_token: str
155
- s3_config: Any
156
- s3_path: str
157
- redis_semantic_cache_use_async: bool
158
- redis_semantic_cache_embedding_model: str
159
- redis_flush_size: int
160
- redis_startup_nodes: list
161
- disk_cache_dir: Any
162
- qdrant_api_base: str
163
- qdrant_api_key: str
164
- qdrant_collection_name: str
165
- qdrant_quantization_config: str
166
- qdrant_semantic_cache_embedding_model: str
167
-
168
-
169
- class RerankOptions(TypedDict, total=False):
170
- """Optional keyword arguments for the rerank method."""
171
-
172
- raw_scores: bool
173
- truncate: bool
174
- truncation_direction: Literal["Left", "Right"]
fabricatio/models/role.py CHANGED
@@ -1,46 +1,44 @@
1
1
  """Module that contains the Role class for managing workflows and their event registrations."""
2
2
 
3
- from typing import Any, Self, Set
3
+ from functools import partial
4
+ from typing import Any, Callable, Dict, Self, Type
4
5
 
5
- from fabricatio.rust import Event
6
- from pydantic import Field, ConfigDict
7
-
8
- from fabricatio.capabilities.propose import Propose
9
- from fabricatio.core import env
6
+ from fabricatio.emitter import env
10
7
  from fabricatio.journal import logger
11
8
  from fabricatio.models.action import WorkFlow
12
9
  from fabricatio.models.generic import WithBriefing
13
- from fabricatio.models.tool import ToolBox
14
- from fabricatio.models.usages import ToolBoxUsage
10
+ from fabricatio.rust import Event
11
+ from fabricatio.utils import is_subclass_of_base
12
+ from pydantic import ConfigDict, Field
13
+
14
+ is_toolbox_usage = partial(is_subclass_of_base, base_module="fabricatio.models.usages", base_name="ToolBoxUsage")
15
+ is_scoped_config = partial(is_subclass_of_base, base_module="fabricatio.models.generic", base_name="ScopedConfig")
15
16
 
16
17
 
17
- class Role(WithBriefing, Propose, ToolBoxUsage):
18
+ class Role(WithBriefing):
18
19
  """Class that represents a role with a registry of events and workflows.
19
20
 
20
21
  A Role serves as a container for workflows, managing their registration to events
21
22
  and providing them with shared configuration like tools and personality.
22
-
23
- Attributes:
24
- registry: Mapping of events to workflows that handle them
25
- toolboxes: Set of toolboxes available to this role and its workflows
26
23
  """
27
- # fixme: not use arbitrary_types_allowed
24
+
28
25
  model_config = ConfigDict(use_attribute_docstrings=True, arbitrary_types_allowed=True)
26
+ name: str = ""
27
+ """The name of the role."""
29
28
  description: str = ""
30
29
  """A brief description of the role's responsibilities and capabilities."""
31
30
 
32
- registry: dict[Event | str, WorkFlow] = Field(default_factory=dict)
31
+ registry: Dict[Event, WorkFlow] = Field(default_factory=dict)
33
32
  """The registry of events and workflows."""
34
33
 
35
- toolboxes: Set[ToolBox] = Field(default_factory=set)
36
- """Collection of tools available to this role."""
37
-
38
34
  def model_post_init(self, __context: Any) -> None:
39
35
  """Initialize the role by resolving configurations and registering workflows.
40
36
 
41
37
  Args:
42
38
  __context: The context used for initialization
43
39
  """
40
+ self.name = self.name or self.__class__.__name__
41
+
44
42
  self.resolve_configuration().register_workflows()
45
43
 
46
44
  def register_workflows(self) -> Self:
@@ -50,9 +48,7 @@ class Role(WithBriefing, Propose, ToolBoxUsage):
50
48
  Self: The role instance for method chaining
51
49
  """
52
50
  for event, workflow in self.registry.items():
53
- logger.debug(
54
- f"Registering workflow: `{workflow.name}` for event: `{Event.instantiate_from(event).collapse()}`"
55
- )
51
+ logger.debug(f"Registering workflow: `{workflow.name}` for event: `{event.collapse()}`")
56
52
  env.on(event, workflow.serve)
57
53
  return self
58
54
 
@@ -67,12 +63,37 @@ class Role(WithBriefing, Propose, ToolBoxUsage):
67
63
  """
68
64
  for workflow in self.registry.values():
69
65
  logger.debug(f"Resolving config for workflow: `{workflow.name}`")
70
- (
71
- workflow.fallback_to(self)
72
- .steps_fallback_to_self()
73
- .inject_personality(self.briefing)
74
- .supply_tools_from(self)
75
- .steps_supply_tools_from_self()
66
+ self._configure_scoped_config(workflow)
67
+ self._configure_toolbox_usage(workflow)
68
+ workflow.inject_personality(self.briefing)
69
+ return self
70
+
71
+ def _propagate_config(
72
+ self,
73
+ workflow: WorkFlow,
74
+ has_capability: Callable[[Type], bool],
75
+ config_method_name: str,
76
+ capability_description: str,
77
+ ) -> None:
78
+ """Propagates configuration to workflow and its actions if they have a given capability."""
79
+ if not has_capability(self.__class__):
80
+ return
81
+
82
+ config_source_for_actions = self
83
+ if has_capability(workflow.__class__):
84
+ logger.debug(
85
+ f"Configuring {capability_description} inherited from `{self.name}` for workflow: `{workflow.name}`"
76
86
  )
87
+ getattr(workflow, config_method_name)(self)
88
+ config_source_for_actions = workflow
77
89
 
78
- return self
90
+ for action in (act for act in workflow.iter_actions() if has_capability(act.__class__)):
91
+ getattr(action, config_method_name)(config_source_for_actions)
92
+
93
+ def _configure_scoped_config(self, workflow: WorkFlow) -> None:
94
+ """Configure scoped configuration for workflow and its actions."""
95
+ self._propagate_config(workflow, is_scoped_config, "fallback_to", "scoped config")
96
+
97
+ def _configure_toolbox_usage(self, workflow: WorkFlow) -> None:
98
+ """Configure toolbox usage for workflow and its actions."""
99
+ self._propagate_config(workflow, is_toolbox_usage, "supply_tools_from", "toolbox usage")
fabricatio/models/task.py CHANGED
@@ -6,12 +6,11 @@ It includes methods to manage the task's lifecycle, such as starting, finishing,
6
6
  from asyncio import Queue
7
7
  from typing import Any, Dict, List, Optional, Self, Union
8
8
 
9
- from fabricatio.rust import CONFIG, TEMPLATE_MANAGER, Event, TaskStatus
10
- from pydantic import Field, PrivateAttr
11
-
12
- from fabricatio.core import env
9
+ from fabricatio.emitter import env
13
10
  from fabricatio.journal import logger
14
11
  from fabricatio.models.generic import ProposedAble, WithBriefing, WithDependency
12
+ from fabricatio.rust import CONFIG, TEMPLATE_MANAGER, Event, TaskStatus
13
+ from pydantic import Field, PrivateAttr
15
14
 
16
15
  type EventLike = Union[str, Event, List[str]]
17
16
 
fabricatio/models/tool.py CHANGED
@@ -10,12 +10,11 @@ from inspect import iscoroutinefunction, signature
10
10
  from types import CodeType, ModuleType
11
11
  from typing import Any, Callable, Dict, List, Optional, Self, cast, overload
12
12
 
13
- from fabricatio.rust import CONFIG
14
- from pydantic import BaseModel, ConfigDict, Field
15
-
16
13
  from fabricatio.decorators import logging_execution_info, use_temp_module
17
14
  from fabricatio.journal import logger
18
- from fabricatio.models.generic import WithBriefing
15
+ from fabricatio.models.generic import Base, WithBriefing
16
+ from fabricatio.rust import CONFIG
17
+ from pydantic import Field
19
18
 
20
19
 
21
20
  class Tool[**P, R](WithBriefing):
@@ -182,7 +181,7 @@ class ToolBox(WithBriefing):
182
181
  return hash(self.briefing)
183
182
 
184
183
 
185
- class ToolExecutor(BaseModel):
184
+ class ToolExecutor(Base):
186
185
  """A class representing a tool executor with a sequence of tools to execute.
187
186
 
188
187
  This class manages a sequence of tools and provides methods to inject tools and data into a module, execute the tools,
@@ -192,7 +191,7 @@ class ToolExecutor(BaseModel):
192
191
  candidates (List[Tool]): The sequence of tools to execute.
193
192
  data (Dict[str, Any]): The data that could be used when invoking the tools.
194
193
  """
195
- model_config = ConfigDict(use_attribute_docstrings=True)
194
+
196
195
  candidates: List[Tool] = Field(default_factory=list, frozen=True)
197
196
  """The sequence of tools to execute."""
198
197
 
@@ -230,7 +229,7 @@ class ToolExecutor(BaseModel):
230
229
  M: The module with injected data.
231
230
  """
232
231
  module = module or cast(
233
- 'M', module_from_spec(spec=ModuleSpec(name=CONFIG.toolbox.data_module_name, loader=None))
232
+ "M", module_from_spec(spec=ModuleSpec(name=CONFIG.toolbox.data_module_name, loader=None))
234
233
  )
235
234
  for key, value in self.data.items():
236
235
  logger.debug(f"Injecting data: {key}")