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.
Files changed (42) hide show
  1. fabricatio/actions/article.py +24 -114
  2. fabricatio/actions/article_rag.py +156 -18
  3. fabricatio/actions/fs.py +25 -0
  4. fabricatio/actions/output.py +17 -3
  5. fabricatio/actions/rag.py +40 -18
  6. fabricatio/actions/rules.py +14 -3
  7. fabricatio/capabilities/check.py +15 -9
  8. fabricatio/capabilities/correct.py +5 -6
  9. fabricatio/capabilities/rag.py +41 -231
  10. fabricatio/capabilities/rating.py +46 -40
  11. fabricatio/config.py +6 -4
  12. fabricatio/constants.py +20 -0
  13. fabricatio/decorators.py +23 -0
  14. fabricatio/fs/readers.py +20 -1
  15. fabricatio/models/adv_kwargs_types.py +35 -0
  16. fabricatio/models/events.py +6 -6
  17. fabricatio/models/extra/advanced_judge.py +4 -4
  18. fabricatio/models/extra/aricle_rag.py +170 -0
  19. fabricatio/models/extra/article_base.py +25 -211
  20. fabricatio/models/extra/article_essence.py +8 -7
  21. fabricatio/models/extra/article_main.py +98 -97
  22. fabricatio/models/extra/article_proposal.py +15 -14
  23. fabricatio/models/extra/patches.py +6 -6
  24. fabricatio/models/extra/problem.py +12 -17
  25. fabricatio/models/extra/rag.py +98 -0
  26. fabricatio/models/extra/rule.py +1 -2
  27. fabricatio/models/generic.py +53 -13
  28. fabricatio/models/kwargs_types.py +8 -36
  29. fabricatio/models/task.py +3 -3
  30. fabricatio/models/usages.py +85 -9
  31. fabricatio/parser.py +5 -5
  32. fabricatio/rust.cp312-win_amd64.pyd +0 -0
  33. fabricatio/rust.pyi +137 -10
  34. fabricatio/utils.py +62 -4
  35. fabricatio-0.2.10.data/scripts/tdown.exe +0 -0
  36. {fabricatio-0.2.9.dev3.dist-info → fabricatio-0.2.10.dist-info}/METADATA +1 -4
  37. fabricatio-0.2.10.dist-info/RECORD +64 -0
  38. fabricatio/models/utils.py +0 -148
  39. fabricatio-0.2.9.dev3.data/scripts/tdown.exe +0 -0
  40. fabricatio-0.2.9.dev3.dist-info/RECORD +0 -61
  41. {fabricatio-0.2.9.dev3.dist-info → fabricatio-0.2.10.dist-info}/WHEEL +0 -0
  42. {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
- from fabricatio.rust import word_count
19
- from fabricatio.utils import ok
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
- """Functional summary of the paragraph's role in document structure."""
27
+ description: str = Field(
28
+ alias="elaboration",
29
+ description=Described.model_fields["description"].description,
30
+ )
27
31
 
28
- writing_aim: List[str]
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
- abs((wc := self.word_count) - self.expected_word_count) / self.expected_word_count
63
- > self._max_word_count_deviation
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
- def gather_dependencies(self, article: ArticleOutlineBase) -> List[ArticleOutlineBase]:
155
- """Gathers dependencies for all sections and subsections in the article.
156
-
157
- This method should be called after the article is fully constructed.
158
- """
159
- depends = [ok(a.deref(self)) for a in article.depend_on]
160
-
161
- supports = []
162
- for a in self.iter_dfs_rev():
163
- if article in {ok(b.deref(self)) for b in a.support_to}:
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
- # Initialize result containers
193
- formatted_code = ""
194
- processed_components = []
195
-
196
- # Process all dependencies
197
- while deps:
198
- component = deps.pop()
199
- # Skip duplicates
200
- if (component_code := component.to_typst_code()) in formatted_code:
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 AsPrompt, PersistentAble, SketchedAble, WithRef
6
-
7
-
8
- class ArticleProposal(SketchedAble, WithRef[str], AsPrompt, PersistentAble):
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
- abstract: str
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 BriefingPatch[T: WithBriefing](Patch[T], WithBriefing):
11
- """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."""
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 RuleSetBriefingPatch(BriefingPatch[RuleSet]):
15
- """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
- language: str
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, Literal, Optional, Self, Tuple, Unpack
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
- """Description of the problem, The """
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
- severity: Literal["low", "medium", "high"]
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
- feasibility: Literal["low", "medium", "high"]
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
- impact: Literal["low", "medium", "high"]
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
@@ -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",...]]) -> Self:
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)),