fabricatio 0.2.8.dev4__cp312-cp312-win_amd64.whl → 0.2.9__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 (46) hide show
  1. fabricatio/__init__.py +4 -11
  2. fabricatio/actions/__init__.py +1 -0
  3. fabricatio/actions/article.py +98 -110
  4. fabricatio/actions/article_rag.py +15 -10
  5. fabricatio/actions/output.py +60 -4
  6. fabricatio/actions/rag.py +2 -1
  7. fabricatio/actions/rules.py +72 -0
  8. fabricatio/capabilities/__init__.py +1 -0
  9. fabricatio/capabilities/censor.py +23 -6
  10. fabricatio/capabilities/check.py +46 -27
  11. fabricatio/capabilities/correct.py +35 -16
  12. fabricatio/capabilities/rag.py +5 -4
  13. fabricatio/capabilities/rating.py +56 -49
  14. fabricatio/capabilities/review.py +1 -1
  15. fabricatio/capabilities/task.py +2 -1
  16. fabricatio/config.py +5 -3
  17. fabricatio/fs/readers.py +20 -1
  18. fabricatio/models/action.py +59 -36
  19. fabricatio/models/extra/__init__.py +1 -0
  20. fabricatio/models/extra/advanced_judge.py +4 -4
  21. fabricatio/models/extra/article_base.py +124 -61
  22. fabricatio/models/extra/article_main.py +100 -17
  23. fabricatio/models/extra/article_outline.py +2 -3
  24. fabricatio/models/extra/article_proposal.py +15 -14
  25. fabricatio/models/extra/patches.py +17 -4
  26. fabricatio/models/extra/problem.py +31 -23
  27. fabricatio/models/extra/rule.py +39 -8
  28. fabricatio/models/generic.py +369 -78
  29. fabricatio/models/task.py +1 -1
  30. fabricatio/models/tool.py +149 -14
  31. fabricatio/models/usages.py +46 -42
  32. fabricatio/parser.py +5 -5
  33. fabricatio/rust.cp312-win_amd64.pyd +0 -0
  34. fabricatio/{_rust.pyi → rust.pyi} +42 -4
  35. fabricatio/{_rust_instances.py → rust_instances.py} +1 -1
  36. fabricatio/utils.py +5 -5
  37. fabricatio/workflows/__init__.py +1 -0
  38. fabricatio/workflows/articles.py +3 -5
  39. fabricatio-0.2.9.data/scripts/tdown.exe +0 -0
  40. {fabricatio-0.2.8.dev4.dist-info → fabricatio-0.2.9.dist-info}/METADATA +1 -1
  41. fabricatio-0.2.9.dist-info/RECORD +61 -0
  42. fabricatio/_rust.cp312-win_amd64.pyd +0 -0
  43. fabricatio-0.2.8.dev4.data/scripts/tdown.exe +0 -0
  44. fabricatio-0.2.8.dev4.dist-info/RECORD +0 -56
  45. {fabricatio-0.2.8.dev4.dist-info → fabricatio-0.2.9.dist-info}/WHEEL +0 -0
  46. {fabricatio-0.2.8.dev4.dist-info → fabricatio-0.2.9.dist-info}/licenses/LICENSE +0 -0
fabricatio/models/task.py CHANGED
@@ -6,13 +6,13 @@ 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, List, Optional, Self
8
8
 
9
- from fabricatio._rust_instances import TEMPLATE_MANAGER
10
9
  from fabricatio.config import configs
11
10
  from fabricatio.core import env
12
11
  from fabricatio.journal import logger
13
12
  from fabricatio.models.events import Event, EventLike
14
13
  from fabricatio.models.generic import ProposedAble, WithBriefing, WithDependency
15
14
  from fabricatio.models.utils import TaskStatus
15
+ from fabricatio.rust_instances import TEMPLATE_MANAGER
16
16
  from pydantic import Field, PrivateAttr
17
17
 
18
18
 
fabricatio/models/tool.py CHANGED
@@ -1,4 +1,8 @@
1
- """A module for defining tools and toolboxes."""
1
+ """A module for defining tools and toolboxes.
2
+
3
+ This module provides classes for defining tools and toolboxes, which can be used to manage and execute callable functions
4
+ with additional functionalities such as logging, execution info, and briefing.
5
+ """
2
6
 
