fabricatio 0.3.14.dev1__cp312-cp312-win_amd64.whl → 0.3.14.dev4__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 (47) hide show
  1. fabricatio/__init__.py +5 -6
  2. fabricatio/actions/article.py +31 -31
  3. fabricatio/actions/article_rag.py +58 -58
  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 +37 -37
  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 +9 -9
  19. fabricatio/{core.py → emitter.py} +17 -19
  20. fabricatio/journal.py +2 -1
  21. fabricatio/models/action.py +9 -11
  22. fabricatio/models/extra/aricle_rag.py +15 -12
  23. fabricatio/models/extra/article_base.py +4 -5
  24. fabricatio/models/extra/article_essence.py +2 -1
  25. fabricatio/models/extra/article_main.py +5 -4
  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 +48 -131
  31. fabricatio/models/kwargs_types.py +1 -9
  32. fabricatio/models/role.py +14 -13
  33. fabricatio/models/task.py +3 -4
  34. fabricatio/models/tool.py +5 -6
  35. fabricatio/models/usages.py +137 -147
  36. fabricatio/parser.py +59 -99
  37. fabricatio/rust.cp312-win_amd64.pyd +0 -0
  38. fabricatio/rust.pyi +39 -59
  39. fabricatio/utils.py +6 -170
  40. fabricatio-0.3.14.dev4.data/scripts/tdown.exe +0 -0
  41. {fabricatio-0.3.14.dev1.data → fabricatio-0.3.14.dev4.data}/scripts/ttm.exe +0 -0
  42. {fabricatio-0.3.14.dev1.dist-info → fabricatio-0.3.14.dev4.dist-info}/METADATA +3 -7
  43. fabricatio-0.3.14.dev4.dist-info/RECORD +64 -0
  44. fabricatio-0.3.14.dev1.data/scripts/tdown.exe +0 -0
  45. fabricatio-0.3.14.dev1.dist-info/RECORD +0 -63
  46. {fabricatio-0.3.14.dev1.dist-info → fabricatio-0.3.14.dev4.dist-info}/WHEEL +0 -0
  47. {fabricatio-0.3.14.dev1.dist-info → fabricatio-0.3.14.dev4.dist-info}/licenses/LICENSE +0 -0
fabricatio/models/role.py CHANGED
@@ -1,20 +1,18 @@
1
1
  """Module that contains the Role class for managing workflows and their event registrations."""
2
+
2
3
  from functools import partial
3
4
  from typing import Any, Dict, Self
4
5
 
5
- from fabricatio.rust import Event
6
- from pydantic import ConfigDict, Field
7
-
8
- from fabricatio.core import env
6
+ from fabricatio.emitter import env
9
7
  from fabricatio.journal import logger
10
8
  from fabricatio.models.action import WorkFlow
11
9
  from fabricatio.models.generic import WithBriefing
10
+ from fabricatio.rust import Event
12
11
  from fabricatio.utils import is_subclass_of_base
12
+ from pydantic import ConfigDict, Field
13
13
 
14
- is_toolbox_usage = partial(is_subclass_of_base, base_module="fabricatio.models.usages",
15
- base_name="ToolBoxUsage")
16
- is_scoped_config = partial(is_subclass_of_base, base_module="fabricatio.models.generic",
17
- base_name="ScopedConfig")
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")
18
16
 
19
17
 
20
18
  class Role(WithBriefing):
@@ -23,7 +21,10 @@ class Role(WithBriefing):
23
21
  A Role serves as a container for workflows, managing their registration to events
24
22
  and providing them with shared configuration like tools and personality.
25
23
  """
24
+
26
25
  model_config = ConfigDict(use_attribute_docstrings=True, arbitrary_types_allowed=True)
26
+ name: str = ""
27
+ """The name of the role."""
27
28
  description: str = ""
28
29
  """A brief description of the role's responsibilities and capabilities."""
29
30
 
@@ -36,6 +37,8 @@ class Role(WithBriefing):
36
37
  Args:
37
38
  __context: The context used for initialization
