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.
Files changed (37) hide show
  1. fabricatio/_rust.cp312-win_amd64.pyd +0 -0
  2. fabricatio/_rust.pyi +1 -1
  3. fabricatio/actions/article.py +112 -121
  4. fabricatio/actions/article_rag.py +55 -45
  5. fabricatio/actions/output.py +4 -3
  6. fabricatio/actions/rag.py +3 -3
  7. fabricatio/capabilities/censor.py +87 -0
  8. fabricatio/capabilities/check.py +194 -0
  9. fabricatio/capabilities/correct.py +142 -98
  10. fabricatio/capabilities/propose.py +20 -4
  11. fabricatio/capabilities/rag.py +3 -2
  12. fabricatio/capabilities/rating.py +67 -22
  13. fabricatio/capabilities/review.py +18 -187
  14. fabricatio/capabilities/task.py +8 -9
  15. fabricatio/config.py +11 -3
  16. fabricatio/models/action.py +8 -5
  17. fabricatio/models/adv_kwargs_types.py +25 -0
  18. fabricatio/models/extra/advanced_judge.py +10 -7
  19. fabricatio/models/extra/article_base.py +47 -27
  20. fabricatio/models/extra/article_essence.py +40 -209
  21. fabricatio/models/extra/article_main.py +3 -4
  22. fabricatio/models/extra/patches.py +7 -0
  23. fabricatio/models/extra/problem.py +153 -0
  24. fabricatio/models/extra/rule.py +21 -0
  25. fabricatio/models/generic.py +71 -37
  26. fabricatio/models/kwargs_types.py +23 -17
  27. fabricatio/models/role.py +4 -1
  28. fabricatio/models/usages.py +17 -20
  29. fabricatio/models/utils.py +0 -46
  30. fabricatio/parser.py +7 -8
  31. fabricatio/utils.py +54 -0
  32. {fabricatio-0.2.8.dev2.data → fabricatio-0.2.8.dev4.data}/scripts/tdown.exe +0 -0
  33. {fabricatio-0.2.8.dev2.dist-info → fabricatio-0.2.8.dev4.dist-info}/METADATA +2 -1
  34. fabricatio-0.2.8.dev4.dist-info/RECORD +56 -0
  35. fabricatio-0.2.8.dev2.dist-info/RECORD +0 -49
  36. {fabricatio-0.2.8.dev2.dist-info → fabricatio-0.2.8.dev4.dist-info}/WHEEL +0 -0
  37. {fabricatio-0.2.8.dev2.dist-info → fabricatio-0.2.8.dev4.dist-info}/licenses/LICENSE +0 -0
@@ -2,9 +2,8 @@
2
2
 
3
3
  from abc import ABC, abstractmethod
4
4
  from enum import StrEnum
5
- from functools import cache
6
5
  from itertools import chain
7
- from typing import Generator, List, Optional, Self, Tuple
6
+ from typing import Generator, List, Optional, Self, Tuple, overload
8
7
 