3
7
  from importlib.machinery import ModuleSpec
4
8
  from importlib.util import module_from_spec
@@ -14,7 +18,16 @@ from pydantic import BaseModel, ConfigDict, Field
14
18
 
15
19
 
16
20
  class Tool[**P, R](WithBriefing):
17
- """A class representing a tool with a callable source function."""
21
+ """A class representing a tool with a callable source function.
22
+
23
+ This class encapsulates a callable function (source) and provides methods to invoke it, log its execution, and generate
24
+ a brief description (briefing) of the tool.
25
+
26
+ Attributes:
27
+ name (str): The name of the tool.
28
+ description (str): The description of the tool.
29
+ source (Callable[P, R]): The source function of the tool.
30
+ """
18
31
 
19
32
  name: str = Field(default="")
20
33
  """The name of the tool."""
@@ -26,7 +39,16 @@ class Tool[**P, R](WithBriefing):
26
39
  """The source function of the tool."""
27
40
 
28
41
  def model_post_init(self, __context: Any) -> None:
29
- """Initialize the tool with a name and a source function."""
42
+ """Initialize the tool with a name and a source function.
43
+
44
+ This method sets the tool's name and description based on the source function's name and docstring.
45
+
46
+ Args:
47
+ __context (Any): Context passed during model initialization.
48
+
49
+ Raises:
50
+ RuntimeError: If the tool does not have a source function.
51
+ """
30
52
  self.name = self.name or self.source.__name__
31
53
 
32
54
  if not self.name:
@@ -36,7 +58,17 @@ class Tool[**P, R](WithBriefing):
36
58
  self.description = self.description.strip()
37
59
 
38
60
  def invoke(self, *args: P.args, **kwargs: P.kwargs) -> R:
39
- """Invoke the tool's source function with the provided arguments."""
61
+ """Invoke the tool's source function with the provided arguments.
62
+
63
+ This method logs the invocation of the tool and then calls the source function with the given arguments.
64
+
65
+ Args:
66
+ *args (P.args): Positional arguments to be passed to the source function.
67
+ **kwargs (P.kwargs): Keyword arguments to be passed to the source function.
68
+
69
+ Returns:
70
+ R: The result of the source function.
71
+ """
40
72
  logger.info(f"Invoking tool: {self.name}")
41
73
  return self.source(*args, **kwargs)
42
74
 
@@ -44,6 +76,8 @@ class Tool[**P, R](WithBriefing):
44
76
  def briefing(self) -> str:
45
77
  """Return a brief description of the tool.
46
78
 
79
+ This method generates a brief description of the tool, including its name, signature, and description.
80
+
47
81
  Returns:
48
82
  str: A brief description of the tool.
49
83
  """
@@ -59,7 +93,18 @@ def _desc_wrapper(desc: str) -> str:
59
93
 
60
94
 
61
95
  class ToolBox(WithBriefing):
62
- """A class representing a collection of tools."""
96
+ """A class representing a collection of tools.
97
+
98
+ This class manages a list of tools and provides methods to add tools, retrieve tools by name, and generate a brief
99
+ description (briefing) of the toolbox.
100
+
101
+ Attributes:
102
+ description (str): The description of the toolbox.
103
+ tools (List[Tool]): A list of tools in the toolbox.
104
+ """
105
+
106
+ description: str = ""
107
+ """The description of the toolbox."""
63
108
 
64
109
  tools: List[Tool] = Field(default_factory=list, frozen=True)
65
110
  """A list of tools in the toolbox."""
@@ -67,6 +112,8 @@ class ToolBox(WithBriefing):
67
112
  def collect_tool[**P, R](self, func: Callable[P, R]) -> Callable[P, R]:
68
113
  """Add a callable function to the toolbox as a tool.
69
114
 
115
+ This method wraps the function with logging execution info and adds it to the toolbox.
116
+
70
117
  Args:
71
118
  func (Callable[P, R]): The function to be added as a tool.
72
119
 
@@ -79,6 +126,8 @@ class ToolBox(WithBriefing):
79
126
  def add_tool[**P, R](self, func: Callable[P, R]) -> Self:
80
127
  """Add a callable function to the toolbox as a tool.