38
39
  """
40
+ self.name = self.name or self.__class__.__name__
41
+
39
42
  self.resolve_configuration().register_workflows()
40
43
 
41
44
  def register_workflows(self) -> Self:
@@ -45,9 +48,7 @@ class Role(WithBriefing):
45
48
  Self: The role instance for method chaining
46
49
  """
47
50
  for event, workflow in self.registry.items():
48
- logger.debug(
49
- f"Registering workflow: `{workflow.name}` for event: `{event.collapse()}`"
50
- )
51
+ logger.debug(f"Registering workflow: `{workflow.name}` for event: `{event.collapse()}`")
51
52
  env.on(event, workflow.serve)
52
53
  return self
53
54
 
@@ -67,7 +68,7 @@ class Role(WithBriefing):
67
68
  workflow.inject_personality(self.briefing)
68
69
  return self
69
70
 
70
- def _configure_scoped_config(self, workflow) -> None:
71
+ def _configure_scoped_config(self, workflow: WorkFlow) -> None:
71
72
  """Configure scoped configuration for workflow and its actions."""
72
73
  if not is_scoped_config(self.__class__):
73
74
  return
@@ -80,7 +81,7 @@ class Role(WithBriefing):
80
81
  for action in (a for a in workflow.iter_actions() if is_scoped_config(a)):
81
82
  action.fallback_to(fallback_target)
82
83
 
83
- def _configure_toolbox_usage(self, workflow) -> None:
84
+ def _configure_toolbox_usage(self, workflow: WorkFlow) -> None:
84
85
  """Configure toolbox usage for workflow and its actions."""
85
86
  if not is_toolbox_usage(self.__class__):
86
87
  return
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
@@ -3,7 +3,6 @@
3
3
  This module provides classes for defining tools and toolboxes, which can be used to manage and execute callable functions
4
4
  with additional functionalities such as logging, execution info, and briefing.
5
5
  """
6
-
7
6
  from importlib.machinery import ModuleSpec
8
7
  from importlib.util import module_from_spec
9
8
  from inspect import iscoroutinefunction, signature
@@ -11,11 +10,11 @@ from types import CodeType, ModuleType
11
10
  from typing import Any, Callable, Dict, List, Optional, Self, cast, overload
12
11
 
13
12
  from fabricatio.rust import CONFIG
14
- from pydantic import BaseModel, ConfigDict, Field
13
+ from pydantic import Field
15
14
 
16
15
  from fabricatio.decorators import logging_execution_info, use_temp_module
17
16
  from fabricatio.journal import logger
18
- from fabricatio.models.generic import WithBriefing
17
+ from fabricatio.models.generic import Base, WithBriefing
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}")
@@ -1,13 +1,25 @@
1
1
  """This module contains classes that manage the usage of language models and tools in tasks."""
2
2
 
3
3
  import traceback
4
+ from abc import ABC
4
5
  from asyncio import gather
5
6
  from typing import Callable, Dict, Iterable, List, Literal, Optional, Self, Sequence, Set, Union, Unpack, overload
6
7
 
7
8
  import asyncstdlib
8
- import litellm
9
+ from fabricatio.decorators import logging_exec_time
10
+ from fabricatio.journal import logger
11
+ from fabricatio.models.generic import ScopedConfig, WithBriefing
12
+ from fabricatio.models.kwargs_types import ChooseKwargs, EmbeddingKwargs, GenerateKwargs, LLMKwargs, ValidateKwargs
13
+ from fabricatio.models.task import Task
14
+ from fabricatio.models.tool import Tool, ToolBox
9
15
  from fabricatio.rust import CONFIG, TEMPLATE_MANAGER
10
- from litellm import RateLimitError, Router, stream_chunk_builder # pyright: ignore [reportPrivateImportUsage]
16
+ from fabricatio.utils import first_available, ok
17
+ from litellm import ( # pyright: ignore [reportPrivateImportUsage]
18
+ RateLimitError,
19
+ Router,
20
+ aembedding,
21
+ stream_chunk_builder,
22
+ )
11
23
  from litellm.types.router import Deployment, LiteLLM_Params, ModelInfo
12
24
  from litellm.types.utils import (
13
25
  Choices,
@@ -20,14 +32,6 @@ from litellm.utils import CustomStreamWrapper, token_counter # pyright: ignore
20
32
  from more_itertools import duplicates_everseen
21
33
  from pydantic import BaseModel, ConfigDict, Field, NonNegativeInt, PositiveInt
22
34
 
23
- from fabricatio.decorators import logging_exec_time
24
- from fabricatio.journal import logger
25
- from fabricatio.models.generic import ScopedConfig, WithBriefing
26
- from fabricatio.models.kwargs_types import ChooseKwargs, EmbeddingKwargs, GenerateKwargs, LLMKwargs, ValidateKwargs
27
- from fabricatio.models.task import Task
28
- from fabricatio.models.tool import Tool, ToolBox
29
- from fabricatio.utils import first_available, ok
30
-
31
35
  ROUTER = Router(
32
36
  routing_strategy="usage-based-routing-v2",
33
37
  default_max_parallel_requests=CONFIG.routing.max_parallel_requests,
@@ -37,7 +41,7 @@ ROUTER = Router(
37
41
  )
38
42
 
39
43
 
40
- class LLMUsage(ScopedConfig):
44
+ class LLMUsage(ScopedConfig, ABC):
41
45
  """Class that manages LLM (Large Language Model) usage parameters and methods.
