fabricatio 0.2.7.dev5__cp312-cp312-win_amd64.whl → 0.2.8.dev1__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/_rust.cp312-win_amd64.pyd +0 -0
- fabricatio/actions/article.py +188 -74
- fabricatio/actions/output.py +36 -1
- fabricatio/capabilities/advanced_judge.py +23 -0
- fabricatio/capabilities/correct.py +26 -6
- fabricatio/capabilities/rating.py +1 -1
- fabricatio/capabilities/review.py +2 -2
- fabricatio/models/action.py +3 -1
- fabricatio/models/extra/advanced_judge.py +22 -0
- fabricatio/models/extra/article_base.py +196 -86
- fabricatio/models/extra/article_essence.py +6 -9
- fabricatio/models/extra/article_main.py +29 -49
- fabricatio/models/extra/article_outline.py +10 -156
- fabricatio/models/extra/article_proposal.py +12 -14
- fabricatio/models/generic.py +12 -16
- fabricatio/models/usages.py +5 -1
- {fabricatio-0.2.7.dev5.data → fabricatio-0.2.8.dev1.data}/scripts/tdown.exe +0 -0
- {fabricatio-0.2.7.dev5.dist-info → fabricatio-0.2.8.dev1.dist-info}/METADATA +1 -1
- {fabricatio-0.2.7.dev5.dist-info → fabricatio-0.2.8.dev1.dist-info}/RECORD +21 -19
- {fabricatio-0.2.7.dev5.dist-info → fabricatio-0.2.8.dev1.dist-info}/WHEEL +0 -0
- {fabricatio-0.2.7.dev5.dist-info → fabricatio-0.2.8.dev1.dist-info}/licenses/LICENSE +0 -0
@@ -1,24 +1,23 @@
|
|
1
1
|
"""A foundation for hierarchical document components with dependency tracking."""
|
2
|
-
|
2
|
+
|
3
|
+
from abc import ABC, abstractmethod
|
3
4
|
from enum import StrEnum
|
4
|
-
from
|
5
|
+
from functools import cache
|
6
|
+
from itertools import chain
|
7
|
+
from typing import Generator, List, Optional, Self, Tuple
|
5
8
|
|
6
9
|
from fabricatio.models.generic import (
|
7
|
-
|
10
|
+
AsPrompt,
|
8
11
|
CensoredAble,
|
9
12
|
Display,
|
13
|
+
FinalizedDumpAble,
|
10
14
|
Introspect,
|
11
15
|
ModelHash,
|
12
16
|
PersistentAble,
|
13
|
-
|
17
|
+
ProposedUpdateAble,
|
14
18
|
ResolveUpdateConflict,
|
15
|
-
UpdateFrom,
|
16
19
|
)
|
17
20
|
|
18
|
-
if TYPE_CHECKING:
|
19
|
-
from fabricatio.models.extra.article_main import Article
|
20
|
-
from fabricatio.models.extra.article_outline import ArticleOutline
|
21
|
-
|
22
21
|
|
23
22
|
class ReferringType(StrEnum):
|
24
23
|
"""Enumeration of different types of references that can be made in an article."""
|
@@ -28,7 +27,11 @@ class ReferringType(StrEnum):
|
|
28
27
|
SUBSECTION = "subsection"
|
29
28
|
|
30
29
|
|
31
|
-
|
30
|
+
type RefKey = Tuple[str, Optional[str], Optional[str]]
|
31
|
+
|
32
|
+
|
33
|
+
@cache
|
34
|
+
class ArticleRef(CensoredAble, Display, ProposedUpdateAble):
|
32
35
|
"""Reference to a specific chapter, section or subsection within the article. You SHALL not refer to an article component that is external and not present within our own article.
|
33
36
|
|
34
37
|
Examples:
|
@@ -61,30 +64,21 @@ class ArticleRef(CensoredAble):
|
|
61
64
|
```
|
62
65
|
"""
|
63
66
|
|
64
|
-
referred_subsection_title: Optional[str] = None
|
65
|
-
"""`title` Field of the referenced subsection."""
|
66
|
-
|
67
|
-
referred_section_title: Optional[str] = None
|
68
|
-
"""`title` Field of the referenced section."""
|
69
|
-
|
70
67
|
referred_chapter_title: str
|
71
68
|
"""`title` Field of the referenced chapter"""
|
69
|
+
referred_section_title: Optional[str] = None
|
70
|
+
"""`title` Field of the referenced section."""
|
71
|
+
referred_subsection_title: Optional[str] = None
|
72
|
+
"""`title` Field of the referenced subsection."""
|
72
73
|
|
73
|
-
def
|
74
|
-
"""
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
"""Dereference the reference to the actual section or subsection within the provided article."""
|
80
|
-
|
81
|
-
@overload
|
82
|
-
def deref(self, article: "ArticleOutline") -> Optional["ArticleOutlineBase"]:
|
83
|
-
"""Dereference the reference to the actual section or subsection within the provided article."""
|
74
|
+
def update_from_inner(self, other: Self) -> Self:
|
75
|
+
"""Updates the current instance with the attributes of another instance."""
|
76
|
+
self.referred_chapter_title = other.referred_chapter_title
|
77
|
+
self.referred_section_title = other.referred_section_title
|
78
|
+
self.referred_subsection_title = other.referred_subsection_title
|
79
|
+
return self
|
84
80
|
|
85
|
-
def deref(
|
86
|
-
self, article: Union["ArticleOutline", "Article"]
|
87
|
-
) -> Union["ArticleOutlineBase", "ArticleMainBase", None]:
|
81
|
+
def deref(self, article: "ArticleBase") -> Optional["ArticleOutlineBase"]:
|
88
82
|
"""Dereference the reference to the actual section or subsection within the provided article.
|
89
83
|
|
90
84
|
Args:
|
@@ -111,21 +105,88 @@ class ArticleRef(CensoredAble):
|
|
111
105
|
return ReferringType.CHAPTER
|
112
106
|
|
113
107
|
|
114
|
-
class
|
115
|
-
|
108
|
+
class ArticleMetaData(CensoredAble, Display):
|
109
|
+
"""Metadata for an article component."""
|
110
|
+
|
111
|
+
description: str
|
112
|
+
"""Description of the research component in academic style."""
|
113
|
+
|
114
|
+
support_to: List[ArticleRef]
|
115
|
+
"""List of references to other component of this articles that this component supports."""
|
116
|
+
depend_on: List[ArticleRef]
|
117
|
+
"""List of references to other component of this articles that this component depends on."""
|
118
|
+
|
119
|
+
writing_aim: List[str]
|
120
|
+
"""List of writing aims of the research component in academic style."""
|
121
|
+
title: str
|
122
|
+
"""Do not add any prefix or suffix to the title. should not contain special characters."""
|
123
|
+
|
124
|
+
|
125
|
+
class ArticleRefPatch(ProposedUpdateAble, Display):
|
126
|
+
"""Patch for article refs."""
|
127
|
+
|
128
|
+
tweaked: List[ArticleRef]
|
129
|
+
"""Tweaked refs"""
|
130
|
+
|
131
|
+
def update_from_inner(self, other: Self) -> Self:
|
132
|
+
"""Updates the current instance with the attributes of another instance."""
|
133
|
+
self.tweaked.clear()
|
134
|
+
self.tweaked.extend(other.tweaked)
|
135
|
+
return self
|
136
|
+
|
137
|
+
@classmethod
|
138
|
+
def default(cls) -> "ArticleRefPatch":
|
139
|
+
"""Defaults to empty list."""
|
140
|
+
return cls(tweaked=[])
|
141
|
+
|
142
|
+
|
143
|
+
class ArticleOutlineBase(
|
144
|
+
ArticleMetaData,
|
145
|
+
ResolveUpdateConflict,
|
146
|
+
ProposedUpdateAble,
|
147
|
+
PersistentAble,
|
148
|
+
ModelHash,
|
116
149
|
Introspect,
|
117
150
|
):
|
118
|
-
"""Base class for article
|
151
|
+
"""Base class for article outlines."""
|
119
152
|
|
120
|
-
|
121
|
-
|
153
|
+
@property
|
154
|
+
def metadata(self) -> ArticleMetaData:
|
155
|
+
"""Returns the metadata of the article component."""
|
156
|
+
return ArticleMetaData.model_validate(self, from_attributes=True)
|
122
157
|
|
158
|
+
def update_metadata(self, other: ArticleMetaData) -> Self:
|
159
|
+
"""Updates the metadata of the current instance with the attributes of another instance."""
|
160
|
+
self.support_to.clear()
|
161
|
+
self.support_to.extend(other.support_to)
|
162
|
+
self.depend_on.clear()
|
163
|
+
self.depend_on.extend(other.depend_on)
|
164
|
+
self.writing_aim.clear()
|
165
|
+
self.writing_aim.extend(other.writing_aim)
|
166
|
+
self.description = other.description
|
167
|
+
return self
|
168
|
+
|
169
|
+
def display_metadata(self) -> str:
|
170
|
+
"""Displays the metadata of the current instance."""
|
171
|
+
return self.model_dump_json(
|
172
|
+
indent=1, include={"title", "writing_aim", "description", "support_to", "depend_on"}
|
173
|
+
)
|
174
|
+
|
175
|
+
def update_from_inner(self, other: Self) -> Self:
|
176
|
+
"""Updates the current instance with the attributes of another instance."""
|
177
|
+
return self.update_metadata(other)
|
178
|
+
|
179
|
+
@abstractmethod
|
123
180
|
def to_typst_code(self) -> str:
|
124
181
|
"""Converts the component into a Typst code snippet for rendering."""
|
125
|
-
return f"=== {self.title}\n"
|
126
182
|
|
127
|
-
|
128
|
-
|
183
|
+
|
184
|
+
class SubSectionBase(ArticleOutlineBase):
|
185
|
+
"""Base class for article sections and subsections."""
|
186
|
+
|
187
|
+
def to_typst_code(self) -> str:
|
188
|
+
"""Converts the component into a Typst code snippet for rendering."""
|
189
|
+
return f"=== {self.title}\n"
|
129
190
|
|
130
191
|
def introspect(self) -> str:
|
131
192
|
"""Introspects the article subsection outline."""
|
@@ -138,16 +199,11 @@ class SubSectionBase(
|
|
138
199
|
return ""
|
139
200
|
|
140
201
|
|
141
|
-
class SectionBase[T: SubSectionBase](
|
142
|
-
UpdateFrom,
|
143
|
-
Introspect,
|
144
|
-
):
|
202
|
+
class SectionBase[T: SubSectionBase](ArticleOutlineBase):
|
145
203
|
"""Base class for article sections and subsections."""
|
146
204
|
|
147
205
|
subsections: List[T]
|
148
206
|
"""Subsections of the section. Contains at least one subsection. You can also add more as needed."""
|
149
|
-
title: str
|
150
|
-
"""Title of the section, do not add any prefix or suffix to the title. should not contain special characters."""
|
151
207
|
|
152
208
|
def to_typst_code(self) -> str:
|
153
209
|
"""Converts the section into a Typst formatted code snippet.
|
@@ -174,6 +230,7 @@ class SectionBase[T: SubSectionBase](
|
|
174
230
|
|
175
231
|
def update_from_inner(self, other: Self) -> Self:
|
176
232
|
"""Updates the current instance with the attributes of another instance."""
|
233
|
+
super().update_from_inner(other)
|
177
234
|
if len(self.subsections) == 0:
|
178
235
|
self.subsections = other.subsections
|
179
236
|
return self
|
@@ -189,16 +246,12 @@ class SectionBase[T: SubSectionBase](
|
|
189
246
|
return ""
|
190
247
|
|
191
248
|
|
192
|
-
class ChapterBase[T: SectionBase](
|
193
|
-
UpdateFrom,
|
194
|
-
Introspect,
|
195
|
-
):
|
249
|
+
class ChapterBase[T: SectionBase](ArticleOutlineBase):
|
196
250
|
"""Base class for article chapters."""
|
197
251
|
|
198
252
|
sections: List[T]
|
199
253
|
"""Sections of the chapter. Contains at least one section. You can also add more as needed."""
|
200
|
-
|
201
|
-
"""Title of the chapter, do not add any prefix or suffix to the title. should not contain special characters."""
|
254
|
+
|
202
255
|
def to_typst_code(self) -> str:
|
203
256
|
"""Converts the chapter into a Typst formatted code snippet for rendering."""
|
204
257
|
return f"= {self.title}\n" + "\n\n".join(sec.to_typst_code() for sec in self.sections)
|
@@ -233,21 +286,35 @@ class ChapterBase[T: SectionBase](
|
|
233
286
|
return ""
|
234
287
|
|
235
288
|
|
236
|
-
class ArticleBase[T: ChapterBase](
|
289
|
+
class ArticleBase[T: ChapterBase](FinalizedDumpAble, AsPrompt, ABC):
|
237
290
|
"""Base class for article outlines."""
|
238
291
|
|
292
|
+
language: str
|
293
|
+
"""Written language of the article. SHALL be aligned to the language of the article proposal provided."""
|
294
|
+
|
295
|
+
title: str
|
296
|
+
"""Title of the academic paper."""
|
297
|
+
|
298
|
+
prospect: str
|
299
|
+
"""Consolidated research statement with four pillars:
|
300
|
+
1. Problem Identification: Current limitations
|
301
|
+
2. Methodological Response: Technical approach
|
302
|
+
3. Empirical Validation: Evaluation strategy
|
303
|
+
4. Scholarly Impact: Field contributions
|
304
|
+
"""
|
305
|
+
|
306
|
+
abstract: str
|
307
|
+
"""The abstract is a concise summary of the academic paper's main findings."""
|
239
308
|
chapters: List[T]
|
240
309
|
"""Chapters of the article. Contains at least one chapter. You can also add more as needed."""
|
241
|
-
title: str
|
242
|
-
"""Title of the article outline, do not add any prefix or suffix to the title. should not contain special characters."""
|
243
310
|
|
244
|
-
def
|
311
|
+
def iter_dfs_rev(
|
245
312
|
self,
|
246
|
-
) -> Generator[
|
247
|
-
"""Performs a depth-first search (DFS) through the article structure.
|
313
|
+
) -> Generator[ArticleOutlineBase, None, None]:
|
314
|
+
"""Performs a depth-first search (DFS) through the article structure in reverse order.
|
248
315
|
|
249
316
|
Returns:
|
250
|
-
Generator[ArticleMainBase]: Each component in the article structure.
|
317
|
+
Generator[ArticleMainBase]: Each component in the article structure in reverse order.
|
251
318
|
"""
|
252
319
|
for chap in self.chapters:
|
253
320
|
for sec in chap.sections:
|
@@ -255,37 +322,80 @@ class ArticleBase[T: ChapterBase](Base):
|
|
255
322
|
yield sec
|
256
323
|
yield chap
|
257
324
|
|
325
|
+
def iter_dfs(self) -> Generator[ArticleOutlineBase, None, None]:
|
326
|
+
"""Performs a depth-first search (DFS) through the article structure.
|
258
327
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
ABC,
|
268
|
-
):
|
269
|
-
"""Base class for article outlines."""
|
328
|
+
Returns:
|
329
|
+
Generator[ArticleMainBase]: Each component in the article structure.
|
330
|
+
"""
|
331
|
+
for chap in self.chapters:
|
332
|
+
yield chap
|
333
|
+
for sec in chap.sections:
|
334
|
+
yield sec
|
335
|
+
yield from sec.subsections
|
270
336
|
|
271
|
-
|
272
|
-
|
337
|
+
def iter_sections(self) -> Generator[Tuple[ChapterBase, SectionBase], None, None]:
|
338
|
+
"""Iterates through all sections in the article.
|
273
339
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
340
|
+
Returns:
|
341
|
+
Generator[ArticleOutlineBase]: Each section in the article.
|
342
|
+
"""
|
343
|
+
for chap in self.chapters:
|
344
|
+
for sec in chap.sections:
|
345
|
+
yield chap, sec
|
278
346
|
|
279
|
-
|
280
|
-
|
347
|
+
def iter_subsections(self) -> Generator[Tuple[ChapterBase, SectionBase, SubSectionBase], None, None]:
|
348
|
+
"""Iterates through all subsections in the article.
|
281
349
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
self.
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
350
|
+
Returns:
|
351
|
+
Generator[ArticleOutlineBase]: Each subsection in the article.
|
352
|
+
"""
|
353
|
+
for chap, sec in self.iter_sections():
|
354
|
+
for subsec in sec.subsections:
|
355
|
+
yield chap, sec, subsec
|
356
|
+
|
357
|
+
def find_introspected(self) -> Optional[Tuple[ArticleOutlineBase, str]]:
|
358
|
+
"""Finds the first introspected component in the article structure."""
|
359
|
+
summary = ""
|
360
|
+
for component in self.iter_dfs_rev():
|
361
|
+
summary += component.introspect()
|
362
|
+
if summary:
|
363
|
+
return component, summary
|
364
|
+
return None
|
365
|
+
|
366
|
+
def find_illegal_ref(self) -> Optional[Tuple[ArticleRef, str]]:
|
367
|
+
"""Finds the first illegal component in the outline.
|
368
|
+
|
369
|
+
Returns:
|
370
|
+
Tuple[ArticleOutlineBase, str]: A tuple containing the illegal component and an error message.
|
371
|
+
"""
|
372
|
+
summary = ""
|
373
|
+
for component in self.iter_dfs_rev():
|
374
|
+
for ref in chain(component.depend_on, component.support_to):
|
375
|
+
if not ref.deref(self):
|
376
|
+
summary += f"Invalid internal reference in `{component.__class__.__name__}` titled `{component.title}`, because the referred {ref.referring_type} is not exists within the article, see the original obj dump: {ref.model_dump()}\n"
|
377
|
+
if summary:
|
378
|
+
return ref, summary
|
379
|
+
return None
|
380
|
+
|
381
|
+
def finalized_dump(self) -> str:
|
382
|
+
"""Generates standardized hierarchical markup for academic publishing systems.
|
383
|
+
|
384
|
+
Implements ACL 2024 outline conventions with four-level structure:
|
385
|
+
= Chapter Title (Level 1)
|
386
|
+
== Section Title (Level 2)
|
387
|
+
=== Subsection Title (Level 3)
|
388
|
+
==== Subsubsection Title (Level 4)
|
389
|
+
|
390
|
+
Returns:
|
391
|
+
str: Strictly formatted outline with academic sectioning
|
392
|
+
|
393
|
+
Example:
|
394
|
+
= Methodology
|
395
|
+
== Neural Architecture Search Framework
|
396
|
+
=== Differentiable Search Space
|
397
|
+
==== Constrained Optimization Parameters
|
398
|
+
=== Implementation Details
|
399
|
+
== Evaluation Protocol
|
400
|
+
"""
|
401
|
+
return "\n\n".join(a.to_typst_code() for a in self.chapters)
|
@@ -134,10 +134,10 @@ class Highlightings(BaseModel):
|
|
134
134
|
|
135
135
|
|
136
136
|
class ArticleEssence(ProposedAble, Display, PrepareVectorization):
|
137
|
-
"""
|
137
|
+
"""ArticleEssence is a structured representation of the core elements of a scientific article."""
|
138
138
|
|
139
|
-
|
140
|
-
"""
|
139
|
+
language: str = Field(...)
|
140
|
+
"""Language of the original article."""
|
141
141
|
|
142
142
|
title: str = Field(...)
|
143
143
|
"""Exact title of the original article without any modification.
|
@@ -149,7 +149,7 @@ class ArticleEssence(ProposedAble, Display, PrepareVectorization):
|
|
149
149
|
"""
|
150
150
|
|
151
151
|
authors: List[str]
|
152
|
-
"""Original author names exactly as they appear in the source document. No translation or paraphrasing.
|
152
|
+
"""Original author full names exactly as they appear in the source document. No translation or paraphrasing.
|
153
153
|
Extract complete list without any modifications or formatting changes."""
|
154
154
|
|
155
155
|
keywords: List[str]
|
@@ -170,11 +170,7 @@ class ArticleEssence(ProposedAble, Display, PrepareVectorization):
|
|
170
170
|
"""Domain tags for research focus."""
|
171
171
|
|
172
172
|
abstract: str = Field(...)
|
173
|
-
"""
|
174
|
-
Paragraph 1: Problem & Motivation (2-3 sentences)
|
175
|
-
Paragraph 2: Methodology & Innovations (3-4 sentences)
|
176
|
-
Paragraph 3: Results & Impact (2-3 sentences)
|
177
|
-
Total length: 150-250 words"""
|
173
|
+
"""Abstract text with original language."""
|
178
174
|
|
179
175
|
core_contributions: List[str]
|
180
176
|
"""3-5 technical contributions using CRediT taxonomy verbs.
|
@@ -184,6 +180,7 @@ class ArticleEssence(ProposedAble, Display, PrepareVectorization):
|
|
184
180
|
- 'Established cross-lingual transfer metrics'"""
|
185
181
|
|
186
182
|
technical_novelty: List[str]
|
183
|
+
|
187
184
|
"""Patent-style claims with technical specificity.
|
188
185
|
Format: 'A [system/method] comprising [novel components]...'
|
189
186
|
Example:
|
@@ -1,13 +1,12 @@
|
|
1
1
|
"""ArticleBase and ArticleSubsection classes for managing hierarchical document components."""
|
2
2
|
|
3
3
|
from itertools import chain
|
4
|
-
from typing import Generator, List, Self, Tuple, override
|
4
|
+
from typing import Dict, Generator, List, Self, Tuple, override
|
5
5
|
|
6
6
|
from fabricatio.journal import logger
|
7
7
|
from fabricatio.models.extra.article_base import (
|
8
8
|
ArticleBase,
|
9
9
|
ArticleOutlineBase,
|
10
|
-
ArticleRef,
|
11
10
|
ChapterBase,
|
12
11
|
SectionBase,
|
13
12
|
SubSectionBase,
|
@@ -28,21 +27,26 @@ class Paragraph(CensoredAble):
|
|
28
27
|
writing_aim: List[str]
|
29
28
|
"""Specific communicative objectives for this paragraph's content."""
|
30
29
|
|
31
|
-
|
32
|
-
"""
|
30
|
+
content: str
|
31
|
+
"""The actual content of the paragraph, represented as a string."""
|
33
32
|
|
34
33
|
|
35
|
-
class ArticleSubsection(
|
34
|
+
class ArticleSubsection(SubSectionBase):
|
36
35
|
"""Atomic argumentative unit with technical specificity."""
|
37
36
|
|
38
37
|
paragraphs: List[Paragraph]
|
39
38
|
"""List of Paragraph objects containing the content of the subsection."""
|
40
39
|
|
40
|
+
def introspect(self) -> str:
|
41
|
+
"""Introspects the subsection and returns a message if it has no paragraphs."""
|
42
|
+
if len(self.paragraphs) == 0:
|
43
|
+
return f"`{self.__class__.__name__}` titled `{self.title}` have no paragraphs, to achieve the goal of `{self.writing_aim}`."
|
44
|
+
return ""
|
45
|
+
|
41
46
|
def update_from_inner(self, other: Self) -> Self:
|
42
47
|
"""Updates the current instance with the attributes of another instance."""
|
43
48
|
logger.debug(f"Updating SubSection {self.title}")
|
44
|
-
|
45
|
-
ArticleOutlineBase.update_from(self, other)
|
49
|
+
super().update_from_inner(other)
|
46
50
|
self.paragraphs.clear()
|
47
51
|
self.paragraphs.extend(other.paragraphs)
|
48
52
|
return self
|
@@ -53,19 +57,17 @@ class ArticleSubsection(ArticleOutlineBase, SubSectionBase):
|
|
53
57
|
Returns:
|
54
58
|
str: Typst code snippet for rendering.
|
55
59
|
"""
|
56
|
-
return f"=== {self.title}\n" + "\n\n".join(
|
60
|
+
return f"=== {self.title}\n" + "\n\n".join(p.content for p in self.paragraphs)
|
57
61
|
|
58
62
|
|
59
|
-
class ArticleSection(
|
63
|
+
class ArticleSection(SectionBase[ArticleSubsection]):
|
60
64
|
"""Atomic argumentative unit with high-level specificity."""
|
61
65
|
|
62
66
|
|
63
|
-
|
64
|
-
class ArticleChapter(ArticleOutlineBase, ChapterBase[ArticleSection]):
|
67
|
+
class ArticleChapter(ChapterBase[ArticleSection]):
|
65
68
|
"""Thematic progression implementing research function."""
|
66
69
|
|
67
70
|
|
68
|
-
|
69
71
|
class Article(
|
70
72
|
Display,
|
71
73
|
CensoredAble,
|
@@ -79,22 +81,17 @@ class Article(
|
|
79
81
|
aiming to provide a comprehensive model for academic papers.
|
80
82
|
"""
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
def _as_prompt_inner(self) -> Dict[str, str]:
|
85
|
+
return {
|
86
|
+
"Original Article Briefing": self.referenced.referenced.referenced,
|
87
|
+
"Original Article Proposal": self.referenced.referenced.display(),
|
88
|
+
"Original Article Outline": self.referenced.display(),
|
89
|
+
"Original Article": self.display(),
|
90
|
+
}
|
87
91
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
def finalized_dump(self) -> str:
|
92
|
-
"""Exports the article in `typst` format.
|
93
|
-
|
94
|
-
Returns:
|
95
|
-
str: Strictly formatted outline with typst formatting.
|
96
|
-
"""
|
97
|
-
return "\n\n".join(c.to_typst_code() for c in self.chapters)
|
92
|
+
@override
|
93
|
+
def iter_subsections(self) -> Generator[Tuple[ArticleChapter, ArticleSection, ArticleSubsection], None, None]:
|
94
|
+
return super().iter_subsections()
|
98
95
|
|
99
96
|
@classmethod
|
100
97
|
def from_outline(cls, outline: ArticleOutline) -> "Article":
|
@@ -107,7 +104,7 @@ class Article(
|
|
107
104
|
Article: The generated article.
|
108
105
|
"""
|
109
106
|
# Set the title from the outline
|
110
|
-
article = Article(**outline.model_dump(
|
107
|
+
article = Article(**outline.model_dump(exclude={"chapters"}), chapters=[])
|
111
108
|
|
112
109
|
for chapter in outline.chapters:
|
113
110
|
# Create a new chapter
|
@@ -132,33 +129,16 @@ class Article(
|
|
132
129
|
article.chapters.append(article_chapter)
|
133
130
|
return article
|
134
131
|
|
135
|
-
@override
|
136
|
-
def iter_dfs(
|
137
|
-
self,
|
138
|
-
) -> Generator[ArticleChapter | ArticleSection | ArticleSubsection, None, None]:
|
139
|
-
return super().iter_dfs()
|
140
|
-
|
141
|
-
def deref(self, ref: ArticleRef) -> ArticleOutlineBase:
|
142
|
-
"""Resolves a reference to the corresponding section or subsection in the article.
|
143
|
-
|
144
|
-
Args:
|
145
|
-
ref (ArticleRef): The reference to resolve.
|
146
|
-
|
147
|
-
Returns:
|
148
|
-
ArticleOutlineBase: The corresponding section or subsection.
|
149
|
-
"""
|
150
|
-
return ok(ref.deref(self), f"{ref} not found in {self.title}")
|
151
|
-
|
152
132
|
def gather_dependencies(self, article: ArticleOutlineBase) -> List[ArticleOutlineBase]:
|
153
133
|
"""Gathers dependencies for all sections and subsections in the article.
|
154
134
|
|
155
135
|
This method should be called after the article is fully constructed.
|
156
136
|
"""
|
157
|
-
depends = [
|
137
|
+
depends = [ok(a.deref(self)) for a in article.depend_on]
|
158
138
|
|
159
139
|
supports = []
|
160
|
-
for a in self.
|
161
|
-
if article in {
|
140
|
+
for a in self.iter_dfs_rev():
|
141
|
+
if article in {ok(b.deref(self)) for b in a.support_to}:
|
162
142
|
supports.append(a)
|
163
143
|
|
164
144
|
return list(set(depends + supports))
|
@@ -220,7 +200,7 @@ class Article(
|
|
220
200
|
if all((not chapter, not section, not subsection)):
|
221
201
|
raise ValueError("At least one of chapter, section, or subsection must be True.")
|
222
202
|
|
223
|
-
for component in self.
|
203
|
+
for component in self.iter_dfs_rev():
|
224
204
|
if not chapter and isinstance(component, ArticleChapter):
|
225
205
|
continue
|
226
206
|
if not section and isinstance(component, ArticleSection):
|