81
128
 
129
+ This method wraps the function with logging execution info and adds it to the toolbox.
130
+
82
131
  Args:
83
132
  func (Callable): The function to be added as a tool.
84
133
 
@@ -92,6 +141,8 @@ class ToolBox(WithBriefing):
92
141
  def briefing(self) -> str:
93
142
  """Return a brief description of the toolbox.
94
143
 
144
+ This method generates a brief description of the toolbox, including its name, description, and a list of tools.
145
+
95
146
  Returns:
96
147
  str: A brief description of the toolbox.
97
148
  """
@@ -102,6 +153,8 @@ class ToolBox(WithBriefing):
102
153
  def get[**P, R](self, name: str) -> Tool[P, R]:
103
154
  """Invoke a tool by name with the provided arguments.
104
155
 
156
+ This method retrieves a tool by its name from the toolbox.
157
+
105
158
  Args:
106
159
  name (str): The name of the tool to invoke.
107
160
 
@@ -120,13 +173,24 @@ class ToolBox(WithBriefing):
120
173
  return tool
121
174
 
122
175
  def __hash__(self) -> int:
123
- """Return a hash of the toolbox based on its briefing."""
176
+ """Return a hash of the toolbox based on its briefing.
177
+
178
+ Returns:
179
+ int: A hash value based on the toolbox's briefing.
180
+ """
124
181
  return hash(self.briefing)
125
182
 
126
183
 
127
184
  class ToolExecutor(BaseModel):
128
- """A class representing a tool executor with a sequence of tools to execute."""
185
+ """A class representing a tool executor with a sequence of tools to execute.
186
+
187
+ This class manages a sequence of tools and provides methods to inject tools and data into a module, execute the tools,
188
+ and retrieve specific outputs.
129
189
 