42
46
 
43
47
  This class provides methods to deploy LLMs, query them for responses, and handle various configurations
@@ -58,10 +62,10 @@ class LLMUsage(ScopedConfig):
58
62
 
59
63
  # noinspection PyTypeChecker,PydanticTypeChecker,t
60
64
  async def aquery(
61
- self,
62
- messages: List[Dict[str, str]],
63
- n: PositiveInt | None = None,
64
- **kwargs: Unpack[LLMKwargs],
65
+ self,
66
+ messages: List[Dict[str, str]],
67
+ n: PositiveInt | None = None,
68
+ **kwargs: Unpack[LLMKwargs],
65
69
  ) -> ModelResponse | CustomStreamWrapper:
66
70
  """Asynchronously queries the language model to generate a response based on the provided messages and parameters.
67
71
 
@@ -108,28 +112,27 @@ class LLMUsage(ScopedConfig):
108
112
  stop=kwargs.get("stop") or self.llm_stop_sign or CONFIG.llm.stop_sign,
109
113
  top_p=kwargs.get("top_p") or self.llm_top_p or CONFIG.llm.top_p,
110
114
  max_tokens=kwargs.get("max_tokens") or self.llm_max_tokens or CONFIG.llm.max_tokens,
111
- stream=first_available((kwargs.get("stream"), self.llm_stream, CONFIG.llm.stream),
112
- "stream is not set at any place"),
115
+ stream=first_available(
116
+ (kwargs.get("stream"), self.llm_stream, CONFIG.llm.stream), "stream is not set at any place"
117
+ ),
113
118
  cache={
114
119
  "no-cache": kwargs.get("no_cache"),
115
120
  "no-store": kwargs.get("no_store"),
116
121
  "cache-ttl": kwargs.get("cache_ttl"),
117
122
  "s-maxage": kwargs.get("s_maxage"),
118
123
  },
119
- presence_penalty=kwargs.get("presence_penalty")
120
- or self.llm_presence_penalty
121
- or CONFIG.llm.presence_penalty,
124
+ presence_penalty=kwargs.get("presence_penalty") or self.llm_presence_penalty or CONFIG.llm.presence_penalty,
122
125
  frequency_penalty=kwargs.get("frequency_penalty")
123
- or self.llm_frequency_penalty
124
- or CONFIG.llm.frequency_penalty,
126
+ or self.llm_frequency_penalty
127
+ or CONFIG.llm.frequency_penalty,
125
128
  )
126
129
 
127
130
  async def ainvoke(
128
- self,
129
- question: str,
130
- system_message: str = "",
131
- n: PositiveInt | None = None,
132
- **kwargs: Unpack[LLMKwargs],
131
+ self,
132
+ question: str,
133
+ system_message: str = "",
134
+ n: PositiveInt | None = None,
135
+ **kwargs: Unpack[LLMKwargs],
133
136
  ) -> Sequence[TextChoices | Choices | StreamingChoices]:
134
137
  """Asynchronously invokes the language model with a question and optional system message.
