fabricatio 0.2.9.dev3__cp312-cp312-win_amd64.whl → 0.2.10.dev0__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 (35) hide show
  1. fabricatio/actions/article.py +13 -113
  2. fabricatio/actions/article_rag.py +9 -2
  3. fabricatio/capabilities/check.py +15 -9
  4. fabricatio/capabilities/correct.py +5 -6
  5. fabricatio/capabilities/rag.py +39 -232
  6. fabricatio/capabilities/rating.py +46 -40
  7. fabricatio/config.py +2 -2
  8. fabricatio/constants.py +20 -0
  9. fabricatio/decorators.py +23 -0
  10. fabricatio/fs/readers.py +20 -1
  11. fabricatio/models/adv_kwargs_types.py +42 -0
  12. fabricatio/models/events.py +6 -6
  13. fabricatio/models/extra/advanced_judge.py +4 -4
  14. fabricatio/models/extra/article_base.py +25 -211
  15. fabricatio/models/extra/article_main.py +69 -95
  16. fabricatio/models/extra/article_proposal.py +15 -14
  17. fabricatio/models/extra/patches.py +6 -6
  18. fabricatio/models/extra/problem.py +12 -17
  19. fabricatio/models/extra/rag.py +72 -0
  20. fabricatio/models/extra/rule.py +1 -2
  21. fabricatio/models/generic.py +34 -10
  22. fabricatio/models/kwargs_types.py +1 -38
  23. fabricatio/models/task.py +3 -3
  24. fabricatio/models/usages.py +78 -8
  25. fabricatio/parser.py +5 -5
  26. fabricatio/rust.cp312-win_amd64.pyd +0 -0
  27. fabricatio/rust.pyi +27 -12
  28. fabricatio-0.2.10.dev0.data/scripts/tdown.exe +0 -0
  29. {fabricatio-0.2.9.dev3.dist-info → fabricatio-0.2.10.dev0.dist-info}/METADATA +1 -1
  30. fabricatio-0.2.10.dev0.dist-info/RECORD +62 -0
  31. fabricatio/models/utils.py +0 -148
  32. fabricatio-0.2.9.dev3.data/scripts/tdown.exe +0 -0
  33. fabricatio-0.2.9.dev3.dist-info/RECORD +0 -61
  34. {fabricatio-0.2.9.dev3.dist-info → fabricatio-0.2.10.dev0.dist-info}/WHEEL +0 -0
  35. {fabricatio-0.2.9.dev3.dist-info → fabricatio-0.2.10.dev0.dist-info}/licenses/LICENSE +0 -0
@@ -5,19 +5,19 @@ from random import sample
5
5
  from typing import Dict, List, Optional, Set, Tuple, Union, Unpack, overload
6
6
 
7
7
  from more_itertools import flatten, windowed
8
- from pydantic import NonNegativeInt, PositiveInt
8
+ from pydantic import Field, NonNegativeInt, PositiveInt, create_model
9
9
 
10
+ from fabricatio.capabilities.propose import Propose
10
11
  from fabricatio.config import configs
11
12
  from fabricatio.journal import logger
12
- from fabricatio.models.generic import Display
13
+ from fabricatio.models.generic import Display, ProposedAble
13
14
  from fabricatio.models.kwargs_types import CompositeScoreKwargs, ValidateKwargs
14
- from fabricatio.models.usages import LLMUsage
15
15
  from fabricatio.parser import JsonCapture
16
16
  from fabricatio.rust_instances import TEMPLATE_MANAGER
17
- from fabricatio.utils import ok, override_kwargs
17
+ from fabricatio.utils import fallback_kwargs, ok, override_kwargs
18
18
 
19
19
 