190
+ Attributes:
191
+ candidates (List[Tool]): The sequence of tools to execute.
192
+ data (Dict[str, Any]): The data that could be used when invoking the tools.
193
+ """
130
194
  model_config = ConfigDict(use_attribute_docstrings=True)
131
195
  candidates: List[Tool] = Field(default_factory=list, frozen=True)
132
196
  """The sequence of tools to execute."""
@@ -135,7 +199,16 @@ class ToolExecutor(BaseModel):
135
199
  """The data that could be used when invoking the tools."""
136
200
 
137
201
  def inject_tools[M: ModuleType](self, module: Optional[M] = None) -> M:
138
- """Inject the tools into the provided module or default."""
202
+ """Inject the tools into the provided module or default.
203
+
204
+ This method injects the tools into the provided module or creates a new module if none is provided.
205
+
206
+ Args:
207
+ module (Optional[M]): The module to inject tools into. If None, a new module is created.
208
+
209
+ Returns:
210
+ M: The module with injected tools.
211
+ """
139
212
  module = module or cast(
140
213
  "M", module_from_spec(spec=ModuleSpec(name=configs.toolbox.tool_module_name, loader=None))
141
214
  )
@@ -145,7 +218,16 @@ class ToolExecutor(BaseModel):
145
218
  return module
146
219
 
147
220
  def inject_data[M: ModuleType](self, module: Optional[M] = None) -> M:
148
- """Inject the data into the provided module or default."""
221
+ """Inject the data into the provided module or default.
222
+
223
+ This method injects the data into the provided module or creates a new module if none is provided.
224
+
225
+ Args:
226
+ module (Optional[M]): The module to inject data into. If None, a new module is created.
227
+
228
+ Returns:
229
+ M: The module with injected data.
230
+ """
149
231
  module = module or cast(
150
232
  'M', module_from_spec(spec=ModuleSpec(name=configs.toolbox.data_module_name, loader=None))
151
233
  )
@@ -155,7 +237,17 @@ class ToolExecutor(BaseModel):
155
237
  return module
156
238
 
157
239
  def execute[C: Dict[str, Any]](self, source: CodeType, cxt: Optional[C] = None) -> C:
158
- """Execute the sequence of tools with the provided context."""
240
+ """Execute the sequence of tools with the provided context.
241
+
242
+ This method executes the tools in the sequence with the provided context.
243
+
244
+ Args:
245
+ source (CodeType): The source code to execute.
246
+ cxt (Optional[C]): The context to execute the tools with. If None, an empty dictionary is used.
247
+
248
+ Returns:
249
+ C: The context after executing the tools.
250
+ """
159
251
  cxt = cxt or {}
160
252
 
161
253
  @use_temp_module([self.inject_data(), self.inject_tools()])
@@ -167,16 +259,49 @@ class ToolExecutor(BaseModel):
167
259
 
168
260
  @overload
169
261
  def take[C: Dict[str, Any]](self, keys: List[str], source: CodeType, cxt: Optional[C] = None) -> C:
170
- """Check the output of the tools with the provided context."""
262
+ """Check the output of the tools with the provided context.
263
+
264
+ This method executes the tools and retrieves specific keys from the context.
265
+
266
+ Args:
267
+ keys (List[str]): The keys to retrieve from the context.
268
+ source (CodeType): The source code to execute.
269
+ cxt (Optional[C]): The context to execute the tools with. If None, an empty dictionary is used.
270
+
271
+ Returns:
272
+ C: A dictionary containing the retrieved keys and their values.
273
+ """
171
274
  ...
172
275
 
173
276
  @overload
174
277
  def take[C: Dict[str, Any]](self, keys: str, source: CodeType, cxt: Optional[C] = None) -> Any:
175
- """Check the output of the tools with the provided context."""
278
+ """Check the output of the tools with the provided context.
279
+
280
+ This method executes the tools and retrieves a specific key from the context.
281
+
282
+ Args:
283
+ keys (str): The key to retrieve from the context.
284
+ source (CodeType): The source code to execute.
285
+ cxt (Optional[C]): The context to execute the tools with. If None, an empty dictionary is used.
286
+
287
+ Returns:
288
+ Any: The value of the retrieved key.
289
+ """
176
290
  ...
177
291
 
178
292
  def take[C: Dict[str, Any]](self, keys: List[str] | str, source: CodeType, cxt: Optional[C] = None) -> C | Any:
179
- """Check the output of the tools with the provided context."""
293
+ """Check the output of the tools with the provided context.
294
+
295
+ This method executes the tools and retrieves specific keys or a specific key from the context.
296
+
297
+ Args:
298
+ keys (List[str] | str): The keys to retrieve from the context. Can be a single key or a list of keys.
299
+ source (CodeType): The source code to execute.
300
+ cxt (Optional[C]): The context to execute the tools with. If None, an empty dictionary is used.
301
+
302
+ Returns:
303
+ C | Any: A dictionary containing the retrieved keys and their values, or the value of the retrieved key.
304
+ """
180
305
  cxt = self.execute(source, cxt)
181
306
  if isinstance(keys, str):
182
307
  return cxt[keys]
@@ -184,7 +309,17 @@ class ToolExecutor(BaseModel):
184
309
 
185
310
  @classmethod
186
311
  def from_recipe(cls, recipe: List[str], toolboxes: List[ToolBox]) -> Self:
187
- """Create a tool executor from a recipe and a list of toolboxes."""
312
+ """Create a tool executor from a recipe and a list of toolboxes.
313
+
314
+ This method creates a tool executor by retrieving tools from the provided toolboxes based on the recipe.
315
+
316
+ Args:
317
+ recipe (List[str]): The recipe specifying the names of the tools to be added.
318
+ toolboxes (List[ToolBox]): The list of toolboxes to retrieve tools from.
319
+
320
+ Returns:
321
+ Self: A new instance of the tool executor with the specified tools.
322
+ """
188
323
  tools = []
189
324
  while tool_name := recipe.pop(0):
190
325
  for toolbox in toolboxes:
@@ -6,7 +6,6 @@ from typing import Callable, Dict, Iterable, List, Optional, Self, Sequence, Set
6
6
 
7
7
  import asyncstdlib
8
8
  import litellm
9
- from fabricatio._rust_instances import TEMPLATE_MANAGER
10
9
  from fabricatio.config import configs
11
10
  from fabricatio.decorators import logging_exec_time
12
11
  from fabricatio.journal import logger
@@ -16,6 +15,7 @@ from fabricatio.models.task import Task
16
15
  from fabricatio.models.tool import Tool, ToolBox
17
16
  from fabricatio.models.utils import Messages
18
17
  from fabricatio.parser import GenericCapture, JsonCapture
18
+ from fabricatio.rust_instances import TEMPLATE_MANAGER
19
19
  from fabricatio.utils import ok
20
20
  from litellm import RateLimitError, Router, stream_chunk_builder # pyright: ignore [reportPrivateImportUsage]
21
21
  from litellm.types.router import Deployment, LiteLLM_Params, ModelInfo
@@ -46,10 +46,21 @@ ROUTER = Router(
46
46
 
47
47
 
48
48
  class LLMUsage(ScopedConfig):
49
- """Class that manages LLM (Large Language Model) usage parameters and methods."""
49
+ """Class that manages LLM (Large Language Model) usage parameters and methods.
50
+
51
+ This class provides methods to deploy LLMs, query them for responses, and handle various configurations
52
+ related to LLM usage such as API keys, endpoints, and rate limits.
53
+ """
50
54
 
51
55
  def _deploy(self, deployment: Deployment) -> Router:
52
- """Add a deployment to the router."""
56
+ """Add a deployment to the router.
57
+
58
+ Args:
59
+ deployment (Deployment): The deployment to be added to the router.
60
+
61
+ Returns:
62
+ Router: The updated router with the added deployment.
63
+ """
53
64
  self._added_deployment = ROUTER.upsert_deployment(deployment)
54
65
  return ROUTER
55
66
 
@@ -119,7 +130,6 @@ class LLMUsage(ScopedConfig):
119
130
  question: str,
120
131
  system_message: str = "",
121
132
  n: PositiveInt | None = None,
122
- stream_buffer_size: int = 50,
123
133
  **kwargs: Unpack[LLMKwargs],
124
134
  ) -> Sequence[TextChoices | Choices | StreamingChoices]:
125
135
  """Asynchronously invokes the language model with a question and optional system message.