135
138
 
@@ -149,54 +152,49 @@ class LLMUsage(ScopedConfig):
149
152
  )
150
153
  if isinstance(resp, ModelResponse):
151
154
  return resp.choices
152
- if isinstance(resp, CustomStreamWrapper):
153
- if pack := stream_chunk_builder(await asyncstdlib.list(resp)):
154
- return pack.choices
155
+ if isinstance(resp, CustomStreamWrapper) and (pack := stream_chunk_builder(await asyncstdlib.list(resp))):
156
+ return pack.choices
155
157
  logger.critical(err := f"Unexpected response type: {type(resp)}")
156
158
  raise ValueError(err)
157
159
 
158
160
  @overload
159
161
  async def aask(
160
- self,
161
- question: List[str],
162
- system_message: List[str],
163
- **kwargs: Unpack[LLMKwargs],
164
- ) -> List[str]:
165
- ...
162
+ self,
163
+ question: List[str],
164
+ system_message: List[str],
165
+ **kwargs: Unpack[LLMKwargs],
166
+ ) -> List[str]: ...
166
167
 
167
168
  @overload
168
169
  async def aask(
169
- self,
170
- question: str,
171
- system_message: List[str],
172
- **kwargs: Unpack[LLMKwargs],
173
- ) -> List[str]:
174
- ...
170
+ self,
171
+ question: str,
172
+ system_message: List[str],
173
+ **kwargs: Unpack[LLMKwargs],
174
+ ) -> List[str]: ...
175
175
 
176
176
  @overload
177
177
  async def aask(
178
- self,
179
- question: List[str],
180
- system_message: Optional[str] = None,
181
- **kwargs: Unpack[LLMKwargs],
182
- ) -> List[str]:
183
- ...
178
+ self,
179
+ question: List[str],
180
+ system_message: Optional[str] = None,
181
+ **kwargs: Unpack[LLMKwargs],
182
+ ) -> List[str]: ...
184
183
 
185
184
  @overload
186
185
  async def aask(
187
- self,
188
- question: str,
189
- system_message: Optional[str] = None,
190
- **kwargs: Unpack[LLMKwargs],
191
- ) -> str:
192
- ...
186
+ self,
187
+ question: str,
188
+ system_message: Optional[str] = None,
189
+ **kwargs: Unpack[LLMKwargs],
190
+ ) -> str: ...
193
191
 
194
192
  @logging_exec_time
195
193
  async def aask(
196
- self,
197
- question: str | List[str],
198
- system_message: Optional[str | List[str]] = None,
199
- **kwargs: Unpack[LLMKwargs],
194
+ self,
195
+ question: str | List[str],
196
+ system_message: Optional[str | List[str]] = None,
197
+ **kwargs: Unpack[LLMKwargs],
200
198
  ) -> str | List[str]:
