fabricatio 0.2.11.dev3__cp312-cp312-manylinux_2_34_x86_64.whl → 0.2.12.dev1__cp312-cp312-manylinux_2_34_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fabricatio/actions/article_rag.py +157 -51
- fabricatio/actions/output.py +35 -3
- fabricatio/config.py +3 -3
- fabricatio/fs/curd.py +1 -1
- fabricatio/models/action.py +6 -8
- fabricatio/models/extra/aricle_rag.py +42 -19
- fabricatio/models/extra/article_base.py +55 -26
- fabricatio/models/extra/article_main.py +56 -4
- fabricatio/models/generic.py +10 -6
- fabricatio/models/kwargs_types.py +1 -1
- fabricatio/models/role.py +5 -4
- fabricatio/rust.cpython-312-x86_64-linux-gnu.so +0 -0
- fabricatio/utils.py +1 -1
- fabricatio-0.2.12.dev1.data/scripts/tdown +0 -0
- {fabricatio-0.2.11.dev3.dist-info → fabricatio-0.2.12.dev1.dist-info}/METADATA +1 -1
- {fabricatio-0.2.11.dev3.dist-info → fabricatio-0.2.12.dev1.dist-info}/RECORD +18 -18
- fabricatio-0.2.11.dev3.data/scripts/tdown +0 -0
- {fabricatio-0.2.11.dev3.dist-info → fabricatio-0.2.12.dev1.dist-info}/WHEEL +0 -0
- {fabricatio-0.2.11.dev3.dist-info → fabricatio-0.2.12.dev1.dist-info}/licenses/LICENSE +0 -0
@@ -4,6 +4,8 @@ from asyncio import gather
|
|
4
4
|
from pathlib import Path
|
5
5
|
from typing import List, Optional
|
6
6
|
|
7
|
+
from pydantic import PositiveInt
|
8
|
+
|
7
9
|
from fabricatio import BibManager
|
8
10
|
from fabricatio.capabilities.censor import Censor
|
9
11
|
from fabricatio.capabilities.extract import Extract
|
@@ -18,13 +20,35 @@ from fabricatio.models.extra.article_outline import ArticleOutline
|
|
18
20
|
from fabricatio.models.extra.rule import RuleSet
|
19
21
|
from fabricatio.utils import ask_retain, ok
|
20
22
|
|
23
|
+
TYPST_CITE_USAGE = (
|
24
|
+
"citation number is REQUIRED to cite any reference!,for example in Auther Pattern: 'Doe et al.[[1]], Jack et al.[[2]]' or in Sentence Suffix Sattern: 'Global requirement is incresing[[1]].'\n"
|
25
|
+
"Everything is build upon the typst language, which is similar to latex, \n"
|
26
|
+
"Legal citing syntax examples(seperated by |): [[1]]|[[1,2]]|[[1-3]]|[[12,13-15]]|[[1-3,5-7]]\n"
|
27
|
+
"Illegal citing syntax examples(seperated by |): [[1],[2],[3]]|[[1],[1-2]]\n"
|
28
|
+
"Those reference mark shall not be omitted during the extraction\n"
|
29
|
+
"It's recommended to cite multiple references that supports your conclusion at a time.\n"
|
30
|
+
"Wrapp inline expression using $ $,like '$>5m$' '$89%$' , and wrapp block equation using $$ $$. if you are using '$' as the money unit, you should add a '\\' before it to avoid being interpreted as a inline equation. For example 'The pants worths 5\\$.'\n"
|
31
|
+
"In addition to that, you can add a label outside the block equation which can be used as a cross reference identifier, the label is a string wrapped in `<` and `>` like `<energy-release-rate-equation>`.Note that the label string should be a summarizing title for the equation being labeled.\n"
|
32
|
+
"you can refer to that label by using the syntax with prefix of `@eqt:`, which indicate that this notation is citing a label from the equations. For example ' @eqt:energy-release-rate-equation ' DO remember that the notation shall have both suffixed and prefixed space char which enable the compiler to distinguish the notation from the plaintext."
|
33
|
+
"Below is a usage example:\n"
|
34
|
+
"```typst\n"
|
35
|
+
"See @eqt:mass-energy-equation , it's the foundation of physics.\n"
|
36
|
+
"$$\n"
|
37
|
+
"E = m c^2\n"
|
38
|
+
"$$ <mass-energy-equation>\n\n\n"
|
39
|
+
"In @eqt:mass-energy-equation , $m$ stands for mass, $c$ stands for speed of light, and $E$ stands for energy. \n"
|
40
|
+
"```"
|
41
|
+
)
|
42
|
+
|
21
43
|
|
22
44
|
class WriteArticleContentRAG(Action, RAG, Extract):
|
23
45
|
"""Write an article based on the provided outline."""
|
24
46
|
|
47
|
+
search_increment_multiplier: float = 1.6
|
48
|
+
"""The increment multiplier of the search increment."""
|
25
49
|
ref_limit: int = 35
|
26
50
|
"""The limit of references to be retrieved"""
|
27
|
-
threshold: float = 0.
|
51
|
+
threshold: float = 0.62
|
28
52
|
"""The threshold of relevance"""
|
29
53
|
extractor_model: str
|
30
54
|
"""The model to use for extracting the content from the retrieved references."""
|
@@ -32,43 +56,24 @@ class WriteArticleContentRAG(Action, RAG, Extract):
|
|
32
56
|
"""The model to use for querying the database"""
|
33
57
|
supervisor: bool = False
|
34
58
|
"""Whether to use supervisor mode"""
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
"Illegal citing syntax examples(seperated by |): [[1],[2],[3]]|[[1],[1-2]]\n"
|
40
|
-
"Those reference mark shall not be omitted during the extraction\n"
|
41
|
-
"It's recommended to cite multiple references that supports your conclusion at a time.\n"
|
42
|
-
"Wrapp inline expression using $ $, and wrapp block equation using $$ $$."
|
43
|
-
"In addition to that, you can add a label outside the block equation which can be used as a cross reference identifier, the label is a string wrapped in `<` and `>`,"
|
44
|
-
"you can refer to that label by using the syntax with prefix of `@eqt:`"
|
45
|
-
"Below is a usage example:\n"
|
46
|
-
"```typst\n"
|
47
|
-
"See @eqt:mass-energy-equation , it's the foundation of physics.\n"
|
48
|
-
"$$\n"
|
49
|
-
"E = m c^2"
|
50
|
-
"$$\n"
|
51
|
-
"<mass-energy-equation>\n\n"
|
52
|
-
"In @eqt:mass-energy-equation , $m$ stands for mass, $c$ stands for speed of light, and $E$ stands for energy. \n"
|
53
|
-
"```"
|
54
|
-
)
|
59
|
+
result_per_query: PositiveInt = 4
|
60
|
+
"""The number of results to be returned per query."""
|
61
|
+
req: str = TYPST_CITE_USAGE
|
62
|
+
"""The req of the write article content."""
|
55
63
|
|
56
64
|
async def _execute(
|
57
65
|
self,
|
58
66
|
article_outline: ArticleOutline,
|
59
|
-
collection_name: str =
|
67
|
+
collection_name: Optional[str] = None,
|
60
68
|
supervisor: Optional[bool] = None,
|
61
69
|
**cxt,
|
62
70
|
) -> Article:
|
63
71
|
article = Article.from_outline(article_outline).update_ref(article_outline)
|
64
|
-
|
72
|
+
self.target_collection = collection_name or self.safe_target_collection
|
65
73
|
if supervisor or (supervisor is None and self.supervisor):
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
for chap, sec, subsec in article.iter_subsections()
|
70
|
-
]
|
71
|
-
)
|
74
|
+
for chap, sec, subsec in article.iter_subsections():
|
75
|
+
await self._supervisor_inner(article, article_outline, chap, sec, subsec)
|
76
|
+
|
72
77
|
else:
|
73
78
|
await gather(
|
74
79
|
*[
|
@@ -92,22 +97,29 @@ class WriteArticleContentRAG(Action, RAG, Extract):
|
|
92
97
|
from questionary import confirm, text
|
93
98
|
from rich import print as r_print
|
94
99
|
|
95
|
-
|
96
|
-
|
97
|
-
cm = CitationManager(article_chunks=await ask_retain([r.chunk for r in ret], ret)).set_cite_number_all()
|
100
|
+
cm = CitationManager()
|
101
|
+
await self.search_database(article, article_outline, chap, sec, subsec, cm)
|
98
102
|
|
99
103
|
raw = await self.write_raw(article, article_outline, chap, sec, subsec, cm)
|
100
104
|
r_print(raw)
|
101
105
|
|
102
106
|
while not await confirm("Accept this version and continue?").ask_async():
|
103
|
-
if await
|
104
|
-
|
105
|
-
|
107
|
+
if inst := await text("Search for more refs for additional spec.").ask_async():
|
108
|
+
await self.search_database(
|
109
|
+
article,
|
110
|
+
article_outline,
|
111
|
+
chap,
|
112
|
+
sec,
|
113
|
+
subsec,
|
114
|
+
cm,
|
115
|
+
supervisor=True,
|
116
|
+
extra_instruction=inst,
|
117
|
+
)
|
106
118
|
|
107
|
-
instruction
|
108
|
-
|
109
|
-
if await
|
110
|
-
raw =
|
119
|
+
if instruction := await text("Enter the instructions to improve").ask_async():
|
120
|
+
raw = await self.write_raw(article, article_outline, chap, sec, subsec, cm, instruction)
|
121
|
+
if edt := await text("Edit", default=raw).ask_async():
|
122
|
+
raw = edt
|
111
123
|
|
112
124
|
r_print(raw)
|
113
125
|
|
@@ -121,11 +133,14 @@ class WriteArticleContentRAG(Action, RAG, Extract):
|
|
121
133
|
sec: ArticleSection,
|
122
134
|
subsec: ArticleSubsection,
|
123
135
|
) -> ArticleSubsection:
|
124
|
-
|
125
|
-
|
136
|
+
cm = CitationManager()
|
137
|
+
|
138
|
+
await self.search_database(article, article_outline, chap, sec, subsec, cm)
|
126
139
|
|
127
140
|
raw_paras = await self.write_raw(article, article_outline, chap, sec, subsec, cm)
|
128
141
|
|
142
|
+
raw_paras = "\n".join(p for p in raw_paras.splitlines() if p and not p.endswith("**") and not p.startswith("#"))
|
143
|
+
|
129
144
|
return await self.extract_new_subsec(subsec, raw_paras, cm)
|
130
145
|
|
131
146
|
async def extract_new_subsec(
|
@@ -139,6 +154,7 @@ class WriteArticleContentRAG(Action, RAG, Extract):
|
|
139
154
|
f"Above is the subsection titled `{subsec.title}`.\n"
|
140
155
|
f"I need you to extract the content to update my subsection obj provided below.\n{self.req}"
|
141
156
|
f"{subsec.display()}\n",
|
157
|
+
model=self.extractor_model,
|
142
158
|
),
|
143
159
|
"Failed to propose new subsection.",
|
144
160
|
)
|
@@ -162,12 +178,15 @@ class WriteArticleContentRAG(Action, RAG, Extract):
|
|
162
178
|
return (
|
163
179
|
(
|
164
180
|
await self.aask(
|
165
|
-
f"{cm.as_prompt()}\nAbove is some related reference retrieved for you."
|
181
|
+
f"{cm.as_prompt()}\nAbove is some related reference from other auther retrieved for you."
|
166
182
|
f"{article_outline.finalized_dump()}\n\nAbove is my article outline, I m writing graduate thesis titled `{article.title}`. "
|
167
183
|
f"More specifically, i m witting the Chapter `{chap.title}` >> Section `{sec.title}` >> Subsection `{subsec.title}`.\n"
|
168
184
|
f"Please help me write the paragraphs of the subsec mentioned above, which is `{subsec.title}`.\n"
|
169
185
|
f"{self.req}\n"
|
170
|
-
f"You SHALL use `{article.language}` as writing language.\n{extra_instruction}"
|
186
|
+
f"You SHALL use `{article.language}` as writing language.\n{extra_instruction}\n"
|
187
|
+
f"Do not use numbered list to display the outcome, you should regard you are writing the main text of the thesis.\n"
|
188
|
+
f"You should not copy others' works from the references directly on to my thesis, we can only harness the conclusion they have drawn.\n"
|
189
|
+
f"No extra explanation is allowed."
|
171
190
|
)
|
172
191
|
)
|
173
192
|
.replace(r" \( ", "$")
|
@@ -175,7 +194,9 @@ class WriteArticleContentRAG(Action, RAG, Extract):
|
|
175
194
|
.replace(r"\(", "$")
|
176
195
|
.replace(r"\)", "$")
|
177
196
|
.replace("\\[\n", "$$\n")
|
197
|
+
.replace("\\[ ", "$$\n")
|
178
198
|
.replace("\n\\]", "\n$$")
|
199
|
+
.replace(" \\]", "\n$$")
|
179
200
|
)
|
180
201
|
|
181
202
|
async def search_database(
|
@@ -185,28 +206,113 @@ class WriteArticleContentRAG(Action, RAG, Extract):
|
|
185
206
|
chap: ArticleChapter,
|
186
207
|
sec: ArticleSection,
|
187
208
|
subsec: ArticleSubsection,
|
209
|
+
cm: CitationManager,
|
188
210
|
extra_instruction: str = "",
|
189
211
|
supervisor: bool = False,
|
190
|
-
) ->
|
212
|
+
) -> None:
|
191
213
|
"""Search database for related references."""
|
214
|
+
search_req = (
|
215
|
+
f"{article_outline.finalized_dump()}\n\nAbove is my article outline, I m writing graduate thesis titled `{article.title}`. "
|
216
|
+
f"More specifically, i m witting the Chapter `{chap.title}` >> Section `{sec.title}` >> Subsection `{subsec.title}`.\n"
|
217
|
+
f"I need to search related references to build up the content of the subsec mentioned above, which is `{subsec.title}`.\n"
|
218
|
+
f"provide 10~16 queries as possible, to get best result!\n"
|
219
|
+
f"You should provide both English version and chinese version of the refined queries!\n{extra_instruction}\n"
|
220
|
+
)
|
221
|
+
|
192
222
|
ref_q = ok(
|
193
223
|
await self.arefined_query(
|
194
|
-
|
195
|
-
f"More specifically, i m witting the Chapter `{chap.title}` >> Section `{sec.title}` >> Subsection `{subsec.title}`.\n"
|
196
|
-
f"I need to search related references to build up the content of the subsec mentioned above, which is `{subsec.title}`.\n"
|
197
|
-
f"provide 10~16 queries as possible, to get best result!\n"
|
198
|
-
f"You should provide both English version and chinese version of the refined queries!\n{extra_instruction}\n",
|
224
|
+
search_req,
|
199
225
|
model=self.query_model,
|
200
226
|
),
|
201
227
|
"Failed to refine query.",
|
202
228
|
)
|
203
229
|
|
230
|
+
if supervisor:
|
231
|
+
ref_q = await ask_retain(ref_q)
|
232
|
+
ret = await self.aretrieve(
|
233
|
+
ref_q,
|
234
|
+
ArticleChunk,
|
235
|
+
final_limit=self.ref_limit,
|
236
|
+
result_per_query=self.result_per_query,
|
237
|
+
similarity_threshold=self.threshold,
|
238
|
+
)
|
239
|
+
|
240
|
+
cm.add_chunks(ok(ret))
|
241
|
+
ref_q = await self.arefined_query(
|
242
|
+
f"{cm.as_prompt()}\n\nAbove is the retrieved references in the first RAG, now we need to perform the second RAG.\n\n{search_req}",
|
243
|
+
model=self.query_model,
|
244
|
+
)
|
245
|
+
|
246
|
+
if ref_q is None:
|
247
|
+
logger.warning("Second refine query is None, skipping.")
|
248
|
+
return
|
204
249
|
if supervisor:
|
205
250
|
ref_q = await ask_retain(ref_q)
|
206
251
|
|
207
|
-
|
208
|
-
ref_q,
|
252
|
+
ret = await self.aretrieve(
|
253
|
+
ref_q,
|
254
|
+
ArticleChunk,
|
255
|
+
final_limit=int(self.ref_limit * self.search_increment_multiplier),
|
256
|
+
result_per_query=int(self.result_per_query * self.search_increment_multiplier),
|
257
|
+
similarity_threshold=self.threshold,
|
209
258
|
)
|
259
|
+
if ret is None:
|
260
|
+
logger.warning("Second retrieve is None, skipping.")
|
261
|
+
return
|
262
|
+
cm.add_chunks(ret)
|
263
|
+
|
264
|
+
|
265
|
+
class ArticleConsultRAG(Action, RAG):
|
266
|
+
"""Write an article based on the provided outline."""
|
267
|
+
|
268
|
+
output_key: str = "consult_count"
|
269
|
+
|
270
|
+
ref_limit: int = 20
|
271
|
+
"""The final limit of references."""
|
272
|
+
ref_per_q: int = 3
|
273
|
+
"""The limit of references to retrieve per query."""
|
274
|
+
similarity_threshold: float = 0.62
|
275
|
+
"""The similarity threshold of references to retrieve."""
|
276
|
+
ref_q_model: Optional[str] = None
|
277
|
+
"""The model to use for refining query."""
|
278
|
+
req: str = TYPST_CITE_USAGE
|
279
|
+
"""The request for the rag model."""
|
280
|
+
|
281
|
+
@precheck_package(
|
282
|
+
"questionary", "`questionary` is required for supervisor mode, please install it by `fabricatio[qa]`"
|
283
|
+
)
|
284
|
+
async def _execute(self, collection_name: Optional[str] = None, **cxt) -> int:
|
285
|
+
from questionary import confirm, text
|
286
|
+
from rich import print as r_print
|
287
|
+
|
288
|
+
from fabricatio.rust import convert_all_block_tex, convert_all_inline_tex
|
289
|
+
|
290
|
+
self.target_collection = collection_name or self.safe_target_collection
|
291
|
+
|
292
|
+
cm = CitationManager()
|
293
|
+
|
294
|
+
counter = 0
|
295
|
+
while (req := await text("User: ").ask_async()) is not None:
|
296
|
+
if await confirm("Empty the cm?").ask_async():
|
297
|
+
cm.empty()
|
298
|
+
ref_q = await self.arefined_query(req, model=self.ref_q_model)
|
299
|
+
refs = await self.aretrieve(
|
300
|
+
ok(ref_q, "Failed to refine query."),
|
301
|
+
ArticleChunk,
|
302
|
+
final_limit=self.ref_limit,
|
303
|
+
result_per_query=self.ref_per_q,
|
304
|
+
similarity_threshold=self.similarity_threshold,
|
305
|
+
)
|
306
|
+
|
307
|
+
ret = await self.aask(f"{cm.add_chunks(refs).as_prompt()}\n{self.req}\n{req}")
|
308
|
+
ret = convert_all_inline_tex(ret)
|
309
|
+
ret = convert_all_block_tex(ret)
|
310
|
+
ret = cm.apply(ret)
|
311
|
+
|
312
|
+
r_print(ret)
|
313
|
+
counter += 1
|
314
|
+
logger.info(f"{counter} rounds of conversation.")
|
315
|
+
return counter
|
210
316
|
|
211
317
|
|
212
318
|
class TweakArticleRAG(Action, RAG, Censor):
|
fabricatio/actions/output.py
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
"""Dump the finalized output to a file."""
|
2
2
|
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import Any, Iterable, List, Mapping, Optional, Type
|
4
|
+
from typing import Any, Dict, Iterable, List, Mapping, Optional, Type
|
5
5
|
|
6
|
+
from fabricatio import TEMPLATE_MANAGER
|
6
7
|
from fabricatio.journal import logger
|
7
8
|
from fabricatio.models.action import Action
|
8
9
|
from fabricatio.models.generic import FinalizedDumpAble, FromMapping, PersistentAble
|
9
10
|
from fabricatio.models.task import Task
|
11
|
+
from fabricatio.models.usages import LLMUsage
|
10
12
|
from fabricatio.utils import ok
|
11
13
|
|
12
14
|
|
13
|
-
class DumpFinalizedOutput(Action):
|
15
|
+
class DumpFinalizedOutput(Action, LLMUsage):
|
14
16
|
"""Dump the finalized output to a file."""
|
15
17
|
|
16
18
|
output_key: str = "dump_path"
|
@@ -38,7 +40,37 @@ class DumpFinalizedOutput(Action):
|
|
38
40
|
return dump_path.as_posix()
|
39
41
|
|
40
42
|
|
41
|
-
class
|
43
|
+
class RenderedDump(Action, LLMUsage):
|
44
|
+
"""Render the data to a file."""
|
45
|
+
|
46
|
+
output_key: str = "dump_path"
|
47
|
+
dump_path: Optional[str] = None
|
48
|
+
|
49
|
+
template_name: str
|
50
|
+
"""The template name to render the data."""
|
51
|
+
|
52
|
+
async def _execute(
|
53
|
+
self,
|
54
|
+
to_dump: Dict[str, Any],
|
55
|
+
task_input: Optional[Task] = None,
|
56
|
+
dump_path: Optional[str | Path] = None,
|
57
|
+
**_,
|
58
|
+
) -> str:
|
59
|
+
dump_path = Path(
|
60
|
+
dump_path
|
61
|
+
or self.dump_path
|
62
|
+
or ok(
|
63
|
+
await self.awhich_pathstr(
|
64
|
+
f"{ok(task_input, 'Neither `task_input` and `dump_path` is provided.').briefing}\n\nExtract a single path of the file, to which I will dump the data."
|
65
|
+
),
|
66
|
+
"Could not find the path of file to dump the data.",
|
67
|
+
)
|
68
|
+
)
|
69
|
+
logger.info(f"Saving output to {dump_path.as_posix()}")
|
70
|
+
return TEMPLATE_MANAGER.render_template(self.template_name, to_dump)
|
71
|
+
|
72
|
+
|
73
|
+
class PersistentAll(Action, LLMUsage):
|
42
74
|
"""Persist all the data to a file."""
|
43
75
|
|
44
76
|
output_key: str = "persistent_count"
|
fabricatio/config.py
CHANGED
@@ -328,9 +328,9 @@ class RoutingConfig(BaseModel):
|
|
328
328
|
allowed_fails: Optional[int] = 3
|
329
329
|
"""The number of allowed fails before the routing is considered failed."""
|
330
330
|
retry_after: int = 15
|
331
|
-
"""
|
332
|
-
cooldown_time: Optional[int] =
|
333
|
-
"""
|
331
|
+
"""Minimum time to wait before retrying a failed request."""
|
332
|
+
cooldown_time: Optional[int] = 60
|
333
|
+
"""Time to cooldown a deployment after failure in seconds."""
|
334
334
|
|
335
335
|
|
336
336
|
class Settings(BaseSettings):
|
fabricatio/fs/curd.py
CHANGED
@@ -20,7 +20,7 @@ def dump_text(path: Union[str, Path], text: str) -> None:
|
|
20
20
|
Returns:
|
21
21
|
None
|
22
22
|
"""
|
23
|
-
Path(path).write_text(text, encoding="utf-8", errors="ignore")
|
23
|
+
Path(path).write_text(text, encoding="utf-8", errors="ignore", newline="\n")
|
24
24
|
|
25
25
|
|
26
26
|
def copy_file(src: Union[str, Path], dst: Union[str, Path]) -> None:
|
fabricatio/models/action.py
CHANGED
@@ -12,12 +12,12 @@ Classes:
|
|
12
12
|
import traceback
|
13
13
|
from abc import abstractmethod
|
14
14
|
from asyncio import Queue, create_task
|
15
|
-
from typing import Any, Dict, Self, Tuple, Type, Union, final
|
15
|
+
from typing import Any, Dict, 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
|
20
|
+
from fabricatio.models.usages import ToolBoxUsage
|
21
21
|
from fabricatio.utils import override_kwargs
|
22
22
|
from pydantic import Field, PrivateAttr
|
23
23
|
|
@@ -26,7 +26,7 @@ OUTPUT_KEY = "task_output"
|
|
26
26
|
INPUT_KEY = "task_input"
|
27
27
|
|
28
28
|
|
29
|
-
class Action(WithBriefing
|
29
|
+
class Action(WithBriefing):
|
30
30
|
"""Class that represents an action to be executed in a workflow.
|
31
31
|
|
32
32
|
Actions are the atomic units of work in a workflow. Each action performs
|
@@ -96,9 +96,9 @@ class Action(WithBriefing, LLMUsage):
|
|
96
96
|
return f"## Your personality: \n{self.personality}\n# The action you are going to perform: \n{super().briefing}"
|
97
97
|
return f"# The action you are going to perform: \n{super().briefing}"
|
98
98
|
|
99
|
-
def to_task_output(self) -> Self:
|
99
|
+
def to_task_output(self, task_output_key: str = OUTPUT_KEY) -> Self:
|
100
100
|
"""Set the output key to OUTPUT_KEY and return the action instance."""
|
101
|
-
self.output_key =
|
101
|
+
self.output_key = task_output_key
|
102
102
|
return self
|
103
103
|
|
104
104
|
|
@@ -123,9 +123,7 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
|
|
123
123
|
_instances: Tuple[Action, ...] = PrivateAttr(default_factory=tuple)
|
124
124
|
"""Instantiated action objects to be executed in this workflow."""
|
125
125
|
|
126
|
-
steps:
|
127
|
-
frozen=True,
|
128
|
-
)
|
126
|
+
steps: Sequence[Union[Type[Action], Action]] = Field(frozen=True)
|
129
127
|
"""The sequence of actions to be executed, can be action classes or instances."""
|
130
128
|
|
131
129
|
task_input_key: str = Field(default=INPUT_KEY)
|
@@ -9,7 +9,7 @@ from fabricatio.journal import logger
|
|
9
9
|
from fabricatio.models.extra.rag import MilvusDataBase
|
10
10
|
from fabricatio.models.generic import AsPrompt
|
11
11
|
from fabricatio.models.kwargs_types import ChunkKwargs
|
12
|
-
from fabricatio.rust import BibManager,
|
12
|
+
from fabricatio.rust import BibManager, blake3_hash, split_into_chunks
|
13
13
|
from fabricatio.utils import ok
|
14
14
|
from more_itertools.recipes import flatten, unique
|
15
15
|
from pydantic import Field
|
@@ -53,7 +53,7 @@ class ArticleChunk(MilvusDataBase, AsPrompt):
|
|
53
53
|
|
54
54
|
def _as_prompt_inner(self) -> Dict[str, str]:
|
55
55
|
return {
|
56
|
-
f"[[{ok(self._cite_number, 'You need to update cite number first.')}]] reference `{self.article_title}`": self.chunk
|
56
|
+
f"[[{ok(self._cite_number, 'You need to update cite number first.')}]] reference `{self.article_title}` from {self.as_auther_seq()}": self.chunk
|
57
57
|
}
|
58
58
|
|
59
59
|
@property
|
@@ -139,15 +139,9 @@ class ArticleChunk(MilvusDataBase, AsPrompt):
|
|
139
139
|
return re.sub(r"\[[\d\s,\\~–-]+]", "", string)
|
140
140
|
|
141
141
|
@property
|
142
|
-
def
|
143
|
-
"""Get the
|
144
|
-
|
145
|
-
for n in self.authors:
|
146
|
-
if is_chinese(n):
|
147
|
-
ret.append(n[0])
|
148
|
-
else:
|
149
|
-
ret.append(n.split()[-1])
|
150
|
-
return ret
|
142
|
+
def auther_lastnames(self) -> List[str]:
|
143
|
+
"""Get the last name of the authors."""
|
144
|
+
return [n.split()[-1] for n in self.authors]
|
151
145
|
|
152
146
|
def as_auther_seq(self) -> str:
|
153
147
|
"""Get the auther sequence."""
|
@@ -155,13 +149,13 @@ class ArticleChunk(MilvusDataBase, AsPrompt):
|
|
155
149
|
case 0:
|
156
150
|
raise ValueError("No authors found")
|
157
151
|
case 1:
|
158
|
-
return f"({self.
|
152
|
+
return f"({self.auther_lastnames[0]},{self.year}){self.as_typst_cite()}"
|
159
153
|
case 2:
|
160
|
-
return f"({self.
|
154
|
+
return f"({self.auther_lastnames[0]}{self.and_word}{self.auther_lastnames[1]},{self.year}){self.as_typst_cite()}"
|
161
155
|
case 3:
|
162
|
-
return f"({self.
|
156
|
+
return f"({self.auther_lastnames[0]},{self.auther_lastnames[1]}{self.and_word}{self.auther_lastnames[2]},{self.year}){self.as_typst_cite()}"
|
163
157
|
case _:
|
164
|
-
return f"({self.
|
158
|
+
return f"({self.auther_lastnames[0]},{self.auther_lastnames[1]}{self.and_word}{self.auther_lastnames[2]}{self.etc_word},{self.year}){self.as_typst_cite()}"
|
165
159
|
|
166
160
|
def update_cite_number(self, cite_number: int) -> Self:
|
167
161
|
"""Update the cite number."""
|
@@ -182,20 +176,32 @@ class CitationManager(AsPrompt):
|
|
182
176
|
abbr_sep: str = "-"
|
183
177
|
"""Separator for abbreviated citation numbers."""
|
184
178
|
|
185
|
-
def update_chunks(
|
179
|
+
def update_chunks(
|
180
|
+
self, article_chunks: List[ArticleChunk], set_cite_number: bool = True, dedup: bool = True
|
181
|
+
) -> Self:
|
186
182
|
"""Update article chunks."""
|
187
183
|
self.article_chunks.clear()
|
188
184
|
self.article_chunks.extend(article_chunks)
|
185
|
+
if dedup:
|
186
|
+
self.article_chunks = list(unique(self.article_chunks, lambda c: blake3_hash(c.chunk.encode())))
|
189
187
|
if set_cite_number:
|
190
188
|
self.set_cite_number_all()
|
191
189
|
return self
|
192
190
|
|
193
|
-
def
|
191
|
+
def empty(self) -> Self:
|
192
|
+
"""Empty the article chunks."""
|
193
|
+
self.article_chunks.clear()
|
194
|
+
return self
|
195
|
+
|
196
|
+
def add_chunks(self, article_chunks: List[ArticleChunk], set_cite_number: bool = True, dedup: bool = True) -> Self:
|
194
197
|
"""Add article chunks."""
|
195
198
|
self.article_chunks.extend(article_chunks)
|
199
|
+
if dedup:
|
200
|
+
self.article_chunks = list(unique(self.article_chunks, lambda c: blake3_hash(c.chunk.encode())))
|
196
201
|
if set_cite_number:
|
197
202
|
self.set_cite_number_all()
|
198
203
|
return self
|
204
|
+
|
199
205
|
def set_cite_number_all(self) -> Self:
|
200
206
|
"""Set citation numbers for all article chunks."""
|
201
207
|
for i, a in enumerate(self.article_chunks, 1):
|
@@ -208,7 +214,7 @@ class CitationManager(AsPrompt):
|
|
208
214
|
|
209
215
|
def apply(self, string: str) -> str:
|
210
216
|
"""Apply citation replacements to the input string."""
|
211
|
-
for origin,m in re.findall(self.pat, string):
|
217
|
+
for origin, m in re.findall(self.pat, string):
|
212
218
|
logger.info(f"Matching citation: {m}")
|
213
219
|
notations = self.convert_to_numeric_notations(m)
|
214
220
|
logger.info(f"Citing Notations: {notations}")
|
@@ -216,9 +222,26 @@ class CitationManager(AsPrompt):
|
|
216
222
|
logger.info(f"Citation Number Sequence: {citation_number_seq}")
|
217
223
|
dedup = self.deduplicate_citation(citation_number_seq)
|
218
224
|
logger.info(f"Deduplicated Citation Number Sequence: {dedup}")
|
219
|
-
string=string.replace(origin, self.unpack_cite_seq(dedup))
|
225
|
+
string = string.replace(origin, self.unpack_cite_seq(dedup))
|
220
226
|
return string
|
221
227
|
|
228
|
+
def citation_count(self, string: str) -> int:
|
229
|
+
"""Get the citation count in the string."""
|
230
|
+
count = 0
|
231
|
+
for _, m in re.findall(self.pat, string):
|
232
|
+
logger.info(f"Matching citation: {m}")
|
233
|
+
notations = self.convert_to_numeric_notations(m)
|
234
|
+
logger.info(f"Citing Notations: {notations}")
|
235
|
+
citation_number_seq = list(flatten(self.decode_expr(n) for n in notations))
|
236
|
+
logger.info(f"Citation Number Sequence: {citation_number_seq}")
|
237
|
+
count += len(dedup := self.deduplicate_citation(citation_number_seq))
|
238
|
+
logger.info(f"Deduplicated Citation Number Sequence: {dedup}")
|
239
|
+
return count
|
240
|
+
|
241
|
+
def citation_coverage(self, string: str) -> float:
|
242
|
+
"""Get the citation coverage in the string."""
|
243
|
+
return self.citation_count(string) / len(self.article_chunks)
|
244
|
+
|
222
245
|
def decode_expr(self, string: str) -> List[int]:
|
223
246
|
"""Decode citation expression into a list of integers."""
|
224
247
|
if self.abbr_sep in string:
|
@@ -46,6 +46,16 @@ class ArticleMetaData(SketchedAble, Described, WordCount, Titled, Language):
|
|
46
46
|
aims: List[str]
|
47
47
|
"""List of writing aims of the research component in academic style."""
|
48
48
|
|
49
|
+
@property
|
50
|
+
def typst_metadata_comment(self) -> str:
|
51
|
+
"""Generates a comment for the metadata of the article component."""
|
52
|
+
return comment(
|
53
|
+
(f"Desc:\n {self.description}\n" if self.description else "")
|
54
|
+
+ (f"Aims:\n {'\n '.join(self.aims)}\n" if self.aims else "")
|
55
|
+
+ (f"Expected Word Count:{self.expected_word_count}" if self.expected_word_count else "")
|
56
|
+
|
57
|
+
)
|
58
|
+
|
49
59
|
|
50
60
|
class ArticleOutlineBase(
|
51
61
|
ArticleMetaData,
|
@@ -89,13 +99,7 @@ class SubSectionBase(ArticleOutlineBase):
|
|
89
99
|
|
90
100
|
def to_typst_code(self) -> str:
|
91
101
|
"""Converts the component into a Typst code snippet for rendering."""
|
92
|
-
return
|
93
|
-
f"=== {self.title}\n"
|
94
|
-
f"{comment(f'Desc:\n{self.description}\nAims:\n{"\n".join(self.aims)}')}\n"
|
95
|
-
+ f"Expected Word Count:{self.expected_word_count}"
|
96
|
-
if self.expected_word_count
|
97
|
-
else ""
|
98
|
-
)
|
102
|
+
return f"=== {self.title}\n{self.typst_metadata_comment}\n"
|
99
103
|
|
100
104
|
def introspect(self) -> str:
|
101
105
|
"""Introspects the article subsection outline."""
|
@@ -120,13 +124,9 @@ class SectionBase[T: SubSectionBase](ArticleOutlineBase):
|
|
120
124
|
Returns:
|
121
125
|
str: The formatted Typst code snippet.
|
122
126
|
"""
|
123
|
-
return (
|
124
|
-
|
125
|
-
|
126
|
-
+ f"Expected Word Count:{self.expected_word_count}"
|
127
|
-
if self.expected_word_count
|
128
|
-
else ""
|
129
|
-
) + "\n\n".join(subsec.to_typst_code() for subsec in self.subsections)
|
127
|
+
return f"== {self.title}\n{self.typst_metadata_comment}\n" + "\n\n".join(
|
128
|
+
subsec.to_typst_code() for subsec in self.subsections
|
129
|
+
)
|
130
130
|
|
131
131
|
def resolve_update_conflict(self, other: Self) -> str:
|
132
132
|
"""Resolve update errors in the article outline."""
|
@@ -169,13 +169,9 @@ class ChapterBase[T: SectionBase](ArticleOutlineBase):
|
|
169
169
|
|
170
170
|
def to_typst_code(self) -> str:
|
171
171
|
"""Converts the chapter into a Typst formatted code snippet for rendering."""
|
172
|
-
return (
|
173
|
-
|
174
|
-
|
175
|
-
+ f"Expected Word Count:{self.expected_word_count}"
|
176
|
-
if self.expected_word_count
|
177
|
-
else ""
|
178
|
-
) + "\n\n".join(sec.to_typst_code() for sec in self.sections)
|
172
|
+
return f"= {self.title}\n{self.typst_metadata_comment}\n" + "\n\n".join(
|
173
|
+
sec.to_typst_code() for sec in self.sections
|
174
|
+
)
|
179
175
|
|
180
176
|
def resolve_update_conflict(self, other: Self) -> str:
|
181
177
|
"""Resolve update errors in the article outline."""
|
@@ -317,8 +313,41 @@ class ArticleBase[T: ChapterBase](FinalizedDumpAble, AsPrompt, WordCount, Descri
|
|
317
313
|
=== Implementation Details
|
318
314
|
== Evaluation Protocol
|
319
315
|
"""
|
320
|
-
return
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
316
|
+
return (
|
317
|
+
comment(
|
318
|
+
f"Title:{self.title}\n"
|
319
|
+
+ (f"Desc:\n{self.description}\n" if self.description else "")
|
320
|
+
+ f"Word Count:{self.expected_word_count}"
|
321
|
+
if self.expected_word_count
|
322
|
+
else ""
|
323
|
+
)
|
324
|
+
+ "\n\n"
|
325
|
+
+ "\n\n".join(a.to_typst_code() for a in self.chapters)
|
326
|
+
)
|
327
|
+
|
328
|
+
def avg_chap_wordcount[S](self: S) -> S:
|
329
|
+
"""Set all chap have same word count sum up to be `self.expected_word_count`."""
|
330
|
+
avg = int(self.expected_word_count / len(self.chapters))
|
331
|
+
for c in self.chapters:
|
332
|
+
c.expected_word_count = avg
|
333
|
+
return self
|
334
|
+
|
335
|
+
def avg_sec_wordcount[S](self: S) -> S:
|
336
|
+
"""Set all sec have same word count sum up to be `self.expected_word_count`."""
|
337
|
+
for c in self.chapters:
|
338
|
+
avg = int(c.expected_word_count / len(c.sections))
|
339
|
+
for s in c.sections:
|
340
|
+
s.expected_word_count = avg
|
341
|
+
return self
|
342
|
+
|
343
|
+
def avg_subsec_wordcount[S](self: S) -> S:
|
344
|
+
"""Set all subsec have same word count sum up to be `self.expected_word_count`."""
|
345
|
+
for _, s in self.iter_sections():
|
346
|
+
avg = int(s.expected_word_count / len(s.subsections))
|
347
|
+
for ss in s.subsections:
|
348
|
+
ss.expected_word_count = avg
|
349
|
+
return self
|
350
|
+
|
351
|
+
def avg_wordcount_recursive(self) -> Self:
|
352
|
+
"""Set all chap, sec, subsec have same word count sum up to be `self.expected_word_count`."""
|
353
|
+
return self.avg_chap_wordcount().avg_sec_wordcount().avg_sec_wordcount()
|
@@ -12,10 +12,14 @@ from fabricatio.models.extra.article_base import (
|
|
12
12
|
SubSectionBase,
|
13
13
|
)
|
14
14
|
from fabricatio.models.extra.article_outline import (
|
15
|
+
ArticleChapterOutline,
|
15
16
|
ArticleOutline,
|
17
|
+
ArticleSectionOutline,
|
18
|
+
ArticleSubsectionOutline,
|
16
19
|
)
|
17
20
|
from fabricatio.models.generic import Described, PersistentAble, SequencePatch, SketchedAble, WithRef, WordCount
|
18
21
|
from fabricatio.rust import convert_all_block_tex, convert_all_inline_tex, word_count
|
22
|
+
from fabricatio.utils import fallback_kwargs
|
19
23
|
from pydantic import Field, NonNegativeInt
|
20
24
|
|
21
25
|
PARAGRAPH_SEP = "// - - -"
|
@@ -89,7 +93,7 @@ class ArticleSubsection(SubSectionBase):
|
|
89
93
|
Returns:
|
90
94
|
str: Typst code snippet for rendering.
|
91
95
|
"""
|
92
|
-
return
|
96
|
+
return super().to_typst_code() + f"\n\n{PARAGRAPH_SEP}\n\n".join(p.content for p in self.paragraphs)
|
93
97
|
|
94
98
|
@classmethod
|
95
99
|
def from_typst_code(cls, title: str, body: str) -> Self:
|
@@ -181,6 +185,50 @@ class Article(
|
|
181
185
|
def iter_subsections(self) -> Generator[Tuple[ArticleChapter, ArticleSection, ArticleSubsection], None, None]:
|
182
186
|
return super().iter_subsections() # pyright: ignore [reportReturnType]
|
183
187
|
|
188
|
+
def extrac_outline(self) -> ArticleOutline:
|
189
|
+
"""Extract outline from article."""
|
190
|
+
# Create an empty list to hold chapter outlines
|
191
|
+
chapters = []
|
192
|
+
|
193
|
+
# Iterate through each chapter in the article
|
194
|
+
for chapter in self.chapters:
|
195
|
+
# Create an empty list to hold section outlines
|
196
|
+
sections = []
|
197
|
+
|
198
|
+
# Iterate through each section in the chapter
|
199
|
+
for section in chapter.sections:
|
200
|
+
# Create an empty list to hold subsection outlines
|
201
|
+
subsections = []
|
202
|
+
|
203
|
+
# Iterate through each subsection in the section
|
204
|
+
for subsection in section.subsections:
|
205
|
+
# Create a subsection outline and add it to the list
|
206
|
+
subsections.append(
|
207
|
+
ArticleSubsectionOutline(**subsection.model_dump(exclude={"paragraphs"}, by_alias=True))
|
208
|
+
)
|
209
|
+
|
210
|
+
# Create a section outline and add it to the list
|
211
|
+
sections.append(
|
212
|
+
ArticleSectionOutline(
|
213
|
+
**section.model_dump(exclude={"subsections"}, by_alias=True),
|
214
|
+
subsections=subsections,
|
215
|
+
)
|
216
|
+
)
|
217
|
+
|
218
|
+
# Create a chapter outline and add it to the list
|
219
|
+
chapters.append(
|
220
|
+
ArticleChapterOutline(
|
221
|
+
**chapter.model_dump(exclude={"sections"}, by_alias=True),
|
222
|
+
sections=sections,
|
223
|
+
)
|
224
|
+
)
|
225
|
+
|
226
|
+
# Create and return the article outline
|
227
|
+
return ArticleOutline(
|
228
|
+
**self.model_dump(exclude={"chapters"}, by_alias=True),
|
229
|
+
chapters=chapters,
|
230
|
+
)
|
231
|
+
|
184
232
|
@classmethod
|
185
233
|
def from_outline(cls, outline: ArticleOutline) -> "Article":
|
186
234
|
"""Generates an article from the given outline.
|
@@ -218,15 +266,18 @@ class Article(
|
|
218
266
|
return article
|
219
267
|
|
220
268
|
@classmethod
|
221
|
-
def from_typst_code(cls, title: str, body: str) -> Self:
|
269
|
+
def from_typst_code(cls, title: str, body: str, **kwargs) -> Self:
|
222
270
|
"""Generates an article from the given Typst code."""
|
223
271
|
return cls(
|
224
272
|
chapters=[
|
225
273
|
ArticleChapter.from_typst_code(*pack) for pack in extract_sections(body, level=1, section_char="=")
|
226
274
|
],
|
227
275
|
heading=title,
|
228
|
-
|
229
|
-
|
276
|
+
**fallback_kwargs(
|
277
|
+
kwargs,
|
278
|
+
expected_word_count=word_count(body),
|
279
|
+
abstract="",
|
280
|
+
),
|
230
281
|
)
|
231
282
|
|
232
283
|
@classmethod
|
@@ -248,3 +299,4 @@ class Article(
|
|
248
299
|
|
249
300
|
for a in self.iter_dfs():
|
250
301
|
a.title = await text(f"Edit `{a.title}`.", default=a.title).ask_async() or a.title
|
302
|
+
return self
|
fabricatio/models/generic.py
CHANGED
@@ -122,7 +122,7 @@ class FromMapping(Base):
|
|
122
122
|
|
123
123
|
@classmethod
|
124
124
|
@abstractmethod
|
125
|
-
def from_mapping(cls, mapping: Mapping[str, Any], **kwargs: Any) -> List[
|
125
|
+
def from_mapping[S](cls: S, mapping: Mapping[str, Any], **kwargs: Any) -> List[S]:
|
126
126
|
"""Generate a list of objects from a mapping."""
|
127
127
|
|
128
128
|
|
@@ -186,7 +186,7 @@ class WithRef[T](Base):
|
|
186
186
|
@overload
|
187
187
|
def update_ref[S: WithRef](self: S, reference: None = None) -> S: ...
|
188
188
|
|
189
|
-
def update_ref[S: WithRef](self: S, reference: Union[T, "WithRef[T]", None] = None) -> S:
|
189
|
+
def update_ref[S: WithRef](self: S, reference: Union[T, "WithRef[T]", None] = None) -> S:
|
190
190
|
"""Update the reference of the object.
|
191
191
|
|
192
192
|
Args:
|
@@ -201,7 +201,7 @@ class WithRef[T](Base):
|
|
201
201
|
self._reference = reference # pyright: ignore [reportAttributeAccessIssue]
|
202
202
|
return self
|
203
203
|
|
204
|
-
def derive[S: WithRef](self: S, reference: Any) -> S:
|
204
|
+
def derive[S: WithRef](self: S, reference: Any) -> S:
|
205
205
|
"""Derive a new object from the current object.
|
206
206
|
|
207
207
|
Args:
|
@@ -789,7 +789,7 @@ class ScopedConfig(Base):
|
|
789
789
|
"""The dimensions of the Milvus server."""
|
790
790
|
|
791
791
|
@final
|
792
|
-
def fallback_to(self, other: "ScopedConfig") -> Self:
|
792
|
+
def fallback_to(self, other: Union["ScopedConfig", Any]) -> Self:
|
793
793
|
"""Merge configuration values with fallback priority.
|
794
794
|
|
795
795
|
Copies non-null values from 'other' to self where current values are None.
|
@@ -800,6 +800,9 @@ class ScopedConfig(Base):
|
|
800
800
|
Returns:
|
801
801
|
Self: Current instance with merged values
|
802
802
|
"""
|
803
|
+
if not isinstance(other, ScopedConfig):
|
804
|
+
return self
|
805
|
+
|
803
806
|
# Iterate over the attribute names and copy values from 'other' to 'self' where applicable
|
804
807
|
# noinspection PydanticTypeChecker,PyTypeChecker
|
805
808
|
for attr_name in ScopedConfig.model_fields:
|
@@ -811,7 +814,7 @@ class ScopedConfig(Base):
|
|
811
814
|
return self
|
812
815
|
|
813
816
|
@final
|
814
|
-
def hold_to(self, others: Union["ScopedConfig", Iterable["ScopedConfig"]]) -> Self:
|
817
|
+
def hold_to(self, others: Union[Union["ScopedConfig", Any], Iterable[Union["ScopedConfig", Any]]]) -> Self:
|
815
818
|
"""Propagate non-null values to other configurations.
|
816
819
|
|
817
820
|
Copies current non-null values to target configurations where they are None.
|
@@ -824,7 +827,8 @@ class ScopedConfig(Base):
|
|
824
827
|
"""
|
825
828
|
if not isinstance(others, Iterable):
|
826
829
|
others = [others]
|
827
|
-
|
830
|
+
|
831
|
+
for other in (o for o in others if isinstance(o, ScopedConfig)):
|
828
832
|
# noinspection PyTypeChecker,PydanticTypeChecker
|
829
833
|
for attr_name in ScopedConfig.model_fields:
|
830
834
|
if (attr := getattr(self, attr_name)) is not None and getattr(other, attr_name) is None:
|
fabricatio/models/role.py
CHANGED
@@ -2,18 +2,18 @@
|
|
2
2
|
|
3
3
|
from typing import Any, Self, Set
|
4
4
|
|
5
|
-
from fabricatio.capabilities.
|
6
|
-
from fabricatio.capabilities.task import HandleTask, ProposeTask
|
5
|
+
from fabricatio.capabilities.propose import Propose
|
7
6
|
from fabricatio.core import env
|
8
7
|
from fabricatio.journal import logger
|
9
8
|
from fabricatio.models.action import WorkFlow
|
10
9
|
from fabricatio.models.events import Event
|
11
10
|
from fabricatio.models.generic import WithBriefing
|
12
11
|
from fabricatio.models.tool import ToolBox
|
12
|
+
from fabricatio.models.usages import ToolBoxUsage
|
13
13
|
from pydantic import Field
|
14
14
|
|
15
15
|
|
16
|
-
class Role(WithBriefing,
|
16
|
+
class Role(WithBriefing, Propose, ToolBoxUsage):
|
17
17
|
"""Class that represents a role with a registry of events and workflows.
|
18
18
|
|
19
19
|
A Role serves as a container for workflows, managing their registration to events
|
@@ -23,7 +23,8 @@ class Role(WithBriefing, ProposeTask, HandleTask, Correct):
|
|
23
23
|
registry: Mapping of events to workflows that handle them
|
24
24
|
toolboxes: Set of toolboxes available to this role and its workflows
|
25
25
|
"""
|
26
|
-
|
26
|
+
|
27
|
+
description: str = ""
|
27
28
|
"""A brief description of the role's responsibilities and capabilities."""
|
28
29
|
|
29
30
|
registry: dict[Event | str, WorkFlow] = Field(default_factory=dict)
|
Binary file
|
fabricatio/utils.py
CHANGED
@@ -47,7 +47,7 @@ async def ask_retain[V](candidates: List[str], value_mapping: Optional[List[V]]
|
|
47
47
|
"Please choose those that should be retained.",
|
48
48
|
choices=[Choice(p, value=p, checked=True) for p in candidates]
|
49
49
|
if value_mapping is None
|
50
|
-
else [Choice(p, value=v) for p, v in zip(candidates, value_mapping, strict=True)],
|
50
|
+
else [Choice(p, value=v, checked=True) for p, v in zip(candidates, value_mapping, strict=True)],
|
51
51
|
).ask_async()
|
52
52
|
|
53
53
|
|
Binary file
|
@@ -1,46 +1,46 @@
|
|
1
|
-
fabricatio-0.2.
|
2
|
-
fabricatio-0.2.
|
3
|
-
fabricatio-0.2.
|
1
|
+
fabricatio-0.2.12.dev1.dist-info/METADATA,sha256=qjBv5RTwJvd0KEFkb-OpKBorNX43NNrWf-3l5mhWOuk,5120
|
2
|
+
fabricatio-0.2.12.dev1.dist-info/WHEEL,sha256=7FgAcpQES0h1xhfN9Ugve9FTUilU6sRAr1WJ5ph2cuw,108
|
3
|
+
fabricatio-0.2.12.dev1.dist-info/licenses/LICENSE,sha256=yDZaTLnOi03bi3Dk6f5IjhLUc5old2yOsihHWU0z-i0,1067
|
4
4
|
fabricatio/decorators.py,sha256=iuFCTtZ4VXwxJpM_z-CtrEpTaVZsv_eBFe5mOhe4wlo,8715
|
5
5
|
fabricatio/constants.py,sha256=JxtaKGTf0IQhM-MNCHtr6x85Ejg8FWYcie-Z_RupCBg,557
|
6
6
|
fabricatio/core.py,sha256=MaEKZ6DDmbdScAY-7F1gwGA6fr7ADX6Mz5rNVi2msFA,6277
|
7
|
-
fabricatio/models/generic.py,sha256=
|
7
|
+
fabricatio/models/generic.py,sha256=a22CjQSlu-0WDdDVQiCIOddylaMFnv9lMLVuIeNKV1w,30392
|
8
8
|
fabricatio/models/tool.py,sha256=VM3rMeDpUbeeFAKpsPfweJ2JGHf-w5f1voDnuhK99ew,12178
|
9
|
-
fabricatio/models/role.py,sha256=
|
10
|
-
fabricatio/models/kwargs_types.py,sha256=
|
9
|
+
fabricatio/models/role.py,sha256=5SJ1Vm6H3FwOVEk5Z-4GBJWABI3OKAKwkz5t170osi8,2855
|
10
|
+
fabricatio/models/kwargs_types.py,sha256=aI844DNQXLbSBC3P0bZQLJpuJxwwF66WTDbbYQTftaE,4618
|
11
11
|
fabricatio/models/extra/article_proposal.py,sha256=4G2qLkMxtK54G1ANgPW0G3w4Pahxgk2lhGPU5KMxuzw,1818
|
12
12
|
fabricatio/models/extra/advanced_judge.py,sha256=CKPP4Lseb_Ey8Y7i2V9HJfB-mZgCknFdqq7Zo41o6s4,1060
|
13
|
-
fabricatio/models/extra/article_main.py,sha256
|
13
|
+
fabricatio/models/extra/article_main.py,sha256=kPa_y5j9eMOW7zfQn779On31CS2ckqZtnSFxOhkpGD8,11522
|
14
14
|
fabricatio/models/extra/problem.py,sha256=1Sd8hsThQK6pXMXhErRhP1ft58z4PvqeB8AV8VcXiaI,7051
|
15
15
|
fabricatio/models/extra/article_essence.py,sha256=zUfZ2_bX3h__RaVPwJlxQ-tkFyfSV8SdX8DsmFX6v_w,2649
|
16
16
|
fabricatio/models/extra/rag.py,sha256=RWv_YJhDX6UL4t3sRtQt-LYMtxN-K-t931nmyiJXkKM,3857
|
17
17
|
fabricatio/models/extra/article_outline.py,sha256=2vqMDhXwfRooHEe_cblkOj-4V96VsIAy68x22KBEQPQ,1387
|
18
18
|
fabricatio/models/extra/__init__.py,sha256=0R9eZsCNu6OV-Xtf15H7FrqhfHTFBFf3fBrcd7ChsJ0,53
|
19
19
|
fabricatio/models/extra/rule.py,sha256=b756_XmWeDoJ1qOFEGy6ZfP8O7rBjOZs4XvfZvWKXXI,2574
|
20
|
-
fabricatio/models/extra/aricle_rag.py,sha256
|
21
|
-
fabricatio/models/extra/article_base.py,sha256=
|
20
|
+
fabricatio/models/extra/aricle_rag.py,sha256=-w1fxs5PrsLTYPmNtUhWSeucQ9evnasUB75aMlzutL0,10722
|
21
|
+
fabricatio/models/extra/article_base.py,sha256=QIcQbsp4-nE6OVpV82jLw1Ki1cXwvsQJVJns6sVhy14,13708
|
22
22
|
fabricatio/models/extra/patches.py,sha256=_ghmnlvTZQq7UJyaH77mTZE9abjvxRJ2mgWHUbezUls,977
|
23
23
|
fabricatio/models/adv_kwargs_types.py,sha256=659KMMuvdVq1xJxavLbUAMWxPOAz0RP9bNaZm3hyz-4,1890
|
24
24
|
fabricatio/models/usages.py,sha256=FVRhh_AulXlJF9uUmJzKEdiLz-di0rAiaQm4snYEid0,32571
|
25
25
|
fabricatio/models/events.py,sha256=-9Xy8kcZug1tYwxmt3GpXtCkNfZUMSFvAH5HdZoRJTI,4030
|
26
26
|
fabricatio/models/task.py,sha256=O4v5T3HuzYblGeeqNzTDOCbulhGovR6olV2ojD0FJvk,10785
|
27
|
-
fabricatio/models/action.py,sha256=
|
27
|
+
fabricatio/models/action.py,sha256=oOyxkhocfWDetfz9EEvAyDU1U3w0X1OrzdtwNHTxDr8,9854
|
28
28
|
fabricatio/toolboxes/fs.py,sha256=OQMdeokYxSNVrCZJAweJ0cYiK4k2QuEiNdIbS5IHIV8,705
|
29
29
|
fabricatio/toolboxes/__init__.py,sha256=dYm_Gd8XolSU_h4wnkA09dlaLDK146eeFz0CUgPZ8_c,380
|
30
30
|
fabricatio/toolboxes/arithmetic.py,sha256=sSTPkKI6-mb278DwQKFO9jKyzc9kCx45xNH7V6bGBpE,1307
|
31
31
|
fabricatio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
32
32
|
fabricatio/fs/readers.py,sha256=hFHfGw1E58Da0ndBXXWcD2t-4HNdR1FimeDxuMI4-oE,1690
|
33
|
-
fabricatio/fs/curd.py,sha256=
|
33
|
+
fabricatio/fs/curd.py,sha256=x7Je9V1ydv-BdZTjlLc3syZ6380gkOhpfrfnhXstisg,4624
|
34
34
|
fabricatio/fs/__init__.py,sha256=abIYGDiX5bZ9vSHfro1-OtogzD_3vuR71FZMvZt8820,750
|
35
35
|
fabricatio/rust_instances.py,sha256=i5fIt6XkE8UwUU4JarmPt50AZs8aJW6efaypSLGLl0I,303
|
36
|
-
fabricatio/config.py,sha256=
|
37
|
-
fabricatio/utils.py,sha256=
|
36
|
+
fabricatio/config.py,sha256=Zc2UG1Jf8u0XfwHR7yrApgynzdX_uC6jInMw8PDm64o,17526
|
37
|
+
fabricatio/utils.py,sha256=DZDOsJN1FxTVqq-i1fAJZdLfDYxyVoMAJFQURuYt1rY,3004
|
38
38
|
fabricatio/journal.py,sha256=Op0wC-JlZumnAc_aDmYM4ljnSNLoKEEMfcIRbCF69ow,455
|
39
39
|
fabricatio/rust.pyi,sha256=EEZTQquqkHZ1G29YUPICwb9SJBzKgCB1B0ILuFNUoR0,10143
|
40
40
|
fabricatio/__init__.py,sha256=OXoMMHJKHEB_vN97_34U4I5QpAKL9xnVQEVcBCvwBCg,986
|
41
41
|
fabricatio/actions/fs.py,sha256=nlTmk-tYDW158nz_fzlsNfuYJwj7j4BHn_MFY5hxdqs,934
|
42
|
-
fabricatio/actions/output.py,sha256=
|
43
|
-
fabricatio/actions/article_rag.py,sha256=
|
42
|
+
fabricatio/actions/output.py,sha256=KR9SKDxLSp6rRWf0sriSGwITwe2HE506QGUP3yj-N4E,7891
|
43
|
+
fabricatio/actions/article_rag.py,sha256=uGnHfw7fNzxHPXNB7ukXe9gfZaBrHtJRA54BVTnZVIc,18506
|
44
44
|
fabricatio/actions/rag.py,sha256=-bA7KkZEFfWEanAPHzYwRHG7zRlTZcNDI7HL3n-lDuE,3496
|
45
45
|
fabricatio/actions/__init__.py,sha256=ZMa1LeM5BNeqp-J-D32W-f5bD53-kdXGyt0zuueJofM,47
|
46
46
|
fabricatio/actions/article.py,sha256=syUjEyKppdT72Xd1LSXKR3Djo1aybRPeFRHRzifNhm0,10632
|
@@ -60,6 +60,6 @@ fabricatio/capabilities/review.py,sha256=EPL8IlxSKO0XStBkXdW7FJMbPztDQMv9w7tHgu6
|
|
60
60
|
fabricatio/capabilities/propose.py,sha256=vOJvmmnMBHUQB6N1AmZNFw42jf7Bl2mBRNlBK15TpNI,1942
|
61
61
|
fabricatio/capabilities/task.py,sha256=_BAQonNy5JH3JxhLmPGfn0nDvn_ENKXyOdql8EVXRLE,4362
|
62
62
|
fabricatio/capabilities/extract.py,sha256=b4_Tuc9O6Pe71y4Tj-JHMb4simdhduVR-rcfD9yW8RA,2425
|
63
|
-
fabricatio/rust.cpython-312-x86_64-linux-gnu.so,sha256=
|
64
|
-
fabricatio-0.2.
|
65
|
-
fabricatio-0.2.
|
63
|
+
fabricatio/rust.cpython-312-x86_64-linux-gnu.so,sha256=ABhIKEaDhWIR9Bx9rY2CqpwvJNBsxdXb1DDYQhbnhvI,4438896
|
64
|
+
fabricatio-0.2.12.dev1.data/scripts/tdown,sha256=EEtn-cmxQQ9M1XIunkzQFqqGRRfo6WQXlk3mv7oFARw,4582192
|
65
|
+
fabricatio-0.2.12.dev1.dist-info/RECORD,,
|
Binary file
|
File without changes
|
File without changes
|