20
- class Rating(LLMUsage):
20
+ class Rating(Propose):
21
21
  """A class that provides functionality to rate tasks based on a rating manual and score range.
22
22
 
23
23
  References:
@@ -30,7 +30,7 @@ class Rating(LLMUsage):
30
30
  rating_manual: Dict[str, str],
31
31
  score_range: Tuple[float, float],
32
32
  **kwargs: Unpack[ValidateKwargs[Dict[str, float]]],
33
- ) -> Optional[Dict[str, float] | List[Dict[str, float]]]:
33
+ ) -> Dict[str, float] | List[Dict[str, float]] | List[Optional[Dict[str, float]]] | None:
34
34
  """Rate a given string based on a rating manual and score range.
35
35
 
36
36
  Args:
@@ -42,45 +42,49 @@ class Rating(LLMUsage):
42
42
  Returns:
43
43
  Dict[str, float]: A dictionary with the ratings for each dimension.
44
44
  """
45
-
46
- def _validator(response: str) -> Optional[Dict[str, float]] :
47
- if (
48
- (json_data := JsonCapture.validate_with(response, dict, str))
49
- and json_data.keys() == rating_manual.keys()
50
- and all(score_range[0] <= v <= score_range[1] for v in json_data.values())
51
- ):
52
- return json_data
53
- return None
54
-
55
- logger.info(f"Rating for {to_rate}")
56
- return await self.aask_validate(
57
- question=(
58
- TEMPLATE_MANAGER.render_template(
59
- configs.templates.rate_fine_grind_template,
60
- {
61
- "to_rate": to_rate,
62
- "min_score": score_range[0],
63
- "max_score": score_range[1],
64
- "rating_manual": rating_manual,
65
- },
45
+ min_score, max_score = score_range
46
+ tip = (max_score - min_score) / 9
47
+
48
+ model = create_model( # pyright: ignore [reportCallIssue]
49
+ "RatingResult",
50
+ __base__=ProposedAble,
51
+ __doc__=f"The rating result contains the scores against each criterion, with min_score={min_score} and max_score={max_score}.",
52
+ **{ # pyright: ignore [reportArgumentType]
53
+ criterion: (
54
+ float,
55
+ Field(
56
+ ge=min_score,
57
+ le=max_score,
58
+ description=desc,
59
+ examples=[round(min_score + tip * i, 2) for i in range(10)],
60
+ ),
66
61
  )
62
+ for criterion, desc in rating_manual.items()
63
+ },
64
+ )
65
+
66
+ res = await self.propose(
67
+ model,
68
+ TEMPLATE_MANAGER.render_template(
69
+ configs.templates.rate_fine_grind_template,
70
+ {"to_rate": to_rate, "min_score": min_score, "max_score": max_score},
67
71
  )
68
72
  if isinstance(to_rate, str)
69
73
  else [
70
74
  TEMPLATE_MANAGER.render_template(
71
75
  configs.templates.rate_fine_grind_template,
72
- {
73
- "to_rate": item,
74
- "min_score": score_range[0],
75
- "max_score": score_range[1],
76
- "rating_manual": rating_manual,
77
- },
76
+ {"to_rate": t, "min_score": min_score, "max_score": max_score},
78
77
  )
79
- for item in to_rate
78
+ for t in to_rate
80
79
  ],
81
- validator=_validator,
82
- **kwargs,
80
+ **override_kwargs(kwargs, default=None),
83
81
  )
82
+ default = kwargs.get("default")
83
+ if isinstance(res, list):
84
+ return [r.model_dump() if r else default for r in res]
85
+ if res is None:
86
+ return default
87
+ return res.model_dump()
84
88
 
85
89
  @overload
86
90
  async def rate(
@@ -112,7 +116,7 @@ class Rating(LLMUsage):
112
116
  manual: Optional[Dict[str, str]] = None,
113
117
  score_range: Tuple[float, float] = (0.0, 1.0),
114
118
  **kwargs: Unpack[ValidateKwargs],
115
- ) -> Optional[Dict[str, float] | List[Dict[str, float]]]:
119
+ ) -> Dict[str, float] | List[Dict[str, float]] | List[Optional[Dict[str, float]]] | None:
116
120
  """Rate a given string or a sequence of strings based on a topic, criteria, and score range.