201
199
  """Asynchronously asks the language model a question and returns the response content.
202
200
 
@@ -224,8 +222,7 @@ class LLMUsage(ScopedConfig):
224
222
  res = await gather(*[self.ainvoke(n=1, question=q, system_message=sm, **kwargs) for sm in sm_seq])
225
223
  out = [r[0].message.content for r in res] # pyright: ignore [reportAttributeAccessIssue]
226
224
  case (str(q), str(sm)):
227
- out = ((await self.ainvoke(n=1, question=q, system_message=sm, **kwargs))[
228
- 0]).message.content # pyright: ignore [reportAttributeAccessIssue]
225
+ out = ((await self.ainvoke(n=1, question=q, system_message=sm, **kwargs))[0]).message.content # pyright: ignore [reportAttributeAccessIssue]
229
226
  case _:
230
227
  raise RuntimeError("Should not reach here.")
231
228
 
@@ -237,55 +234,51 @@ class LLMUsage(ScopedConfig):
237
234
 
238
235
  @overload
239
236
  async def aask_validate[T](
240
- self,
241
- question: str,
242
- validator: Callable[[str], T | None],
243
- default: T = ...,
244
- max_validations: PositiveInt = 2,
245
- **kwargs: Unpack[GenerateKwargs],
246
- ) -> T:
247
- ...
237
+ self,
238
+ question: str,
239
+ validator: Callable[[str], T | None],
240
+ default: T = ...,
241
+ max_validations: PositiveInt = 2,
242
+ **kwargs: Unpack[GenerateKwargs],
243
+ ) -> T: ...
248
244
 
249
245
  @overload
250
246
  async def aask_validate[T](
251
- self,
252
- question: List[str],
253
- validator: Callable[[str], T | None],
254
- default: T = ...,
255
- max_validations: PositiveInt = 2,
256
- **kwargs: Unpack[GenerateKwargs],
257
- ) -> List[T]:
258
- ...
247
+ self,
248
+ question: List[str],
249
+ validator: Callable[[str], T | None],
250
+ default: T = ...,
251
+ max_validations: PositiveInt = 2,
252
+ **kwargs: Unpack[GenerateKwargs],
253
+ ) -> List[T]: ...
259
254
 
260
255
  @overload
261
256
  async def aask_validate[T](
262
- self,
263
- question: str,
264
- validator: Callable[[str], T | None],
265
- default: None = None,
266
- max_validations: PositiveInt = 2,
267
- **kwargs: Unpack[GenerateKwargs],
268
- ) -> Optional[T]:
269
- ...
257
+ self,
258
+ question: str,
259
+ validator: Callable[[str], T | None],
260
+ default: None = None,
261
+ max_validations: PositiveInt = 2,
262
+ **kwargs: Unpack[GenerateKwargs],
263
+ ) -> Optional[T]: ...
270
264
 
271
265
  @overload
272
266
  async def aask_validate[T](
273
- self,
274
- question: List[str],
275
- validator: Callable[[str], T | None],
276
- default: None = None,
277
- max_validations: PositiveInt = 2,
278
- **kwargs: Unpack[GenerateKwargs],
279
- ) -> List[Optional[T]]:
280
- ...
267
+ self,
268
+ question: List[str],
269
+ validator: Callable[[str], T | None],
270
+ default: None = None,
271
+ max_validations: PositiveInt = 2,
272
+ **kwargs: Unpack[GenerateKwargs],
273
+ ) -> List[Optional[T]]: ...
281
274
 
282
275
  async def aask_validate[T](
283
- self,
284
- question: str | List[str],
285
- validator: Callable[[str], T | None],
286
- default: Optional[T] = None,
287
- max_validations: PositiveInt = 3,
288
- **kwargs: Unpack[GenerateKwargs],
276
+ self,
277
+ question: str | List[str],
278
+ validator: Callable[[str], T | None],
279
+ default: Optional[T] = None,
280
+ max_validations: PositiveInt = 3,
281
+ **kwargs: Unpack[GenerateKwargs],
289
282
  ) -> Optional[T] | List[Optional[T]] | List[T] | T:
290
283
  """Asynchronously asks a question and validates the response using a given validator.
291
284
 
@@ -325,7 +318,7 @@ class LLMUsage(ScopedConfig):
325
318
  return await (gather(*[_inner(q) for q in question]) if isinstance(question, list) else _inner(question))
326
319
 
327
320
  async def alist_str(
328
- self, requirement: str, k: NonNegativeInt = 0, **kwargs: Unpack[ValidateKwargs[List[str]]]
321
+ self, requirement: str, k: NonNegativeInt = 0, **kwargs: Unpack[ValidateKwargs[List[str]]]
329
322
  ) -> Optional[List[str]]:
330
323
  """Asynchronously generates a list of strings based on a given requirement.
331
324
 
@@ -377,9 +370,9 @@ class LLMUsage(ScopedConfig):
377
370
  Optional[str]: The validated response as a single string.
378
371
  """
379
372
  if paths := await self.apathstr(
380
- requirement,
381
- k=1,
382
- **kwargs,
373
+ requirement,
374
+ k=1,
375
+ **kwargs,
383
376
  ):
384
377
  return paths.pop()
