fabricatio 0.2.7.dev4__tar.gz → 0.2.7.dev5__tar.gz
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-0.2.7.dev4 → fabricatio-0.2.7.dev5}/PKG-INFO +1 -1
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/pyproject.toml +1 -1
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/actions/article.py +26 -19
- fabricatio-0.2.7.dev5/python/fabricatio/models/extra/article_base.py +291 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/extra/article_main.py +29 -92
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/extra/article_outline.py +30 -24
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/generic.py +59 -4
- fabricatio-0.2.7.dev5/templates.tar.gz +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/uv.lock +1 -1
- fabricatio-0.2.7.dev4/python/fabricatio/models/extra/article_base.py +0 -192
- fabricatio-0.2.7.dev4/templates.tar.gz +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/.github/workflows/build-package.yaml +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/.github/workflows/ruff.yaml +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/.github/workflows/tests.yaml +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/.gitignore +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/.python-version +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/Cargo.lock +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/Cargo.toml +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/LICENSE +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/Makefile +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/README.md +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/correct/correct.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/correct/correct_loop.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/extract_and_inject/.gitignore +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/extract_and_inject/article_rag.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/extract_and_inject/ask.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/extract_and_inject/extract_and_inject.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/extract_article/extract.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/llm_usages/llm_usage.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/make_a_rating/rating.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/make_diary/commits.json +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/make_diary/diary.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/minor/hello_fabricatio.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/minor/write_a_poem.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/propose_task/propose.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/reviewer/review.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/search_bibtex/.gitignore +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/search_bibtex/search.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/simple_chat/chat.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/simple_rag/simple_rag.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/task_handle/handle_task.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/write_article/.gitignore +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/write_article/write_article.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/write_outline/.gitignore +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/write_outline/write_outline.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/examples/write_outline/write_outline_corrected.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/__init__.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/_rust.pyi +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/_rust_instances.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/actions/article_rag.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/actions/output.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/actions/rag.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/capabilities/correct.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/capabilities/propose.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/capabilities/rag.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/capabilities/rating.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/capabilities/review.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/capabilities/task.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/config.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/core.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/decorators.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/fs/__init__.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/fs/curd.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/fs/readers.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/journal.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/action.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/events.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/extra/article_essence.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/extra/article_proposal.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/kwargs_types.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/role.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/task.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/tool.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/usages.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/utils.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/parser.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/py.typed +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/toolboxes/__init__.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/toolboxes/arithmetic.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/toolboxes/fs.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/workflows/articles.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/workflows/rag.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/src/bib_tools.rs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/src/hash.rs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/src/hbs_helpers.rs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/src/lib.rs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/src/templates.rs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/as_prompt.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/binary-exploitation-ctf-solver.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/claude-xml.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/clean-up-code.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/co_validation.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/correct.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/create_json_obj.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/cryptography-ctf-solver.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/dependencies.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/document-the-code.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/draft_rating_criteria.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/draft_rating_manual.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/draft_rating_weights_klee.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/draft_tool_usage_code.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/extract_criteria_from_reasons.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/extract_reasons_from_examples.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/find-security-vulnerabilities.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/fix-bugs.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/generic_string.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/improve-performance.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/liststr.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/make_choice.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/make_judgment.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/pathstr.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/rate_fine_grind.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/refactor.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/refined_query.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/retrieved_display.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/reverse-engineering-ctf-solver.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/review_string.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/task_briefing.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/web-ctf-solver.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/write-git-commit.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/write-github-pull-request.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/templates/built-in/write-github-readme.hbs +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/tests/test_config.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/tests/test_models/test_action.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/tests/test_models/test_advanced.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/tests/test_models/test_generic.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/tests/test_models/test_role.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/tests/test_models/test_task.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/tests/test_models/test_tool.py +0 -0
- {fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/tests/test_models/test_usages.py +0 -0
@@ -61,7 +61,7 @@ class GenerateArticleProposal(Action):
|
|
61
61
|
logger.error("Task not approved, since all inputs are None.")
|
62
62
|
return None
|
63
63
|
|
64
|
-
return (
|
64
|
+
return ok(
|
65
65
|
await self.propose(
|
66
66
|
ArticleProposal,
|
67
67
|
briefing := (
|
@@ -70,14 +70,15 @@ class GenerateArticleProposal(Action):
|
|
70
70
|
ok(
|
71
71
|
article_briefing_path
|
72
72
|
or await self.awhich_pathstr(
|
73
|
-
f"{task_input.briefing}\nExtract the path of file which contains the article briefing."
|
73
|
+
f"{ok(task_input).briefing}\nExtract the path of file which contains the article briefing."
|
74
74
|
),
|
75
75
|
"Could not find the path of file to read.",
|
76
76
|
)
|
77
77
|
)
|
78
78
|
),
|
79
79
|
**self.prepend_sys_msg(),
|
80
|
-
)
|
80
|
+
),
|
81
|
+
"Could not generate the proposal."
|
81
82
|
).update_ref(briefing)
|
82
83
|
|
83
84
|
|
@@ -92,27 +93,33 @@ class GenerateOutline(Action):
|
|
92
93
|
article_proposal: ArticleProposal,
|
93
94
|
**_,
|
94
95
|
) -> Optional[ArticleOutline]:
|
95
|
-
out =
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
out = ok(
|
97
|
+
await self.propose(
|
98
|
+
ArticleOutline,
|
99
|
+
article_proposal.as_prompt(),
|
100
|
+
**self.prepend_sys_msg(),
|
101
|
+
),
|
102
|
+
"Could not generate the outline.",
|
99
103
|
)
|
100
104
|
|
101
|
-
manual = await self.draft_rating_manual(
|
105
|
+
manual = ok(await self.draft_rating_manual(
|
102
106
|
topic=(
|
103
107
|
topic
|
104
108
|
:= "Fix the internal referring error, make sure there is no more `ArticleRef` pointing to a non-existing article component."
|
105
109
|
),
|
106
|
-
)
|
107
|
-
|
110
|
+
),"Could not generate the rating manual.")
|
111
|
+
|
112
|
+
while pack := out.find_illegal():
|
113
|
+
component, err = ok(pack)
|
108
114
|
logger.warning(f"Found error in the outline: \n{err}")
|
109
|
-
|
110
|
-
|
111
|
-
reference=f"#
|
115
|
+
corrected = ok(await self.correct_obj(
|
116
|
+
component,
|
117
|
+
reference=f"# Original Article Outline\n{out.display()}\n# Error Need to be fixed\n{err}",
|
112
118
|
topic=topic,
|
113
119
|
rating_manual=manual,
|
114
120
|
supervisor_check=False,
|
115
|
-
)
|
121
|
+
),"Could not correct the component.")
|
122
|
+
component.update_from(corrected)
|
116
123
|
return out.update_ref(article_proposal)
|
117
124
|
|
118
125
|
|
@@ -156,15 +163,15 @@ class GenerateArticle(Action):
|
|
156
163
|
) -> Optional[Article]:
|
157
164
|
article: Article = Article.from_outline(article_outline).update_ref(article_outline)
|
158
165
|
|
159
|
-
writing_manual = await self.draft_rating_manual(
|
166
|
+
writing_manual = ok(await self.draft_rating_manual(
|
160
167
|
topic=(
|
161
168
|
topic_1
|
162
169
|
:= "improve the content of the subsection to fit the outline. SHALL never add or remove any section or subsection, you can only add or delete paragraphs within the subsection."
|
163
170
|
),
|
164
|
-
)
|
165
|
-
err_resolve_manual = await self.draft_rating_manual(
|
171
|
+
))
|
172
|
+
err_resolve_manual = ok(await self.draft_rating_manual(
|
166
173
|
topic=(topic_2 := "this article component has violated the constrain, please correct it.")
|
167
|
-
)
|
174
|
+
))
|
168
175
|
for c, deps in article.iter_dfs_with_deps(chapter=False):
|
169
176
|
logger.info(f"Updating the article component: \n{c.display()}")
|
170
177
|
|
@@ -180,7 +187,7 @@ class GenerateArticle(Action):
|
|
180
187
|
),
|
181
188
|
"Could not correct the article component.",
|
182
189
|
)
|
183
|
-
while err := c.
|
190
|
+
while err := c.resolve_update_conflict(out):
|
184
191
|
logger.warning(f"Found error in the article component: \n{err}")
|
185
192
|
out = ok(
|
186
193
|
await self.correct_obj(
|
@@ -0,0 +1,291 @@
|
|
1
|
+
"""A foundation for hierarchical document components with dependency tracking."""
|
2
|
+
from abc import ABC
|
3
|
+
from enum import StrEnum
|
4
|
+
from typing import TYPE_CHECKING, Generator, List, Optional, Self, Union, overload
|
5
|
+
|
6
|
+
from fabricatio.models.generic import (
|
7
|
+
Base,
|
8
|
+
CensoredAble,
|
9
|
+
Display,
|
10
|
+
Introspect,
|
11
|
+
ModelHash,
|
12
|
+
PersistentAble,
|
13
|
+
ProposedAble,
|
14
|
+
ResolveUpdateConflict,
|
15
|
+
UpdateFrom,
|
16
|
+
)
|
17
|
+
|
18
|
+
if TYPE_CHECKING:
|
19
|
+
from fabricatio.models.extra.article_main import Article
|
20
|
+
from fabricatio.models.extra.article_outline import ArticleOutline
|
21
|
+
|
22
|
+
|
23
|
+
class ReferringType(StrEnum):
|
24
|
+
"""Enumeration of different types of references that can be made in an article."""
|
25
|
+
|
26
|
+
CHAPTER = "chapter"
|
27
|
+
SECTION = "section"
|
28
|
+
SUBSECTION = "subsection"
|
29
|
+
|
30
|
+
|
31
|
+
class ArticleRef(CensoredAble):
|
32
|
+
"""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
|
+
|
34
|
+
Examples:
|
35
|
+
- Referring to a chapter titled `Introduction`:
|
36
|
+
Using Python
|
37
|
+
```python
|
38
|
+
ArticleRef(referred_chapter_title="Introduction")
|
39
|
+
```
|
40
|
+
Using JSON
|
41
|
+
```json
|
42
|
+
{referred_chapter_title="Introduction"}
|
43
|
+
```
|
44
|
+
- Referring to a section titled `Background` under the `Introduction` chapter:
|
45
|
+
Using Python
|
46
|
+
```python
|
47
|
+
ArticleRef(referred_chapter_title="Introduction", referred_section_title="Background")
|
48
|
+
```
|
49
|
+
Using JSON
|
50
|
+
```json
|
51
|
+
{referred_chapter_title="Introduction", referred_section_title="Background"}
|
52
|
+
```
|
53
|
+
- Referring to a subsection titled `Related Work` under the `Background` section of the `Introduction` chapter:
|
54
|
+
Using Python
|
55
|
+
```python
|
56
|
+
ArticleRef(referred_chapter_title="Introduction", referred_section_title="Background", referred_subsection_title="Related Work")
|
57
|
+
```
|
58
|
+
Using JSON
|
59
|
+
```json
|
60
|
+
{referred_chapter_title="Introduction", referred_section_title="Background", referred_subsection_title="Related Work"}
|
61
|
+
```
|
62
|
+
"""
|
63
|
+
|
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
|
+
referred_chapter_title: str
|
71
|
+
"""`title` Field of the referenced chapter"""
|
72
|
+
|
73
|
+
def __hash__(self) -> int:
|
74
|
+
"""Overrides the default hash function to ensure consistent hashing across instances."""
|
75
|
+
return hash((self.referred_chapter_title, self.referred_section_title, self.referred_subsection_title))
|
76
|
+
|
77
|
+
@overload
|
78
|
+
def deref(self, article: "Article") -> Optional["ArticleMainBase"]:
|
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."""
|
84
|
+
|
85
|
+
def deref(
|
86
|
+
self, article: Union["ArticleOutline", "Article"]
|
87
|
+
) -> Union["ArticleOutlineBase", "ArticleMainBase", None]:
|
88
|
+
"""Dereference the reference to the actual section or subsection within the provided article.
|
89
|
+
|
90
|
+
Args:
|
91
|
+
article (ArticleOutline | Article): The article to dereference the reference from.
|
92
|
+
|
93
|
+
Returns:
|
94
|
+
ArticleMainBase | ArticleOutline | None: The dereferenced section or subsection, or None if not found.
|
95
|
+
"""
|
96
|
+
chap = next((chap for chap in article.chapters if chap.title == self.referred_chapter_title), None)
|
97
|
+
if self.referred_section_title is None or chap is None:
|
98
|
+
return chap
|
99
|
+
sec = next((sec for sec in chap.sections if sec.title == self.referred_section_title), None)
|
100
|
+
if self.referred_subsection_title is None or sec is None:
|
101
|
+
return sec
|
102
|
+
return next((subsec for subsec in sec.subsections if subsec.title == self.referred_subsection_title), None)
|
103
|
+
|
104
|
+
@property
|
105
|
+
def referring_type(self) -> ReferringType:
|
106
|
+
"""Determine the type of reference based on the presence of specific attributes."""
|
107
|
+
if self.referred_subsection_title is not None:
|
108
|
+
return ReferringType.SUBSECTION
|
109
|
+
if self.referred_section_title is not None:
|
110
|
+
return ReferringType.SECTION
|
111
|
+
return ReferringType.CHAPTER
|
112
|
+
|
113
|
+
|
114
|
+
class SubSectionBase(
|
115
|
+
UpdateFrom,
|
116
|
+
Introspect,
|
117
|
+
):
|
118
|
+
"""Base class for article sections and subsections."""
|
119
|
+
|
120
|
+
title: str
|
121
|
+
"""Title of the subsection, do not add any prefix or suffix to the title. should not contain special characters."""
|
122
|
+
|
123
|
+
def to_typst_code(self) -> str:
|
124
|
+
"""Converts the component into a Typst code snippet for rendering."""
|
125
|
+
return f"=== {self.title}\n"
|
126
|
+
|
127
|
+
def update_from_inner(self, other: Self) -> Self:
|
128
|
+
return self
|
129
|
+
|
130
|
+
def introspect(self) -> str:
|
131
|
+
"""Introspects the article subsection outline."""
|
132
|
+
return ""
|
133
|
+
|
134
|
+
def resolve_update_conflict(self, other: Self) -> str:
|
135
|
+
"""Resolve update errors in the article outline."""
|
136
|
+
if self.title != other.title:
|
137
|
+
return f"Title mismatched, expected `{self.title}`, got `{other.title}`"
|
138
|
+
return ""
|
139
|
+
|
140
|
+
|
141
|
+
class SectionBase[T: SubSectionBase](
|
142
|
+
UpdateFrom,
|
143
|
+
Introspect,
|
144
|
+
):
|
145
|
+
"""Base class for article sections and subsections."""
|
146
|
+
|
147
|
+
subsections: List[T]
|
148
|
+
"""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
|
+
|
152
|
+
def to_typst_code(self) -> str:
|
153
|
+
"""Converts the section into a Typst formatted code snippet.
|
154
|
+
|
155
|
+
Returns:
|
156
|
+
str: The formatted Typst code snippet.
|
157
|
+
"""
|
158
|
+
return f"== {self.title}\n" + "\n\n".join(subsec.to_typst_code() for subsec in self.subsections)
|
159
|
+
|
160
|
+
def resolve_update_conflict(self, other: Self) -> str:
|
161
|
+
"""Resolve update errors in the article outline."""
|
162
|
+
out = ""
|
163
|
+
if self.title != other.title:
|
164
|
+
out += f"Title mismatched, expected `{self.title}`, got `{other.title}`"
|
165
|
+
if len(self.subsections) != len(other.subsections):
|
166
|
+
out += f"Section count mismatched, expected `{len(self.subsections)}`, got `{len(other.subsections)}`"
|
167
|
+
return out or "\n".join(
|
168
|
+
[
|
169
|
+
conf
|
170
|
+
for s, o in zip(self.subsections, other.subsections, strict=True)
|
171
|
+
if (conf := s.resolve_update_conflict(o))
|
172
|
+
]
|
173
|
+
)
|
174
|
+
|
175
|
+
def update_from_inner(self, other: Self) -> Self:
|
176
|
+
"""Updates the current instance with the attributes of another instance."""
|
177
|
+
if len(self.subsections) == 0:
|
178
|
+
self.subsections = other.subsections
|
179
|
+
return self
|
180
|
+
|
181
|
+
for self_subsec, other_subsec in zip(self.subsections, other.subsections, strict=True):
|
182
|
+
self_subsec.update_from(other_subsec)
|
183
|
+
return self
|
184
|
+
|
185
|
+
def introspect(self) -> str:
|
186
|
+
"""Introspects the article section outline."""
|
187
|
+
if len(self.subsections) == 0:
|
188
|
+
return f"Section `{self.title}` contains no subsections, expected at least one, but got 0, you can add one or more as needed."
|
189
|
+
return ""
|
190
|
+
|
191
|
+
|
192
|
+
class ChapterBase[T: SectionBase](
|
193
|
+
UpdateFrom,
|
194
|
+
Introspect,
|
195
|
+
):
|
196
|
+
"""Base class for article chapters."""
|
197
|
+
|
198
|
+
sections: List[T]
|
199
|
+
"""Sections of the chapter. Contains at least one section. You can also add more as needed."""
|
200
|
+
title: str
|
201
|
+
"""Title of the chapter, do not add any prefix or suffix to the title. should not contain special characters."""
|
202
|
+
def to_typst_code(self) -> str:
|
203
|
+
"""Converts the chapter into a Typst formatted code snippet for rendering."""
|
204
|
+
return f"= {self.title}\n" + "\n\n".join(sec.to_typst_code() for sec in self.sections)
|
205
|
+
|
206
|
+
def resolve_update_conflict(self, other: Self) -> str:
|
207
|
+
"""Resolve update errors in the article outline."""
|
208
|
+
out = ""
|
209
|
+
|
210
|
+
if self.title != other.title:
|
211
|
+
out += f"Title mismatched, expected `{self.title}`, got `{other.title}`"
|
212
|
+
if len(self.sections) == len(other.sections):
|
213
|
+
out += f"Chapter count mismatched, expected `{len(self.sections)}`, got `{len(other.sections)}`"
|
214
|
+
|
215
|
+
return out or "\n".join(
|
216
|
+
[conf for s, o in zip(self.sections, other.sections, strict=True) if (conf := s.resolve_update_conflict(o))]
|
217
|
+
)
|
218
|
+
|
219
|
+
def update_from_inner(self, other: Self) -> Self:
|
220
|
+
"""Updates the current instance with the attributes of another instance."""
|
221
|
+
if len(self.sections) == 0:
|
222
|
+
self.sections = other.sections
|
223
|
+
return self
|
224
|
+
|
225
|
+
for self_sec, other_sec in zip(self.sections, other.sections, strict=True):
|
226
|
+
self_sec.update_from(other_sec)
|
227
|
+
return self
|
228
|
+
|
229
|
+
def introspect(self) -> str:
|
230
|
+
"""Introspects the article chapter outline."""
|
231
|
+
if len(self.sections) == 0:
|
232
|
+
return f"Chapter `{self.title}` contains no sections, expected at least one, but got 0, you can add one or more as needed."
|
233
|
+
return ""
|
234
|
+
|
235
|
+
|
236
|
+
class ArticleBase[T: ChapterBase](Base):
|
237
|
+
"""Base class for article outlines."""
|
238
|
+
|
239
|
+
chapters: List[T]
|
240
|
+
"""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
|
+
|
244
|
+
def iter_dfs(
|
245
|
+
self,
|
246
|
+
) -> Generator[ChapterBase | SectionBase | SubSectionBase, None, None]:
|
247
|
+
"""Performs a depth-first search (DFS) through the article structure.
|
248
|
+
|
249
|
+
Returns:
|
250
|
+
Generator[ArticleMainBase]: Each component in the article structure.
|
251
|
+
"""
|
252
|
+
for chap in self.chapters:
|
253
|
+
for sec in chap.sections:
|
254
|
+
yield from sec.subsections
|
255
|
+
yield sec
|
256
|
+
yield chap
|
257
|
+
|
258
|
+
|
259
|
+
class ArticleOutlineBase(
|
260
|
+
CensoredAble,
|
261
|
+
UpdateFrom,
|
262
|
+
ResolveUpdateConflict,
|
263
|
+
ProposedAble,
|
264
|
+
PersistentAble,
|
265
|
+
Display,
|
266
|
+
ModelHash,
|
267
|
+
ABC,
|
268
|
+
):
|
269
|
+
"""Base class for article outlines."""
|
270
|
+
|
271
|
+
description: str
|
272
|
+
"""Description of the research component in academic style."""
|
273
|
+
|
274
|
+
support_to: List[ArticleRef]
|
275
|
+
"""List of references to other component of this articles that this component supports."""
|
276
|
+
depend_on: List[ArticleRef]
|
277
|
+
"""List of references to other component of this articles that this component depends on."""
|
278
|
+
|
279
|
+
writing_aim: List[str]
|
280
|
+
"""List of writing aims of the research component in academic style."""
|
281
|
+
|
282
|
+
def update_from_inner(self, other: Self) -> Self:
|
283
|
+
"""Updates the current instance with the attributes of another instance."""
|
284
|
+
self.support_to.clear()
|
285
|
+
self.support_to.extend(other.support_to)
|
286
|
+
self.depend_on.clear()
|
287
|
+
self.depend_on.extend(other.depend_on)
|
288
|
+
self.writing_aim.clear()
|
289
|
+
self.writing_aim.extend(other.writing_aim)
|
290
|
+
self.description = other.description
|
291
|
+
return self
|
{fabricatio-0.2.7.dev4 → fabricatio-0.2.7.dev5}/python/fabricatio/models/extra/article_main.py
RENAMED
@@ -1,12 +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
|
4
|
+
from typing import 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
10
|
ArticleRef,
|
11
11
|
ChapterBase,
|
12
12
|
SectionBase,
|
@@ -32,22 +32,19 @@ class Paragraph(CensoredAble):
|
|
32
32
|
"""List of sentences forming the paragraph's content."""
|
33
33
|
|
34
34
|
|
35
|
-
class ArticleSubsection(
|
35
|
+
class ArticleSubsection(ArticleOutlineBase, SubSectionBase):
|
36
36
|
"""Atomic argumentative unit with technical specificity."""
|
37
37
|
|
38
38
|
paragraphs: List[Paragraph]
|
39
39
|
"""List of Paragraph objects containing the content of the subsection."""
|
40
40
|
|
41
|
-
def
|
42
|
-
"""Resolve update errors in the article outline."""
|
43
|
-
if self.title != other.title:
|
44
|
-
return f"Title `{other.title}` mismatched, expected `{self.title}`. "
|
45
|
-
return ""
|
46
|
-
|
47
|
-
def _update_from_inner(self, other: Self) -> Self:
|
41
|
+
def update_from_inner(self, other: Self) -> Self:
|
48
42
|
"""Updates the current instance with the attributes of another instance."""
|
49
43
|
logger.debug(f"Updating SubSection {self.title}")
|
50
|
-
self
|
44
|
+
SubSectionBase.update_from(self, other)
|
45
|
+
ArticleOutlineBase.update_from(self, other)
|
46
|
+
self.paragraphs.clear()
|
47
|
+
self.paragraphs.extend(other.paragraphs)
|
51
48
|
return self
|
52
49
|
|
53
50
|
def to_typst_code(self) -> str:
|
@@ -59,77 +56,23 @@ class ArticleSubsection(ArticleMainBase, SubSectionBase):
|
|
59
56
|
return f"=== {self.title}\n" + "\n\n".join("".join(p.sentences) for p in self.paragraphs)
|
60
57
|
|
61
58
|
|
62
|
-
class ArticleSection(
|
59
|
+
class ArticleSection(ArticleOutlineBase, SectionBase[ArticleSubsection]):
|
63
60
|
"""Atomic argumentative unit with high-level specificity."""
|
64
61
|
|
65
|
-
def resolve_update_error(self, other: Self) -> str:
|
66
|
-
"""Resolve update errors in the article outline."""
|
67
|
-
if (s_len := len(self.subsections)) == 0:
|
68
|
-
return ""
|
69
|
-
|
70
|
-
if s_len != len(other.subsections):
|
71
|
-
return f"Subsections length mismatched, expected {len(self.subsections)}, got {len(other.subsections)}"
|
72
|
-
|
73
|
-
sub_sec_err_seq = [
|
74
|
-
out for s, o in zip(self.subsections, other.subsections, strict=True) if (out := s.resolve_update_error(o))
|
75
|
-
]
|
76
|
-
|
77
|
-
if sub_sec_err_seq:
|
78
|
-
return "\n".join(sub_sec_err_seq)
|
79
|
-
return ""
|
80
|
-
|
81
|
-
def _update_from_inner(self, other: Self) -> Self:
|
82
|
-
"""Updates the current instance with the attributes of another instance."""
|
83
|
-
if len(self.subsections) == 0:
|
84
|
-
self.subsections = other.subsections
|
85
|
-
return self
|
86
|
-
|
87
|
-
for self_subsec, other_subsec in zip(self.subsections, other.subsections, strict=True):
|
88
|
-
self_subsec.update_from(other_subsec)
|
89
|
-
return self
|
90
|
-
|
91
|
-
def to_typst_code(self) -> str:
|
92
|
-
"""Converts the section into a Typst formatted code snippet.
|
93
|
-
|
94
|
-
Returns:
|
95
|
-
str: The formatted Typst code snippet.
|
96
|
-
"""
|
97
|
-
return f"== {self.title}\n" + "\n\n".join(subsec.to_typst_code() for subsec in self.subsections)
|
98
62
|
|
99
63
|
|
100
|
-
class ArticleChapter(
|
64
|
+
class ArticleChapter(ArticleOutlineBase, ChapterBase[ArticleSection]):
|
101
65
|
"""Thematic progression implementing research function."""
|
102
66
|
|
103
|
-
def resolve_update_error(self, other: Self) -> str:
|
104
|
-
"""Resolve update errors in the article outline."""
|
105
|
-
if (s_len := len(self.sections)) == 0:
|
106
|
-
return ""
|
107
|
-
|
108
|
-
if s_len != len(other.sections):
|
109
|
-
return f"Sections length mismatched, expected {len(self.sections)}, got {len(other.sections)}"
|
110
|
-
sec_err_seq = [
|
111
|
-
out for s, o in zip(self.sections, other.sections, strict=True) if (out := s.resolve_update_error(o))
|
112
|
-
]
|
113
|
-
if sec_err_seq:
|
114
|
-
return "\n".join(sec_err_seq)
|
115
|
-
return ""
|
116
|
-
|
117
|
-
def _update_from_inner(self, other: Self) -> Self:
|
118
|
-
"""Updates the current instance with the attributes of another instance."""
|
119
|
-
if len(self.sections) == 0:
|
120
|
-
self.sections = other.sections
|
121
|
-
return self
|
122
|
-
|
123
|
-
for self_sec, other_sec in zip(self.sections, other.sections, strict=True):
|
124
|
-
self_sec.update_from(other_sec)
|
125
|
-
return self
|
126
67
|
|
127
|
-
def to_typst_code(self) -> str:
|
128
|
-
"""Converts the chapter into a Typst formatted code snippet for rendering."""
|
129
|
-
return f"= {self.title}\n" + "\n\n".join(sec.to_typst_code() for sec in self.sections)
|
130
68
|
|
131
|
-
|
132
|
-
|
69
|
+
class Article(
|
70
|
+
Display,
|
71
|
+
CensoredAble,
|
72
|
+
WithRef[ArticleOutline],
|
73
|
+
PersistentAble,
|
74
|
+
ArticleBase[ArticleChapter],
|
75
|
+
):
|
133
76
|
"""Represents a complete academic paper specification, incorporating validation constraints.
|
134
77
|
|
135
78
|
This class integrates display, censorship processing, article structure referencing, and persistence capabilities,
|
@@ -189,30 +132,24 @@ class Article(Display, CensoredAble, WithRef[ArticleOutline], PersistentAble, Ar
|
|
189
132
|
article.chapters.append(article_chapter)
|
190
133
|
return article
|
191
134
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
for sec in chap.sections:
|
200
|
-
yield from sec.subsections
|
201
|
-
yield sec
|
202
|
-
yield chap
|
203
|
-
|
204
|
-
def deref(self, ref: ArticleRef) -> ArticleMainBase:
|
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:
|
205
142
|
"""Resolves a reference to the corresponding section or subsection in the article.
|
206
143
|
|
207
144
|
Args:
|
208
145
|
ref (ArticleRef): The reference to resolve.
|
209
146
|
|
210
147
|
Returns:
|
211
|
-
|
148
|
+
ArticleOutlineBase: The corresponding section or subsection.
|
212
149
|
"""
|
213
150
|
return ok(ref.deref(self), f"{ref} not found in {self.title}")
|
214
151
|
|
215
|
-
def gather_dependencies(self, article:
|
152
|
+
def gather_dependencies(self, article: ArticleOutlineBase) -> List[ArticleOutlineBase]:
|
216
153
|
"""Gathers dependencies for all sections and subsections in the article.
|
217
154
|
|
218
155
|
This method should be called after the article is fully constructed.
|
@@ -226,11 +163,11 @@ class Article(Display, CensoredAble, WithRef[ArticleOutline], PersistentAble, Ar
|
|
226
163
|
|
227
164
|
return list(set(depends + supports))
|
228
165
|
|
229
|
-
def gather_dependencies_recursive(self, article:
|
166
|
+
def gather_dependencies_recursive(self, article: ArticleOutlineBase) -> List[ArticleOutlineBase]:
|
230
167
|
"""Gathers all dependencies recursively for the given article.
|
231
168
|
|
232
169
|
Args:
|
233
|
-
article (
|
170
|
+
article (ArticleOutlineBase): The article to gather dependencies for.
|
234
171
|
|
235
172
|
Returns:
|
236
173
|
List[ArticleBase]: A list of all dependencies for the given article.
|
@@ -269,7 +206,7 @@ class Article(Display, CensoredAble, WithRef[ArticleOutline], PersistentAble, Ar
|
|
269
206
|
|
270
207
|
def iter_dfs_with_deps(
|
271
208
|
self, chapter: bool = True, section: bool = True, subsection: bool = True
|
272
|
-
) -> Generator[Tuple[
|
209
|
+
) -> Generator[Tuple[ArticleOutlineBase, List[ArticleOutlineBase]], None, None]:
|
273
210
|
"""Iterates through the article in a depth-first manner, yielding each component and its dependencies.
|
274
211
|
|
275
212
|
Args:
|