fabricatio 0.2.10.dev1__cp312-cp312-manylinux_2_34_x86_64.whl → 0.2.11.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.py +38 -9
- fabricatio/actions/article_rag.py +115 -13
- fabricatio/actions/fs.py +25 -0
- fabricatio/actions/output.py +17 -3
- fabricatio/actions/rag.py +3 -3
- fabricatio/actions/rules.py +14 -3
- fabricatio/capabilities/extract.py +70 -0
- fabricatio/capabilities/rating.py +5 -2
- fabricatio/capabilities/task.py +16 -16
- fabricatio/config.py +9 -2
- fabricatio/decorators.py +30 -30
- fabricatio/fs/__init__.py +9 -2
- fabricatio/fs/readers.py +6 -10
- fabricatio/models/extra/aricle_rag.py +125 -9
- fabricatio/models/extra/article_main.py +46 -2
- fabricatio/models/extra/problem.py +5 -1
- fabricatio/models/generic.py +29 -11
- fabricatio/models/kwargs_types.py +3 -1
- fabricatio/models/usages.py +9 -26
- fabricatio/parser.py +16 -12
- fabricatio/rust.cpython-312-x86_64-linux-gnu.so +0 -0
- fabricatio/rust.pyi +124 -6
- fabricatio/utils.py +11 -3
- fabricatio-0.2.11.dev1.data/scripts/tdown +0 -0
- {fabricatio-0.2.10.dev1.dist-info → fabricatio-0.2.11.dev1.dist-info}/METADATA +17 -8
- {fabricatio-0.2.10.dev1.dist-info → fabricatio-0.2.11.dev1.dist-info}/RECORD +28 -26
- fabricatio-0.2.10.dev1.data/scripts/tdown +0 -0
- {fabricatio-0.2.10.dev1.dist-info → fabricatio-0.2.11.dev1.dist-info}/WHEEL +0 -0
- {fabricatio-0.2.10.dev1.dist-info → fabricatio-0.2.11.dev1.dist-info}/licenses/LICENSE +0 -0
fabricatio/actions/article.py
CHANGED
@@ -4,10 +4,12 @@ from asyncio import gather
|
|
4
4
|
from pathlib import Path
|
5
5
|
from typing import Callable, List, Optional
|
6
6
|
|
7
|
-
from fabricatio.rust import BibManager, detect_language
|
8
7
|
from more_itertools import filter_map
|
8
|
+
from pydantic import Field
|
9
|
+
from rich import print as r_print
|
9
10
|
|
10
11
|
from fabricatio.capabilities.censor import Censor
|
12
|
+
from fabricatio.capabilities.extract import Extract
|
11
13
|
from fabricatio.capabilities.propose import Propose
|
12
14
|
from fabricatio.fs import safe_text_read
|
13
15
|
from fabricatio.journal import logger
|
@@ -17,8 +19,10 @@ from fabricatio.models.extra.article_main import Article
|
|
17
19
|
from fabricatio.models.extra.article_outline import ArticleOutline
|
18
20
|
from fabricatio.models.extra.article_proposal import ArticleProposal
|
19
21
|
from fabricatio.models.extra.rule import RuleSet
|
22
|
+
from fabricatio.models.kwargs_types import ValidateKwargs
|
20
23
|
from fabricatio.models.task import Task
|
21
|
-
from fabricatio.
|
24
|
+
from fabricatio.rust import BibManager, detect_language
|
25
|
+
from fabricatio.utils import ok, wrapp_in_block
|
22
26
|
|
23
27
|
|
24
28
|
class ExtractArticleEssence(Action, Propose):
|
@@ -130,29 +134,45 @@ class GenerateArticleProposal(Action, Propose):
|
|
130
134
|
).update_ref(briefing)
|
131
135
|
|
132
136
|
|
133
|
-
class GenerateInitialOutline(Action,
|
137
|
+
class GenerateInitialOutline(Action, Extract):
|
134
138
|
"""Generate the initial article outline based on the article proposal."""
|
135
139
|
|
136
140
|
output_key: str = "initial_article_outline"
|
137
141
|
"""The key of the output data."""
|
138
142
|
|
143
|
+
supervisor: bool = False
|
144
|
+
"""Whether to use the supervisor to fix the outline."""
|
145
|
+
|
146
|
+
extract_kwargs: ValidateKwargs[Optional[ArticleOutline]] = Field(default_factory=ValidateKwargs)
|
147
|
+
"""The kwargs to extract the outline."""
|
148
|
+
|
139
149
|
async def _execute(
|
140
150
|
self,
|
141
151
|
article_proposal: ArticleProposal,
|
142
152
|
**_,
|
143
153
|
) -> Optional[ArticleOutline]:
|
144
154
|
raw_outline = await self.aask(
|
145
|
-
f"{(article_proposal.as_prompt())}\n
|
155
|
+
f"{(article_proposal.as_prompt())}\n"
|
146
156
|
f"Design each chapter of a proper and academic and ready for release manner.\n"
|
147
157
|
f"You Must make sure every chapter have sections, and every section have subsections.\n"
|
148
|
-
f"Make the chapter and sections and subsections bing divided into a specific enough article component
|
158
|
+
f"Make the chapter and sections and subsections bing divided into a specific enough article component.\n"
|
159
|
+
f"Every chapter must have sections, every section must have subsections.\n"
|
160
|
+
f"Note that you SHALL use `{article_proposal.language}` as written language",
|
149
161
|
)
|
150
162
|
|
163
|
+
if self.supervisor:
|
164
|
+
from questionary import confirm, text
|
165
|
+
|
166
|
+
r_print(raw_outline)
|
167
|
+
while not await confirm("Accept this version and continue?", default=True).ask_async():
|
168
|
+
imp = await text("Enter the improvement:").ask_async()
|
169
|
+
raw_outline = await self.aask(
|
170
|
+
f"{article_proposal.as_prompt()}\n{wrapp_in_block(raw_outline, 'Previous ArticleOutline')}\n{imp}"
|
171
|
+
)
|
172
|
+
r_print(raw_outline)
|
173
|
+
|
151
174
|
return ok(
|
152
|
-
await self.
|
153
|
-
ArticleOutline,
|
154
|
-
f"{raw_outline}\n\n\n\noutline provided above is the outline i need to extract to a JSON,",
|
155
|
-
),
|
175
|
+
await self.extract(ArticleOutline, raw_outline, **self.extract_kwargs),
|
156
176
|
"Could not generate the initial outline.",
|
157
177
|
).update_ref(article_proposal)
|
158
178
|
|
@@ -226,3 +246,12 @@ class GenerateArticle(Action, Censor):
|
|
226
246
|
)
|
227
247
|
|
228
248
|
return article
|
249
|
+
|
250
|
+
|
251
|
+
class LoadArticle(Action):
|
252
|
+
"""Load the article from the outline and typst code."""
|
253
|
+
|
254
|
+
output_key: str = "loaded_article"
|
255
|
+
|
256
|
+
async def _execute(self, article_outline: ArticleOutline, typst_code: str, **cxt) -> Article:
|
257
|
+
return Article.from_mixed_source(article_outline, typst_code)
|
@@ -6,15 +6,121 @@ from typing import List, Optional
|
|
6
6
|
|
7
7
|
from fabricatio import BibManager
|
8
8
|
from fabricatio.capabilities.censor import Censor
|
9
|
+
from fabricatio.capabilities.extract import Extract
|
9
10
|
from fabricatio.capabilities.rag import RAG
|
11
|
+
from fabricatio.journal import logger
|
10
12
|
from fabricatio.models.action import Action
|
11
|
-
from fabricatio.models.extra.aricle_rag import ArticleChunk
|
13
|
+
from fabricatio.models.extra.aricle_rag import ArticleChunk, CitationManager
|
12
14
|
from fabricatio.models.extra.article_essence import ArticleEssence
|
13
|
-
from fabricatio.models.extra.article_main import Article, ArticleSubsection
|
15
|
+
from fabricatio.models.extra.article_main import Article, ArticleChapter, ArticleSection, ArticleSubsection
|
16
|
+
from fabricatio.models.extra.article_outline import ArticleOutline
|
14
17
|
from fabricatio.models.extra.rule import RuleSet
|
15
18
|
from fabricatio.utils import ok
|
16
19
|
|
17
20
|
|
21
|
+
class WriteArticleContentRAG(Action, RAG, Extract):
|
22
|
+
"""Write an article based on the provided outline."""
|
23
|
+
|
24
|
+
ref_limit: int = 35
|
25
|
+
"""The limit of references to be retrieved"""
|
26
|
+
extractor_model: str
|
27
|
+
"""The model to use for extracting the content from the retrieved references."""
|
28
|
+
query_model: str
|
29
|
+
"""The model to use for querying the database"""
|
30
|
+
|
31
|
+
req: str = (
|
32
|
+
"citation number is REQUIRED to cite any reference!\n"
|
33
|
+
"Everything is build upon the typst language, which is similar to latex, \n"
|
34
|
+
"Legal citing syntax examples(seperated by |): [[1]]|[[1,2]]|[[1-3]]|[[12,13-15]]|[[1-3,5-7]]\n"
|
35
|
+
"Illegal citing syntax examples(seperated by |): [[1],[2],[3]]|[[1],[1-2]]\n"
|
36
|
+
"Those reference mark shall not be omitted during the extraction\n"
|
37
|
+
"It's recommended to cite multiple references that supports your conclusion at a time.\n"
|
38
|
+
"Wrapp inline expression using $ $, and wrapp block equation using $$ $$."
|
39
|
+
"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 `>`,"
|
40
|
+
"you can refer to that label by using the syntax with prefix of `@eqt:`"
|
41
|
+
"Below is a usage example:\n"
|
42
|
+
"```typst\n"
|
43
|
+
"See @eqt:mass-energy-equation , it's the equation.\n"
|
44
|
+
"$$\n"
|
45
|
+
"E = m c^2"
|
46
|
+
"$$\n"
|
47
|
+
"<mass-energy-equation>"
|
48
|
+
"In @eqt:mass-energy-equation , we get the foundation of physics.\n"
|
49
|
+
"```"
|
50
|
+
)
|
51
|
+
|
52
|
+
async def _execute(
|
53
|
+
self,
|
54
|
+
article_outline: ArticleOutline,
|
55
|
+
writing_ruleset: RuleSet,
|
56
|
+
collection_name: str = "article_chunks",
|
57
|
+
**cxt,
|
58
|
+
) -> Article:
|
59
|
+
article = Article.from_outline(article_outline).update_ref(article_outline)
|
60
|
+
await gather(
|
61
|
+
*[
|
62
|
+
self._inner(article, article_outline, chap, sec, subsec)
|
63
|
+
for chap, sec, subsec in article.iter_subsections()
|
64
|
+
]
|
65
|
+
)
|
66
|
+
return article.convert_tex()
|
67
|
+
|
68
|
+
async def _inner(
|
69
|
+
self,
|
70
|
+
article: Article,
|
71
|
+
article_outline: ArticleOutline,
|
72
|
+
chap: ArticleChapter,
|
73
|
+
sec: ArticleSection,
|
74
|
+
subsec: ArticleSubsection,
|
75
|
+
) -> ArticleSubsection:
|
76
|
+
ref_q = ok(
|
77
|
+
await self.arefined_query(
|
78
|
+
f"{article_outline.display()}\n\nAbove is my article outline, I m writing graduate thesis titled `{article.title}`. "
|
79
|
+
f"More specifically, i m witting the Chapter `{chap.title}` >> Section `{sec.title}` >> Subsection `{subsec.title}`.\n"
|
80
|
+
f"I need to search related references to build up the content of the subsec mentioned above, which is `{subsec.title}`.\n"
|
81
|
+
f"plus, you can search required formulas by using latex equation code.\n"
|
82
|
+
f"provide 10 queries as possible, to get best result!\n"
|
83
|
+
f"You should provide both English version and chinese version of the refined queries!\n",
|
84
|
+
model=self.query_model,
|
85
|
+
),
|
86
|
+
"Failed to refine query.",
|
87
|
+
)
|
88
|
+
ret = await self.aretrieve(ref_q, ArticleChunk, final_limit=self.ref_limit, result_per_query=6)
|
89
|
+
ret.reverse()
|
90
|
+
cm = CitationManager().update_chunks(ret)
|
91
|
+
|
92
|
+
raw_paras = await self.aask(
|
93
|
+
f"{cm.as_prompt()}\nAbove is some related reference retrieved for you."
|
94
|
+
f"{article.referenced.display()}\n\nAbove is my article outline, I m writing graduate thesis titled `{article.title}`. "
|
95
|
+
f"More specifically, i m witting the Chapter `{chap.title}` >> Section `{sec.title}` >> Subsection `{subsec.title}`.\n"
|
96
|
+
f"Please help me write the paragraphs of the subsec mentioned above, which is `{subsec.title}`.\n"
|
97
|
+
f"{self.req}\n"
|
98
|
+
f"You SHALL use `{article.language}` as writing language."
|
99
|
+
)
|
100
|
+
|
101
|
+
raw_paras = (
|
102
|
+
raw_paras.replace(r" \( ", "$").replace(r" \) ", "$").replace("\\[\n", "$$\n").replace("\n\\]", "\n$$")
|
103
|
+
)
|
104
|
+
|
105
|
+
new_subsec = ok(
|
106
|
+
await self.extract(
|
107
|
+
ArticleSubsection,
|
108
|
+
raw_paras,
|
109
|
+
f"Above is the subsection titled `{subsec.title}`.\n"
|
110
|
+
f"I need you to extract the content to update my subsection obj provided below.\n{self.req}"
|
111
|
+
f"{subsec.display()}\n",
|
112
|
+
),
|
113
|
+
"Failed to propose new subsection.",
|
114
|
+
)
|
115
|
+
|
116
|
+
for p in new_subsec.paragraphs:
|
117
|
+
p.content = cm.apply(p.content).replace("$$", "\n$$\n")
|
118
|
+
|
119
|
+
subsec.update_from(new_subsec)
|
120
|
+
logger.debug(f"{subsec.title}:rpl\n{subsec.display()}")
|
121
|
+
return subsec
|
122
|
+
|
123
|
+
|
18
124
|
class TweakArticleRAG(Action, RAG, Censor):
|
19
125
|
"""Write an article based on the provided outline.
|
20
126
|
|
@@ -43,7 +149,7 @@ class TweakArticleRAG(Action, RAG, Censor):
|
|
43
149
|
twk_rag_ruleset: Optional[RuleSet] = None,
|
44
150
|
parallel: bool = False,
|
45
151
|
**cxt,
|
46
|
-
) ->
|
152
|
+
) -> Article:
|
47
153
|
"""Write an article based on the provided outline.
|
48
154
|
|
49
155
|
This method processes the article outline, either in parallel or sequentially, by enhancing each subsection
|
@@ -57,7 +163,7 @@ class TweakArticleRAG(Action, RAG, Censor):
|
|
57
163
|
**cxt: Additional context parameters.
|
58
164
|
|
59
165
|
Returns:
|
60
|
-
|
166
|
+
Article: The processed article with enhanced subsections and applied censoring rules.
|
61
167
|
"""
|
62
168
|
self.view(collection_name)
|
63
169
|
|
@@ -90,12 +196,7 @@ class TweakArticleRAG(Action, RAG, Censor):
|
|
90
196
|
"""
|
91
197
|
refind_q = ok(
|
92
198
|
await self.arefined_query(
|
93
|
-
f"{article.referenced.as_prompt()}\n"
|
94
|
-
f"# Subsection requiring reference enhancement\n"
|
95
|
-
f"{subsec.display()}\n"
|
96
|
-
f"# Requirement\n"
|
97
|
-
f"Search related articles in the base to find reference candidates, "
|
98
|
-
f"provide queries in both `English` and `{subsec.language}` can get more accurate results.",
|
199
|
+
f"{article.referenced.as_prompt()}\n# Subsection requiring reference enhancement\n{subsec.display()}\n"
|
99
200
|
)
|
100
201
|
)
|
101
202
|
await self.censor_obj_inplace(
|
@@ -112,7 +213,7 @@ class TweakArticleRAG(Action, RAG, Censor):
|
|
112
213
|
class ChunkArticle(Action):
|
113
214
|
"""Chunk an article into smaller chunks."""
|
114
215
|
|
115
|
-
output_key:str = "article_chunks"
|
216
|
+
output_key: str = "article_chunks"
|
116
217
|
"""The key used to store the output of the action."""
|
117
218
|
max_chunk_size: Optional[int] = None
|
118
219
|
"""The maximum size of each chunk."""
|
@@ -131,6 +232,7 @@ class ChunkArticle(Action):
|
|
131
232
|
article_path,
|
132
233
|
bib_manager,
|
133
234
|
max_chunk_size=ok(max_chunk_size or self.max_chunk_size, "No max_chunk_size provided!"),
|
134
|
-
max_overlapping_rate=ok(
|
235
|
+
max_overlapping_rate=ok(
|
236
|
+
max_overlapping_rate or self.max_overlapping_rate, "No max_overlapping_rate provided!"
|
237
|
+
),
|
135
238
|
)
|
136
|
-
|
fabricatio/actions/fs.py
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
"""A module for file system utilities."""
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Any, List, Mapping, Self
|
5
|
+
|
6
|
+
from fabricatio.fs import safe_text_read
|
7
|
+
from fabricatio.journal import logger
|
8
|
+
from fabricatio.models.action import Action
|
9
|
+
from fabricatio.models.generic import FromMapping
|
10
|
+
|
11
|
+
|
12
|
+
class ReadText(Action, FromMapping):
|
13
|
+
"""Read text from a file."""
|
14
|
+
output_key: str = "read_text"
|
15
|
+
read_path: str | Path
|
16
|
+
"""Path to the file to read."""
|
17
|
+
|
18
|
+
async def _execute(self, *_: Any, **cxt) -> str:
|
19
|
+
logger.info(f"Read text from {Path(self.read_path).as_posix()} to {self.output_key}")
|
20
|
+
return safe_text_read(self.read_path)
|
21
|
+
|
22
|
+
@classmethod
|
23
|
+
def from_mapping(cls, mapping: Mapping[str, str | Path], **kwargs: Any) -> List[Self]:
|
24
|
+
"""Create a list of ReadText actions from a mapping of output_key to read_path."""
|
25
|
+
return [cls(read_path=p, output_key=k, **kwargs) for k, p in mapping.items()]
|
fabricatio/actions/output.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
"""Dump the finalized output to a file."""
|
2
2
|
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import Any, Iterable, List, Optional, Type
|
4
|
+
from typing import Any, Iterable, List, Mapping, Optional, Type
|
5
5
|
|
6
6
|
from fabricatio.journal import logger
|
7
7
|
from fabricatio.models.action import Action
|
8
|
-
from fabricatio.models.generic import FinalizedDumpAble, PersistentAble
|
8
|
+
from fabricatio.models.generic import FinalizedDumpAble, FromMapping, PersistentAble
|
9
9
|
from fabricatio.models.task import Task
|
10
10
|
from fabricatio.utils import ok
|
11
11
|
|
@@ -115,7 +115,7 @@ class RetrieveFromPersistent[T: PersistentAble](Action):
|
|
115
115
|
return self.retrieve_cls.from_persistent(self.load_path)
|
116
116
|
|
117
117
|
|
118
|
-
class RetrieveFromLatest[T: PersistentAble](RetrieveFromPersistent[T]):
|
118
|
+
class RetrieveFromLatest[T: PersistentAble](RetrieveFromPersistent[T], FromMapping):
|
119
119
|
"""Retrieve the object from the latest persistent file in the dir at `load_path`."""
|
120
120
|
|
121
121
|
async def _execute(self, /, **_) -> Optional[T]:
|
@@ -130,6 +130,20 @@ class RetrieveFromLatest[T: PersistentAble](RetrieveFromPersistent[T]):
|
|
130
130
|
logger.error(f"Path {self.load_path} is not a directory")
|
131
131
|
return None
|
132
132
|
|
133
|
+
@classmethod
|
134
|
+
def from_mapping(
|
135
|
+
cls,
|
136
|
+
mapping: Mapping[str, str | Path],
|
137
|
+
*,
|
138
|
+
retrieve_cls: Type[T],
|
139
|
+
**kwargs,
|
140
|
+
) -> List["RetrieveFromLatest[T]"]:
|
141
|
+
"""Create a list of `RetrieveFromLatest` from the mapping."""
|
142
|
+
return [
|
143
|
+
cls(retrieve_cls=retrieve_cls, load_path=Path(p).as_posix(), output_key=o, **kwargs)
|
144
|
+
for o, p in mapping.items()
|
145
|
+
]
|
146
|
+
|
133
147
|
|
134
148
|
class GatherAsList(Action):
|
135
149
|
"""Gather the objects from the context as a list.
|
fabricatio/actions/rag.py
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
from typing import List, Optional
|
4
4
|
|
5
|
-
from questionary import text
|
6
|
-
|
7
5
|
from fabricatio.capabilities.rag import RAG
|
8
6
|
from fabricatio.config import configs
|
9
7
|
from fabricatio.journal import logger
|
@@ -21,7 +19,7 @@ class InjectToDB(Action, RAG):
|
|
21
19
|
"""The name of the collection to inject data into."""
|
22
20
|
|
23
21
|
async def _execute[T: MilvusDataBase](
|
24
|
-
|
22
|
+
self, to_inject: Optional[T] | List[Optional[T]], override_inject: bool = False, **_
|
25
23
|
) -> Optional[str]:
|
26
24
|
from pymilvus.milvus_client import IndexParams
|
27
25
|
|
@@ -74,6 +72,8 @@ class RAGTalk(Action, RAG):
|
|
74
72
|
output_key: str = "task_output"
|
75
73
|
|
76
74
|
async def _execute(self, task_input: Task[str], **kwargs) -> int:
|
75
|
+
from questionary import text
|
76
|
+
|
77
77
|
collection_name = kwargs.get("collection_name", "my_collection")
|
78
78
|
counter = 0
|
79
79
|
|
fabricatio/actions/rules.py
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
"""A module containing the DraftRuleSet action."""
|
2
2
|
|
3
|
-
from typing import List, Optional
|
3
|
+
from typing import Any, List, Mapping, Optional, Self, Tuple
|
4
4
|
|
5
5
|
from fabricatio.capabilities.check import Check
|
6
6
|
from fabricatio.journal import logger
|
7
7
|
from fabricatio.models.action import Action
|
8
8
|
from fabricatio.models.extra.rule import RuleSet
|
9
|
+
from fabricatio.models.generic import FromMapping
|
9
10
|
from fabricatio.utils import ok
|
10
11
|
|
11
12
|
|
12
|
-
class DraftRuleSet(Action, Check):
|
13
|
+
class DraftRuleSet(Action, Check, FromMapping):
|
13
14
|
"""Action to draft a ruleset based on a given requirement description."""
|
14
15
|
|
15
16
|
output_key: str = "drafted_ruleset"
|
@@ -45,8 +46,13 @@ class DraftRuleSet(Action, Check):
|
|
45
46
|
logger.warning(f"Drafting Rule Failed for:\n{ruleset_requirement}")
|
46
47
|
return ruleset
|
47
48
|
|
49
|
+
@classmethod
|
50
|
+
def from_mapping(cls, mapping: Mapping[str, Tuple[int, str]], **kwargs) -> List[Self]:
|
51
|
+
"""Create a list of DraftRuleSet actions from a mapping of output keys to tuples of rule counts and requirements."""
|
52
|
+
return [cls(ruleset_requirement=r, rule_count=c, output_key=k, **kwargs) for k, (c, r) in mapping.items()]
|
48
53
|
|
49
|
-
|
54
|
+
|
55
|
+
class GatherRuleset(Action, FromMapping):
|
50
56
|
"""Action to gather a ruleset from a given requirement description."""
|
51
57
|
|
52
58
|
output_key: str = "gathered_ruleset"
|
@@ -55,6 +61,11 @@ class GatherRuleset(Action):
|
|
55
61
|
to_gather: List[str]
|
56
62
|
"""the cxt name of RuleSet to gather"""
|
57
63
|
|
64
|
+
@classmethod
|
65
|
+
def from_mapping(cls, mapping: Mapping[str, List[str]], **kwargs: Any) -> List[Self]:
|
66
|
+
"""Create a list of GatherRuleset actions from a mapping of output keys to tuples of rule counts and requirements."""
|
67
|
+
return [cls(to_gather=t, output_key=k, **kwargs) for k, t in mapping.items()]
|
68
|
+
|
58
69
|
async def _execute(self, **cxt) -> RuleSet:
|
59
70
|
logger.info(f"Gathering Ruleset from {self.to_gather}")
|
60
71
|
# Fix for not_found
|
@@ -0,0 +1,70 @@
|
|
1
|
+
"""A module that provide capabilities for extracting information from a given source to a model."""
|
2
|
+
|
3
|
+
from typing import List, Optional, Type, Unpack, overload
|
4
|
+
|
5
|
+
from fabricatio import TEMPLATE_MANAGER
|
6
|
+
from fabricatio.capabilities.propose import Propose
|
7
|
+
from fabricatio.config import configs
|
8
|
+
from fabricatio.models.generic import ProposedAble
|
9
|
+
from fabricatio.models.kwargs_types import ValidateKwargs
|
10
|
+
|
11
|
+
|
12
|
+
class Extract(Propose):
|
13
|
+
"""A class that extract information from a given source to a model."""
|
14
|
+
|
15
|
+
@overload
|
16
|
+
async def extract[M: ProposedAble](
|
17
|
+
self,
|
18
|
+
cls: Type[M],
|
19
|
+
source: str,
|
20
|
+
extract_requirement: Optional[str] = None,
|
21
|
+
align_language: bool = True,
|
22
|
+
**kwargs: Unpack[ValidateKwargs[M]],
|
23
|
+
) -> M: ...
|
24
|
+
@overload
|
25
|
+
async def extract[M: ProposedAble](
|
26
|
+
self,
|
27
|
+
cls: Type[M],
|
28
|
+
source: str,
|
29
|
+
extract_requirement: Optional[str] = None,
|
30
|
+
align_language: bool = True,
|
31
|
+
**kwargs: Unpack[ValidateKwargs[None]],
|
32
|
+
) -> Optional[M]: ...
|
33
|
+
|
34
|
+
@overload
|
35
|
+
async def extract[M: ProposedAble](
|
36
|
+
self,
|
37
|
+
cls: Type[M],
|
38
|
+
source: List[str],
|
39
|
+
extract_requirement: Optional[str] = None,
|
40
|
+
align_language: bool = True,
|
41
|
+
**kwargs: Unpack[ValidateKwargs[M]],
|
42
|
+
) -> List[M]: ...
|
43
|
+
@overload
|
44
|
+
async def extract[M: ProposedAble](
|
45
|
+
self,
|
46
|
+
cls: Type[M],
|
47
|
+
source: List[str],
|
48
|
+
extract_requirement: Optional[str] = None,
|
49
|
+
align_language: bool = True,
|
50
|
+
**kwargs: Unpack[ValidateKwargs[None]],
|
51
|
+
) -> List[Optional[M]]: ...
|
52
|
+
async def extract[M: ProposedAble](
|
53
|
+
self,
|
54
|
+
cls: Type[M],
|
55
|
+
source: List[str] | str,
|
56
|
+
extract_requirement: Optional[str] = None,
|
57
|
+
align_language: bool = True,
|
58
|
+
**kwargs: Unpack[ValidateKwargs[Optional[M]]],
|
59
|
+
) -> M | List[M] | Optional[M] | List[Optional[M]]:
|
60
|
+
"""Extract information from a given source to a model."""
|
61
|
+
return await self.propose(
|
62
|
+
cls,
|
63
|
+
prompt=TEMPLATE_MANAGER.render_template(
|
64
|
+
configs.templates.extract_template,
|
65
|
+
[{"source": s, "extract_requirement": extract_requirement} for s in source]
|
66
|
+
if isinstance(source, list)
|
67
|
+
else {"source": source, "extract_requirement": extract_requirement, "align_language": align_language},
|
68
|
+
),
|
69
|
+
**kwargs,
|
70
|
+
)
|
@@ -14,7 +14,7 @@ from fabricatio.models.generic import Display, ProposedAble
|
|
14
14
|
from fabricatio.models.kwargs_types import CompositeScoreKwargs, ValidateKwargs
|
15
15
|
from fabricatio.parser import JsonCapture
|
16
16
|
from fabricatio.rust_instances import TEMPLATE_MANAGER
|
17
|
-
from fabricatio.utils import
|
17
|
+
from fabricatio.utils import ok, override_kwargs
|
18
18
|
|
19
19
|
|
20
20
|
class Rating(Propose):
|
@@ -137,7 +137,7 @@ class Rating(Propose):
|
|
137
137
|
or dict(zip(criteria, criteria, strict=True))
|
138
138
|
)
|
139
139
|
|
140
|
-
return await self.rate_fine_grind(to_rate, manual, score_range, **
|
140
|
+
return await self.rate_fine_grind(to_rate, manual, score_range, **kwargs)
|
141
141
|
|
142
142
|
async def draft_rating_manual(
|
143
143
|
self, topic: str, criteria: Optional[Set[str]] = None, **kwargs: Unpack[ValidateKwargs[Dict[str, str]]]
|
@@ -338,6 +338,7 @@ class Rating(Propose):
|
|
338
338
|
criteria: Optional[Set[str]] = None,
|
339
339
|
weights: Optional[Dict[str, float]] = None,
|
340
340
|
manual: Optional[Dict[str, str]] = None,
|
341
|
+
approx: bool = False,
|
341
342
|
**kwargs: Unpack[ValidateKwargs[List[Dict[str, float]]]],
|
342
343
|
) -> List[float]:
|
343
344
|
"""Calculates the composite scores for a list of items based on a given topic and criteria.
|
@@ -348,6 +349,7 @@ class Rating(Propose):
|
|
348
349
|
criteria (Optional[Set[str]]): A set of criteria for the rating. Defaults to None.
|
349
350
|
weights (Optional[Dict[str, float]]): A dictionary of rating weights for each criterion. Defaults to None.
|
350
351
|
manual (Optional[Dict[str, str]]): A dictionary of manual ratings for each item. Defaults to None.
|
352
|
+
approx (bool): Whether to use approximate rating criteria. Defaults to False.
|
351
353
|
**kwargs (Unpack[ValidateKwargs]): Additional keyword arguments for the LLM usage.
|
352
354
|
|
353
355
|
Returns:
|
@@ -355,6 +357,7 @@ class Rating(Propose):
|
|
355
357
|
"""
|
356
358
|
criteria = ok(
|
357
359
|
criteria
|
360
|
+
or (await self.draft_rating_criteria(topic, **override_kwargs(kwargs, default=None)) if approx else None)
|
358
361
|
or await self.draft_rating_criteria_from_examples(topic, to_rate, **override_kwargs(kwargs, default=None))
|
359
362
|
)
|
360
363
|
weights = ok(
|
fabricatio/capabilities/task.py
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
from types import CodeType
|
4
4
|
from typing import Any, Dict, List, Optional, Tuple, Unpack
|
5
5
|
|
6
|
-
import
|
6
|
+
import ujson
|
7
7
|
|
8
8
|
from fabricatio.capabilities.propose import Propose
|
9
9
|
from fabricatio.config import configs
|
@@ -20,9 +20,9 @@ class ProposeTask(Propose):
|
|
20
20
|
"""A class that proposes a task based on a prompt."""
|
21
21
|
|
22
22
|
async def propose_task[T](
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
self,
|
24
|
+
prompt: str,
|
25
|
+
**kwargs: Unpack[ValidateKwargs[Task[T]]],
|
26
26
|
) -> Optional[Task[T]]:
|
27
27
|
"""Asynchronously proposes a task based on a given prompt and parameters.
|
28
28
|
|
@@ -44,11 +44,11 @@ class HandleTask(ToolBoxUsage):
|
|
44
44
|
"""A class that handles a task based on a task object."""
|
45
45
|
|
46
46
|
async def draft_tool_usage_code(
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
self,
|
48
|
+
task: Task,
|
49
|
+
tools: List[Tool],
|
50
|
+
data: Dict[str, Any],
|
51
|
+
**kwargs: Unpack[ValidateKwargs],
|
52
52
|
) -> Optional[Tuple[CodeType, List[str]]]:
|
53
53
|
"""Asynchronously drafts the tool usage code for a task based on a given task object and tools."""
|
54
54
|
logger.info(f"Drafting tool usage code for task: {task.briefing}")
|
@@ -60,7 +60,7 @@ class HandleTask(ToolBoxUsage):
|
|
60
60
|
|
61
61
|
def _validator(response: str) -> Tuple[CodeType, List[str]] | None:
|
62
62
|
if (source := PythonCapture.convert_with(response, lambda resp: compile(resp, "<string>", "exec"))) and (
|
63
|
-
|
63
|
+
to_extract := JsonCapture.convert_with(response, ujson.loads)
|
64
64
|
):
|
65
65
|
return source, to_extract
|
66
66
|
|
@@ -85,12 +85,12 @@ class HandleTask(ToolBoxUsage):
|
|
85
85
|
)
|
86
86
|
|
87
87
|
async def handle_fine_grind(
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
88
|
+
self,
|
89
|
+
task: Task,
|
90
|
+
data: Dict[str, Any],
|
91
|
+
box_choose_kwargs: Optional[ChooseKwargs] = None,
|
92
|
+
tool_choose_kwargs: Optional[ChooseKwargs] = None,
|
93
|
+
**kwargs: Unpack[ValidateKwargs],
|
94
94
|
) -> Optional[Tuple]:
|
95
95
|
"""Asynchronously handles a task based on a given task object and parameters."""
|
96
96
|
logger.info(f"Handling task: \n{task.briefing}")
|
fabricatio/config.py
CHANGED
@@ -86,8 +86,10 @@ class LLMConfig(BaseModel):
|
|
86
86
|
|
87
87
|
tpm: Optional[PositiveInt] = Field(default=1000000)
|
88
88
|
"""The rate limit of the LLM model in tokens per minute. None means not checked."""
|
89
|
-
|
90
|
-
|
89
|
+
presence_penalty:Optional[PositiveFloat]=None
|
90
|
+
"""The presence penalty of the LLM model."""
|
91
|
+
frequency_penalty:Optional[PositiveFloat]=None
|
92
|
+
"""The frequency penalty of the LLM model."""
|
91
93
|
class EmbeddingConfig(BaseModel):
|
92
94
|
"""Embedding configuration class."""
|
93
95
|
|
@@ -249,6 +251,11 @@ class TemplateConfig(BaseModel):
|
|
249
251
|
|
250
252
|
rule_requirement_template: str = Field(default="rule_requirement")
|
251
253
|
"""The name of the rule requirement template which will be used to generate a rule requirement."""
|
254
|
+
|
255
|
+
|
256
|
+
extract_template: str = Field(default="extract")
|
257
|
+
"""The name of the extract template which will be used to extract model from string."""
|
258
|
+
|
252
259
|
class MagikaConfig(BaseModel):
|
253
260
|
"""Magika configuration class."""
|
254
261
|
|