385
378
 
@@ -407,11 +400,11 @@ class LLMUsage(ScopedConfig):
407
400
  )
408
401
 
409
402
  async def achoose[T: WithBriefing](
410
- self,
411
- instruction: str,
412
- choices: List[T],
413
- k: NonNegativeInt = 0,
414
- **kwargs: Unpack[ValidateKwargs[List[T]]],
403
+ self,
404
+ instruction: str,
405
+ choices: List[T],
406
+ k: NonNegativeInt = 0,
407
+ **kwargs: Unpack[ValidateKwargs[List[T]]],
415
408
  ) -> Optional[List[T]]:
416
409
  """Asynchronously executes a multi-choice decision-making process, generating a prompt based on the instruction and options, and validates the returned selection results.
417
410
 
@@ -456,10 +449,10 @@ class LLMUsage(ScopedConfig):
456
449
  )
457
450
 
458
451
  async def apick[T: WithBriefing](
459
- self,
460
- instruction: str,
461
- choices: List[T],
462
- **kwargs: Unpack[ValidateKwargs[List[T]]],
452
+ self,
453
+ instruction: str,
454
+ choices: List[T],
455
+ **kwargs: Unpack[ValidateKwargs[List[T]]],
463
456
  ) -> T:
464
457
  """Asynchronously picks a single choice from a list of options using AI validation.
465
458
 
@@ -484,11 +477,11 @@ class LLMUsage(ScopedConfig):
484
477
  )[0]
485
478
 
486
479
  async def ajudge(
487
- self,
488
- prompt: str,
489
- affirm_case: str = "",
490
- deny_case: str = "",
491
- **kwargs: Unpack[ValidateKwargs[bool]],
480
+ self,
481
+ prompt: str,
482
+ affirm_case: str = "",
483
+ deny_case: str = "",
484
+ **kwargs: Unpack[ValidateKwargs[bool]],
492
485
  ) -> Optional[bool]:
493
486
  """Asynchronously judges a prompt using AI validation.
494
487
 
@@ -513,19 +506,19 @@ class LLMUsage(ScopedConfig):
513
506
  )
514
507
 
515
508
 
516
- class EmbeddingUsage(LLMUsage):
509
+ class EmbeddingUsage(LLMUsage, ABC):
517
510
  """A class representing the embedding model.
518
511
 
519
512
  This class extends LLMUsage and provides methods to generate embeddings for input text using various models.
520
513
  """
521
514
 
522
515
  async def aembedding(
523
- self,
524
- input_text: List[str],
525
- model: Optional[str] = None,
526
- dimensions: Optional[int] = None,
527
- timeout: Optional[PositiveInt] = None,
528
- caching: Optional[bool] = False,
516
+ self,
517
+ input_text: List[str],
518
+ model: Optional[str] = None,
519
+ dimensions: Optional[int] = None,
520
+ timeout: Optional[PositiveInt] = None,
521
+ caching: Optional[bool] = False,
529
522
  ) -> EmbeddingResponse:
530
523
  """Asynchronously generates embeddings for the given input text.
531
524
 
@@ -545,16 +538,16 @@ class EmbeddingUsage(LLMUsage):
545
538
  logger.error(err := f"Input text exceeds maximum sequence length {max_len}, got {length}.")
546
539
  raise ValueError(err)
547
540
 
548
- return await litellm.aembedding(
541
+ return await aembedding(
549
542
  input=input_text,
550
543
  caching=caching or self.embedding_caching or CONFIG.embedding.caching,
551
544
  dimensions=dimensions or self.embedding_dimensions or CONFIG.embedding.dimensions,
552
545
  model=model or self.embedding_model or CONFIG.embedding.model or self.llm_model or CONFIG.llm.model,
553
546
  timeout=timeout
554
- or self.embedding_timeout
555
- or CONFIG.embedding.timeout
556
- or self.llm_timeout
557
- or CONFIG.llm.timeout,
547
+ or self.embedding_timeout
548
+ or CONFIG.embedding.timeout
549
+ or self.llm_timeout
550
+ or CONFIG.llm.timeout,
558
551
  api_key=ok(
559
552
  self.embedding_api_key or CONFIG.embedding.api_key or self.llm_api_key or CONFIG.llm.api_key
560
553
  ).get_secret_value(),
@@ -563,21 +556,18 @@ class EmbeddingUsage(LLMUsage):
563
556
  or CONFIG.embedding.api_endpoint
564
557
  or self.llm_api_endpoint
565
558
  or CONFIG.llm.api_endpoint
566
- )
567
- .rstrip("/"),
559
+ ).rstrip("/"),
568
560
  # seems embedding function takes no base_url end with a slash