@@ -128,11 +138,10 @@ class LLMUsage(ScopedConfig):
128
138
  question (str): The question to ask the model.
129
139
  system_message (str): The system message to provide context to the model. Defaults to an empty string.
130
140
  n (PositiveInt | None): The number of responses to generate. Defaults to the instance's `llm_generation_count` or the global configuration.
131
- stream_buffer_size (int): The buffer size for streaming responses. Defaults to 50.
132
141
  **kwargs (Unpack[LLMKwargs]): Additional keyword arguments for the LLM usage.
133
142
 
134
143
  Returns:
135
- List[Choices | StreamingChoices]: A list of choices or streaming choices from the model response.
144
+ Sequence[TextChoices | Choices | StreamingChoices]: A sequence of choices or streaming choices from the model response.
136
145
  """
137
146
  resp = await self.aquery(
138
147
  messages=Messages().add_system_message(system_message).add_user_message(question).as_list(),
@@ -144,16 +153,7 @@ class LLMUsage(ScopedConfig):
144
153
  if isinstance(resp, CustomStreamWrapper):
145
154
  if not configs.debug.streaming_visible and (pack := stream_chunk_builder(await asyncstdlib.list())):
146
155
  return pack.choices
147
- chunks = []
148
- buffer = ""
149
- async for chunk in resp:
150
- chunks.append(chunk)
151
- buffer += chunk.choices[0].delta.content or ""
152
- if len(buffer) > stream_buffer_size:
153
- print(buffer, end="") # noqa: T201
154
- buffer = ""
155
- print(buffer) # noqa: T201
156
- if pack := stream_chunk_builder(chunks):
156
+ if pack := stream_chunk_builder(await asyncstdlib.list(resp)):
157
157
  return pack.choices
158
158
  logger.critical(err := f"Unexpected response type: {type(resp)}")
159
159
  raise ValueError(err)
@@ -284,26 +284,26 @@ class LLMUsage(ScopedConfig):
284
284
  """Asynchronously asks a question and validates the response using a given validator.
285
285
 
286
286
  Args:
287
- question (str): The question to ask.
287
+ question (str | List[str]): The question to ask.
288
288
  validator (Callable[[str], T | None]): A function to validate the response.
289
289
  default (T | None): Default value to return if validation fails. Defaults to None.