9
8
  from fabricatio.models.generic import (
10
9
  AsPrompt,
@@ -16,6 +15,7 @@ from fabricatio.models.generic import (
16
15
  PersistentAble,
17
16
  ProposedUpdateAble,
18
17
  ResolveUpdateConflict,
18
+ SequencePatch,
19
19
  )
20
20
 
21
21
 
@@ -30,8 +30,7 @@ class ReferringType(StrEnum):
30
30
  type RefKey = Tuple[str, Optional[str], Optional[str]]
31
31
 
32
32
 
33
- @cache
34
- class ArticleRef(CensoredAble, Display, ProposedUpdateAble):
33
+ class ArticleRef(CensoredAble, ProposedUpdateAble):
35
34
  """Reference to a specific chapter, section or subsection within the article. You SHALL not refer to an article component that is external and not present within our own article.
36
35
 
37
36
  Examples:
@@ -122,30 +121,10 @@ class ArticleMetaData(CensoredAble, Display):
122
121
  """Do not add any prefix or suffix to the title. should not contain special characters."""
123
122
 
124
123
 
125
- class Patch[T](ProposedUpdateAble, Display):
126
- """Base class for patches."""
127
-
128
- tweaked: List[T]
129
- """Tweaked content list"""
130
- def update_from_inner(self, other: Self) -> Self:
131
- """Updates the current instance with the attributes of another instance."""
132
- self.tweaked.clear()
133
- self.tweaked.extend(other.tweaked)
134
- return self
135
-
136
-
137
- @classmethod
138
- def default(cls) -> Self:
139
- """Defaults to empty list."""
140
- return cls(tweaked=[])
141
-
142
-
143
- class ArticleRefPatch(Patch[ArticleRef]):
124
+ class ArticleRefSequencePatch(SequencePatch[ArticleRef]):
144
125
  """Patch for article refs."""
145
126
 
146
127
 
147
-
148
-
149
128
  class ArticleOutlineBase(
150
129
  ArticleMetaData,
151
130
  ResolveUpdateConflict,
@@ -340,6 +319,34 @@ class ArticleBase[T: ChapterBase](FinalizedDumpAble, AsPrompt, ABC):
340
319
  yield sec
341
320
  yield from sec.subsections
342
321
 
322
+ def iter_support_on(self, rev: bool = False) -> Generator[ArticleRef, None, None]:
323
+ """Iterates over all references that the article components support.
324
+
325
+ Args:
326
+ rev (bool): If True, iterate in reverse order.
327
+
328
+ Yields:
329
+ ArticleRef: Each reference that the article components support.
330
+ """
331
+ if rev:
332
+ yield from chain(*[a.support_to for a in self.iter_dfs_rev()])
333
+ return
334
+ yield from chain(*[a.support_to for a in self.iter_dfs()])
335
+
336
+ def iter_depend_on(self, rev: bool = False) -> Generator[ArticleRef, None, None]:
337
+ """Iterates over all references that the article components depend on.
338
+
339
+ Args:
340
+ rev (bool): If True, iterate in reverse order.
341
+
342
+ Yields:
343
+ ArticleRef: Each reference that the article components depend on.
344
+ """
345
+ if rev:
346
+ yield from chain(*[a.depend_on for a in self.iter_dfs_rev()])
347
+ return
348
+ yield from chain(*[a.depend_on for a in self.iter_dfs()])
349
+
343
350
  def iter_sections(self) -> Generator[Tuple[ChapterBase, SectionBase], None, None]:
344
351
  """Iterates through all sections in the article.
345
352
 
@@ -369,7 +376,13 @@ class ArticleBase[T: ChapterBase](FinalizedDumpAble, AsPrompt, ABC):
369
376
  return component, summary
370
377
  return None
371
378
 
372
- def find_illegal_ref(self) -> Optional[Tuple[ArticleRef, str]]:
379
+ @overload
380
+ def find_illegal_ref(self, gather_identical: bool) -> Optional[Tuple[ArticleRef | List[ArticleRef], str]]: ...
381
+
382
+ @overload
383
+ def find_illegal_ref(self) -> Optional[Tuple[ArticleRef, str]]: ...
384
+
385
+ def find_illegal_ref(self, gather_identical: bool = False) -> Optional[Tuple[ArticleRef | List[ArticleRef], str]]:
373
386
  """Finds the first illegal component in the outline.
374
387
 
375
388
  Returns:
@@ -380,8 +393,15 @@ class ArticleBase[T: ChapterBase](FinalizedDumpAble, AsPrompt, ABC):
380
393
  for ref in chain(component.depend_on, component.support_to):
381
394
  if not ref.deref(self):
382
395
  summary += f"Invalid internal reference in `{component.__class__.__name__}` titled `{component.title}`, because the referred {ref.referring_type} is not exists within the article, see the original obj dump: {ref.model_dump()}\n"
383
- if summary:
396
+ if summary and not gather_identical:
384
397
  return ref, summary
398
+ if summary and gather_identical:
399
+ return [
400
+ identical_ref
401
+ for identical_ref in chain(self.iter_depend_on(), self.iter_support_on())
402
+ if identical_ref == ref
403
+ ], summary
404
+
385
405
  return None
386
406
 
387
407
  def finalized_dump(self) -> str:
@@ -2,267 +2,98 @@
2
2
 
3
3
  from typing import List, Self
4
4
 
5
- from fabricatio.models.generic import Display, PersistentAble, PrepareVectorization, ProposedAble
6
- from pydantic import BaseModel, Field
5
+ from fabricatio.models.generic import Display, PersistentAble, ProposedAble, Vectorizable
6
+ from pydantic import BaseModel
7
7
 
8
8
 
9
9
  class Equation(BaseModel):
10
- """Mathematical formalism specification for research contributions.
11
-
12
- Encodes equations with dual representation: semantic meaning and typeset-ready notation.
13
- """
10
+ """Mathematical formalism specification for research contributions."""
14
11
 
15
12
  description: str
16
- """Equation significance structured in three elements:
17
- 1. Physical/conceptual meaning of the equation.
18
- 2. Role in technical workflow (e.g., derivation, optimization, or analysis).
19
- 3. Relationship to the paper's core contribution (e.g., theoretical foundation, empirical validation).
20
- Example: "Defines constrained search space dimensionality reduction. Used in architecture optimization phase (Section 3.2). Enables 40% parameter reduction."
13
+ """Structured significance including:
14
+ 1. Conceptual meaning
15
+ 2. Technical workflow role
16
+ 3. Contribution relationship
21
17
  """
22
18
 
23
- typst_code: str
24
- r"""The typst code for the equation, including the equation itself and any necessary formatting.
25
- #let x = 5 // Define a code variable
26
-
27
- // Basic syntax examples
28
- $x^2$ // Inline formula
29
- $ x^2 $ // Block formula (spaces before/after $ for standalone display)
30
-
31
- // Variables and text handling
32
- $ A = pi r^2 $ // Single-letter variables as-is
33
- $"area" = pi dot "radius"^2 $ // Multi-letter variables in quotes
34
- $ cal(A) := { x in RR | x "is natural" } $ // Calligraphic font and text
35
- $ #x < 17 $ // Access code variables with #
36
-
37
- // Symbols and shorthands
38
- $x < y => x gt.eq.not y $ // Symbol shorthand (=> for ⇒, gt.eq.not for ≯)
39
-
40
- // Multi-line equations with alignment
41
- $ sum_(k=0)^n k
42
- &= 1 + ... + n \
43
- &= (n(n+1))/2 $ // Multi-line with & alignment
44
-
45
- // Function calls and formatting
46
- $ frac(a^2, 2) $ // Fraction
47
- $ vec(1, 2, delim: "[") $ // Custom vector delimiter
48
- $ mat(1, 2; 3, 4) $ // 2D matrix (semicolon separates rows)
49
- $ mat(..#range(1, 5).chunks(2)) $ // Dynamic matrix with array expansion
50
-
51
- // Advanced alignment example
52
- $ (3x + y)/7 &= 9 && "given" \
53
- 3x + y &= 63 & "multiply by 7" \
54
- 3x &= 63 - y && "subtract y" \
55
- x &= 21 - y/3 & "divide by 3" $
56
- // && skips a column alignment (left/right alternation)
57
-
58
- // Math font configuration
59
- #show math.equation: set text(font: "Fira Math") // Set math font (requires Fira Math installed)
60
- $ sum_(i in NN) 1 + i $ // Display with new font
61
-
62
- // Escaping and special syntax
63
- $ frac(a\,, b) $ // Escape comma to display as literal
64
- $ f(x; y) $ // Literal semicolon (not for 2D arrays)
65
- $ lim_x = op("lim", limits: #true)_x $ // Custom operator with limits
66
- """
19
+ latex_code: str
20
+ """Typeset-ready notation."""
67
21
 
68
22
 
69
23
  class Figure(BaseModel):
70
- """Visual component specification for technical communication.
71
-
72
- Combines graphical assets with structured academic captioning.Extracted from the article provided
73
- """
24
+ """Visual component with academic captioning."""
74
25
 
75
26
  description: str
76
- """Figure interpretation guide containing:
77
- 1. Key visual elements mapping (e.g., axes, legends, annotations).
78
- 2. Data representation methodology (e.g., visualization type, statistical measures).
79
- 3. Connection to research findings (e.g., supports hypothesis, demonstrates performance).
80
- Example: "Architecture search space topology (left) vs. convergence curves (right). Demonstrates NAS efficiency gains through constrained search."
27
+ """Interpretation guide covering:
28
+ 1. Visual element mapping
29
+ 2. Data representation method
30
+ 3. Research connection
81
31
  """
82
32
 
83
33
  figure_caption: str
84
- """Complete caption following Nature-style guidelines:
85
- 1. Brief overview statement (首句总结).
86
- 2. Technical detail layer (e.g., data sources, experimental conditions).
87
- 3. Result implication (e.g., key insights, implications for future work).
88
- Example: "Figure 3: Differentiable NAS framework. (a) Search space topology with constrained dimensions. (b) Training convergence across language pairs. Dashed lines indicate baseline methods."
34
+ """Nature-style caption containing:
35
+ 1. Overview statement
36
+ 2. Technical details
37
+ 3. Result implications
89
38
  """
90
39
 
91
40
  figure_serial_number: int
92
- """The Image serial number extracted from the Markdown article provided, the path usually in the form of `![](images/1.jpg)`, in this case the serial number is `1`"""
93
-
94
-
95
- class Algorithm(BaseModel):
96
- """Algorithm specification for research contributions."""
97
-
98
- title: str
99
- """Algorithm title with technical focus descriptor (e.g., 'Gradient Descent Optimization').
100
-
101
- Tip: Do not attempt to translate the original element titles when generating JSON.
102
- """
103
-
104
- description: str
105
- """Algorithm description with technical focus descriptor:
106
- - Includes input/output specifications.
107
- - Describes key steps and their purpose.
108
- - Explains its role in the research workflow.
109
- Example: "Proposed algorithm for neural architecture search. Inputs include search space constraints and training data. Outputs optimized architecture."
110
- """
111
-
112
-
113
- class Table(BaseModel):
114
- """Table specification for research contributions."""
115
-
116
- title: str
117
- """Table title with technical focus descriptor (e.g., 'Comparison of Model Performance Metrics').
118
-
119
- Tip: Do not attempt to translate the original element titles when generating JSON.
120
- """
121
-
122
- description: str
123
- """Table description with technical focus descriptor:
124
- - Includes data source and structure.
125
- - Explains key columns/rows and their significance.
126
- - Connects to research findings or hypotheses.
127
- Example: "Performance metrics for different architectures. Columns represent accuracy, F1-score, and inference time. Highlights efficiency gains of proposed method."
128
- """
41
+ """Image serial number extracted from Markdown path"""
129
42
 
130
43
 
131
44
  class Highlightings(BaseModel):
132
- """Technical showcase aggregator for research artifacts.
133
-
134
- Curates core scientific components with machine-parseable annotations.
135
- """
45
+ """Technical component aggregator."""
136
46
 
137
47
  highlighted_equations: List[Equation]
138
- """3-5 pivotal equations representing theoretical contributions:
139
- - Each equation must be wrapped in $$ for display math.
140
- - Contain at least one novel operator/symbol.
141
- - Be referenced in Methods/Results sections.
142
- Example: Equation describing proposed loss function.
143
- """
144
-
145
- highlighted_algorithms: List[Algorithm]
146
- """1-2 key algorithms demonstrating methodological contributions:
147
- - Include pseudocode or step-by-step descriptions.
148
- - Highlight innovation in computational approach.
149
- Example: Algorithm for constrained search space exploration.
150
-
151
- Tip: Do not attempt to translate the original element titles when generating JSON.
152
- """
48
+ """Equations that highlight the article's core contributions"""
153
49
 
154
50
  highlighted_figures: List[Figure]
155
- """4-6 key figures demonstrating:
156
- 1. Framework overview (1 required).
157
- 2. Quantitative results (2-3 required).
158
- 3. Ablation studies (1 optional).
159
- Each must appear in Results/Discussion chapters.
160
- Example: Figure showing architecture topology and convergence curves.
161
- """
162
-
163
- highlighted_tables: List[Table]
164
- """2-3 key tables summarizing:
165
- - Comparative analysis of methods.
166
- - Empirical results supporting claims.
167
- Example: Table comparing model performance across datasets.
168
-
169
- Tip: Do not attempt to translate the original element titles when generating JSON.
51
+ """key figures requiring:
52
+ 1. Framework overview
53
+ 2. Quantitative results
170
54
  """
171
55
 
172
56
 
173
- class ArticleEssence(ProposedAble, Display, PersistentAble, PrepareVectorization):
174
- """ArticleEssence is a structured representation of the core elements of a scientific article,using its original language."""
57
+ class ArticleEssence(ProposedAble, Display, PersistentAble, Vectorizable):
58
+ """Structured representation of a scientific article's core elements in its original language."""
175
59
 
176
60
  language: str
177
- """Language of the original article, note that you should not attempt to translate the original language when generating JSON."""
61
+ """Language of the original article."""
178
62
 
179
- title: str = Field(...)
180
- """Exact title of the original article without any modification.
181
- Must be preserved precisely from the source material without:
182
- - Translation
183
- - Paraphrasing
184
- - Adding/removing words
185
- - Altering style or formatting
186
- """
63
+ title: str
64
+ """Exact title of the original article."""
187
65
 
188
66
  authors: List[str]
189
- """Original author full names exactly as they appear in the source document. No translation or paraphrasing.
190
- Extract complete list without any modifications or formatting changes."""
67
+ """Original author full names as they appear in the source document."""
191
68
 
192
69
  keywords: List[str]
193
- """Original keywords exactly as they appear in the source document. No translation or paraphrasing.
194
- Extract the complete set without modifying format or terminology."""
70
+ """Original keywords as they appear in the source document."""
195
71
 
196
72
  publication_year: int
197
- """Publication timestamp in ISO 8601 (YYYY format)."""
73
+ """Publication year in ISO 8601 (YYYY format)."""
198
74
 
199
75
  highlightings: Highlightings
200
- """Technical highlight reel containing:
201
- - Core equations (Theory)
202
- - Key algorithms (Implementation)
203
- - Critical figures (Results)
204
- - Benchmark tables (Evaluation)"""
76
+ """Technical highlights including equations, algorithms, figures, and tables."""
205
77
 
206
- domain: List[str]
207
- """Domain tags for research focus."""
208
-
209
- abstract: str = Field(...)
210
- """Abstract text with original language."""
78
+ abstract: str
79
+ """Abstract text in the original language."""
211
80
 
212
81
  core_contributions: List[str]
213
- """3-5 technical contributions using CRediT taxonomy verbs.
214
- Each item starts with action verb.
215
- Example:
216
- - 'Developed constrained NAS framework'
217
- - 'Established cross-lingual transfer metrics'"""
82
+ """Technical contributions using CRediT taxonomy verbs."""
218
83
 
219
84
  technical_novelty: List[str]
220
-
221
- """Patent-style claims with technical specificity.
222
- Format: 'A [system/method] comprising [novel components]...'
223
- Example:
224
- 'A neural architecture search system comprising:
225
- a differentiable constrained search space;
226
- multi-lingual transferability predictors...'"""
85
+ """Patent-style claims with technical specificity."""
227
86
 
228
87
  research_problems: List[str]
229
- """Problem statements as how/why questions.
230
- Example:
231
- - 'How to reduce NAS computational overhead while maintaining search diversity?'
232
- - 'Why do existing architectures fail in low-resource cross-lingual transfer?'"""
88
+ """Problem statements as how/why questions."""
233
89
 
234
90
  limitations: List[str]
235
- """Technical limitations analysis containing:
236
- 1. Constraint source (data/method/theory)
237
- 2. Impact quantification
238
- 3. Mitigation pathway
239
- Example:
240
- 'Methodology constraint: Single-objective optimization (affects 5% edge cases),
241
- mitigated through future multi-task extension'"""
242
-
243
- future_work: List[str]
244
- """Research roadmap items with 3 horizons:
245
- 1. Immediate extensions (1 year)
246
- 2. Mid-term directions (2-3 years)
247
- 3. Long-term vision (5+ years)
248
- Example:
249
- 'Short-term: Adapt framework for vision transformers (ongoing with CVPR submission)'"""
250
-
251
- impact_analysis: List[str]
252
- """Bibliometric impact projections:
253
- - Expected citation counts (next 3 years)
254
- - Target application domains
255
- - Standard adoption potential
256
- Example:
257
- 'Predicted 150+ citations via integration into MMEngine (Alibaba OpenMMLab)'"""
91
+ """Technical limitations analysis."""
258
92
 
259
93
  bibtex_cite_key: str
260
- """Bibtex cite_key of the original article."""
94
+ """Bibtex cite key of the original article."""
261
95
 
262
96
  def update_cite_key(self, new_cite_key: str) -> Self:
263
97
  """Update the bibtex_cite_key of the article."""
264
98
  self.bibtex_cite_key = new_cite_key
265
99
  return self
266
-
267
- def _prepare_vectorization_inner(self) -> str:
268
- return self.model_dump_json()
@@ -8,15 +8,14 @@ from fabricatio.models.extra.article_base import (
8
8
  ArticleBase,
9
9
  ArticleOutlineBase,
10
10
  ChapterBase,
11
- Patch,
12
11
  SectionBase,
13
12
  SubSectionBase,
14
13
  )
15
14
  from fabricatio.models.extra.article_outline import (
16
15
  ArticleOutline,
17
16
  )
18
- from fabricatio.models.generic import CensoredAble, Display, PersistentAble, WithRef
19
- from fabricatio.models.utils import ok
17
+ from fabricatio.models.generic import CensoredAble, Display, PersistentAble, SequencePatch, WithRef
18
+ from fabricatio.utils import ok
20
19
 
21
20
 
22
21
  class Paragraph(CensoredAble):
@@ -32,7 +31,7 @@ class Paragraph(CensoredAble):
32
31
  """The actual content of the paragraph, represented as a string."""
33
32
 
34
33
 
35
- class ArticleParagraphPatch(Patch[Paragraph]):
34
+ class ArticleParagraphSequencePatch(SequencePatch[Paragraph]):
36
35
  """Patch for `Paragraph` list of `ArticleSubsection`."""
37
36
 
38
37
 
@@ -0,0 +1,7 @@
1
+ """A patch class for updating the description and name of a `WithBriefing` object."""
2
+
3
+ from fabricatio.models.generic import Patch, WithBriefing
4
+
5
+
6
+ class BriefingPatch[T:WithBriefing](Patch[T], WithBriefing):
7
+ """Patch class for updating the description and name of a `WithBriefing` object."""
@@ -0,0 +1,153 @@
1
+ """A class representing a problem-solution pair identified during a review process."""
2
+
3
+ from itertools import chain
4
+ from typing import List, Literal, Optional, Self
5
+
6
+ from fabricatio.journal import logger
7
+ from fabricatio.models.generic import SketchedAble, WithBriefing
8
+ from fabricatio.utils import ask_edit
9
+ from questionary import Choice, checkbox, text
10
+ from rich import print as r_print
11
+
12
+
13
+ class Problem(SketchedAble, WithBriefing):
14
+ """Represents a problem identified during review."""
15
+
16
+ description: str
17
+ """Description of the problem, The """
18
+
19
+ severity: Literal["low", "medium", "high"]
20
+ """Severity level of the problem."""
21
+
22
+ category: str
23
+ """Category of the problem."""
24
+
25
+ location: str
26
+ """Location where the problem was identified."""
27
+
28
+ recommendation: str
29
+ """Recommended solution or action."""
30
+
31
+
32
+ class Solution(SketchedAble, WithBriefing):
33
+ """Represents a proposed solution to a problem."""
34
+
35
+ description: str
36
+ """Description of the solution, including a detailed description of the execution steps, and the mechanics, principle or fact."""
37
+
38
+ execute_steps: List[str]
39
+ """A list of steps to execute to implement the solution, which is expected to be able to finally solve the corresponding problem."""
40
+
41
+ feasibility: Literal["low", "medium", "high"]
42
+ """Feasibility level of the solution."""
43
+
44
+ impact: Literal["low", "medium", "high"]
45
+ """Impact level of the solution."""
46
+
47
+
48
+ class ProblemSolutions(SketchedAble):
49
+ """Represents a problem-solution pair identified during a review process."""
50
+
51
+ problem: Problem
52
+ """The problem identified in the review."""
53
+ solutions: List[Solution]
54
+ """A collection of potential solutions."""
55
+
56
+ def update_from_inner(self, other: Self) -> Self:
57
+ """Update the current instance with another instance's attributes."""
58
+ self.solutions.clear()
59
+ self.solutions.extend(other.solutions)
60
+ return self
61
+
62
+ def update_problem(self, problem: Problem) -> Self:
63
+ """Update the problem description."""
64
+ self.problem = problem
65
+ return self
66
+
67
+ def update_solutions(self, solutions: List[Solution]) -> Self:
68
+ """Update the list of potential solutions."""
69
+ self.solutions = solutions
70
+ return self
71
+
72
+ async def edit_problem(self) -> Self:
73
+ """Interactively edit the problem description."""
74
+ self.problem = Problem.model_validate_strings(
75
+ await text("Please edit the problem below:", default=self.problem.display()).ask_async()
76
+ )
77
+ return self
78
+
79
+ async def edit_solutions(self) -> Self:
80
+ """Interactively edit the list of potential solutions."""
81
+ r_print(self.problem.display())
82
+ string_seq = await ask_edit([s.display() for s in self.solutions])
83
+ self.solutions = [Solution.model_validate_strings(s) for s in string_seq]
84
+ return self
85
+
86
+ def decided(self) -> bool:
87
+ """Check if the improvement is decided."""
88
+ return len(self.solutions) == 1
89
+
90
+ def final_solution(self) -> Optional[Solution]:
91
+ """Get the final solution."""
92
+ if not self.decided():
93
+ logger.error(
94
+ f"There is more than one solution for problem {self.problem.name}, please decide which solution is eventually adopted."
95
+ )
96
+ return None
97
+ return self.solutions[0]
98
+
99
+
100
+ class Improvement(SketchedAble):
101
+ """A class representing an improvement suggestion."""
102
+
103
+ focused_on: str
104
+ """The focused on topic of the improvement"""
105
+
106
+ problem_solutions: List[ProblemSolutions]
107
+ """Collection of problems identified during review along with their potential solutions."""
108
+
109
+ async def supervisor_check(self, check_solutions: bool = True) -> Self:
110
+ """Perform an interactive review session to filter problems and solutions.
111
+
112
+ Presents an interactive prompt allowing a supervisor to select which
113
+ problems (and optionally solutions) should be retained in the final review.
114
+
115
+ Args:
116
+ check_solutions (bool, optional): When True, also prompts for filtering
117
+ individual solutions for each retained problem. Defaults to False.
118
+
119
+ Returns:
120
+ Self: The current instance with filtered problems and solutions.
121
+ """
122
+ # Choose the problems to retain
123
+ chosen_ones: List[ProblemSolutions] = await checkbox(
124
+ "Please choose the problems you want to retain.(Default: retain all)",
125
+ choices=[Choice(p.problem.name, p, checked=True) for p in self.problem_solutions],
126
+ ).ask_async()
127
+ self.problem_solutions = [await p.edit_problem() for p in chosen_ones]
128
+ if not check_solutions:
129
+ return self
130
+
131
+ # Choose the solutions to retain
132
+ for to_exam in self.problem_solutions:
133
+ to_exam.update_solutions(
134
+ await checkbox(
135
+ f"Please choose the solutions you want to retain.(Default: retain all)\n\t`{to_exam.problem}`",
136
+ choices=[Choice(s.name, s, checked=True) for s in to_exam.solutions],
137
+ ).ask_async()
138
+ )
139
+ await to_exam.edit_solutions()
140
+
141
+ return self
142
+
143
+ def decided(self) -> bool:
144
+ """Check if the improvement is decided."""
145
+ return all(ps.decided() for ps in self.problem_solutions)
146
+
147
+ @classmethod
148
+ def gather(cls, *improvements: Self) -> Self:
149
+ """Gather multiple improvements into a single instance."""
150
+ return cls(
151
+ focused_on="\n".join(imp.focused_on for imp in improvements),
152
+ problem_solutions=list(chain(*(imp.problem_solutions for imp in improvements))),
153
+ )
@@ -0,0 +1,21 @@
1
+ """A module containing classes related to rule sets and rules."""
2
+
3
+ from typing import List
4
+
5
+ from fabricatio.models.generic import Display, PersistentAble, ProposedAble, WithBriefing
6
+
7
+
8
+ class Rule(WithBriefing,ProposedAble,Display):
9
+ """Represents a rule or guideline for a specific topic."""
10
+
11
+ violation_examples: List[str]
12
+ """Examples of violations of the rule."""
13
+ compliance_examples: List[str]
14
+ """Examples of how to comply with the rule."""
15
+
16
+
17
+ class RuleSet(ProposedAble, Display, PersistentAble, WithBriefing):
18
+ """Represents a collection of rules and guidelines for a particular topic."""
19
+
20
+ rules: List[Rule]
21
+ """The rules and guidelines contained in the rule set."""