fabricatio 0.2.9.dev3__cp312-cp312-win_amd64.whl → 0.2.10__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/actions/article.py +24 -114
- fabricatio/actions/article_rag.py +156 -18
- fabricatio/actions/fs.py +25 -0
- fabricatio/actions/output.py +17 -3
- fabricatio/actions/rag.py +40 -18
- fabricatio/actions/rules.py +14 -3
- fabricatio/capabilities/check.py +15 -9
- fabricatio/capabilities/correct.py +5 -6
- fabricatio/capabilities/rag.py +41 -231
- fabricatio/capabilities/rating.py +46 -40
- fabricatio/config.py +6 -4
- fabricatio/constants.py +20 -0
- fabricatio/decorators.py +23 -0
- fabricatio/fs/readers.py +20 -1
- fabricatio/models/adv_kwargs_types.py +35 -0
- fabricatio/models/events.py +6 -6
- fabricatio/models/extra/advanced_judge.py +4 -4
- fabricatio/models/extra/aricle_rag.py +170 -0
- fabricatio/models/extra/article_base.py +25 -211
- fabricatio/models/extra/article_essence.py +8 -7
- fabricatio/models/extra/article_main.py +98 -97
- fabricatio/models/extra/article_proposal.py +15 -14
- fabricatio/models/extra/patches.py +6 -6
- fabricatio/models/extra/problem.py +12 -17
- fabricatio/models/extra/rag.py +98 -0
- fabricatio/models/extra/rule.py +1 -2
- fabricatio/models/generic.py +53 -13
- fabricatio/models/kwargs_types.py +8 -36
- fabricatio/models/task.py +3 -3
- fabricatio/models/usages.py +85 -9
- fabricatio/parser.py +5 -5
- fabricatio/rust.cp312-win_amd64.pyd +0 -0
- fabricatio/rust.pyi +137 -10
- fabricatio/utils.py +62 -4
- fabricatio-0.2.10.data/scripts/tdown.exe +0 -0
- {fabricatio-0.2.9.dev3.dist-info → fabricatio-0.2.10.dist-info}/METADATA +1 -4
- fabricatio-0.2.10.dist-info/RECORD +64 -0
- fabricatio/models/utils.py +0 -148
- fabricatio-0.2.9.dev3.data/scripts/tdown.exe +0 -0
- fabricatio-0.2.9.dev3.dist-info/RECORD +0 -61
- {fabricatio-0.2.9.dev3.dist-info → fabricatio-0.2.10.dist-info}/WHEEL +0 -0
- {fabricatio-0.2.9.dev3.dist-info → fabricatio-0.2.10.dist-info}/licenses/LICENSE +0 -0
@@ -1,12 +1,14 @@
|
|
1
1
|
"""ArticleBase and ArticleSubsection classes for managing hierarchical document components."""
|
2
2
|
|
3
|
-
from itertools import chain
|
4
3
|
from typing import Dict, Generator, List, Self, Tuple, override
|
5
4
|
|
5
|
+
from fabricatio.rust import word_count, convert_all_block_tex, convert_all_inline_tex
|
6
|
+
from pydantic import Field
|
7
|
+
|
8
|
+
from fabricatio.fs.readers import extract_sections
|
6
9
|
from fabricatio.journal import logger
|
7
10
|
from fabricatio.models.extra.article_base import (
|
8
11
|
ArticleBase,
|
9
|
-
ArticleOutlineBase,
|
10
12
|
ChapterBase,
|
11
13
|
SectionBase,
|
12
14
|
SubSectionBase,
|
@@ -14,26 +16,30 @@ from fabricatio.models.extra.article_base import (
|
|
14
16
|
from fabricatio.models.extra.article_outline import (
|
15
17
|
ArticleOutline,
|
16
18
|
)
|
17
|
-
from fabricatio.models.generic import PersistentAble, SequencePatch, SketchedAble, WithRef
|
18
|
-
|
19
|
-
|
19
|
+
from fabricatio.models.generic import Described, PersistentAble, SequencePatch, SketchedAble, WithRef, WordCount
|
20
|
+
|
21
|
+
PARAGRAPH_SEP = "// - - -"
|
20
22
|
|
21
23
|
|
22
|
-
class Paragraph(SketchedAble):
|
24
|
+
class Paragraph(SketchedAble, WordCount, Described):
|
23
25
|
"""Structured academic paragraph blueprint for controlled content generation."""
|
24
26
|
|
25
|
-
description: str
|
26
|
-
|
27
|
+
description: str = Field(
|
28
|
+
alias="elaboration",
|
29
|
+
description=Described.model_fields["description"].description,
|
30
|
+
)
|
27
31
|
|
28
|
-
|
32
|
+
aims: List[str]
|
29
33
|
"""Specific communicative objectives for this paragraph's content."""
|
30
34
|
|
31
|
-
expected_word_count: int
|
32
|
-
"""Expected word count for the paragraph."""
|
33
|
-
|
34
35
|
content: str
|
35
36
|
"""The actual content of the paragraph, represented as a string."""
|
36
37
|
|
38
|
+
@classmethod
|
39
|
+
def from_content(cls, content: str) -> Self:
|
40
|
+
"""Create a Paragraph object from the given content."""
|
41
|
+
return cls(elaboration="", aims=[], expected_word_count=word_count(content), content=content)
|
42
|
+
|
37
43
|
|
38
44
|
class ArticleParagraphSequencePatch(SequencePatch[Paragraph]):
|
39
45
|
"""Patch for `Paragraph` list of `ArticleSubsection`."""
|
@@ -57,10 +63,10 @@ class ArticleSubsection(SubSectionBase):
|
|
57
63
|
"""Introspects the subsection and returns a summary of its state."""
|
58
64
|
summary = ""
|
59
65
|
if len(self.paragraphs) == 0:
|
60
|
-
summary += f"`{self.__class__.__name__}` titled `{self.title}` have no paragraphs!\n"
|
66
|
+
summary += f"`{self.__class__.__name__}` titled `{self.title}` have no paragraphs, You should add some!\n"
|
61
67
|
if (
|
62
|
-
|
63
|
-
|
68
|
+
abs((wc := self.word_count) - self.expected_word_count) / self.expected_word_count
|
69
|
+
> self._max_word_count_deviation
|
64
70
|
):
|
65
71
|
summary += f"`{self.__class__.__name__}` titled `{self.title}` have {wc} words, expected {self.expected_word_count} words!"
|
66
72
|
|
@@ -80,16 +86,53 @@ class ArticleSubsection(SubSectionBase):
|
|
80
86
|
Returns:
|
81
87
|
str: Typst code snippet for rendering.
|
82
88
|
"""
|
83
|
-
return f"=== {self.title}\n" + "\n\n".join(p.content for p in self.paragraphs)
|
89
|
+
return f"=== {self.title}\n" + f"\n{PARAGRAPH_SEP}\n".join(p.content for p in self.paragraphs)
|
90
|
+
|
91
|
+
@classmethod
|
92
|
+
def from_typst_code(cls, title: str, body: str) -> Self:
|
93
|
+
"""Creates an Article object from the given Typst code."""
|
94
|
+
return cls(
|
95
|
+
heading=title,
|
96
|
+
elaboration="",
|
97
|
+
paragraphs=[Paragraph.from_content(p) for p in body.split(PARAGRAPH_SEP)],
|
98
|
+
expected_word_count=word_count(body),
|
99
|
+
aims=[],
|
100
|
+
)
|
84
101
|
|
85
102
|
|
86
103
|
class ArticleSection(SectionBase[ArticleSubsection]):
|
87
104
|
"""Atomic argumentative unit with high-level specificity."""
|
88
105
|
|
106
|
+
@classmethod
|
107
|
+
def from_typst_code(cls, title: str, body: str) -> Self:
|
108
|
+
"""Creates an Article object from the given Typst code."""
|
109
|
+
return cls(
|
110
|
+
subsections=[
|
111
|
+
ArticleSubsection.from_typst_code(*pack) for pack in extract_sections(body, level=3, section_char="=")
|
112
|
+
],
|
113
|
+
heading=title,
|
114
|
+
elaboration="",
|
115
|
+
expected_word_count=word_count(body),
|
116
|
+
aims=[],
|
117
|
+
)
|
118
|
+
|
89
119
|
|
90
120
|
class ArticleChapter(ChapterBase[ArticleSection]):
|
91
121
|
"""Thematic progression implementing research function."""
|
92
122
|
|
123
|
+
@classmethod
|
124
|
+
def from_typst_code(cls, title: str, body: str) -> Self:
|
125
|
+
"""Creates an Article object from the given Typst code."""
|
126
|
+
return cls(
|
127
|
+
sections=[
|
128
|
+
ArticleSection.from_typst_code(*pack) for pack in extract_sections(body, level=2, section_char="=")
|
129
|
+
],
|
130
|
+
heading=title,
|
131
|
+
elaboration="",
|
132
|
+
expected_word_count=word_count(body),
|
133
|
+
aims=[],
|
134
|
+
)
|
135
|
+
|
93
136
|
|
94
137
|
class Article(
|
95
138
|
SketchedAble,
|
@@ -111,6 +154,22 @@ class Article(
|
|
111
154
|
"Original Article": self.display(),
|
112
155
|
}
|
113
156
|
|
157
|
+
def convert_tex(self) -> Self:
|
158
|
+
"""Convert tex to typst code"""
|
159
|
+
for _, _, subsec in self.iter_subsections():
|
160
|
+
for p in subsec.paragraphs:
|
161
|
+
p.content = convert_all_inline_tex(p.content)
|
162
|
+
p.content = convert_all_block_tex(p.content)
|
163
|
+
return self
|
164
|
+
|
165
|
+
def fix_wrapper(self) -> Self:
|
166
|
+
"""Fix wrapper"""
|
167
|
+
for _, _, subsec in self.iter_subsections():
|
168
|
+
for p in subsec.paragraphs:
|
169
|
+
p.content = p.content.replace(r" \( ", "$").replace(r" \) ", "$").replace("\\[\n", "$$\n").replace(
|
170
|
+
"\n\\]", "\n$$")
|
171
|
+
return self
|
172
|
+
|
114
173
|
@override
|
115
174
|
def iter_subsections(self) -> Generator[Tuple[ArticleChapter, ArticleSection, ArticleSubsection], None, None]:
|
116
175
|
return super().iter_subsections() # pyright: ignore [reportReturnType]
|
@@ -126,107 +185,49 @@ class Article(
|
|
126
185
|
Article: The generated article.
|
127
186
|
"""
|
128
187
|
# Set the title from the outline
|
129
|
-
article = Article(**outline.model_dump(exclude={"chapters"}), chapters=[])
|
188
|
+
article = Article(**outline.model_dump(exclude={"chapters"}, by_alias=True), chapters=[])
|
130
189
|
|
131
190
|
for chapter in outline.chapters:
|
132
191
|
# Create a new chapter
|
133
192
|
article_chapter = ArticleChapter(
|
134
193
|
sections=[],
|
135
|
-
**chapter.model_dump(exclude={"sections"}),
|
194
|
+
**chapter.model_dump(exclude={"sections"}, by_alias=True),
|
136
195
|
)
|
137
196
|
for section in chapter.sections:
|
138
197
|
# Create a new section
|
139
198
|
article_section = ArticleSection(
|
140
199
|
subsections=[],
|
141
|
-
**section.model_dump(exclude={"subsections"}),
|
200
|
+
**section.model_dump(exclude={"subsections"}, by_alias=True),
|
142
201
|
)
|
143
202
|
for subsection in section.subsections:
|
144
203
|
# Create a new subsection
|
145
204
|
article_subsection = ArticleSubsection(
|
146
205
|
paragraphs=[],
|
147
|
-
**subsection.model_dump(),
|
206
|
+
**subsection.model_dump(by_alias=True),
|
148
207
|
)
|
149
208
|
article_section.subsections.append(article_subsection)
|
150
209
|
article_chapter.sections.append(article_section)
|
151
210
|
article.chapters.append(article_chapter)
|
152
211
|
return article
|
153
212
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
supports.append(a)
|
165
|
-
|
166
|
-
return list(set(depends + supports))
|
167
|
-
|
168
|
-
def gather_dependencies_recursive(self, article: ArticleOutlineBase) -> List[ArticleOutlineBase]:
|
169
|
-
"""Gathers all dependencies recursively for the given article.
|
170
|
-
|
171
|
-
Args:
|
172
|
-
article (ArticleOutlineBase): The article to gather dependencies for.
|
173
|
-
|
174
|
-
Returns:
|
175
|
-
List[ArticleBase]: A list of all dependencies for the given article.
|
176
|
-
"""
|
177
|
-
q = self.gather_dependencies(article)
|
178
|
-
|
179
|
-
deps = []
|
180
|
-
while q:
|
181
|
-
a = q.pop()
|
182
|
-
deps.extend(self.gather_dependencies(a))
|
183
|
-
|
184
|
-
deps = list(
|
185
|
-
chain(
|
186
|
-
filter(lambda x: isinstance(x, ArticleChapter), deps),
|
187
|
-
filter(lambda x: isinstance(x, ArticleSection), deps),
|
188
|
-
filter(lambda x: isinstance(x, ArticleSubsection), deps),
|
189
|
-
)
|
213
|
+
@classmethod
|
214
|
+
def from_typst_code(cls, title: str, body: str) -> Self:
|
215
|
+
"""Generates an article from the given Typst code."""
|
216
|
+
return cls(
|
217
|
+
chapters=[
|
218
|
+
ArticleChapter.from_typst_code(*pack) for pack in extract_sections(body, level=1, section_char="=")
|
219
|
+
],
|
220
|
+
heading=title,
|
221
|
+
expected_word_count=word_count(body),
|
222
|
+
abstract="",
|
190
223
|
)
|
191
224
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
continue
|
202
|
-
|
203
|
-
# Add this component
|
204
|
-
formatted_code += component_code
|
205
|
-
processed_components.append(component)
|
206
|
-
|
207
|
-
return processed_components
|
208
|
-
|
209
|
-
def iter_dfs_with_deps(
|
210
|
-
self, chapter: bool = True, section: bool = True, subsection: bool = True
|
211
|
-
) -> Generator[Tuple[ArticleOutlineBase, List[ArticleOutlineBase]], None, None]:
|
212
|
-
"""Iterates through the article in a depth-first manner, yielding each component and its dependencies.
|
213
|
-
|
214
|
-
Args:
|
215
|
-
chapter (bool, optional): Whether to include chapter components. Defaults to True.
|
216
|
-
section (bool, optional): Whether to include section components. Defaults to True.
|
217
|
-
subsection (bool, optional): Whether to include subsection components. Defaults to True.
|
218
|
-
|
219
|
-
Yields:
|
220
|
-
Tuple[ArticleBase, List[ArticleBase]]: Each component and its dependencies.
|
221
|
-
"""
|
222
|
-
if all((not chapter, not section, not subsection)):
|
223
|
-
raise ValueError("At least one of chapter, section, or subsection must be True.")
|
224
|
-
|
225
|
-
for component in self.iter_dfs_rev():
|
226
|
-
if not chapter and isinstance(component, ArticleChapter):
|
227
|
-
continue
|
228
|
-
if not section and isinstance(component, ArticleSection):
|
229
|
-
continue
|
230
|
-
if not subsection and isinstance(component, ArticleSubsection):
|
231
|
-
continue
|
232
|
-
yield component, (self.gather_dependencies_recursive(component))
|
225
|
+
@classmethod
|
226
|
+
def from_mixed_source(cls, article_outline: ArticleOutline, typst_code: str) -> Self:
|
227
|
+
"""Generates an article from the given outline and Typst code."""
|
228
|
+
self = cls.from_typst_code(article_outline.title, typst_code)
|
229
|
+
self.expected_word_count = article_outline.expected_word_count
|
230
|
+
self.description = article_outline.description
|
231
|
+
for a, o in zip(self.iter_dfs(), article_outline.iter_dfs(), strict=True):
|
232
|
+
a.update_metadata(o)
|
233
|
+
return self.update_ref(article_outline)
|
@@ -2,21 +2,25 @@
|
|
2
2
|
|
3
3
|
from typing import Dict, List
|
4
4
|
|
5
|
-
from fabricatio.models.generic import
|
6
|
-
|
7
|
-
|
8
|
-
|
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):
|
9
19
|
"""Structured proposal for academic paper development with core research elements.
|
10
20
|
|
11
21
|
Guides LLM in generating comprehensive research proposals with clearly defined components.
|
12
22
|
"""
|
13
23
|
|
14
|
-
language: str
|
15
|
-
"""The language in which the article is written. This should align with the language specified in the article briefing."""
|
16
|
-
|
17
|
-
title: str
|
18
|
-
"""The title of the academic paper, formatted in Title Case."""
|
19
|
-
|
20
24
|
focused_problem: List[str]
|
21
25
|
"""A list of specific research problems or questions that the paper aims to address."""
|
22
26
|
|
@@ -38,12 +42,9 @@ class ArticleProposal(SketchedAble, WithRef[str], AsPrompt, PersistentAble):
|
|
38
42
|
keywords: List[str]
|
39
43
|
"""A list of keywords that represent the main topics and focus areas of the research."""
|
40
44
|
|
41
|
-
|
45
|
+
description: str = Field(alias="abstract")
|
42
46
|
"""A concise summary of the research proposal, outlining the main points and objectives."""
|
43
47
|
|
44
|
-
expected_word_count: int
|
45
|
-
"""The estimated word count of the final academic paper."""
|
46
|
-
|
47
48
|
def _as_prompt_inner(self) -> Dict[str, str]:
|
48
49
|
return {
|
49
50
|
"ArticleBriefing": self.referenced,
|
@@ -3,17 +3,17 @@
|
|
3
3
|
from typing import Optional, Type
|
4
4
|
|
5
5
|
from fabricatio.models.extra.rule import RuleSet
|
6
|
-
from fabricatio.models.generic import Patch, WithBriefing
|
6
|
+
from fabricatio.models.generic import Language, Patch, WithBriefing
|
7
7
|
from pydantic import BaseModel
|
8
8
|
|
9
9
|
|
10
|
-
class
|
11
|
-
"""
|
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
12
|
|
13
13
|
|
14
|
-
class
|
15
|
-
"""
|
16
|
-
|
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
17
|
@staticmethod
|
18
18
|
def ref_cls() -> Optional[Type[BaseModel]]:
|
19
19
|
"""Get the reference class of the model."""
|
@@ -1,11 +1,12 @@
|
|
1
1
|
"""A class representing a problem-solution pair identified during a review process."""
|
2
2
|
|
3
3
|
from itertools import chain
|
4
|
-
from typing import Any, List,
|
4
|
+
from typing import Any, List, Optional, Self, Tuple, Unpack
|
5
5
|
|
6
6
|
from fabricatio.journal import logger
|
7
7
|
from fabricatio.models.generic import SketchedAble, WithBriefing
|
8
8
|
from fabricatio.utils import ask_edit
|
9
|
+
from pydantic import Field
|
9
10
|
from questionary import Choice, checkbox, text
|
10
11
|
from rich import print as r_print
|
11
12
|
|
@@ -13,36 +14,30 @@ from rich import print as r_print
|
|
13
14
|
class Problem(SketchedAble, WithBriefing):
|
14
15
|
"""Represents a problem identified during review."""
|
15
16
|
|
16
|
-
description: str
|
17
|
-
"""
|
17
|
+
description: str = Field(alias="cause")
|
18
|
+
"""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
|
|
19
|
-
|
20
|
-
"""Severity level of the problem."""
|
21
|
-
|
22
|
-
category: str
|
23
|
-
"""Category of the problem."""
|
20
|
+
severity_level: int = Field(ge=0, le=10)
|
21
|
+
"""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."""
|
24
22
|
|
25
23
|
location: str
|
26
24
|
"""Location where the problem was identified."""
|
27
25
|
|
28
|
-
recommendation: str
|
29
|
-
"""Recommended solution or action."""
|
30
|
-
|
31
26
|
|
32
27
|
class Solution(SketchedAble, WithBriefing):
|
33
28
|
"""Represents a proposed solution to a problem."""
|
34
29
|
|
35
|
-
description: str
|
30
|
+
description: str = Field(alias="mechanism")
|
36
31
|
"""Description of the solution, including a detailed description of the execution steps, and the mechanics, principle or fact."""
|
37
32
|
|
38
33
|
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."""
|
34
|
+
"""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."""
|
40
35
|
|
41
|
-
|
42
|
-
"""Feasibility level of the solution."""
|
36
|
+
feasibility_level: int = Field(ge=0, le=10)
|
37
|
+
"""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."""
|
43
38
|
|
44
|
-
|
45
|
-
"""Impact level of the solution."""
|
39
|
+
impact_level: int = Field(ge=0, le=10)
|
40
|
+
"""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."""
|
46
41
|
|
47
42
|
|
48
43
|
class ProblemSolutions(SketchedAble):
|
@@ -0,0 +1,98 @@
|
|
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 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(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
|
fabricatio/models/extra/rule.py
CHANGED
@@ -40,12 +40,11 @@ class RuleSet(SketchedAble, PersistentAble, WithBriefing, Language):
|
|
40
40
|
framework for the topic or domain covered by the rule set."""
|
41
41
|
|
42
42
|
@classmethod
|
43
|
-
def gather(cls, *rulesets: Unpack[Tuple["RuleSet"
|
43
|
+
def gather(cls, *rulesets: Unpack[Tuple["RuleSet", ...]]) -> Self:
|
44
44
|
"""Gathers multiple rule sets into a single rule set."""
|
45
45
|
if not rulesets:
|
46
46
|
raise ValueError("No rulesets provided")
|
47
47
|
return cls(
|
48
|
-
language=rulesets[0].language,
|
49
48
|
name=";".join(ruleset.name for ruleset in rulesets),
|
50
49
|
description=";".join(ruleset.description for ruleset in rulesets),
|
51
50
|
rules=list(flatten(r.rules for r in rulesets)),
|