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.
Files changed (37) hide show
  1. fabricatio/__init__.py +7 -24
  2. fabricatio/_rust.cp312-win_amd64.pyd +0 -0
  3. fabricatio/_rust.pyi +22 -0
  4. fabricatio/actions/article.py +168 -19
  5. fabricatio/actions/article_rag.py +35 -0
  6. fabricatio/actions/output.py +21 -6
  7. fabricatio/actions/rag.py +51 -3
  8. fabricatio/capabilities/correct.py +55 -11
  9. fabricatio/capabilities/rag.py +67 -16
  10. fabricatio/capabilities/rating.py +15 -6
  11. fabricatio/capabilities/review.py +7 -4
  12. fabricatio/capabilities/task.py +5 -5
  13. fabricatio/config.py +29 -21
  14. fabricatio/decorators.py +32 -0
  15. fabricatio/models/action.py +117 -43
  16. fabricatio/models/extra/article_base.py +378 -0
  17. fabricatio/models/extra/article_essence.py +226 -0
  18. fabricatio/models/extra/article_main.py +196 -0
  19. fabricatio/models/extra/article_outline.py +32 -0
  20. fabricatio/models/extra/article_proposal.py +35 -0
  21. fabricatio/models/generic.py +164 -14
  22. fabricatio/models/kwargs_types.py +51 -10
  23. fabricatio/models/role.py +30 -6
  24. fabricatio/models/tool.py +6 -2
  25. fabricatio/models/usages.py +94 -47
  26. fabricatio/models/utils.py +29 -2
  27. fabricatio/parser.py +2 -0
  28. fabricatio/workflows/articles.py +12 -1
  29. fabricatio-0.2.7.data/scripts/tdown.exe +0 -0
  30. fabricatio-0.2.7.dist-info/METADATA +181 -0
  31. fabricatio-0.2.7.dist-info/RECORD +47 -0
  32. {fabricatio-0.2.6.dev1.dist-info → fabricatio-0.2.7.dist-info}/WHEEL +1 -1
  33. fabricatio/models/extra.py +0 -171
  34. fabricatio-0.2.6.dev1.data/scripts/tdown.exe +0 -0
  35. fabricatio-0.2.6.dev1.dist-info/METADATA +0 -312
  36. fabricatio-0.2.6.dev1.dist-info/RECORD +0 -42
  37. {fabricatio-0.2.6.dev1.dist-info → fabricatio-0.2.7.dist-info}/licenses/LICENSE +0 -0
@@ -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 prepend[D: Dict[str, Any]](self, kwargs: D) -> D:
79
- """Prepend the briefing to the system message in the kwargs.
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
- kwargs (Dict[str, Any]): The keyword arguments to modify.
216
+ system_msg_like (str | dict): The system message or a dictionary containing the system message.
83
217
 
84
218
  Returns:
85
- Dict[str, Any]: The modified keyword arguments.
219
+ dict: The system message with the briefing prepended.
86
220
  """
87
- kwargs["system_message"] = f"# your personal briefing: \n{self.briefing}\n" + kwargs.get("system_message", "")
88
- return kwargs
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 | orjson.OPT_SORT_KEYS,
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 (LLMUsage): Another instance from which to copy attribute values.
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 (LLMUsage | Iterable[LLMUsage]): Another instance or iterable of instances from which to copy attribute values.
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 typing import Any, TypedDict
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 CollectionSimpleConfigKwargs(TypedDict, total=False):
10
- """Configuration parameters for a vector collection.
13
+ class CollectionConfigKwargs(TypedDict, total=False):
14
+ """Configuration parameters for a vector collection.
11
15
 
12
- These arguments are typically used when configuring connections to vector databases.
13
- """
16
+ These arguments are typically used when configuring connections to vector databases.
17
+ """
14
18
 
15
- dimension: int | None
16
- timeout: float
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](ValidateKwargs[T], total=False):
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
- topic: str
95
- criteria: set[str]
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
- """ The registry of events and workflows."""
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
- """Register the workflows in the role to the event bus."""
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 the workflows in the role to the event bus."""
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
- """Resolve the configuration of the role."""
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(M, module_from_spec(spec=ModuleSpec(name=configs.toolbox.tool_module_name, loader=None)))
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(M,module_from_spec(spec=ModuleSpec(name=configs.toolbox.data_module_name, loader=None)))
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)