117
121
 
118
122
  Args:
@@ -133,7 +137,7 @@ class Rating(LLMUsage):
133
137
  or dict(zip(criteria, criteria, strict=True))
134
138
  )
135
139
 
136
- return await self.rate_fine_grind(to_rate, manual, score_range, **kwargs)
140
+ return await self.rate_fine_grind(to_rate, manual, score_range, **fallback_kwargs(kwargs, co_extractor={}))
137
141
 
138
142
  async def draft_rating_manual(
139
143
  self, topic: str, criteria: Optional[Set[str]] = None, **kwargs: Unpack[ValidateKwargs[Dict[str, str]]]
@@ -244,7 +248,7 @@ class Rating(LLMUsage):
244
248
 
245
249
  # extract reasons from the comparison of ordered pairs of extracted from examples
246
250
  reasons = flatten(
247
- await self.aask_validate(
251
+ await self.aask_validate( # pyright: ignore [reportArgumentType]
248
252
  question=[
249
253
  TEMPLATE_MANAGER.render_template(
250
254
  configs.templates.extract_reasons_from_examples_template,
@@ -319,9 +323,11 @@ class Rating(LLMUsage):
319
323
  validator=lambda resp: JsonCapture.validate_with(resp, target_type=float),
320
324
  **kwargs,
321
325
  )
326
+ if not all(relative_weights):
327
+ raise ValueError(f"found illegal weight: {relative_weights}")
322
328
  weights = [1.0]
323
329
  for rw in relative_weights:
324
- weights.append(weights[-1] * rw)
330
+ weights.append(weights[-1] * rw) # pyright: ignore [reportOperatorIssue]
325
331
  total = sum(weights)
326
332
  return dict(zip(criteria_seq, [w / total for w in weights], strict=True))
327
333
 
fabricatio/config.py CHANGED
@@ -44,7 +44,7 @@ class LLMConfig(BaseModel):
44
44
  top_p (NonNegativeFloat): The top p of the LLM model. Controls diversity via nucleus sampling. Set to 0.35 as per request.
45
45
  generation_count (PositiveInt): The number of generations to generate. Default is 1.
46
46
  stream (bool): Whether to stream the LLM model's response. Default is False.
47
- max_tokens (PositiveInt): The maximum number of tokens to generate. Set to 8192 as per request.
47
+ max_tokens (PositiveInt): The maximum number of tokens to generate.
48
48
  """
49
49
 
50
50
  model_config = ConfigDict(use_attribute_docstrings=True)
@@ -79,7 +79,7 @@ class LLMConfig(BaseModel):
79
79
  """Whether to stream the LLM model's response. Default is False."""
80
80
 
81
81
  max_tokens: Optional[PositiveInt] = Field(default=None)
82
- """The maximum number of tokens to generate. Set to 8192 as per request."""
82
+ """The maximum number of tokens to generate."""
83
83
 
84
84
  rpm: Optional[PositiveInt] = Field(default=100)
85
85
  """The rate limit of the LLM model in requests per minute. None means not checked."""
@@ -0,0 +1,20 @@
1
+ """A module containing constants used throughout the library."""
2
+ from enum import StrEnum
3
+
4
+
5
+ class TaskStatus(StrEnum):
6
+ """An enumeration representing the status of a task.
7
+
8
+ Attributes:
9
+ Pending: The task is pending.
10
+ Running: The task is currently running.
11
+ Finished: The task has been successfully completed.
12
+ Failed: The task has failed.
13
+ Cancelled: The task has been cancelled.
14
+ """
15
+
16
+ Pending = "pending"
17
+ Running = "running"
18
+ Finished = "finished"
19
+ Failed = "failed"
20
+ Cancelled = "cancelled"
fabricatio/decorators.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from asyncio import iscoroutinefunction
4
4
  from functools import wraps
5
+ from importlib.util import find_spec
5
6
  from inspect import signature
6
7
  from shutil import which
7
8
  from types import ModuleType
@@ -209,3 +210,25 @@ def logging_exec_time[**P, R](func: Callable[P, R]) -> Callable[P, R]:
209
210
  return result
210
211
 
211
212
  return _wrapper
213
+
214
+
215
+ def precheck_package[**P, R](package_name: str, msg: str) -> Callable[[Callable[P, R]], Callable[P, R]]:
216
+ """Check if a package exists in the current environment.
217
+
218
+ Args:
219
+ package_name (str): The name of the package to check.
220
+ msg (str): The message to display if the package is not found.
221
+
222
+ Returns:
223
+ bool: True if the package exists, False otherwise.
224
+ """
225
+
226
+ def _wrapper(func: Callable[P, R]) -> Callable[P, R]:
227
+ def _inner(*args: P.args, **kwargs: P.kwargs) -> R:
228
+ if find_spec(package_name):
229
+ return func(*args, **kwargs)
230
+ raise RuntimeError(msg)
231
+
232
+ return _inner
233
+
234
+ return _wrapper
fabricatio/fs/readers.py CHANGED
@@ -1,9 +1,10 @@
1
1
  """Filesystem readers for Fabricatio."""
2
2
 
3
3
  from pathlib import Path
4
- from typing import Dict
4
+ from typing import Dict, List, Tuple
5
5
 
6
6
  import orjson
7
+ import regex
7
8
  from magika import Magika
8
9
 
9
10
  from fabricatio.config import configs
@@ -44,3 +45,21 @@ def safe_json_read(path: Path | str) -> Dict:
44
45
  except (orjson.JSONDecodeError, IsADirectoryError, FileNotFoundError) as e:
45
46
  logger.error(f"Failed to read file {path}: {e!s}")
46
47
  return {}
48
+
49
+
50
+ def extract_sections(string: str, level: int, section_char: str = "#") -> List[Tuple[str, str]]:
51
+ """Extract sections from markdown-style text by header level.
52
+
53
+ Args:
54
+ string (str): Input text to parse
55
+ level (int): Header level (e.g., 1 for '#', 2 for '##')
56
+ section_char (str, optional): The character used for headers (default: '#')
57
+
58
+ Returns:
59
+ List[Tuple[str, str]]: List of (header_text, section_content) tuples
60
+ """
61
+ return regex.findall(
62
+ r"^%s{%d}\s+(.+?)\n((?:(?!^%s{%d}\s).|\n)*)" % (section_char, level, section_char, level),
63
+ string,
64
+ regex.MULTILINE,
65
+ )
@@ -1,5 +1,10 @@
1
1
  """A module containing kwargs types for content correction and checking operations."""
2
+
3
+ from importlib.util import find_spec
4
+ from typing import Required, Type, TypedDict
5
+
2
6
  from fabricatio.models.extra.problem import Improvement
7
+ from fabricatio.models.extra.rag import MilvusDataBase
3
8
  from fabricatio.models.extra.rule import RuleSet
4
9
  from fabricatio.models.generic import SketchedAble
5
10
  from fabricatio.models.kwargs_types import ReferencedKwargs
@@ -23,3 +28,40 @@ class CheckKwargs(ReferencedKwargs[Improvement], total=False):
23
28
  """
24
29
 
25
30
  ruleset: RuleSet
31
+
32
+
33
+ if find_spec("pymilvus"):
34
+ from pymilvus import CollectionSchema
35
+ from pymilvus.milvus_client import IndexParams
36
+
37
+ class CollectionConfigKwargs(TypedDict, total=False):
38
+ """Configuration parameters for a vector collection.
39
+
40
+ These arguments are typically used when configuring connections to vector databases.
41
+ """
42
+
43
+ dimension: int | None
44
+ primary_field_name: str
45
+ id_type: str
46
+ vector_field_name: str
47
+ metric_type: str
48
+ timeout: float | None
49
+ schema: CollectionSchema | None
50
+ index_params: IndexParams | None
51
+
52
+ class FetchKwargs[D: MilvusDataBase](TypedDict, total=False):
53
+ """Arguments for fetching data from vector collections.
54
+
55
+ Controls how data is retrieved from vector databases, including filtering
56
+ and result limiting parameters.
57
+ """
58
+
59
+ document_model: Required[Type[D]]
60
+ collection_name: str | None
61
+ similarity_threshold: float
62
+ result_per_query: int
63
+
64
+ class RetrievalKwargs(FetchKwargs, total=False):
65
+ """Arguments for retrieval operations."""
66
+
67
+ final_limit: int
@@ -3,7 +3,7 @@
3
3
  from typing import List, Self, Union
4
4
 
5
5
  from fabricatio.config import configs
6
- from fabricatio.models.utils import TaskStatus
6
+ from fabricatio.constants import TaskStatus
7
7
  from pydantic import BaseModel, ConfigDict, Field
8
8
 
9
9
  type EventLike = Union[str, List[str], "Event"]
@@ -77,23 +77,23 @@ class Event(BaseModel):
77
77
 
78
78
  def push_pending(self) -> Self:
79
79
  """Push a pending segment to the event."""
80
- return self.push(TaskStatus.Pending.value)
80
+ return self.push(TaskStatus.Pending)
81
81
 
82
82
  def push_running(self) -> Self:
83
83
  """Push a running segment to the event."""
84
- return self.push(TaskStatus.Running.value)
84
+ return self.push(TaskStatus.Running)
85
85
 
86
86
  def push_finished(self) -> Self:
87
87
  """Push a finished segment to the event."""
88
- return self.push(TaskStatus.Finished.value)
88
+ return self.push(TaskStatus.Finished)
89
89
 
90
90
  def push_failed(self) -> Self:
91
91
  """Push a failed segment to the event."""
92
- return self.push(TaskStatus.Failed.value)
92
+ return self.push(TaskStatus.Failed)
93
93
 
94
94
  def push_cancelled(self) -> Self:
95
95
  """Push a cancelled segment to the event."""
96
- return self.push(TaskStatus.Cancelled.value)
96
+ return self.push(TaskStatus.Cancelled)
97
97
 
98
98
  def pop(self) -> str:
99
99
  """Pop a segment from the event."""
@@ -2,17 +2,17 @@
2
2
 
3
3
  from typing import List
4
4
 
5
- from fabricatio.models.generic import Display, ProposedAble
5
+ from fabricatio.models.generic import SketchedAble
6
6
 
7
7
 
8
- class JudgeMent(ProposedAble, Display):
8
+ class JudgeMent(SketchedAble):
9
9
  """Represents a judgment result containing supporting/denying evidence and final verdict.
10
10
 
11
11
  The class stores both affirmative and denies evidence, truth and reasons lists along with the final boolean judgment.
12
12
  """
13
13
 
14
14
  issue_to_judge: str
15
- """The issue to be judged"""
15
+ """The issue to be judged, including the original question and context"""
16
16
 
17
17
  deny_evidence: List[str]
18
18
  """List of clues supporting the denial."""
@@ -21,7 +21,7 @@ class JudgeMent(ProposedAble, Display):
21
21
  """List of clues supporting the affirmation."""
22
22
 
23
23
  final_judgement: bool
24
- """The final judgment made according to all extracted clues."""
24
+ """The final judgment made according to all extracted clues. true for the `issue_to_judge` is correct and false for incorrect."""
25
25
 
26
26
  def __bool__(self) -> bool:
27
27
  """Return the final judgment value.