fabricatio 0.2.13.dev3__cp312-cp312-win_amd64.whl → 0.3.14__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/__init__.py +7 -14
- fabricatio/actions/article.py +58 -23
- fabricatio/actions/article_rag.py +6 -15
- fabricatio/actions/output.py +38 -3
- fabricatio/actions/rag.py +4 -4
- fabricatio/capabilities/advanced_judge.py +4 -7
- fabricatio/capabilities/advanced_rag.py +2 -1
- fabricatio/capabilities/censor.py +5 -4
- fabricatio/capabilities/check.py +6 -7
- fabricatio/capabilities/correct.py +5 -5
- fabricatio/capabilities/extract.py +7 -3
- fabricatio/capabilities/persist.py +103 -0
- fabricatio/capabilities/propose.py +2 -2
- fabricatio/capabilities/rag.py +43 -43
- fabricatio/capabilities/rating.py +11 -10
- fabricatio/capabilities/review.py +8 -6
- fabricatio/capabilities/task.py +22 -22
- fabricatio/decorators.py +4 -2
- fabricatio/{core.py → emitter.py} +35 -39
- fabricatio/fs/__init__.py +1 -2
- fabricatio/journal.py +2 -11
- fabricatio/models/action.py +14 -30
- fabricatio/models/extra/aricle_rag.py +14 -8
- fabricatio/models/extra/article_base.py +56 -25
- fabricatio/models/extra/article_essence.py +2 -1
- fabricatio/models/extra/article_main.py +16 -13
- fabricatio/models/extra/article_outline.py +2 -1
- fabricatio/models/extra/article_proposal.py +1 -1
- fabricatio/models/extra/rag.py +2 -2
- fabricatio/models/extra/rule.py +2 -1
- fabricatio/models/generic.py +56 -166
- fabricatio/models/kwargs_types.py +1 -54
- fabricatio/models/role.py +49 -26
- fabricatio/models/task.py +8 -9
- fabricatio/models/tool.py +7 -7
- fabricatio/models/usages.py +67 -61
- fabricatio/parser.py +60 -100
- fabricatio/rust.cp312-win_amd64.pyd +0 -0
- fabricatio/rust.pyi +469 -74
- fabricatio/utils.py +63 -162
- fabricatio-0.3.14.data/scripts/tdown.exe +0 -0
- fabricatio-0.3.14.data/scripts/ttm.exe +0 -0
- {fabricatio-0.2.13.dev3.dist-info → fabricatio-0.3.14.dist-info}/METADATA +10 -15
- fabricatio-0.3.14.dist-info/RECORD +64 -0
- {fabricatio-0.2.13.dev3.dist-info → fabricatio-0.3.14.dist-info}/WHEEL +1 -1
- fabricatio/config.py +0 -430
- fabricatio/constants.py +0 -20
- fabricatio/models/events.py +0 -120
- fabricatio/rust_instances.py +0 -10
- fabricatio-0.2.13.dev3.data/scripts/tdown.exe +0 -0
- fabricatio-0.2.13.dev3.data/scripts/ttm.exe +0 -0
- fabricatio-0.2.13.dev3.dist-info/RECORD +0 -67
- {fabricatio-0.2.13.dev3.dist-info → fabricatio-0.3.14.dist-info}/licenses/LICENSE +0 -0
fabricatio/models/action.py
CHANGED
@@ -12,12 +12,11 @@ Classes:
|
|
12
12
|
import traceback
|
13
13
|
from abc import abstractmethod
|
14
14
|
from asyncio import Queue, create_task
|
15
|
-
from typing import Any, ClassVar, Dict, Self, Sequence, Tuple, Type, Union, final
|
15
|
+
from typing import Any, ClassVar, Dict, Generator, Self, Sequence, Tuple, Type, Union, final
|
16
16
|
|
17
17
|
from fabricatio.journal import logger
|
18
18
|
from fabricatio.models.generic import WithBriefing
|
19
19
|
from fabricatio.models.task import Task
|
20
|
-
from fabricatio.models.usages import ToolBoxUsage
|
21
20
|
from fabricatio.utils import override_kwargs
|
22
21
|
from pydantic import Field, PrivateAttr
|
23
22
|
|
@@ -99,24 +98,21 @@ class Action(WithBriefing):
|
|
99
98
|
return f"## Your personality: \n{self.personality}\n# The action you are going to perform: \n{super().briefing}"
|
100
99
|
return f"# The action you are going to perform: \n{super().briefing}"
|
101
100
|
|
102
|
-
def to_task_output(self,
|
101
|
+
def to_task_output(self, to: Union[str, "WorkFlow"] = OUTPUT_KEY) -> Self:
|
103
102
|
"""Set the output key to OUTPUT_KEY and return the action instance."""
|
104
|
-
self.output_key = task_output_key
|
103
|
+
self.output_key = to.task_output_key if isinstance(to, WorkFlow) else to
|
105
104
|
return self
|
106
105
|
|
107
106
|
|
108
|
-
class WorkFlow(WithBriefing
|
107
|
+
class WorkFlow(WithBriefing):
|
109
108
|
"""Manages sequences of actions to fulfill tasks.
|
110
109
|
|
111
110
|
Handles context propagation between actions, error handling, and task lifecycle
|
112
111
|
events like cancellation and completion.
|
113
|
-
|
114
|
-
Attributes:
|
115
|
-
steps (Tuple): Sequence of Action instances or classes to execute.
|
116
|
-
task_input_key (str): Key for storing task instance in context.
|
117
|
-
task_output_key (str): Key to retrieve final result from context.
|
118
112
|
"""
|
119
113
|
|
114
|
+
name: str = "WorkFlow"
|
115
|
+
"""The name of the workflow, which is used to identify and describe the workflow."""
|
120
116
|
description: str = ""
|
121
117
|
"""The description of the workflow, which describes the workflow's purpose and requirements."""
|
122
118
|
|
@@ -129,10 +125,10 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
|
|
129
125
|
steps: Sequence[Union[Type[Action], Action]] = Field(frozen=True)
|
130
126
|
"""The sequence of actions to be executed, can be action classes or instances."""
|
131
127
|
|
132
|
-
task_input_key: str =
|
128
|
+
task_input_key: ClassVar[str] = INPUT_KEY
|
133
129
|
"""Key used to store the input task in the context dictionary."""
|
134
130
|
|
135
|
-
task_output_key: str =
|
131
|
+
task_output_key: ClassVar[str] = OUTPUT_KEY
|
136
132
|
"""Key used to extract the final result from the context dictionary."""
|
137
133
|
|
138
134
|
extra_init_context: Dict[str, Any] = Field(default_factory=dict, frozen=True)
|
@@ -143,10 +139,16 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
|
|
143
139
|
|
144
140
|
Args:
|
145
141
|
__context: The context to be used for initialization.
|
142
|
+
|
146
143
|
"""
|
144
|
+
self.name = self.name or self.__class__.__name__
|
147
145
|
# Convert any action classes to instances
|
148
146
|
self._instances = tuple(step if isinstance(step, Action) else step() for step in self.steps)
|
149
147
|
|
148
|
+
def iter_actions(self) -> Generator[Action, None, None]:
|
149
|
+
"""Iterate over action instances."""
|
150
|
+
yield from self._instances
|
151
|
+
|
150
152
|
def inject_personality(self, personality: str) -> Self:
|
151
153
|
"""Set personality for actions without existing personality.
|
152
154
|
|
@@ -248,24 +250,6 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
|
|
248
250
|
|
249
251
|
await self._context.put({self.task_input_key: task, **ctx})
|
250
252
|
|
251
|
-
def steps_fallback_to_self(self) -> Self:
|
252
|
-
"""Configure all steps to use this workflow's configuration as fallback.
|
253
|
-
|
254
|
-
Returns:
|
255
|
-
Self: The workflow instance for method chaining.
|
256
|
-
"""
|
257
|
-
self.hold_to(self._instances)
|
258
|
-
return self
|
259
|
-
|
260
|
-
def steps_supply_tools_from_self(self) -> Self:
|
261
|
-
"""Provide this workflow's tools to all steps in the workflow.
|
262
|
-
|
263
|
-
Returns:
|
264
|
-
Self: The workflow instance for method chaining.
|
265
|
-
"""
|
266
|
-
self.provide_tools_to(i for i in self._instances if isinstance(i, ToolBoxUsage))
|
267
|
-
return self
|
268
|
-
|
269
253
|
def update_init_context(self, /, **kwargs) -> Self:
|
270
254
|
"""Update the initial context with additional key-value pairs.
|
271
255
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""A Module containing the article rag models."""
|
2
2
|
|
3
3
|
import re
|
4
|
+
from dataclasses import dataclass, field
|
4
5
|
from itertools import groupby
|
5
6
|
from pathlib import Path
|
6
7
|
from typing import ClassVar, Dict, List, Optional, Self, Unpack
|
@@ -55,6 +56,7 @@ class ArticleChunk(MilvusDataBase):
|
|
55
56
|
|
56
57
|
@property
|
57
58
|
def reference_header(self) -> str:
|
59
|
+
"""Get the reference header."""
|
58
60
|
return f"[[{ok(self._cite_number, 'You need to update cite number first.')}]] reference `{self.article_title}` from {self.as_auther_seq()}"
|
59
61
|
|
60
62
|
@property
|
@@ -67,7 +69,7 @@ class ArticleChunk(MilvusDataBase):
|
|
67
69
|
|
68
70
|
@classmethod
|
69
71
|
def from_file[P: str | Path](
|
70
|
-
|
72
|
+
cls, path: P | List[P], bib_mgr: BibManager, **kwargs: Unpack[ChunkKwargs]
|
71
73
|
) -> List[Self]:
|
72
74
|
"""Load the article chunks from the file."""
|
73
75
|
if isinstance(path, list):
|
@@ -84,9 +86,9 @@ class ArticleChunk(MilvusDataBase):
|
|
84
86
|
title_seg = path.stem.split(" - ").pop()
|
85
87
|
|
86
88
|
key = (
|
87
|
-
|
88
|
-
|
89
|
-
|
89
|
+
bib_mgr.get_cite_key_by_title(title_seg)
|
90
|
+
or bib_mgr.get_cite_key_by_title_fuzzy(title_seg)
|
91
|
+
or bib_mgr.get_cite_key_fuzzy(path.stem)
|
90
92
|
)
|
91
93
|
if key is None:
|
92
94
|
logger.warning(f"no cite key found for {path.as_posix()}, skip.")
|
@@ -164,10 +166,11 @@ class ArticleChunk(MilvusDataBase):
|
|
164
166
|
return self
|
165
167
|
|
166
168
|
|
169
|
+
@dataclass
|
167
170
|
class CitationManager(AsPrompt):
|
168
171
|
"""Citation manager."""
|
169
172
|
|
170
|
-
article_chunks: List[ArticleChunk] =
|
173
|
+
article_chunks: List[ArticleChunk] = field(default_factory=list)
|
171
174
|
"""Article chunks."""
|
172
175
|
|
173
176
|
pat: str = r"(\[\[([\d\s,-]*)]])"
|
@@ -178,7 +181,7 @@ class CitationManager(AsPrompt):
|
|
178
181
|
"""Separator for abbreviated citation numbers."""
|
179
182
|
|
180
183
|
def update_chunks(
|
181
|
-
|
184
|
+
self, article_chunks: List[ArticleChunk], set_cite_number: bool = True, dedup: bool = True
|
182
185
|
) -> Self:
|
183
186
|
"""Update article chunks."""
|
184
187
|
self.article_chunks.clear()
|
@@ -217,8 +220,9 @@ class CitationManager(AsPrompt):
|
|
217
220
|
def _as_prompt_inner(self) -> Dict[str, str]:
|
218
221
|
"""Generate prompt inner representation."""
|
219
222
|
seg = []
|
220
|
-
for k,
|
221
|
-
g = list(
|
223
|
+
for k, g_iter in groupby(self.article_chunks, key=lambda a: a.bibtex_cite_key):
|
224
|
+
g = list(g_iter)
|
225
|
+
|
222
226
|
logger.debug(f"Group [{k}]: {len(g)}")
|
223
227
|
seg.append(wrapp_in_block("\n\n".join(a.chunk for a in g), first(g).reference_header))
|
224
228
|
return {"References": "\n".join(seg)}
|
@@ -276,5 +280,7 @@ class CitationManager(AsPrompt):
|
|
276
280
|
return "".join(a.as_typst_cite() for a in chunk_seq.values())
|
277
281
|
|
278
282
|
def as_milvus_filter_expr(self, blacklist: bool = True) -> str:
|
283
|
+
"""Asynchronously fetches documents from a Milvus database based on input vectors."""
|
279
284
|
if blacklist:
|
280
285
|
return " and ".join(f'bibtex_cite_key != "{a.bibtex_cite_key}"' for a in self.article_chunks)
|
286
|
+
return " or ".join(f'bibtex_cite_key == "{a.bibtex_cite_key}"' for a in self.article_chunks)
|
@@ -5,6 +5,7 @@ from enum import StrEnum
|
|
5
5
|
from pathlib import Path
|
6
6
|
from typing import ClassVar, Generator, List, Optional, Self, Tuple, Type
|
7
7
|
|
8
|
+
from fabricatio.capabilities.persist import PersistentAble
|
8
9
|
from fabricatio.fs import dump_text, safe_text_read
|
9
10
|
from fabricatio.fs.readers import extract_sections
|
10
11
|
from fabricatio.journal import logger
|
@@ -15,14 +16,20 @@ from fabricatio.models.generic import (
|
|
15
16
|
Introspect,
|
16
17
|
Language,
|
17
18
|
ModelHash,
|
18
|
-
PersistentAble,
|
19
19
|
ProposedUpdateAble,
|
20
|
-
ResolveUpdateConflict,
|
21
20
|
SketchedAble,
|
22
21
|
Titled,
|
23
22
|
WordCount,
|
24
23
|
)
|
25
|
-
from fabricatio.rust import
|
24
|
+
from fabricatio.rust import (
|
25
|
+
comment,
|
26
|
+
extract_body,
|
27
|
+
replace_thesis_body,
|
28
|
+
split_out_metadata,
|
29
|
+
strip_comment,
|
30
|
+
to_metadata,
|
31
|
+
word_count,
|
32
|
+
)
|
26
33
|
from fabricatio.utils import fallback_kwargs, ok
|
27
34
|
from pydantic import Field
|
28
35
|
|
@@ -53,10 +60,17 @@ class ArticleMetaData(SketchedAble, Described, WordCount, Titled, Language):
|
|
53
60
|
aims: List[str]
|
54
61
|
"""List of writing aims of the research component in academic style."""
|
55
62
|
|
63
|
+
unstructured_body: str = ""
|
64
|
+
"""Store the source of the unknown information."""
|
65
|
+
|
56
66
|
@property
|
57
67
|
def typst_metadata_comment(self) -> str:
|
58
68
|
"""Generates a comment for the metadata of the article component."""
|
59
|
-
|
69
|
+
data = self.model_dump(
|
70
|
+
include={"description", "aims", "expected_word_count"},
|
71
|
+
by_alias=True,
|
72
|
+
)
|
73
|
+
return to_metadata({k: v for k, v in data.items() if v})
|
60
74
|
|
61
75
|
|
62
76
|
class FromTypstCode(ArticleMetaData):
|
@@ -69,12 +83,7 @@ class FromTypstCode(ArticleMetaData):
|
|
69
83
|
|
70
84
|
return cls(
|
71
85
|
heading=title,
|
72
|
-
**fallback_kwargs(
|
73
|
-
data or {},
|
74
|
-
elaboration="",
|
75
|
-
expected_word_count=word_count(body),
|
76
|
-
aims=[],
|
77
|
-
),
|
86
|
+
**fallback_kwargs(data or {}, elaboration="", expected_word_count=word_count(body), aims=[]),
|
78
87
|
**kwargs,
|
79
88
|
)
|
80
89
|
|
@@ -84,11 +93,10 @@ class ToTypstCode(ArticleMetaData):
|
|
84
93
|
|
85
94
|
def to_typst_code(self) -> str:
|
86
95
|
"""Converts the component into a Typst code snippet for rendering."""
|
87
|
-
return f"{self.title}\n{self.typst_metadata_comment}\n"
|
96
|
+
return f"{self.title}\n{self.typst_metadata_comment}\n\n{self.unstructured_body}"
|
88
97
|
|
89
98
|
|
90
99
|
class ArticleOutlineBase(
|
91
|
-
ResolveUpdateConflict,
|
92
100
|
ProposedUpdateAble,
|
93
101
|
PersistentAble,
|
94
102
|
ModelHash,
|
@@ -153,12 +161,12 @@ class SectionBase[T: SubSectionBase](ArticleOutlineBase):
|
|
153
161
|
@classmethod
|
154
162
|
def from_typst_code(cls, title: str, body: str, **kwargs) -> Self:
|
155
163
|
"""Creates an Article object from the given Typst code."""
|
164
|
+
raw_subsec = extract_sections(body, level=3, section_char="=")
|
156
165
|
return super().from_typst_code(
|
157
166
|
title,
|
158
167
|
body,
|
159
|
-
subsections=[
|
160
|
-
|
161
|
-
],
|
168
|
+
subsections=[cls.child_type.from_typst_code(*pack) for pack in raw_subsec],
|
169
|
+
unstructured_body="" if raw_subsec else strip_comment(body),
|
162
170
|
)
|
163
171
|
|
164
172
|
def resolve_update_conflict(self, other: Self) -> str:
|
@@ -193,6 +201,11 @@ class SectionBase[T: SubSectionBase](ArticleOutlineBase):
|
|
193
201
|
return f"Section `{self.title}` contains no subsections, expected at least one, but got 0, you can add one or more as needed."
|
194
202
|
return ""
|
195
203
|
|
204
|
+
@property
|
205
|
+
def exact_word_count(self) -> int:
|
206
|
+
"""Returns the exact word count of the article section outline."""
|
207
|
+
return sum(a.exact_word_count for a in self.subsections)
|
208
|
+
|
196
209
|
|
197
210
|
class ChapterBase[T: SectionBase](ArticleOutlineBase):
|
198
211
|
"""Base class for article chapters."""
|
@@ -208,12 +221,12 @@ class ChapterBase[T: SectionBase](ArticleOutlineBase):
|
|
208
221
|
@classmethod
|
209
222
|
def from_typst_code(cls, title: str, body: str, **kwargs) -> Self:
|
210
223
|
"""Creates an Article object from the given Typst code."""
|
224
|
+
raw_sec = extract_sections(body, level=2, section_char="=")
|
211
225
|
return super().from_typst_code(
|
212
226
|
title,
|
213
227
|
body,
|
214
|
-
sections=[
|
215
|
-
|
216
|
-
],
|
228
|
+
sections=[cls.child_type.from_typst_code(*pack) for pack in raw_sec],
|
229
|
+
unstructured_body="" if raw_sec else strip_comment(body),
|
217
230
|
)
|
218
231
|
|
219
232
|
def resolve_update_conflict(self, other: Self) -> str:
|
@@ -245,6 +258,15 @@ class ChapterBase[T: SectionBase](ArticleOutlineBase):
|
|
245
258
|
return f"Chapter `{self.title}` contains no sections, expected at least one, but got 0, you can add one or more as needed."
|
246
259
|
return ""
|
247
260
|
|
261
|
+
@property
|
262
|
+
def exact_word_count(self) -> int:
|
263
|
+
"""Calculates the total word count across all sections in the chapter.
|
264
|
+
|
265
|
+
Returns:
|
266
|
+
int: The cumulative word count of all sections.
|
267
|
+
"""
|
268
|
+
return sum(a.exact_word_count for a in self.sections)
|
269
|
+
|
248
270
|
|
249
271
|
class ArticleBase[T: ChapterBase](FinalizedDumpAble, AsPrompt, FromTypstCode, ToTypstCode, ABC):
|
250
272
|
"""Base class for article outlines."""
|
@@ -265,15 +287,24 @@ class ArticleBase[T: ChapterBase](FinalizedDumpAble, AsPrompt, FromTypstCode, To
|
|
265
287
|
|
266
288
|
child_type: ClassVar[Type[ChapterBase]]
|
267
289
|
|
290
|
+
@property
|
291
|
+
def exact_word_count(self) -> int:
|
292
|
+
"""Calculates the total word count across all chapters in the article.
|
293
|
+
|
294
|
+
Returns:
|
295
|
+
int: The cumulative word count of all chapters.
|
296
|
+
"""
|
297
|
+
return sum(ch.exact_word_count for ch in self.chapters)
|
298
|
+
|
268
299
|
@classmethod
|
269
300
|
def from_typst_code(cls, title: str, body: str, **kwargs) -> Self:
|
270
301
|
"""Generates an article from the given Typst code."""
|
302
|
+
raw_chap = extract_sections(body, level=1, section_char="=")
|
271
303
|
return super().from_typst_code(
|
272
304
|
title,
|
273
305
|
body,
|
274
|
-
chapters=[
|
275
|
-
|
276
|
-
],
|
306
|
+
chapters=[cls.child_type.from_typst_code(*pack) for pack in raw_chap],
|
307
|
+
unstructured_body="" if raw_chap else strip_comment(body),
|
277
308
|
)
|
278
309
|
|
279
310
|
def iter_dfs_rev(
|
@@ -352,7 +383,7 @@ class ArticleBase[T: ChapterBase](FinalizedDumpAble, AsPrompt, FromTypstCode, To
|
|
352
383
|
|
353
384
|
def to_typst_code(self) -> str:
|
354
385
|
"""Generates the Typst code representation of the article."""
|
355
|
-
return f"
|
386
|
+
return comment(f"#Title: {super().to_typst_code()}\n") + "\n\n".join(a.to_typst_code() for a in self.chapters)
|
356
387
|
|
357
388
|
def finalized_dump(self) -> str:
|
358
389
|
"""Generates standardized hierarchical markup for academic publishing systems.
|
@@ -403,11 +434,11 @@ class ArticleBase[T: ChapterBase](FinalizedDumpAble, AsPrompt, FromTypstCode, To
|
|
403
434
|
"""Set all chap, sec, subsec have same word count sum up to be `self.expected_word_count`."""
|
404
435
|
return self.avg_chap_wordcount().avg_sec_wordcount().avg_subsec_wordcount()
|
405
436
|
|
406
|
-
def update_article_file(self, file: str | Path) ->
|
437
|
+
def update_article_file[S: "ArticleBase"](self: S, file: str | Path) -> S:
|
407
438
|
"""Update the article file."""
|
408
439
|
file = Path(file)
|
409
440
|
string = safe_text_read(file)
|
410
|
-
if updated :=
|
441
|
+
if updated := replace_thesis_body(string, ARTICLE_WRAPPER, f"\n\n{self.to_typst_code()}\n\n"):
|
411
442
|
dump_text(file, updated)
|
412
443
|
logger.success(f"Successfully updated {file.as_posix()}.")
|
413
444
|
else:
|
@@ -415,7 +446,7 @@ class ArticleBase[T: ChapterBase](FinalizedDumpAble, AsPrompt, FromTypstCode, To
|
|
415
446
|
return self
|
416
447
|
|
417
448
|
@classmethod
|
418
|
-
def from_article_file(cls, file: str | Path, title: str) ->
|
449
|
+
def from_article_file[S: "ArticleBase"](cls: Type[S], file: str | Path, title: str) -> S:
|
419
450
|
"""Load article from file."""
|
420
451
|
file = Path(file)
|
421
452
|
string = safe_text_read(file)
|
@@ -2,8 +2,9 @@
|
|
2
2
|
|
3
3
|
from typing import List
|
4
4
|
|
5
|
+
from fabricatio.capabilities.persist import PersistentAble
|
5
6
|
from fabricatio.models.extra.rag import MilvusDataBase
|
6
|
-
from fabricatio.models.generic import
|
7
|
+
from fabricatio.models.generic import SketchedAble
|
7
8
|
from pydantic import BaseModel
|
8
9
|
|
9
10
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
from typing import ClassVar, Dict, Generator, List, Self, Tuple, Type, override
|
4
4
|
|
5
|
+
from fabricatio.capabilities.persist import PersistentAble
|
5
6
|
from fabricatio.decorators import precheck_package
|
6
7
|
from fabricatio.journal import logger
|
7
8
|
from fabricatio.models.extra.article_base import (
|
@@ -16,17 +17,16 @@ from fabricatio.models.extra.article_outline import (
|
|
16
17
|
ArticleSectionOutline,
|
17
18
|
ArticleSubsectionOutline,
|
18
19
|
)
|
19
|
-
from fabricatio.models.generic import Described,
|
20
|
+
from fabricatio.models.generic import Described, SequencePatch, SketchedAble, WithRef, WordCount
|
20
21
|
from fabricatio.rust import (
|
21
|
-
|
22
|
-
convert_all_inline_tex,
|
22
|
+
convert_all_tex_math,
|
23
23
|
fix_misplaced_labels,
|
24
24
|
split_out_metadata,
|
25
25
|
word_count,
|
26
26
|
)
|
27
27
|
from pydantic import Field, NonNegativeInt
|
28
28
|
|
29
|
-
PARAGRAPH_SEP = "
|
29
|
+
PARAGRAPH_SEP = "// - - -"
|
30
30
|
|
31
31
|
|
32
32
|
class Paragraph(SketchedAble, WordCount, Described):
|
@@ -49,10 +49,10 @@ class Paragraph(SketchedAble, WordCount, Described):
|
|
49
49
|
@classmethod
|
50
50
|
def from_content(cls, content: str) -> Self:
|
51
51
|
"""Create a Paragraph object from the given content."""
|
52
|
-
return cls(elaboration="", aims=[], expected_word_count=word_count(content), content=content)
|
52
|
+
return cls(elaboration="", aims=[], expected_word_count=word_count(content), content=content.strip())
|
53
53
|
|
54
54
|
@property
|
55
|
-
def
|
55
|
+
def exact_word_count(self) -> int:
|
56
56
|
"""Calculates the exact word count of the content."""
|
57
57
|
return word_count(self.content)
|
58
58
|
|
@@ -70,6 +70,11 @@ class ArticleSubsection(SubSectionBase):
|
|
70
70
|
_max_word_count_deviation: float = 0.3
|
71
71
|
"""Maximum allowed deviation from the expected word count, as a percentage."""
|
72
72
|
|
73
|
+
@property
|
74
|
+
def exact_word_count(self) -> int:
|
75
|
+
"""Calculates the exact word count of all paragraphs in the subsection."""
|
76
|
+
return sum(a.exact_word_count for a in self.paragraphs)
|
77
|
+
|
73
78
|
@property
|
74
79
|
def word_count(self) -> int:
|
75
80
|
"""Calculates the total word count of all paragraphs in the subsection."""
|
@@ -102,7 +107,7 @@ class ArticleSubsection(SubSectionBase):
|
|
102
107
|
Returns:
|
103
108
|
str: Typst code snippet for rendering.
|
104
109
|
"""
|
105
|
-
return super().to_typst_code() + PARAGRAPH_SEP.join(p.content for p in self.paragraphs)
|
110
|
+
return super().to_typst_code() + f"\n\n{PARAGRAPH_SEP}\n\n".join(p.content for p in self.paragraphs)
|
106
111
|
|
107
112
|
@classmethod
|
108
113
|
def from_typst_code(cls, title: str, body: str, **kwargs) -> Self:
|
@@ -154,15 +159,13 @@ class Article(
|
|
154
159
|
if descriptions:
|
155
160
|
for a in self.iter_dfs():
|
156
161
|
a.description = fix_misplaced_labels(a.description)
|
157
|
-
a.description =
|
158
|
-
a.description = convert_all_block_tex(a.description)
|
162
|
+
a.description = convert_all_tex_math(a.description)
|
159
163
|
|
160
164
|
if paragraphs:
|
161
165
|
for _, _, subsec in self.iter_subsections():
|
162
166
|
for p in subsec.paragraphs:
|
163
167
|
p.content = fix_misplaced_labels(p.content)
|
164
|
-
p.content =
|
165
|
-
p.content = convert_all_block_tex(p.content)
|
168
|
+
p.content = convert_all_tex_math(p.content)
|
166
169
|
return self
|
167
170
|
|
168
171
|
@override
|
@@ -275,9 +278,9 @@ class Article(
|
|
275
278
|
err = []
|
276
279
|
for chap, sec, subsec in self.iter_subsections():
|
277
280
|
for i, p in enumerate(subsec.paragraphs):
|
278
|
-
if p.
|
281
|
+
if p.exact_word_count <= threshold:
|
279
282
|
err.append(
|
280
|
-
f"{chap.title}->{sec.title}->{subsec.title}-> Paragraph [{i}] is too short, {p.
|
283
|
+
f"{chap.title}->{sec.title}->{subsec.title}-> Paragraph [{i}] is too short, {p.exact_word_count} words."
|
281
284
|
)
|
282
285
|
|
283
286
|
return "\n".join(err)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
from typing import ClassVar, Dict, Type
|
4
4
|
|
5
|
+
from fabricatio.capabilities.persist import PersistentAble
|
5
6
|
from fabricatio.models.extra.article_base import (
|
6
7
|
ArticleBase,
|
7
8
|
ChapterBase,
|
@@ -9,7 +10,7 @@ from fabricatio.models.extra.article_base import (
|
|
9
10
|
SubSectionBase,
|
10
11
|
)
|
11
12
|
from fabricatio.models.extra.article_proposal import ArticleProposal
|
12
|
-
from fabricatio.models.generic import
|
13
|
+
from fabricatio.models.generic import WithRef
|
13
14
|
|
14
15
|
|
15
16
|
class ArticleSubsectionOutline(SubSectionBase):
|
fabricatio/models/extra/rag.py
CHANGED
@@ -5,7 +5,7 @@ from functools import partial
|
|
5
5
|
from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Self, Sequence, Set
|
6
6
|
|
7
7
|
from fabricatio.decorators import precheck_package
|
8
|
-
from fabricatio.models.generic import Vectorizable
|
8
|
+
from fabricatio.models.generic import Base, Vectorizable
|
9
9
|
from fabricatio.utils import ok
|
10
10
|
from pydantic import JsonValue
|
11
11
|
|
@@ -18,7 +18,7 @@ if TYPE_CHECKING:
|
|
18
18
|
from pymilvus import CollectionSchema
|
19
19
|
|
20
20
|
|
21
|
-
class MilvusDataBase(Vectorizable, ABC):
|
21
|
+
class MilvusDataBase(Base, Vectorizable, ABC):
|
22
22
|
"""A base class for Milvus data."""
|
23
23
|
|
24
24
|
primary_field_name: ClassVar[str] = "id"
|
fabricatio/models/extra/rule.py
CHANGED
@@ -10,7 +10,8 @@ complex rule management systems.
|
|
10
10
|
|
11
11
|
from typing import List, Self, Tuple, Unpack
|
12
12
|
|
13
|
-
from fabricatio.
|
13
|
+
from fabricatio.capabilities.persist import PersistentAble
|
14
|
+
from fabricatio.models.generic import Language, SketchedAble, WithBriefing
|
14
15
|
from more_itertools import flatten
|
15
16
|
|
16
17
|
|