fabricatio 0.3.15.dev5__cp313-cp313-win_amd64.whl → 0.4.0.dev0__cp313-cp313-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 (62) hide show
  1. fabricatio/__init__.py +8 -9
  2. fabricatio/rust.cp313-win_amd64.pyd +0 -0
  3. fabricatio/toolboxes/arithmetic.py +1 -1
  4. fabricatio/toolboxes/fs.py +2 -2
  5. fabricatio/workflows/rag.py +2 -1
  6. fabricatio-0.4.0.dev0.data/scripts/tdown.exe +0 -0
  7. {fabricatio-0.3.15.dev5.dist-info → fabricatio-0.4.0.dev0.dist-info}/METADATA +22 -16
  8. fabricatio-0.4.0.dev0.dist-info/RECORD +13 -0
  9. fabricatio/actions/__init__.py +0 -1
  10. fabricatio/actions/article.py +0 -415
  11. fabricatio/actions/article_rag.py +0 -407
  12. fabricatio/actions/fs.py +0 -25
  13. fabricatio/actions/output.py +0 -247
  14. fabricatio/actions/rag.py +0 -96
  15. fabricatio/actions/rules.py +0 -83
  16. fabricatio/capabilities/__init__.py +0 -1
  17. fabricatio/capabilities/advanced_judge.py +0 -20
  18. fabricatio/capabilities/advanced_rag.py +0 -61
  19. fabricatio/capabilities/censor.py +0 -105
  20. fabricatio/capabilities/check.py +0 -212
  21. fabricatio/capabilities/correct.py +0 -228
  22. fabricatio/capabilities/extract.py +0 -74
  23. fabricatio/capabilities/propose.py +0 -65
  24. fabricatio/capabilities/rag.py +0 -264
  25. fabricatio/capabilities/rating.py +0 -404
  26. fabricatio/capabilities/review.py +0 -114
  27. fabricatio/capabilities/task.py +0 -113
  28. fabricatio/decorators.py +0 -253
  29. fabricatio/emitter.py +0 -177
  30. fabricatio/fs/__init__.py +0 -35
  31. fabricatio/fs/curd.py +0 -153
  32. fabricatio/fs/readers.py +0 -61
  33. fabricatio/journal.py +0 -12
  34. fabricatio/models/action.py +0 -263
  35. fabricatio/models/adv_kwargs_types.py +0 -63
  36. fabricatio/models/extra/__init__.py +0 -1
  37. fabricatio/models/extra/advanced_judge.py +0 -32
  38. fabricatio/models/extra/aricle_rag.py +0 -286
  39. fabricatio/models/extra/article_base.py +0 -488
  40. fabricatio/models/extra/article_essence.py +0 -98
  41. fabricatio/models/extra/article_main.py +0 -285
  42. fabricatio/models/extra/article_outline.py +0 -45
  43. fabricatio/models/extra/article_proposal.py +0 -52
  44. fabricatio/models/extra/patches.py +0 -20
  45. fabricatio/models/extra/problem.py +0 -165
  46. fabricatio/models/extra/rag.py +0 -98
  47. fabricatio/models/extra/rule.py +0 -51
  48. fabricatio/models/generic.py +0 -904
  49. fabricatio/models/kwargs_types.py +0 -121
  50. fabricatio/models/role.py +0 -156
  51. fabricatio/models/task.py +0 -310
  52. fabricatio/models/tool.py +0 -328
  53. fabricatio/models/usages.py +0 -791
  54. fabricatio/parser.py +0 -114
  55. fabricatio/rust.pyi +0 -846
  56. fabricatio/utils.py +0 -156
  57. fabricatio/workflows/articles.py +0 -24
  58. fabricatio-0.3.15.dev5.data/scripts/tdown.exe +0 -0
  59. fabricatio-0.3.15.dev5.data/scripts/ttm.exe +0 -0
  60. fabricatio-0.3.15.dev5.dist-info/RECORD +0 -63
  61. {fabricatio-0.3.15.dev5.dist-info → fabricatio-0.4.0.dev0.dist-info}/WHEEL +0 -0
  62. {fabricatio-0.3.15.dev5.dist-info → fabricatio-0.4.0.dev0.dist-info}/licenses/LICENSE +0 -0
