fabricatio 0.2.8.dev2__cp312-cp312-win_amd64.whl → 0.2.8.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.
- fabricatio/_rust.cp312-win_amd64.pyd +0 -0
- fabricatio/_rust.pyi +1 -1
- fabricatio/actions/article.py +112 -121
- fabricatio/actions/article_rag.py +55 -45
- fabricatio/actions/output.py +4 -3
- fabricatio/actions/rag.py +3 -3
- fabricatio/capabilities/censor.py +87 -0
- fabricatio/capabilities/check.py +194 -0
- fabricatio/capabilities/correct.py +142 -98
- fabricatio/capabilities/propose.py +20 -4
- fabricatio/capabilities/rag.py +3 -2
- fabricatio/capabilities/rating.py +67 -22
- fabricatio/capabilities/review.py +18 -187
- fabricatio/capabilities/task.py +8 -9
- fabricatio/config.py +11 -3
- fabricatio/models/action.py +8 -5
- fabricatio/models/adv_kwargs_types.py +25 -0
- fabricatio/models/extra/advanced_judge.py +10 -7
- fabricatio/models/extra/article_base.py +47 -27
- fabricatio/models/extra/article_essence.py +40 -209
- fabricatio/models/extra/article_main.py +3 -4
- fabricatio/models/extra/patches.py +7 -0
- fabricatio/models/extra/problem.py +153 -0
- fabricatio/models/extra/rule.py +21 -0
- fabricatio/models/generic.py +71 -37
- fabricatio/models/kwargs_types.py +23 -17
- fabricatio/models/role.py +4 -1
- fabricatio/models/usages.py +17 -20
- fabricatio/models/utils.py +0 -46
- fabricatio/parser.py +7 -8
- fabricatio/utils.py +54 -0
- {fabricatio-0.2.8.dev2.data → fabricatio-0.2.8.dev4.data}/scripts/tdown.exe +0 -0
- {fabricatio-0.2.8.dev2.dist-info → fabricatio-0.2.8.dev4.dist-info}/METADATA +2 -1
- fabricatio-0.2.8.dev4.dist-info/RECORD +56 -0
- fabricatio-0.2.8.dev2.dist-info/RECORD +0 -49
- {fabricatio-0.2.8.dev2.dist-info → fabricatio-0.2.8.dev4.dist-info}/WHEEL +0 -0
- {fabricatio-0.2.8.dev2.dist-info → fabricatio-0.2.8.dev4.dist-info}/licenses/LICENSE +0 -0
fabricatio/models/generic.py
CHANGED
@@ -6,13 +6,15 @@ from pathlib import Path
|
|
6
6
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Self, Union, final, overload
|
7
7
|
|
8
8
|
import orjson
|
9
|
+
import rtoml
|
9
10
|
from fabricatio._rust import blake3_hash
|
10
11
|
from fabricatio._rust_instances import TEMPLATE_MANAGER
|
11
12
|
from fabricatio.config import configs
|
12
13
|
from fabricatio.fs.readers import MAGIKA, safe_text_read
|
13
14
|
from fabricatio.journal import logger
|
14
|
-
from fabricatio.models.utils import ok
|
15
15
|
from fabricatio.parser import JsonCapture
|
16
|
+
from fabricatio.utils import ok
|
17
|
+
from litellm.utils import token_counter
|
16
18
|
from pydantic import (
|
17
19
|
BaseModel,
|
18
20
|
ConfigDict,
|
@@ -52,6 +54,11 @@ class Display(Base):
|
|
52
54
|
"""
|
53
55
|
return self.model_dump_json()
|
54
56
|
|
57
|
+
@staticmethod
|
58
|
+
def seq_display(seq: Iterable["Display"], compact: bool = False) -> str:
|
59
|
+
"""Display a sequence of Display objects in a formatted JSON string."""
|
60
|
+
return "\n".join(d.compact() if compact else d.display() for d in seq)
|
61
|
+
|
55
62
|
|
56
63
|
class Named(Base):
|
57
64
|
"""Class that includes a name attribute."""
|
@@ -63,7 +70,7 @@ class Named(Base):
|
|
63
70
|
class Described(Base):
|
64
71
|
"""Class that includes a description attribute."""
|
65
72
|
|
66
|
-
description: str = Field(
|
73
|
+
description: str = Field(frozen=True)
|
67
74
|
"""The description of the object."""
|
68
75
|
|
69
76
|
|
@@ -98,14 +105,28 @@ class WithRef[T](Base):
|
|
98
105
|
self._reference, f"`{self.__class__.__name__}`' s `_reference` field is None. Have you called `update_ref`?"
|
99
106
|
)
|
100
107
|
|
101
|
-
|
108
|
+
@overload
|
109
|
+
def update_ref[S: WithRef](self: S, reference: T) -> S: ...
|
110
|
+
|
111
|
+
@overload
|
112
|
+
def update_ref[S: WithRef](self: S, reference: "WithRef[T]") -> S: ...
|
113
|
+
|
114
|
+
@overload
|
115
|
+
def update_ref[S: WithRef](self: S, reference: None = None) -> S: ...
|
116
|
+
def update_ref[S: WithRef](self: S, reference: Union[T, "WithRef[T]", None] = None) -> S: # noqa: PYI019
|
102
117
|
"""Update the reference of the object."""
|
103
118
|
if isinstance(reference, self.__class__):
|
104
119
|
self._reference = reference.referenced
|
105
120
|
else:
|
106
|
-
self._reference = reference
|
121
|
+
self._reference = reference # pyright: ignore [reportAttributeAccessIssue]
|
107
122
|
return self
|
108
123
|
|
124
|
+
def derive[S: WithRef](self: S, reference: Any) -> S: # noqa: PYI019
|
125
|
+
"""Derive a new object from the current object."""
|
126
|
+
new = self.model_copy()
|
127
|
+
new._reference = reference
|
128
|
+
return new
|
129
|
+
|
109
130
|
|
110
131
|
class PersistentAble(Base):
|
111
132
|
"""Class that provides a method to persist the object."""
|
@@ -120,10 +141,10 @@ class PersistentAble(Base):
|
|
120
141
|
Self: The current instance of the object.
|
121
142
|
"""
|
122
143
|
p = Path(path)
|
123
|
-
out = self.model_dump_json(
|
144
|
+
out = self.model_dump_json()
|
124
145
|
|
125
146
|
# Generate a timestamp in the format YYYYMMDD_HHMMSS
|
126
|
-
timestamp = datetime.now().strftime("%Y%m%
|
147
|
+
timestamp = datetime.now().strftime("%Y%m%d")
|
127
148
|
|
128
149
|
# Generate the hash
|
129
150
|
file_hash = blake3_hash(out.encode())[:6]
|
@@ -150,7 +171,7 @@ class PersistentAble(Base):
|
|
150
171
|
Returns:
|
151
172
|
Self: The current instance of the object.
|
152
173
|
"""
|
153
|
-
return cls.model_validate_json(
|
174
|
+
return cls.model_validate_json(safe_text_read(path))
|
154
175
|
|
155
176
|
|
156
177
|
class ModelHash(Base):
|
@@ -220,27 +241,6 @@ class WithBriefing(Named, Described):
|
|
220
241
|
"""
|
221
242
|
return f"{self.name}: {self.description}" if self.description else self.name
|
222
243
|
|
223
|
-
def _prepend_inner(self, input_text: str) -> str:
|
224
|
-
return f"# your personal briefing: \n{self.briefing}\n{input_text}"
|
225
|
-
|
226
|
-
def prepend_sys_msg[D: (Dict[str, Any], str)](self, system_msg_like: D = "") -> Dict[str, Any]:
|
227
|
-
"""Prepend the system message with the briefing.
|
228
|
-
|
229
|
-
Args:
|
230
|
-
system_msg_like (str | dict): The system message or a dictionary containing the system message.
|
231
|
-
|
232
|
-
Returns:
|
233
|
-
dict: The system message with the briefing prepended.
|
234
|
-
"""
|
235
|
-
match system_msg_like:
|
236
|
-
case dict(d):
|
237
|
-
d["system_message"] = self._prepend_inner(d.get("system_message", ""))
|
238
|
-
return d
|
239
|
-
case str(s):
|
240
|
-
return {"system_message": self._prepend_inner(s)}
|
241
|
-
case _:
|
242
|
-
raise TypeError(f"{system_msg_like} is not a dict or str")
|
243
|
-
|
244
244
|
|
245
245
|
class UnsortGenerate(GenerateJsonSchema):
|
246
246
|
"""Class that provides a reverse JSON schema of the model."""
|
@@ -314,14 +314,20 @@ class InstantiateFromString(Base):
|
|
314
314
|
Returns:
|
315
315
|
Self | None: The instance of the class or None if the string is not valid.
|
316
316
|
"""
|
317
|
-
|
317
|
+
obj = JsonCapture.convert_with(string, cls.model_validate_json)
|
318
|
+
logger.debug(f"Instantiate `{cls.__name__}` from string, {'Failed' if obj is None else 'Success'}.")
|
319
|
+
return obj
|
318
320
|
|
319
321
|
|
320
322
|
class ProposedAble(CreateJsonObjPrompt, InstantiateFromString):
|
321
323
|
"""Class that provides a method to propose a JSON object based on the requirement."""
|
322
324
|
|
323
325
|
|
324
|
-
class
|
326
|
+
class SketchedAble(ProposedAble, Display):
|
327
|
+
"""Class that provides a method to scratch the object."""
|
328
|
+
|
329
|
+
|
330
|
+
class ProposedUpdateAble(SketchedAble, UpdateFrom, ABC):
|
325
331
|
"""Make the obj can be updated from the proposed obj in place."""
|
326
332
|
|
327
333
|
|
@@ -349,8 +355,6 @@ class FinalizedDumpAble(Base):
|
|
349
355
|
return self
|
350
356
|
|
351
357
|
|
352
|
-
class CensoredAble(ProposedAble, FinalizedDumpAble):
|
353
|
-
"""Class that provides a method to censor the object."""
|
354
358
|
|
355
359
|
|
356
360
|
class WithDependency(Base):
|
@@ -441,13 +445,13 @@ class WithDependency(Base):
|
|
441
445
|
)
|
442
446
|
|
443
447
|
|
444
|
-
class
|
448
|
+
class Vectorizable(Base):
|
445
449
|
"""Class that prepares the vectorization of the model."""
|
446
450
|
|
447
|
-
@abstractmethod
|
448
451
|
def _prepare_vectorization_inner(self) -> str:
|
449
|
-
|
452
|
+
return rtoml.dumps(self.model_dump())
|
450
453
|
|
454
|
+
@final
|
451
455
|
def prepare_vectorization(self, max_length: Optional[int] = None) -> str:
|
452
456
|
"""Prepare the vectorization of the model.
|
453
457
|
|
@@ -456,8 +460,8 @@ class PrepareVectorization(Base):
|
|
456
460
|
"""
|
457
461
|
max_length = max_length or configs.embedding.max_sequence_length
|
458
462
|
chunk = self._prepare_vectorization_inner()
|
459
|
-
if max_length and
|
460
|
-
logger.error(err := f"Chunk exceeds maximum sequence length {max_length}
|
463
|
+
if max_length and (length := token_counter(text=chunk)) > max_length:
|
464
|
+
logger.error(err := f"Chunk exceeds maximum sequence length {max_length}, got {length},see {chunk}")
|
461
465
|
raise ValueError(err)
|
462
466
|
|
463
467
|
return chunk
|
@@ -572,3 +576,33 @@ class ScopedConfig(Base):
|
|
572
576
|
if (attr := getattr(self, attr_name)) is not None and getattr(other, attr_name) is None:
|
573
577
|
setattr(other, attr_name, attr)
|
574
578
|
return self
|
579
|
+
|
580
|
+
|
581
|
+
class Patch[T](ProposedAble):
|
582
|
+
"""Base class for patches."""
|
583
|
+
|
584
|
+
def apply(self, other: T) -> T:
|
585
|
+
"""Apply the patch to another instance."""
|
586
|
+
for field in self.__class__.model_fields:
|
587
|
+
if not hasattr(other, field):
|
588
|
+
raise ValueError(f"{field} not found in {other}, are you applying to the wrong type?")
|
589
|
+
setattr(other, field, getattr(self, field))
|
590
|
+
return other
|
591
|
+
|
592
|
+
|
593
|
+
class SequencePatch[T](ProposedUpdateAble):
|
594
|
+
"""Base class for patches."""
|
595
|
+
|
596
|
+
tweaked: List[T]
|
597
|
+
"""Tweaked content list"""
|
598
|
+
|
599
|
+
def update_from_inner(self, other: Self) -> Self:
|
600
|
+
"""Updates the current instance with the attributes of another instance."""
|
601
|
+
self.tweaked.clear()
|
602
|
+
self.tweaked.extend(other.tweaked)
|
603
|
+
return self
|
604
|
+
|
605
|
+
@classmethod
|
606
|
+
def default(cls) -> Self:
|
607
|
+
"""Defaults to empty list."""
|
608
|
+
return cls(tweaked=[])
|
@@ -1,7 +1,7 @@
|
|
1
1
|
"""This module contains the types for the keyword arguments of the methods in the models module."""
|
2
2
|
|
3
3
|
from importlib.util import find_spec
|
4
|
-
from typing import Any, Dict, Required, TypedDict
|
4
|
+
from typing import Any, Dict, List, Optional, Required, TypedDict
|
5
5
|
|
6
6
|
from litellm.caching.caching import CacheMode
|
7
7
|
from litellm.types.caching import CachingSupportedCallTypes
|
@@ -95,11 +95,30 @@ class ValidateKwargs[T](GenerateKwargs, total=False):
|
|
95
95
|
such as limiting the number of validation attempts.
|
96
96
|
"""
|
97
97
|
|
98
|
-
default: T
|
98
|
+
default: Optional[T]
|
99
99
|
max_validations: int
|
100
100
|
co_extractor: GenerateKwargs
|
101
101
|
|
102
102
|
|
103
|
+
class CompositeScoreKwargs(ValidateKwargs[List[Dict[str, float]]], total=False):
|
104
|
+
"""Arguments for composite score generation operations.
|
105
|
+
|
106
|
+
Extends GenerateKwargs with parameters for generating composite scores
|
107
|
+
based on specific criteria and weights.
|
108
|
+
"""
|
109
|
+
|
110
|
+
topic: str
|
111
|
+
criteria: set[str]
|
112
|
+
weights: Dict[str, float]
|
113
|
+
manual: Dict[str, str]
|
114
|
+
|
115
|
+
|
116
|
+
class BestKwargs(CompositeScoreKwargs, total=False):
|
117
|
+
"""Arguments for choose top-k operations."""
|
118
|
+
|
119
|
+
k: int
|
120
|
+
|
121
|
+
|
103
122
|
class ReviewInnerKwargs[T](ValidateKwargs[T], total=False):
|
104
123
|
"""Arguments for content review operations."""
|
105
124
|
|
@@ -118,22 +137,9 @@ class ReviewKwargs[T](ReviewInnerKwargs[T], total=False):
|
|
118
137
|
topic: Required[str]
|
119
138
|
|
120
139
|
|
121
|
-
class
|
122
|
-
"""Arguments for content
|
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
|
-
|
140
|
+
class ReferencedKwargs[T](ValidateKwargs[T], total=False):
|
141
|
+
"""Arguments for content review operations."""
|
135
142
|
reference: str
|
136
|
-
supervisor_check: bool
|
137
143
|
|
138
144
|
|
139
145
|
# noinspection PyTypedDict
|
fabricatio/models/role.py
CHANGED
@@ -8,11 +8,12 @@ from fabricatio.core import env
|
|
8
8
|
from fabricatio.journal import logger
|
9
9
|
from fabricatio.models.action import WorkFlow
|
10
10
|
from fabricatio.models.events import Event
|
11
|
+
from fabricatio.models.generic import WithBriefing
|
11
12
|
from fabricatio.models.tool import ToolBox
|
12
13
|
from pydantic import Field
|
13
14
|
|
14
15
|
|
15
|
-
class Role(ProposeTask, HandleTask, Correct):
|
16
|
+
class Role(WithBriefing, ProposeTask, HandleTask, Correct):
|
16
17
|
"""Class that represents a role with a registry of events and workflows.
|
17
18
|
|
18
19
|
A Role serves as a container for workflows, managing their registration to events
|
@@ -22,6 +23,8 @@ class Role(ProposeTask, HandleTask, Correct):
|
|
22
23
|
registry: Mapping of events to workflows that handle them
|
23
24
|
toolboxes: Set of toolboxes available to this role and its workflows
|
24
25
|
"""
|
26
|
+
description:str =""
|
27
|
+
"""A brief description of the role's responsibilities and capabilities."""
|
25
28
|
|
26
29
|
registry: dict[Event | str, WorkFlow] = Field(default_factory=dict)
|
27
30
|
"""The registry of events and workflows."""
|
fabricatio/models/usages.py
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
import traceback
|
4
4
|
from asyncio import gather
|
5
|
-
from typing import Callable, Dict, Iterable, List, Optional, Self, Sequence, Set,
|
5
|
+
from typing import Callable, Dict, Iterable, List, Optional, Self, Sequence, Set, Union, Unpack, overload
|
6
6
|
|
7
7
|
import asyncstdlib
|
8
8
|
import litellm
|
@@ -14,8 +14,9 @@ from fabricatio.models.generic import ScopedConfig, WithBriefing
|
|
14
14
|
from fabricatio.models.kwargs_types import ChooseKwargs, EmbeddingKwargs, GenerateKwargs, LLMKwargs, ValidateKwargs
|
15
15
|
from fabricatio.models.task import Task
|
16
16
|
from fabricatio.models.tool import Tool, ToolBox
|
17
|
-
from fabricatio.models.utils import Messages
|
17
|
+
from fabricatio.models.utils import Messages
|
18
18
|
from fabricatio.parser import GenericCapture, JsonCapture
|
19
|
+
from fabricatio.utils import ok
|
19
20
|
from litellm import RateLimitError, Router, stream_chunk_builder # pyright: ignore [reportPrivateImportUsage]
|
20
21
|
from litellm.types.router import Deployment, LiteLLM_Params, ModelInfo
|
21
22
|
from litellm.types.utils import (
|
@@ -52,10 +53,6 @@ class LLMUsage(ScopedConfig):
|
|
52
53
|
self._added_deployment = ROUTER.upsert_deployment(deployment)
|
53
54
|
return ROUTER
|
54
55
|
|
55
|
-
@classmethod
|
56
|
-
def _scoped_model(cls) -> Type["LLMUsage"]:
|
57
|
-
return LLMUsage
|
58
|
-
|
59
56
|
# noinspection PyTypeChecker,PydanticTypeChecker
|
60
57
|
async def aquery(
|
61
58
|
self,
|
@@ -280,7 +277,7 @@ class LLMUsage(ScopedConfig):
|
|
280
277
|
question: str | List[str],
|
281
278
|
validator: Callable[[str], T | None],
|
282
279
|
default: Optional[T] = None,
|
283
|
-
max_validations: PositiveInt =
|
280
|
+
max_validations: PositiveInt = 3,
|
284
281
|
co_extractor: Optional[GenerateKwargs] = None,
|
285
282
|
**kwargs: Unpack[GenerateKwargs],
|
286
283
|
) -> Optional[T] | List[Optional[T]] | List[T] | T:
|
@@ -302,12 +299,11 @@ class LLMUsage(ScopedConfig):
|
|
302
299
|
async def _inner(q: str) -> Optional[T]:
|
303
300
|
for lap in range(max_validations):
|
304
301
|
try:
|
305
|
-
if (
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
response := await self.aask(
|
302
|
+
if ((validated := validator(response := await self.aask(question=q, **kwargs))) is not None) or (
|
303
|
+
co_extractor
|
304
|
+
and (
|
305
|
+
validated := validator(
|
306
|
+
await self.aask(
|
311
307
|
question=(
|
312
308
|
TEMPLATE_MANAGER.render_template(
|
313
309
|
configs.templates.co_validation_template,
|
@@ -318,7 +314,8 @@ class LLMUsage(ScopedConfig):
|
|
318
314
|
)
|
319
315
|
)
|
320
316
|
)
|
321
|
-
|
317
|
+
is not None
|
318
|
+
):
|
322
319
|
logger.debug(f"Successfully validated the response at {lap}th attempt.")
|
323
320
|
return validated
|
324
321
|
|
@@ -338,7 +335,7 @@ class LLMUsage(ScopedConfig):
|
|
338
335
|
|
339
336
|
return await (gather(*[_inner(q) for q in question]) if isinstance(question, list) else _inner(question))
|
340
337
|
|
341
|
-
async def
|
338
|
+
async def alist_str(
|
342
339
|
self, requirement: str, k: NonNegativeInt = 0, **kwargs: Unpack[ValidateKwargs[List[str]]]
|
343
340
|
) -> Optional[List[str]]:
|
344
341
|
"""Asynchronously generates a list of strings based on a given requirement.
|
@@ -370,7 +367,7 @@ class LLMUsage(ScopedConfig):
|
|
370
367
|
Returns:
|
371
368
|
List[str]: The validated response as a list of strings.
|
372
369
|
"""
|
373
|
-
return await self.
|
370
|
+
return await self.alist_str(
|
374
371
|
TEMPLATE_MANAGER.render_template(
|
375
372
|
configs.templates.pathstr_template,
|
376
373
|
{"requirement": requirement},
|
@@ -550,8 +547,8 @@ class EmbeddingUsage(LLMUsage):
|
|
550
547
|
"""
|
551
548
|
# check seq length
|
552
549
|
max_len = self.embedding_max_sequence_length or configs.embedding.max_sequence_length
|
553
|
-
if max_len and any(
|
554
|
-
logger.error(err := f"Input text exceeds maximum sequence length {max_len}.")
|
550
|
+
if max_len and any(length := (token_counter(text=t)) > max_len for t in input_text):
|
551
|
+
logger.error(err := f"Input text exceeds maximum sequence length {max_len}, got {length}.")
|
555
552
|
raise ValueError(err)
|
556
553
|
|
557
554
|
return await litellm.aembedding(
|
@@ -712,7 +709,7 @@ class ToolBoxUsage(LLMUsage):
|
|
712
709
|
"""
|
713
710
|
if isinstance(others, ToolBoxUsage):
|
714
711
|
others = [others]
|
715
|
-
for other in others:
|
712
|
+
for other in (x for x in others if isinstance(x, ToolBoxUsage)):
|
716
713
|
self.toolboxes.update(other.toolboxes)
|
717
714
|
return self
|
718
715
|
|
@@ -728,6 +725,6 @@ class ToolBoxUsage(LLMUsage):
|
|
728
725
|
"""
|
729
726
|
if isinstance(others, ToolBoxUsage):
|
730
727
|
others = [others]
|
731
|
-
for other in others:
|
728
|
+
for other in (x for x in others if isinstance(x, ToolBoxUsage)):
|
732
729
|
other.toolboxes.update(self.toolboxes)
|
733
730
|
return self
|
fabricatio/models/utils.py
CHANGED
@@ -4,7 +4,6 @@ from enum import Enum
|
|
4
4
|
from typing import Any, Dict, List, Literal, Optional, Self
|
5
5
|
|
6
6
|
from pydantic import BaseModel, ConfigDict, Field
|
7
|
-
from questionary import text
|
8
7
|
|
9
8
|
|
10
9
|
class Message(BaseModel):
|
@@ -147,48 +146,3 @@ class TaskStatus(Enum):
|
|
147
146
|
Cancelled = "cancelled"
|
148
147
|
|
149
148
|
|
150
|
-
async def ask_edit(
|
151
|
-
text_seq: List[str],
|
152
|
-
) -> List[str]:
|
153
|
-
"""Asks the user to edit a list of texts.
|
154
|
-
|
155
|
-
Args:
|
156
|
-
text_seq (List[str]): A list of texts to be edited.
|
157
|
-
|
158
|
-
Returns:
|
159
|
-
List[str]: A list of edited texts.
|
160
|
-
If the user does not edit a text, it will not be included in the returned list.
|
161
|
-
"""
|
162
|
-
res = []
|
163
|
-
for i, t in enumerate(text_seq):
|
164
|
-
edited = await text(f"[{i}] ", default=t).ask_async()
|
165
|
-
if edited:
|
166
|
-
res.append(edited)
|
167
|
-
return res
|
168
|
-
|
169
|
-
|
170
|
-
def override_kwargs[T](kwargs: Dict[str, T], **overrides) -> Dict[str, T]:
|
171
|
-
"""Override the values in kwargs with the provided overrides."""
|
172
|
-
kwargs.update({k: v for k, v in overrides.items() if v is not None})
|
173
|
-
return kwargs
|
174
|
-
|
175
|
-
|
176
|
-
def fallback_kwargs[T](kwargs: Dict[str, T], **overrides) -> Dict[str, T]:
|
177
|
-
"""Fallback the values in kwargs with the provided overrides."""
|
178
|
-
kwargs.update({k: v for k, v in overrides.items() if k not in kwargs})
|
179
|
-
return kwargs
|
180
|
-
|
181
|
-
|
182
|
-
def ok[T](val: Optional[T], msg: str = "Value is None") -> T:
|
183
|
-
"""Check if a value is None and raise a ValueError with the provided message if it is.
|
184
|
-
|
185
|
-
Args:
|
186
|
-
val: The value to check.
|
187
|
-
msg: The message to include in the ValueError if val is None.
|
188
|
-
|
189
|
-
Returns:
|
190
|
-
T: The value if it is not None.
|
191
|
-
"""
|
192
|
-
if val is None:
|
193
|
-
raise ValueError(msg)
|
194
|
-
return val
|
fabricatio/parser.py
CHANGED
@@ -45,14 +45,14 @@ class Capture(BaseModel):
|
|
45
45
|
str | List[str]: The fixed text with the same type as input.
|
46
46
|
"""
|
47
47
|
match self.capture_type:
|
48
|
-
case "json":
|
48
|
+
case "json" if configs.general.use_json_repair:
|
49
|
+
logger.debug("Applying json repair to text.")
|
49
50
|
if isinstance(text, str):
|
50
51
|
return repair_json(text, ensure_ascii=False)
|
51
52
|
return [repair_json(item, ensure_ascii=False) for item in text]
|
52
53
|
case _:
|
53
54
|
return text
|
54
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.
|
58
58
|
|
@@ -63,11 +63,10 @@ class Capture(BaseModel):
|
|
63
63
|
str | None: The captured text if the pattern is found, otherwise None.
|
64
64
|
|
65
65
|
"""
|
66
|
-
match
|
67
|
-
|
68
|
-
logger.debug(f"Capture Failed: \n{text}")
|
66
|
+
if (match :=self._compiled.match(text) or self._compiled.search(text) ) is None:
|
67
|
+
logger.debug(f"Capture Failed {type(text)}: \n{text}")
|
69
68
|
return None
|
70
|
-
groups = self.fix(match.groups())
|
69
|
+
groups = self.fix(match.groups())
|
71
70
|
if self.target_groups:
|
72
71
|
cap = tuple(groups[g - 1] for g in self.target_groups)
|
73
72
|
logger.debug(f"Captured text: {'\n\n'.join(cap)}")
|
@@ -134,7 +133,7 @@ class Capture(BaseModel):
|
|
134
133
|
Returns:
|
135
134
|
Self: The instance of the class with the captured code block.
|
136
135
|
"""
|
137
|
-
return cls(pattern=f"```{language}
|
136
|
+
return cls(pattern=f"```{language}(.*?)```", capture_type=language)
|
138
137
|
|
139
138
|
@classmethod
|
140
139
|
def capture_generic_block(cls, language: str) -> Self:
|
@@ -143,7 +142,7 @@ class Capture(BaseModel):
|
|
143
142
|
Returns:
|
144
143
|
Self: The instance of the class with the captured code block.
|
145
144
|
"""
|
146
|
-
return cls(pattern=f"--- Start of {language}
|
145
|
+
return cls(pattern=f"--- Start of {language} ---(.*?)--- end of {language} ---", capture_type=language)
|
147
146
|
|
148
147
|
|
149
148
|
JsonCapture = Capture.capture_code_block("json")
|
fabricatio/utils.py
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
"""A collection of utility functions for the fabricatio package."""
|
2
|
+
|
3
|
+
from typing import Any, Dict, List, Optional
|
4
|
+
|
5
|
+
from questionary import text
|
6
|
+
|
7
|
+
|
8
|
+
async def ask_edit(
|
9
|
+
text_seq: List[str],
|
10
|
+
) -> List[str]:
|
11
|
+
"""Asks the user to edit a list of texts.
|
12
|
+
|
13
|
+
Args:
|
14
|
+
text_seq (List[str]): A list of texts to be edited.
|
15
|
+
|
16
|
+
Returns:
|
17
|
+
List[str]: A list of edited texts.
|
18
|
+
If the user does not edit a text, it will not be included in the returned list.
|
19
|
+
"""
|
20
|
+
res = []
|
21
|
+
for i, t in enumerate(text_seq):
|
22
|
+
edited = await text(f"[{i}] ", default=t).ask_async()
|
23
|
+
if edited:
|
24
|
+
res.append(edited)
|
25
|
+
return res
|
26
|
+
|
27
|
+
|
28
|
+
def override_kwargs(kwargs: Dict[str,Any], **overrides) -> Dict[str, Any]:
|
29
|
+
"""Override the values in kwargs with the provided overrides."""
|
30
|
+
new_kwargs = kwargs.copy()
|
31
|
+
new_kwargs.update({k: v for k, v in overrides.items() if v is not None})
|
32
|
+
return new_kwargs
|
33
|
+
|
34
|
+
|
35
|
+
def fallback_kwargs(kwargs: Dict[str, Any], **overrides) -> Dict[str, Any]:
|
36
|
+
"""Fallback the values in kwargs with the provided overrides."""
|
37
|
+
new_kwargs = kwargs.copy()
|
38
|
+
new_kwargs.update({k: v for k, v in overrides.items() if k not in new_kwargs and v is not None})
|
39
|
+
return new_kwargs
|
40
|
+
|
41
|
+
|
42
|
+
def ok[T](val: Optional[T], msg: str = "Value is None") -> T:
|
43
|
+
"""Check if a value is None and raise a ValueError with the provided message if it is.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
val: The value to check.
|
47
|
+
msg: The message to include in the ValueError if val is None.
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
T: The value if it is not None.
|
51
|
+
"""
|
52
|
+
if val is None:
|
53
|
+
raise ValueError(msg)
|
54
|
+
return val
|
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fabricatio
|
3
|
-
Version: 0.2.8.
|
3
|
+
Version: 0.2.8.dev4
|
4
4
|
Classifier: License :: OSI Approved :: MIT License
|
5
5
|
Classifier: Programming Language :: Rust
|
6
6
|
Classifier: Programming Language :: Python :: 3.12
|
@@ -23,6 +23,7 @@ Requires-Dist: pymitter>=1.0.0
|
|
23
23
|
Requires-Dist: questionary>=2.1.0
|
24
24
|
Requires-Dist: regex>=2024.11.6
|
25
25
|
Requires-Dist: rich>=13.9.4
|
26
|
+
Requires-Dist: rtoml>=0.12.0
|
26
27
|
Requires-Dist: pymilvus>=2.5.4 ; extra == 'rag'
|
27
28
|
Requires-Dist: fabricatio[calc,plot,rag] ; extra == 'full'
|
28
29
|
Requires-Dist: sympy>=1.13.3 ; extra == 'calc'
|
@@ -0,0 +1,56 @@
|
|
1
|
+
fabricatio-0.2.8.dev4.dist-info/METADATA,sha256=m8008QWQ2qtSzryx4jr2DpTqfNQDyhBUscJQgQzmM0I,5288
|
2
|
+
fabricatio-0.2.8.dev4.dist-info/WHEEL,sha256=jABKVkLC9kJr8mi_er5jOqpiQUjARSLXDUIIxDqsS50,96
|
3
|
+
fabricatio-0.2.8.dev4.dist-info/licenses/LICENSE,sha256=do7J7EiCGbq0QPbMAL_FqLYufXpHnCnXBOuqVPwSV8Y,1088
|
4
|
+
fabricatio/actions/article.py,sha256=i5-u5tCiJd7b_lQ4_vHjV57ZXDoUIAHmgD9QFoFaTuM,12787
|
5
|
+
fabricatio/actions/article_rag.py,sha256=dkfskNqntVPi81Xm_NFdTQM8v2nR9FJIexzkK9rg-NU,4352
|
6
|
+
fabricatio/actions/output.py,sha256=-FfTzXEHIb_zOT-j4T4b5ND96zHLDEGdjlmmPviIbiM,3754
|
7
|
+
fabricatio/actions/rag.py,sha256=wb3vt-gS6fDHYJ57Yfu_OR0kpewT9vMqwtXsqXd42Kg,2735
|
8
|
+
fabricatio/capabilities/advanced_judge.py,sha256=selB0Gwf1F4gGJlwBiRo6gI4KOUROgh3WnzO3mZFEls,706
|
9
|
+
fabricatio/capabilities/censor.py,sha256=-FZTDFfqlIwqMd4hkKzEHAknlp2pH5sawXDQ-7XJcXA,3784
|
10
|
+
fabricatio/capabilities/check.py,sha256=_4FS0kTa37A3M8Cjl1oVxp1j971W5O58NxmtsU1TizA,8005
|
11
|
+
fabricatio/capabilities/correct.py,sha256=8ax8oa9e4EIzho-cTXku-Sy7rC1zrOdlo23ooDZEyuM,9178
|
12
|
+
fabricatio/capabilities/propose.py,sha256=hkBeSlmcTdfYWT-ph6nlbtHXBozi_JXqXlWcnBy3W78,2007
|
13
|
+
fabricatio/capabilities/rag.py,sha256=7xDxDEvhlmb7Y-mEquSgvlVIYpHsM2YFxA9LjRpVajo,17720
|
14
|
+
fabricatio/capabilities/rating.py,sha256=3gBqmYpEpzKge4mpxclJ4f9Nl_MTnADjuj4uqxw2Ilo,17011
|
15
|
+
fabricatio/capabilities/review.py,sha256=1MGyJudPxHVOQod_GYKJ7NyB3jOWuwZhqBP30hAZ5Z4,5061
|
16
|
+
fabricatio/capabilities/task.py,sha256=JG9kD2n86FvZQIjqZq-aqw8j9jpuuDpEDKTJCB6HzX4,4416
|
17
|
+
fabricatio/config.py,sha256=aA-wirVVfjRuk1AXj-l9UFQFaDEBtV3YnzQIwCPE_G0,17503
|
18
|
+
fabricatio/core.py,sha256=VQ_JKgUGIy2gZ8xsTBZCdr_IP7wC5aPg0_bsOmjQ588,6458
|
19
|
+
fabricatio/decorators.py,sha256=C0Gi7wcXC-0sWITqsSv3JdBGcgVJOlRvOt0FfO0aUsA,7554
|
20
|
+
fabricatio/fs/curd.py,sha256=p8y0LGKgVDk-CWOlm37E6wg7RK6RCD6denKo-VsW28c,4763
|
21
|
+
fabricatio/fs/readers.py,sha256=EZKN_AZdrp8DggJECP53QHw3uHeSDf-AwCAA_V7fNKU,1202
|
22
|
+
fabricatio/fs/__init__.py,sha256=PCf0s_9KDjVfNw7AfPoJzGt3jMq4gJOfbcT4pb0D0ZY,588
|
23
|
+
fabricatio/journal.py,sha256=stnEP88aUBA_GmU9gfTF2EZI8FS2OyMLGaMSTgK4QgA,476
|
24
|
+
fabricatio/models/action.py,sha256=dZkPP-7DaJIOjsFYWnp6vcOObMgjvda1O2FjboSDYjo,9003
|
25
|
+
fabricatio/models/adv_kwargs_types.py,sha256=dcYMLn6xcnWLZTLTBdtpgUZWi-VBeub721GzHRZFT1g,860
|
26
|
+
fabricatio/models/events.py,sha256=QvlnS8FEELg6KNabcJMeh2GV_y0ZBzKOPphcteKYWYU,4183
|
27
|
+
fabricatio/models/extra/advanced_judge.py,sha256=mi3KiB8FUuSYICzXPXKwVhCyRE1GL3gHLkwuc-4mh3c,999
|
28
|
+
fabricatio/models/extra/article_base.py,sha256=1Fg3iWbod1TCU3nIJK9mOq_8K3oGBtSW03VUwi2I5tg,17058
|
29
|
+
fabricatio/models/extra/article_essence.py,sha256=xd6j-PDqjhrMjgUmyfk6HqkyMLu-sS9feUo0sZ3QABY,2825
|
30
|
+
fabricatio/models/extra/article_main.py,sha256=0Xj54pRxUw5Iaj9npYmHKT-ZMvEIBlZ6G1ysNJRgceM,8225
|
31
|
+
fabricatio/models/extra/article_outline.py,sha256=jFbVgiwlo7rnwCGS6ToVgeMUOoRe99Edgbx95THR6z8,1450
|
32
|
+
fabricatio/models/extra/article_proposal.py,sha256=L2kPvH1XCCQSNcI1KQU3ULGq7C24Y88ssugX43LgbsE,2043
|
33
|
+
fabricatio/models/extra/patches.py,sha256=_yyyDbaQ8wkj6QP-NU-3I74HehFgwD889vD0SlCjynU,303
|
34
|
+
fabricatio/models/extra/problem.py,sha256=KwYkc7kjoEG7cwj9C8sWLoZgtBqJVuxlU_7KkvtSgO0,5828
|
35
|
+
fabricatio/models/extra/rule.py,sha256=_ThlHOViuHcJdAhc6qdEUHaFOevvQYHvH89STzucUyM,719
|
36
|
+
fabricatio/models/generic.py,sha256=uuCwpG4DS5DwnZ-2lRMBDufWbKp_5x4yuh1eAFwkFKY,20682
|
37
|
+
fabricatio/models/kwargs_types.py,sha256=sMDA85SoC1AOJ5k6qC8qUiUv0Ne0_5ThU9FZITRNen4,5673
|
38
|
+
fabricatio/models/role.py,sha256=-CRcj5_M3_ciLPzwiNn92grBmwoSLQ-n4koVZiCNTBM,2953
|
39
|
+
fabricatio/models/task.py,sha256=8NaR7ojQWyM740EDTqt9stwHKdrD6axCRpLKo0QzS-I,10492
|
40
|
+
fabricatio/models/tool.py,sha256=kD0eB7OxO9geZOxO6JIKvCBeG-KOpRAkfRZqK_WGfW4,7105
|
41
|
+
fabricatio/models/usages.py,sha256=UC-igtnfW0scIkedb5leZuuR4XoSZYI7kf1S0L418CU,31813
|
42
|
+
fabricatio/models/utils.py,sha256=Ac5g-8ic6q_w7dhNuh-iiofpL1sqOACxbjPPTljP2LY,4417
|
43
|
+
fabricatio/parser.py,sha256=UOSvXigEXK-eXsr3m3b7glOhbBWs4kDJTeTNyuqA9ic,6315
|
44
|
+
fabricatio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
45
|
+
fabricatio/toolboxes/arithmetic.py,sha256=WLqhY-Pikv11Y_0SGajwZx3WhsLNpHKf9drzAqOf_nY,1369
|
46
|
+
fabricatio/toolboxes/fs.py,sha256=l4L1CVxJmjw9Ld2XUpIlWfV0_Fu_2Og6d3E13I-S4aE,736
|
47
|
+
fabricatio/toolboxes/__init__.py,sha256=KBJi5OG_pExscdlM7Bnt_UF43j4I3Lv6G71kPVu4KQU,395
|
48
|
+
fabricatio/utils.py,sha256=QJR00IuclL2nNTSfpTNBRYJmNjc_DNXGtrYWjatWpq8,1681
|
49
|
+
fabricatio/workflows/articles.py,sha256=G5HGRr-DHuYuEcfhFdFAuDvTTJ9aSU_UQ2yYXEjTMtM,1047
|
50
|
+
fabricatio/workflows/rag.py,sha256=-YYp2tlE9Vtfgpg6ROpu6QVO8j8yVSPa6yDzlN3qVxs,520
|
51
|
+
fabricatio/_rust.pyi,sha256=_N8Jw1DMOFAaoibSQolxkKZ07nCfJao7Z9qkojHtLy0,5104
|
52
|
+
fabricatio/_rust_instances.py,sha256=2GwF8aVfYNemRI2feBzH1CZfBGno-XJJE5imJokGEYw,314
|
53
|
+
fabricatio/__init__.py,sha256=SzBYsRhZeL77jLtfJEjmoHOSwHwUGyvMATX6xfndLDM,1135
|
54
|
+
fabricatio/_rust.cp312-win_amd64.pyd,sha256=y_AwUxK1t-eJJnlDm9MowMbM8s_GzUXAPX5W9Ao_06U,1892352
|
55
|
+
fabricatio-0.2.8.dev4.data/scripts/tdown.exe,sha256=OKVp-_Q3lDufrVIc_ZmFJRKukM6TGqWnMMs0YOXULQE,3402240
|
56
|
+
fabricatio-0.2.8.dev4.dist-info/RECORD,,
|