290
- max_validations (PositiveInt): Maximum number of validation attempts. Defaults to 2.
290
+ max_validations (PositiveInt): Maximum number of validation attempts. Defaults to 3.
291
291
  co_extractor (Optional[GenerateKwargs]): Keyword arguments for the co-extractor, if provided will enable co-extraction.
292
- **kwargs (Unpack[LLMKwargs]): Additional keyword arguments for the LLM usage.
292
+ **kwargs (Unpack[GenerateKwargs]): Additional keyword arguments for the LLM usage.
293
293
 
294
294
  Returns:
295
- T: The validated response.
296
-
295
+ Optional[T] | List[Optional[T]] | List[T] | T: The validated response.
297
296
  """
298
297
 
299
298
  async def _inner(q: str) -> Optional[T]:
300
299
  for lap in range(max_validations):
301
300
  try:
302
301
  if ((validated := validator(response := await self.aask(question=q, **kwargs))) is not None) or (
303
- co_extractor
302
+ co_extractor is not None
303
+ and logger.debug("Co-extraction is enabled.") is None
304
304
  and (
305
305
  validated := validator(
306
- await self.aask(
306
+ response:=await self.aask(
307
307
  question=(
308
308
  TEMPLATE_MANAGER.render_template(
309
309
  configs.templates.co_validation_template,
@@ -320,12 +320,13 @@ class LLMUsage(ScopedConfig):
320
320
  return validated
321
321
 
322
322
  except RateLimitError as e:
323
- logger.warning(f"Rate limit error: {e}")
323
+ logger.warning(f"Rate limit error:\n{e}")
324
324
  continue
325
325
  except Exception as e: # noqa: BLE001
326
- logger.error(f"Error during validation: \n{e}")
326
+ logger.error(f"Error during validation:\n{e}")
327
327
  logger.debug(traceback.format_exc())
328
328
  break
329
+ logger.error(f"Failed to validate the response at {lap}th attempt:\n{response}")
329
330
  if not kwargs.get("no_cache"):
330
331
  kwargs["no_cache"] = True
331
332
  logger.debug("Closed the cache for the next attempt")
@@ -346,7 +347,7 @@ class LLMUsage(ScopedConfig):
346
347
  **kwargs (Unpack[ValidateKwargs]): Additional keyword arguments for the LLM usage.
347
348
 
348
349
  Returns:
349
- List[str]: The validated response as a list of strings.
350
+ Optional[List[str]]: The validated response as a list of strings.
350
351
  """