@@ -1,285 +0,0 @@
1
- """ArticleBase and ArticleSubsection classes for managing hierarchical document components."""
2
-
3
- from typing import ClassVar, Dict, Generator, List, Self, Tuple, Type, override
4
-
5
- from fabricatio.decorators import precheck_package
6
- from fabricatio.journal import logger
7
- from fabricatio.models.extra.article_base import (
8
- ArticleBase,
9
- ChapterBase,
10
- SectionBase,
11
- SubSectionBase,
12
- )
13
- from fabricatio.models.extra.article_outline import (
14
- ArticleChapterOutline,
15
- ArticleOutline,
16
- ArticleSectionOutline,
17
- ArticleSubsectionOutline,
18
- )
19
- from fabricatio.models.generic import Described, PersistentAble, SequencePatch, SketchedAble, WithRef, WordCount
20
- from fabricatio.rust import (
21
- convert_all_tex_math,
22
- fix_misplaced_labels,
23
- split_out_metadata,
24
- word_count,
25
- )
26
- from pydantic import Field, NonNegativeInt
27
-
28
- PARAGRAPH_SEP = "// - - -"
29
-
30
-
31
- class Paragraph(SketchedAble, WordCount, Described):
32
- """Structured academic paragraph blueprint for controlled content generation."""
33
-
34
- expected_word_count: NonNegativeInt = 0
35
- """The expected word count of this paragraph, 0 means not specified"""
36
-
37
- description: str = Field(
38
- alias="elaboration",
39
- description=Described.model_fields["description"].description,
40
- )
41
-
42
- aims: List[str]
43
- """Specific communicative objectives for this paragraph's content."""
44
-
45
- content: str
46
- """The actual content of the paragraph, represented as a string."""
47
-
48
- @classmethod
49
- def from_content(cls, content: str) -> Self:
50
- """Create a Paragraph object from the given content."""
51
- return cls(elaboration="", aims=[], expected_word_count=word_count(content), content=content.strip())
52
-
53
- @property
54
- def exact_word_count(self) -> int:
55
- """Calculates the exact word count of the content."""
56
- return word_count(self.content)
57
-
58
-
59
- class ArticleParagraphSequencePatch(SequencePatch[Paragraph]):
60
- """Patch for `Paragraph` list of `ArticleSubsection`."""
61
-
62
-
63
- class ArticleSubsection(SubSectionBase):
64
- """Atomic argumentative unit with technical specificity."""
65
-
66
- paragraphs: List[Paragraph]
67
- """List of Paragraph objects containing the content of the subsection."""
68
-
69
- _max_word_count_deviation: float = 0.3
70
- """Maximum allowed deviation from the expected word count, as a percentage."""
71
-
72
- @property
73
- def exact_word_count(self) -> int:
74
- """Calculates the exact word count of all paragraphs in the subsection."""
75
- return sum(a.exact_word_count for a in self.paragraphs)
76
-
77
- @property
78
- def word_count(self) -> int:
79
- """Calculates the total word count of all paragraphs in the subsection."""
80
- return sum(word_count(p.content) for p in self.paragraphs)
81
-
82
- def introspect(self) -> str:
83
- """Introspects the subsection and returns a summary of its state."""
84
- summary = ""
85
- if len(self.paragraphs) == 0:
86
- summary += f"`{self.__class__.__name__}` titled `{self.title}` have no paragraphs, You should add some!\n"
87
- if (
88
- abs((wc := self.word_count) - self.expected_word_count) / self.expected_word_count
89
- > self._max_word_count_deviation
90
- ):
91
- summary += f"`{self.__class__.__name__}` titled `{self.title}` have {wc} words, expected {self.expected_word_count} words!"
92
-
93
- return summary
94
-
95
- def update_from_inner(self, other: Self) -> Self:
96
- """Updates the current instance with the attributes of another instance."""
97
- logger.debug(f"Updating SubSection {self.title}")
98
- super().update_from_inner(other)
99
- self.paragraphs.clear()
100
- self.paragraphs.extend(other.paragraphs)
101
- return self
102
-
103
- def to_typst_code(self) -> str:
104
- """Converts the component into a Typst code snippet for rendering.
105
-
106
- Returns:
107
- str: Typst code snippet for rendering.
108
- """
109
- return super().to_typst_code() + f"\n\n{PARAGRAPH_SEP}\n\n".join(p.content for p in self.paragraphs)
110
-
111
- @classmethod
112
- def from_typst_code(cls, title: str, body: str, **kwargs) -> Self:
113
- """Creates an Article object from the given Typst code."""
114
- _, para_body = split_out_metadata(body)
115
-
116
- return super().from_typst_code(
117
- title,
118
- body,
119
- paragraphs=[Paragraph.from_content(p) for p in para_body.split(PARAGRAPH_SEP)],
120
- )
121
-
122
-
123
- class ArticleSection(SectionBase[ArticleSubsection]):
124
- """Atomic argumentative unit with high-level specificity."""
125
-
126
- child_type: ClassVar[Type[SubSectionBase]] = ArticleSubsection
127
-
128
-
129
- class ArticleChapter(ChapterBase[ArticleSection]):
130
- """Thematic progression implementing research function."""
131
-
132
- child_type: ClassVar[Type[SectionBase]] = ArticleSection
133
-
134
-
135
- class Article(
136
- WithRef[ArticleOutline],
137
- PersistentAble,
138
- ArticleBase[ArticleChapter],
139
- ):
140
- """Represents a complete academic paper specification, incorporating validation constraints.
141
-
142
- This class integrates display, censorship processing, article structure referencing, and persistence capabilities,
143
- aiming to provide a comprehensive model for academic papers.
144
- """
145
-
146
- child_type: ClassVar[Type[ChapterBase]] = ArticleChapter
147
-
148
- def _as_prompt_inner(self) -> Dict[str, str]:
149
- return {
150
- "Original Article Briefing": self.referenced.referenced.referenced,
151
- "Original Article Proposal": self.referenced.referenced.display(),
152
- "Original Article Outline": self.referenced.display(),
153
- "Original Article": self.display(),
154
- }
155
-
156
- def convert_tex(self, paragraphs: bool = True, descriptions: bool = True) -> Self:
157
- """Convert tex to typst code."""
158
- if descriptions:
159
- for a in self.iter_dfs():
160
- a.description = fix_misplaced_labels(a.description)
161
- a.description = convert_all_tex_math(a.description)
162
-
163
- if paragraphs:
164
- for _, _, subsec in self.iter_subsections():
165
- for p in subsec.paragraphs:
166
- p.content = fix_misplaced_labels(p.content)
167
- p.content = convert_all_tex_math(p.content)
168
- return self
169
-
170
- @override
171
- def iter_subsections(self) -> Generator[Tuple[ArticleChapter, ArticleSection, ArticleSubsection], None, None]:
172
- return super().iter_subsections() # pyright: ignore [reportReturnType]
173
-
174
- def extrac_outline(self) -> ArticleOutline:
175
- """Extract outline from article."""
176
- # Create an empty list to hold chapter outlines
177
- chapters = []
178
-
179
- # Iterate through each chapter in the article
180
- for chapter in self.chapters:
181
- # Create an empty list to hold section outlines
182
- sections = []
183
-
184
- # Iterate through each section in the chapter
185
- for section in chapter.sections:
186
- # Create an empty list to hold subsection outlines
187
- subsections = []
188
-
189
- # Iterate through each subsection in the section
190
- for subsection in section.subsections:
191
- # Create a subsection outline and add it to the list
192
- subsections.append(
193
- ArticleSubsectionOutline(**subsection.model_dump(exclude={"paragraphs"}, by_alias=True))
194
- )
195
-
196
- # Create a section outline and add it to the list
197
- sections.append(
198
- ArticleSectionOutline(
199
- **section.model_dump(exclude={"subsections"}, by_alias=True),
200
- subsections=subsections,
201
- )
202
- )
203
-
204
- # Create a chapter outline and add it to the list
205
- chapters.append(
206
- ArticleChapterOutline(
207
- **chapter.model_dump(exclude={"sections"}, by_alias=True),
208
- sections=sections,
209
- )
210
- )
211
-
212
- # Create and return the article outline
213
- return ArticleOutline(
214
- **self.model_dump(exclude={"chapters"}, by_alias=True),
215
- chapters=chapters,
216
- )
217
-
218
- @classmethod
219
- def from_outline(cls, outline: ArticleOutline) -> "Article":
220
- """Generates an article from the given outline.
221
-
222
- Args:
223
- outline (ArticleOutline): The outline to generate the article from.
224
-
225
- Returns:
226
- Article: The generated article.
227
- """
228
- # Set the title from the outline
229
- article = Article(**outline.model_dump(exclude={"chapters"}, by_alias=True), chapters=[])
230
-
231
- for chapter in outline.chapters:
232
- # Create a new chapter
233
- article_chapter = ArticleChapter(
234
- sections=[],
235
- **chapter.model_dump(exclude={"sections"}, by_alias=True),
236
- )
237
- for section in chapter.sections:
238
- # Create a new section
239
- article_section = ArticleSection(
240
- subsections=[],
241
- **section.model_dump(exclude={"subsections"}, by_alias=True),
242
- )
243
- for subsection in section.subsections:
244
- # Create a new subsection
245
- article_subsection = ArticleSubsection(
246
- paragraphs=[],
247
- **subsection.model_dump(by_alias=True),
248
- )
249
- article_section.subsections.append(article_subsection)
250
- article_chapter.sections.append(article_section)
251
- article.chapters.append(article_chapter)
252
- return article
253
-
254
- @classmethod
255
- def from_mixed_source(cls, article_outline: ArticleOutline, typst_code: str) -> Self:
256
- """Generates an article from the given outline and Typst code."""
257
- self = cls.from_typst_code(article_outline.title, typst_code)
258
- self.expected_word_count = article_outline.expected_word_count
259
- self.description = article_outline.description
260
- for a, o in zip(self.iter_dfs(), article_outline.iter_dfs(), strict=True):
261
- a.update_metadata(o)
262
- return self.update_ref(article_outline)
263
-
264
- @precheck_package(
265
- "questionary", "'questionary' is required to run this function. Have you installed `fabricatio[qa]`?."
266
- )
267
- async def edit_titles(self) -> Self:
268
- """Edits the titles of the article."""
269
- from questionary import text
270
-
271
- for a in self.iter_dfs():
272
- a.title = await text(f"Edit `{a.title}`.", default=a.title).ask_async() or a.title
273
- return self
274
-
275
- def check_short_paragraphs(self, threshold: int = 60) -> str:
276
- """Checks for short paragraphs in the article."""
277
- err = []
278
- for chap, sec, subsec in self.iter_subsections():
279
- for i, p in enumerate(subsec.paragraphs):
280
- if p.exact_word_count <= threshold:
281
- err.append(
282
- f"{chap.title}->{sec.title}->{subsec.title}-> Paragraph [{i}] is too short, {p.exact_word_count} words."
283
- )
284
-
285
- return "\n".join(err)
@@ -1,45 +0,0 @@
1
- """A module containing the ArticleOutline class, which represents the outline of an academic paper."""
2
-
3
- from typing import ClassVar, Dict, Type
4
-
5
- from fabricatio.models.extra.article_base import (
6
- ArticleBase,
7
- ChapterBase,
8
- SectionBase,
9
- SubSectionBase,
10
- )
11
- from fabricatio.models.extra.article_proposal import ArticleProposal
12
- from fabricatio.models.generic import PersistentAble, WithRef
13
-
14
-
15
- class ArticleSubsectionOutline(SubSectionBase):
16
- """Atomic research component specification for academic paper generation."""
17
-
18
-
19
- class ArticleSectionOutline(SectionBase[ArticleSubsectionOutline]):
20
- """A slightly more detailed research component specification for academic paper generation, Must contain subsections."""
21
-
22
- child_type: ClassVar[Type[SubSectionBase]] = ArticleSubsectionOutline
23
-
24
-
25
- class ArticleChapterOutline(ChapterBase[ArticleSectionOutline]):
26
- """Macro-structural unit implementing standard academic paper organization. Must contain sections."""
27
-
28
- child_type: ClassVar[Type[SectionBase]] = ArticleSectionOutline
29
-
30
-
31
- class ArticleOutline(
32
- WithRef[ArticleProposal],
33
- PersistentAble,
34
- ArticleBase[ArticleChapterOutline],
35
- ):
36
- """Outline of an academic paper, containing chapters, sections, subsections."""
37
-
38
- child_type: ClassVar[Type[ChapterBase]] = ArticleChapterOutline
39
-
40
- def _as_prompt_inner(self) -> Dict[str, str]:
41
- return {
42
- "Original Article Briefing": self.referenced.referenced,
43
- "Original Article Proposal": self.referenced.display(),
44
- "Original Article Outline": self.display(),
45
- }
@@ -1,52 +0,0 @@
1
- """A structured proposal for academic paper development with core research elements."""
2
-
3
- from typing import Dict, List
4
-
5
- from fabricatio.models.generic import (
6
- AsPrompt,
7
- Described,
8
- Language,
9
- PersistentAble,
10
- SketchedAble,
11
- Titled,
12
- WithRef,
13
- WordCount,
14
- )
15
- from pydantic import Field
16
-
17
-
18
- class ArticleProposal(SketchedAble, WithRef[str], AsPrompt, PersistentAble, WordCount, Described, Titled, Language):
19
- """Structured proposal for academic paper development with core research elements.
20
-
21
- Guides LLM in generating comprehensive research proposals with clearly defined components.
22
- """
23
-
24
- focused_problem: List[str]
25
- """A list of specific research problems or questions that the paper aims to address."""
26
-
27
- technical_approaches: List[str]
28
- """A list of technical approaches or methodologies used to solve the research problems."""
29
-
30
- research_methods: List[str]
31
- """A list of methodological components, including techniques and tools utilized in the research."""
32
-
33
- research_aim: List[str]
34
- """A list of primary research objectives that the paper seeks to achieve."""
35
-
36
- literature_review: List[str]
37
- """A list of key references and literature that support the research context and background."""
38
-
39
- expected_outcomes: List[str]
40
- """A list of anticipated results or contributions that the research aims to achieve."""
41
-
42
- keywords: List[str]
43
- """A list of keywords that represent the main topics and focus areas of the research."""
44
-
45
- description: str = Field(alias="abstract")
46
- """A concise summary of the research proposal, outlining the main points and objectives."""
47
-
48
- def _as_prompt_inner(self) -> Dict[str, str]:
49
- return {
50
- "ArticleBriefing": self.referenced,
51
- "ArticleProposal": self.display(),
52
- }
@@ -1,20 +0,0 @@
1
- """A patch class for updating the description and name of a `WithBriefing` object, all fields within this instance will be directly copied onto the target model's field."""
2
-
3
- from typing import Optional, Type
4
-
5
- from fabricatio.models.extra.rule import RuleSet
6
- from fabricatio.models.generic import Language, Patch, WithBriefing
7
- from pydantic import BaseModel
8
-
9
-
10
- class BriefingMetadata[T: WithBriefing](Patch[T], WithBriefing):
11
- """A patch class for updating the description and name of a `WithBriefing` object, all fields within this instance will be directly copied onto the target model's field."""
12
-
13
-
14
- class RuleSetMetadata(BriefingMetadata[RuleSet], Language):
15
- """A patch class for updating the description and name of a `RuleSet` object, all fields within this instance will be directly copied onto the target model's field."""
16
-
17
- @staticmethod
18
- def ref_cls() -> Optional[Type[BaseModel]]:
19
- """Get the reference class of the model."""
20
- return RuleSet
@@ -1,165 +0,0 @@
1
- """A class representing a problem-solution pair identified during a review process."""
2
-
3
- from itertools import chain
4
- from typing import Any, List, Optional, Self, Tuple, Unpack
5
-
6
- from fabricatio.journal import logger
7
- from fabricatio.models.generic import SketchedAble, WithBriefing
8
- from fabricatio.utils import ask_edit
9
- from pydantic import Field
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 = Field(alias="cause")
17
- """The cause of the problem, including the root cause, the context, and the impact, make detailed enough for engineer to understand the problem and its impact."""
18
-
19
- severity_level: int = Field(ge=0, le=10)
20
- """Severity level of the problem, which is a number between 0 and 10, 0 means the problem is not severe, 10 means the problem is extremely severe."""
21
-
22
- location: str
23
- """Location where the problem was identified."""
24
-
25
-
26
- class Solution(SketchedAble, WithBriefing):
27
- """Represents a proposed solution to a problem."""
28
-
29
- description: str = Field(alias="mechanism")
30
- """Description of the solution, including a detailed description of the execution steps, and the mechanics, principle or fact."""
31
-
32
- execute_steps: List[str]
33
- """A list of steps to execute to implement the solution, which is expected to be able to finally solve the corresponding problem, and which should be an Idiot-proof tutorial."""
34
-
35
- feasibility_level: int = Field(ge=0, le=10)
36
- """Feasibility level of the solution, which is a number between 0 and 10, 0 means the solution is not feasible, 10 means the solution is complete feasible."""
37
-
38
- impact_level: int = Field(ge=0, le=10)
39
- """Impact level of the solution, which is a number between 0 and 10, 0 means the solution is not impactful, 10 means the solution is extremely impactful."""
40
-
41
-
42
- class ProblemSolutions(SketchedAble):
43
- """Represents a problem-solution pair identified during a review process."""
44
-
45
- problem: Problem
46
- """The problem identified in the review."""
47
- solutions: List[Solution]
48
- """A collection of potential solutions, spread the thought, add more solution as possible.Do not leave this as blank"""
49
-
50
- def model_post_init(self, context: Any, /) -> None:
51
- """Initialize the problem-solution pair with a problem and a list of solutions."""
52
- if len(self.solutions) == 0:
53
- logger.warning(f"No solution found for problem {self.problem.name}, please add more solutions manually.")
54
-
55
- def update_from_inner(self, other: Self) -> Self:
56
- """Update the current instance with another instance's attributes."""
57
- self.solutions.clear()
58
- self.solutions.extend(other.solutions)
59
- return self
60
-
61
- def update_problem(self, problem: Problem) -> Self:
62
- """Update the problem description."""
63
- self.problem = problem
64
- return self
65
-
66
- def update_solutions(self, solutions: List[Solution]) -> Self:
67
- """Update the list of potential solutions."""
68
- self.solutions = solutions
69
- return self
70
-
71
- def has_solutions(self) -> bool:
72
- """Check if the problem-solution pair has any solutions."""
73
- return len(self.solutions) > 0
74
-
75
- async def edit_problem(self) -> Self:
76
- """Interactively edit the problem description."""
77
- from questionary import text
78
-
79
- """Interactively edit the problem description."""
80
- self.problem = Problem.model_validate_strings(
81
- await text("Please edit the problem below:", default=self.problem.display()).ask_async()
82
- )
83
- return self
84
-
85
- async def edit_solutions(self) -> Self:
86
- """Interactively edit the list of potential solutions."""
87
- r_print(self.problem.display())
88
- string_seq = await ask_edit([s.display() for s in self.solutions])
89
- self.solutions = [Solution.model_validate_strings(s) for s in string_seq]
90
- return self
91
-
92
- def decided(self) -> bool:
93
- """Check if the improvement is decided."""
94
- return len(self.solutions) == 1
95
-
96
- def final_solution(self, always_use_first: bool = False) -> Optional[Solution]:
97
- """Get the final solution."""
98
- if not always_use_first and not self.decided():
99
- logger.error(
100
- f"There is {len(self.solutions)} solutions for problem {self.problem.name}, please decide which solution is eventually adopted."
101
- )
102
- return None
103
- return self.solutions[0]
104
-
105
-
106
- class Improvement(SketchedAble):
107
- """A class representing an improvement suggestion."""
108
-
109
- focused_on: str
110
- """The focused on topic of the improvement"""
111
-
112
- problem_solutions: List[ProblemSolutions]
113
- """Collection of problems identified during review along with their potential solutions."""
114
-
115
- def all_problems_have_solutions(self) -> bool:
116
- """Check if all problems have solutions."""
117
- return all(ps.has_solutions() for ps in self.problem_solutions)
118
-
119
- async def supervisor_check(self, check_solutions: bool = True) -> Self:
120
- """Perform an interactive review session to filter problems and solutions.
121
-
122
- Presents an interactive prompt allowing a supervisor to select which
123
- problems (and optionally solutions) should be retained in the final review.
124
-
125
- Args:
126
- check_solutions (bool, optional): When True, also prompts for filtering
127
- individual solutions for each retained problem. Defaults to False.
128
-
129
- Returns:
130
- Self: The current instance with filtered problems and solutions.
131
- """
132
- from questionary import Choice, checkbox
133
-
134
- # Choose the problems to retain
135
- chosen_ones: List[ProblemSolutions] = await checkbox(
136
- "Please choose the problems you want to retain.(Default: retain all)",
137
- choices=[Choice(p.problem.name, p, checked=True) for p in self.problem_solutions],
138
- ).ask_async()
139
- self.problem_solutions = [await p.edit_problem() for p in chosen_ones]
140
- if not check_solutions:
141
- return self
142
-
143
- # Choose the solutions to retain
144
- for to_exam in self.problem_solutions:
145
- to_exam.update_solutions(
146
- await checkbox(
147
- f"Please choose the solutions you want to retain.(Default: retain all)\n\t`{to_exam.problem}`",
148
- choices=[Choice(s.name, s, checked=True) for s in to_exam.solutions],
149
- ).ask_async()
150
- )
151
- await to_exam.edit_solutions()
152
-
153
- return self
154
-
155
- def decided(self) -> bool:
156
- """Check if the improvement is decided."""
157
- return all(ps.decided() for ps in self.problem_solutions)
158
-
159
- @classmethod
160
- def gather(cls, *improvements: Unpack[Tuple["Improvement", ...]]) -> Self:
161
- """Gather multiple improvements into a single instance."""
162
- return cls(
163
- focused_on=";".join(imp.focused_on for imp in improvements),
164
- problem_solutions=list(chain(*(imp.problem_solutions for imp in improvements))),
165
- )
@@ -1,98 +0,0 @@
1
- """A module containing the RAG (Retrieval-Augmented Generation) models."""
2
-
3
- from abc import ABC
4
- from functools import partial
5
- from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Self, Sequence, Set
6
-
7
- from fabricatio.decorators import precheck_package
8
- from fabricatio.models.generic import Base, Vectorizable
9
- from fabricatio.utils import ok
10
- from pydantic import JsonValue
11
-
12
- if TYPE_CHECKING:
13
- from importlib.util import find_spec
14
-
15
- from pydantic.fields import FieldInfo
16
-
17
- if find_spec("pymilvus"):
18
- from pymilvus import CollectionSchema
19
-
20
-
21
- class MilvusDataBase(Base, Vectorizable, ABC):
22
- """A base class for Milvus data."""
23
-
24
- primary_field_name: ClassVar[str] = "id"
25
- """The name of the primary field in Milvus."""
26
- vector_field_name: ClassVar[str] = "vector"
27
- """The name of the vector field in Milvus."""
28
-
29
- index_type: ClassVar[str] = "FLAT"
30
- """The type of index to be used in Milvus."""
31
- metric_type: ClassVar[str] = "COSINE"
32
- """The type of metric to be used in Milvus."""
33
-
34
- def prepare_insertion(self, vector: List[float]) -> Dict[str, Any]:
35
- """Prepares the data for insertion into Milvus.
36
-
37
- Returns:
38
- dict: A dictionary containing the data to be inserted into Milvus.
39
- """
40
- return {**self.model_dump(exclude_none=True, by_alias=True), self.vector_field_name: vector}
41
-
42
- @classmethod
43
- @precheck_package(
44
- "pymilvus", "pymilvus is not installed. Have you installed `fabricatio[rag]` instead of `fabricatio`?"
45
- )
46
- def as_milvus_schema(cls, dimension: int = 1024) -> "CollectionSchema":
47
- """Generates the schema for Milvus collection."""
48
- from pymilvus import CollectionSchema, DataType, FieldSchema
49
-
50
- fields = [
51
- FieldSchema(cls.primary_field_name, dtype=DataType.INT64, is_primary=True, auto_id=True),
52
- FieldSchema(cls.vector_field_name, dtype=DataType.FLOAT_VECTOR, dim=dimension),
53
- ]
54
-
55
- for k, v in cls.model_fields.items():
56
- k: str
57
- v: FieldInfo
58
- schema = partial(FieldSchema, k, description=v.description or "")
59
- anno = ok(v.annotation)
60
-
61
- if anno == int:
62
- fields.append(schema(dtype=DataType.INT64))
63
- elif anno == str:
64
- fields.append(schema(dtype=DataType.VARCHAR, max_length=65535))
65
- elif anno == float:
66
- fields.append(schema(dtype=DataType.DOUBLE))
67
- elif anno == list[str] or anno == List[str] or anno == set[str] or anno == Set[str]:
68
- fields.append(
69
- schema(dtype=DataType.ARRAY, element_type=DataType.VARCHAR, max_length=65535, max_capacity=4096)
70
- )
71
- elif anno == list[int] or anno == List[int] or anno == set[int] or anno == Set[int]:
72
- fields.append(schema(dtype=DataType.ARRAY, element_type=DataType.INT64, max_capacity=4096))
73
- elif anno == list[float] or anno == List[float] or anno == set[float] or anno == Set[float]:
74
- fields.append(schema(dtype=DataType.ARRAY, element_type=DataType.DOUBLE, max_capacity=4096))
75
- elif anno == JsonValue:
76
- fields.append(schema(dtype=DataType.JSON))
77
-
78
- else:
79
- raise NotImplementedError(f"{k}:{anno} is not supported")
80
-
81
- return CollectionSchema(fields)
82
-
83
- @classmethod
84
- def from_sequence(cls, data: Sequence[Dict[str, Any]]) -> List[Self]:
85
- """Constructs a list of instances from a sequence of dictionaries."""
86
- return [cls(**d) for d in data]
87
-
88
-
89
- class MilvusClassicModel(MilvusDataBase):
90
- """A class representing a classic model stored in Milvus."""
91
-
92
- text: str
93
- """The text to be stored in Milvus."""
94
- subject: str = ""
95
- """The subject of the text."""
96
-
97
- def _prepare_vectorization_inner(self) -> str:
98
- return self.text