569
561
  )
570
562
 
571
563
  @overload
572
- async def vectorize(self, input_text: List[str], **kwargs: Unpack[EmbeddingKwargs]) -> List[List[float]]:
573
- ...
564
+ async def vectorize(self, input_text: List[str], **kwargs: Unpack[EmbeddingKwargs]) -> List[List[float]]: ...
574
565
 
575
566
  @overload
576
- async def vectorize(self, input_text: str, **kwargs: Unpack[EmbeddingKwargs]) -> List[float]:
577
- ...
567
+ async def vectorize(self, input_text: str, **kwargs: Unpack[EmbeddingKwargs]) -> List[float]: ...
578
568
 
579
569
  async def vectorize(
580
- self, input_text: List[str] | str, **kwargs: Unpack[EmbeddingKwargs]
570
+ self, input_text: List[str] | str, **kwargs: Unpack[EmbeddingKwargs]
581
571
  ) -> List[List[float]] | List[float]:
582
572
  """Asynchronously generates vector embeddings for the given input text.
583
573
 
@@ -594,7 +584,7 @@ class EmbeddingUsage(LLMUsage):
594
584
  return [o.get("embedding") for o in (await self.aembedding(input_text, **kwargs)).data]
595
585
 
596
586
 
597
- class ToolBoxUsage(LLMUsage):
587
+ class ToolBoxUsage(LLMUsage, ABC):
598
588
  """A class representing the usage of tools in a task.
599
589
 
600
590
  This class extends LLMUsage and provides methods to manage and use toolboxes and tools within tasks.
@@ -613,9 +603,9 @@ class ToolBoxUsage(LLMUsage):
613
603
  return [toolbox.name for toolbox in self.toolboxes]
614
604
 
615
605
  async def choose_toolboxes(
616
- self,
617
- task: Task,
618
- **kwargs: Unpack[ChooseKwargs[List[ToolBox]]],
606
+ self,
607
+ task: Task,
608
+ **kwargs: Unpack[ChooseKwargs[List[ToolBox]]],
619
609
  ) -> Optional[List[ToolBox]]:
620
610
  """Asynchronously executes a multi-choice decision-making process to choose toolboxes.
621
611
 
@@ -636,10 +626,10 @@ class ToolBoxUsage(LLMUsage):
636
626
  )
637
627
 
638
628
  async def choose_tools(
639
- self,
640
- task: Task,
641
- toolbox: ToolBox,
642
- **kwargs: Unpack[ChooseKwargs[List[Tool]]],
629
+ self,
630
+ task: Task,
631
+ toolbox: ToolBox,
632
+ **kwargs: Unpack[ChooseKwargs[List[Tool]]],
643
633
  ) -> Optional[List[Tool]]:
644
634
  """Asynchronously executes a multi-choice decision-making process to choose tools.
645
635
 
@@ -661,10 +651,10 @@ class ToolBoxUsage(LLMUsage):
661
651
  )
662
652
 
663
653
  async def gather_tools_fine_grind(
664
- self,
665
- task: Task,
666
- box_choose_kwargs: Optional[ChooseKwargs] = None,
667
- tool_choose_kwargs: Optional[ChooseKwargs] = None,
654
+ self,
655
+ task: Task,
656
+ box_choose_kwargs: Optional[ChooseKwargs] = None,
657
+ tool_choose_kwargs: Optional[ChooseKwargs] = None,
668
658
  ) -> List[Tool]:
669
659
  """Asynchronously gathers tools based on the provided task and toolbox and tool selection criteria.
670
660