351
352
  return await self.aask_validate(
352
353
  TEMPLATE_MANAGER.render_template(
@@ -365,7 +366,7 @@ class LLMUsage(ScopedConfig):
365
366
  **kwargs (Unpack[ChooseKwargs]): Additional keyword arguments for the LLM usage.
366
367
 
367
368
  Returns:
368
- List[str]: The validated response as a list of strings.
369
+ Optional[List[str]]: The validated response as a list of strings.
369
370
  """
370
371
  return await self.alist_str(
371
372
  TEMPLATE_MANAGER.render_template(
@@ -383,7 +384,7 @@ class LLMUsage(ScopedConfig):
383
384
  **kwargs (Unpack[ValidateKwargs]): Additional keyword arguments for the LLM usage.
384
385
 
385
386
  Returns:
386
- str: The validated response as a single string.
387
+ Optional[str]: The validated response as a single string.
387
388
  """
388
389
  if paths := await self.apathstr(
389
390
  requirement,
@@ -402,7 +403,7 @@ class LLMUsage(ScopedConfig):
402
403
  **kwargs (Unpack[GenerateKwargs]): Additional keyword arguments for the LLM usage.
403
404
 
404
405
  Returns:
405
- str: The generated string.
406
+ Optional[str]: The generated string.
406
407
  """
407
408
  return await self.aask_validate( # pyright: ignore [reportReturnType]
408
409
  TEMPLATE_MANAGER.render_template(
@@ -429,12 +430,7 @@ class LLMUsage(ScopedConfig):
429
430
  **kwargs (Unpack[ValidateKwargs]): Additional keyword arguments for the LLM usage.
430
431
 
431
432
  Returns:
432
- List[T]: The final validated selection result list, with element types matching the input `choices`.
433
-
434
- Important:
435
- - Uses a template engine to generate structured prompts.
436
- - Ensures response compliance through JSON parsing and format validation.
437
- - Relies on `aask_validate` to implement retry mechanisms with validation.
433
+ Optional[List[T]]: The final validated selection result list, with element types matching the input `choices`.
438
434
  """
439
435
  if dup := duplicates_everseen(choices, key=lambda x: x.name):
440
436
  logger.error(err := f"Redundant choices: {dup}")
@@ -522,7 +518,10 @@ class LLMUsage(ScopedConfig):
522
518
 
523
519
 
524
520
  class EmbeddingUsage(LLMUsage):
525
- """A class representing the embedding model."""
521
+ """A class representing the embedding model.
522
+
523
+ This class extends LLMUsage and provides methods to generate embeddings for input text using various models.
524
+ """
526
525
 
527
526
  async def aembedding(
528
527
  self,
@@ -541,7 +540,6 @@ class EmbeddingUsage(LLMUsage):
541
540
  timeout (Optional[PositiveInt]): The timeout for the embedding request. Defaults to the instance's `llm_timeout` or the global configuration.
542
541
  caching (Optional[bool]): Whether to cache the embedding result. Defaults to False.
543
542
 
544
-
545
543
  Returns:
546
544
  EmbeddingResponse: The response containing the embeddings.
547
545
  """
@@ -599,14 +597,21 @@ class EmbeddingUsage(LLMUsage):
599
597
 
600
598
 
601
599
  class ToolBoxUsage(LLMUsage):
602
- """A class representing the usage of tools in a task."""
600
+ """A class representing the usage of tools in a task.
601
+
602
+ This class extends LLMUsage and provides methods to manage and use toolboxes and tools within tasks.
603
+ """
603
604
 
604
605
  toolboxes: Set[ToolBox] = Field(default_factory=set)
605
606
  """A set of toolboxes used by the instance."""
606
607
 
607
608
  @property
608
609
  def available_toolbox_names(self) -> List[str]:
609
- """Return a list of available toolbox names."""
610
+ """Return a list of available toolbox names.
611
+
612
+ Returns:
613
+ List[str]: A list of names of the available toolboxes.
614
+ """
610
615
  return [toolbox.name for toolbox in self.toolboxes]
611
616
 
612
617
  async def choose_toolboxes(
@@ -618,11 +623,10 @@ class ToolBoxUsage(LLMUsage):
618
623
 
619
624
  Args:
620
625
  task (Task): The task for which to choose toolboxes.
621
- system_message (str): Custom system-level prompt, defaults to an empty string.
622
626
  **kwargs (Unpack[LLMKwargs]): Additional keyword arguments for the LLM usage.
623
627
 
624
628
  Returns:
625
- List[ToolBox]: The selected toolboxes.
629
+ Optional[List[ToolBox]]: The selected toolboxes.
626
630
  """
627
631
  if not self.toolboxes:
628
632
  logger.warning("No toolboxes available.")
@@ -647,7 +651,7 @@ class ToolBoxUsage(LLMUsage):
647
651
  **kwargs (Unpack[LLMKwargs]): Additional keyword arguments for the LLM usage.
648
652
 
649
653
  Returns:
650
- List[Tool]: The selected tools.
654
+ Optional[List[Tool]]: The selected tools.
651
655
  """
652
656
  if not toolbox.tools:
653
657
  logger.warning(f"No tools available in toolbox {toolbox.name}.")
fabricatio/parser.py CHANGED
@@ -48,10 +48,10 @@ class Capture(BaseModel):
48
48
  case "json" if configs.general.use_json_repair:
49
49
  logger.debug("Applying json repair to text.")
50
50
  if isinstance(text, str):
51
- return repair_json(text, ensure_ascii=False)
52
- return [repair_json(item, ensure_ascii=False) for item in text]
51
+ return repair_json(text, ensure_ascii=False) # pyright: ignore [reportReturnType]
52
+ return [repair_json(item, ensure_ascii=False) for item in text] # pyright: ignore [reportReturnType, reportGeneralTypeIssues]
53
53
  case _:
54
- return text
54
+ return text # pyright: ignore [reportReturnType]
55
55
 
56
56
  def capture(self, text: str) -> Tuple[str, ...] | str | None:
57
57
  """Capture the first occurrence of the pattern in the given text.
@@ -88,7 +88,7 @@ class Capture(BaseModel):
88
88
  if (cap := self.capture(text)) is None:
89
89
  return None
90
90
  try:
91
- return convertor(cap)
91
+ return convertor(cap) # pyright: ignore [reportArgumentType]
92
92
  except (ValueError, SyntaxError, ValidationError) as e:
93
93
  logger.error(f"Failed to convert text using {convertor.__name__} to convert.\nerror: {e}\n {cap}")
94
94
  return None
@@ -120,7 +120,7 @@ class Capture(BaseModel):
120
120
  judges.append(lambda output_obj: len(output_obj) == length)
121
121
 
122
122
  if (out := self.convert_with(text, deserializer)) and all(j(out) for j in judges):
123
- return out
123
+ return out # pyright: ignore [reportReturnType]
124
124
  return None
125
125
 
126
126
  @classmethod
Binary file
@@ -1,5 +1,20 @@
1
+ """Python interface definitions for Rust-based functionality.
2
+
3
+ This module provides type stubs and documentation for Rust-implemented utilities,
4
+ including template rendering, cryptographic hashing, language detection, and
5
+ bibliography management. The actual implementations are provided by Rust modules.
6
+
7
+ Key Features:
8
+ - TemplateManager: Handles Handlebars template rendering and management.
9
+ - BibManager: Manages BibTeX bibliography parsing and querying.
10
+ - Cryptographic utilities: BLAKE3 hashing.
11
+ - Text utilities: Word boundary splitting and word counting.
12
+ """
13
+
1
14
  from pathlib import Path
2
- from typing import Any, Dict, List, Optional
15
+ from typing import List, Optional
16
+
17
+ from pydantic import JsonValue
3
18
 
4
19
  class TemplateManager:
5
20
  """Template rendering engine using Handlebars templates.
@@ -41,7 +56,7 @@ class TemplateManager:
41
56
  This refreshes the template cache, finding any new or modified templates.
42
57
  """
43
58
 
44
- def render_template(self, name: str, data: Dict[str, Any]) -> str:
59
+ def render_template(self, name: str, data: JsonValue) -> str:
45
60
  """Render a template with context data.
46
61
 
47
62
  Args:
@@ -55,7 +70,7 @@ class TemplateManager:
55
70
  RuntimeError: If template rendering fails
56
71
  """
57
72
 
58
- def render_template_raw(self, template: str, data: Dict[str, Any]) -> str:
73
+ def render_template_raw(self, template: str, data: JsonValue) -> str:
59
74
  """Render a template with context data.
60
75
 
61
76
  Args:
@@ -76,6 +91,29 @@ def blake3_hash(content: bytes) -> str:
76
91
  Hex-encoded BLAKE3 hash string
77
92
  """
78
93
 
94
+ def detect_language(string: str) -> str:
95
+ """Detect the language of a given string."""
96
+
97
+ def split_word_bounds(string: str) -> List[str]:
98
+ """Split the string into words based on word boundaries.
99
+
100
+ Args:
101
+ string: The input string to be split.
102
+
103
+ Returns:
104
+ A list of words extracted from the string.
105
+ """
106
+
107
+ def word_count(string: str) -> int:
108
+ """Count the number of words in the string.
109
+
110
+ Args:
111
+ string: The input string to count words from.
112
+
113
+ Returns:
114
+ The number of words in the string.
115
+ """
116
+
79
117
  class BibManager:
80
118
  """BibTeX bibliography manager for parsing and querying citation data."""
81
119
 
@@ -162,7 +200,7 @@ class BibManager:
162
200
  Title if found, None otherwise
163
201
  """
164
202
 
165
- def get_field_by_key(self, key: str, field: str)-> Optional[str]:
203
+ def get_field_by_key(self, key: str, field: str) -> Optional[str]:
166
204
  """Retrieve a specific field by citation key.
167
205
 
168
206
  Args:
@@ -1,7 +1,7 @@
1
1
  """Some necessary instances."""
2
2
 
3
- from fabricatio._rust import TemplateManager
4
3
  from fabricatio.config import configs
4
+ from fabricatio.rust import TemplateManager
5
5
 
6
6
  TEMPLATE_MANAGER = TemplateManager(
7
7
  template_dirs=configs.templates.template_dir,