fabricatio 0.2.3.dev3__cp312-cp312-win_amd64.whl → 0.2.4__cp312-cp312-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fabricatio/__init__.py +18 -5
- fabricatio/_rust.cp312-win_amd64.pyd +0 -0
- fabricatio/actions/article.py +81 -0
- fabricatio/actions/output.py +21 -0
- fabricatio/actions/rag.py +25 -0
- fabricatio/capabilities/propose.py +55 -0
- fabricatio/capabilities/rag.py +193 -52
- fabricatio/capabilities/rating.py +12 -36
- fabricatio/capabilities/task.py +6 -23
- fabricatio/config.py +43 -2
- fabricatio/fs/__init__.py +24 -2
- fabricatio/fs/curd.py +14 -8
- fabricatio/fs/readers.py +5 -2
- fabricatio/models/action.py +19 -4
- fabricatio/models/events.py +36 -0
- fabricatio/models/extra.py +168 -0
- fabricatio/models/generic.py +218 -7
- fabricatio/models/kwargs_types.py +15 -0
- fabricatio/models/task.py +5 -37
- fabricatio/models/tool.py +3 -2
- fabricatio/models/usages.py +153 -184
- fabricatio/models/utils.py +19 -0
- fabricatio/parser.py +35 -8
- fabricatio/toolboxes/__init__.py +1 -3
- fabricatio/toolboxes/fs.py +15 -1
- fabricatio/workflows/articles.py +15 -0
- fabricatio/workflows/rag.py +11 -0
- fabricatio-0.2.4.data/scripts/tdown.exe +0 -0
- {fabricatio-0.2.3.dev3.dist-info → fabricatio-0.2.4.dist-info}/METADATA +66 -178
- fabricatio-0.2.4.dist-info/RECORD +40 -0
- fabricatio/actions/__init__.py +0 -5
- fabricatio/actions/communication.py +0 -15
- fabricatio/actions/transmission.py +0 -23
- fabricatio/toolboxes/task.py +0 -6
- fabricatio-0.2.3.dev3.data/scripts/tdown.exe +0 -0
- fabricatio-0.2.3.dev3.dist-info/RECORD +0 -37
- {fabricatio-0.2.3.dev3.dist-info → fabricatio-0.2.4.dist-info}/WHEEL +0 -0
- {fabricatio-0.2.3.dev3.dist-info → fabricatio-0.2.4.dist-info}/licenses/LICENSE +0 -0
@@ -131,8 +131,7 @@ class GiveRating(WithBriefing, LLMUsage):
|
|
131
131
|
|
132
132
|
def _validator(response: str) -> Dict[str, str] | None:
|
133
133
|
if (
|
134
|
-
(json_data := JsonCapture.
|
135
|
-
and isinstance(json_data, dict)
|
134
|
+
(json_data := JsonCapture.validate_with(response, target_type=dict, elements_type=str)) is not None
|
136
135
|
and json_data.keys() == criteria
|
137
136
|
and all(isinstance(v, str) for v in json_data.values())
|
138
137
|
):
|
@@ -173,11 +172,10 @@ class GiveRating(WithBriefing, LLMUsage):
|
|
173
172
|
|
174
173
|
def _validator(response: str) -> Set[str] | None:
|
175
174
|
if (
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
):
|
175
|
+
json_data := JsonCapture.validate_with(
|
176
|
+
response, target_type=list, elements_type=str, length=criteria_count
|
177
|
+
)
|
178
|
+
) is not None:
|
181
179
|
return set(json_data)
|
182
180
|
return None
|
183
181
|
|
@@ -219,27 +217,6 @@ class GiveRating(WithBriefing, LLMUsage):
|
|
219
217
|
Returns:
|
220
218
|
Set[str]: A set of drafted rating criteria.
|
221
219
|
"""
|
222
|
-
|
223
|
-
def _reasons_validator(response: str) -> List[str] | None:
|
224
|
-
if (
|
225
|
-
(json_data := JsonCapture.convert_with(response, orjson.loads)) is not None
|
226
|
-
and isinstance(json_data, list)
|
227
|
-
and all(isinstance(v, str) for v in json_data)
|
228
|
-
and len(json_data) == reasons_count
|
229
|
-
):
|
230
|
-
return json_data
|
231
|
-
return None
|
232
|
-
|
233
|
-
def _criteria_validator(response: str) -> Set[str] | None:
|
234
|
-
if (
|
235
|
-
(json_data := JsonCapture.convert_with(response, orjson.loads)) is not None
|
236
|
-
and isinstance(json_data, list)
|
237
|
-
and all(isinstance(v, str) for v in json_data)
|
238
|
-
and len(json_data) == criteria_count
|
239
|
-
):
|
240
|
-
return set(json_data)
|
241
|
-
return None
|
242
|
-
|
243
220
|
kwargs = GenerateKwargs(system_message=f"# your personal briefing: \n{self.briefing}", **kwargs)
|
244
221
|
# extract reasons from the comparison of ordered pairs of extracted from examples
|
245
222
|
reasons = flatten(
|
@@ -256,7 +233,9 @@ class GiveRating(WithBriefing, LLMUsage):
|
|
256
233
|
)
|
257
234
|
for pair in (permutations(examples, 2))
|
258
235
|
],
|
259
|
-
validator=
|
236
|
+
validator=lambda resp: JsonCapture.validate_with(
|
237
|
+
resp, target_type=list, elements_type=str, length=reasons_count
|
238
|
+
),
|
260
239
|
**kwargs,
|
261
240
|
)
|
262
241
|
)
|
@@ -272,7 +251,9 @@ class GiveRating(WithBriefing, LLMUsage):
|
|
272
251
|
},
|
273
252
|
)
|
274
253
|
),
|
275
|
-
validator=
|
254
|
+
validator=lambda resp: set(out)
|
255
|
+
if (out := JsonCapture.validate_with(resp, target_type=list, elements_type=str, length=criteria_count))
|
256
|
+
else None,
|
276
257
|
**kwargs,
|
277
258
|
)
|
278
259
|
|
@@ -295,11 +276,6 @@ class GiveRating(WithBriefing, LLMUsage):
|
|
295
276
|
if len(criteria) < 2: # noqa: PLR2004
|
296
277
|
raise ValueError("At least two criteria are required to draft rating weights")
|
297
278
|
|
298
|
-
def _validator(resp: str) -> float | None:
|
299
|
-
if (cap := JsonCapture.convert_with(resp, orjson.loads)) is not None and isinstance(cap, float):
|
300
|
-
return cap
|
301
|
-
return None
|
302
|
-
|
303
279
|
criteria = list(criteria) # freeze the order
|
304
280
|
windows = windowed(criteria, 2)
|
305
281
|
|
@@ -316,7 +292,7 @@ class GiveRating(WithBriefing, LLMUsage):
|
|
316
292
|
)
|
317
293
|
for pair in windows
|
318
294
|
],
|
319
|
-
validator=
|
295
|
+
validator=lambda resp: JsonCapture.validate_with(resp, target_type=float),
|
320
296
|
**GenerateKwargs(system_message=f"# your personal briefing: \n{self.briefing}", **kwargs),
|
321
297
|
)
|
322
298
|
weights = [1]
|
fabricatio/capabilities/task.py
CHANGED
@@ -5,21 +5,21 @@ from typing import Any, Dict, List, Optional, Tuple, Unpack
|
|
5
5
|
|
6
6
|
import orjson
|
7
7
|
from fabricatio._rust_instances import template_manager
|
8
|
+
from fabricatio.capabilities.propose import Propose
|
8
9
|
from fabricatio.config import configs
|
9
10
|
from fabricatio.models.generic import WithBriefing
|
10
11
|
from fabricatio.models.kwargs_types import ChooseKwargs, ValidateKwargs
|
11
12
|
from fabricatio.models.task import Task
|
12
13
|
from fabricatio.models.tool import Tool, ToolExecutor
|
13
|
-
from fabricatio.models.usages import
|
14
|
+
from fabricatio.models.usages import ToolBoxUsage
|
14
15
|
from fabricatio.parser import JsonCapture, PythonCapture
|
15
16
|
from loguru import logger
|
16
|
-
from pydantic import ValidationError
|
17
17
|
|
18
18
|
|
19
|
-
class ProposeTask(WithBriefing,
|
19
|
+
class ProposeTask(WithBriefing, Propose):
|
20
20
|
"""A class that proposes a task based on a prompt."""
|
21
21
|
|
22
|
-
async def
|
22
|
+
async def propose_task[T](
|
23
23
|
self,
|
24
24
|
prompt: str,
|
25
25
|
**kwargs: Unpack[ValidateKwargs],
|
@@ -34,27 +34,10 @@ class ProposeTask(WithBriefing, LLMUsage):
|
|
34
34
|
A Task object based on the proposal result.
|
35
35
|
"""
|
36
36
|
if not prompt:
|
37
|
-
err
|
38
|
-
logger.error(err)
|
37
|
+
logger.error(err := f"{self.name}: Prompt must be provided.")
|
39
38
|
raise ValueError(err)
|
40
39
|
|
41
|
-
|
42
|
-
try:
|
43
|
-
cap = JsonCapture.capture(response)
|
44
|
-
logger.debug(f"Response: \n{response}")
|
45
|
-
logger.info(f"Captured JSON: \n{cap}")
|
46
|
-
return Task.model_validate_json(cap)
|
47
|
-
except ValidationError as e:
|
48
|
-
logger.error(f"Failed to parse task from JSON: {e}")
|
49
|
-
return None
|
50
|
-
|
51
|
-
template_data = {"prompt": prompt, "json_example": Task.json_example()}
|
52
|
-
return await self.aask_validate(
|
53
|
-
question=template_manager.render_template(configs.templates.propose_task_template, template_data),
|
54
|
-
validator=_validate_json,
|
55
|
-
system_message=f"# your personal briefing: \n{self.briefing}",
|
56
|
-
**kwargs,
|
57
|
-
)
|
40
|
+
return await self.propose(Task, prompt, system_message=f"# your personal briefing: \n{self.briefing}", **kwargs)
|
58
41
|
|
59
42
|
|
60
43
|
class HandleTask(WithBriefing, ToolBoxUsage):
|
fabricatio/config.py
CHANGED
@@ -80,6 +80,33 @@ class LLMConfig(BaseModel):
|
|
80
80
|
"""The maximum number of tokens to generate. Set to 8192 as per request."""
|
81
81
|
|
82
82
|
|
83
|
+
class EmbeddingConfig(BaseModel):
|
84
|
+
"""Embedding configuration class."""
|
85
|
+
|
86
|
+
model_config = ConfigDict(use_attribute_docstrings=True)
|
87
|
+
|
88
|
+
model: str = Field(default="text-embedding-ada-002")
|
89
|
+
"""The embedding model name. """
|
90
|
+
|
91
|
+
dimensions: Optional[PositiveInt] = Field(default=None)
|
92
|
+
"""The dimensions of the embedding. None means not checked."""
|
93
|
+
|
94
|
+
timeout: Optional[PositiveInt] = Field(default=None)
|
95
|
+
"""The timeout of the embedding model in seconds."""
|
96
|
+
|
97
|
+
max_sequence_length: PositiveInt = Field(default=8192)
|
98
|
+
"""The maximum sequence length of the embedding model. Default is 8192 as per request."""
|
99
|
+
|
100
|
+
caching: bool = Field(default=False)
|
101
|
+
"""Whether to cache the embedding. Default is False."""
|
102
|
+
|
103
|
+
api_endpoint: Optional[HttpUrl] = None
|
104
|
+
"""The OpenAI API endpoint."""
|
105
|
+
|
106
|
+
api_key: Optional[SecretStr] = None
|
107
|
+
"""The OpenAI API key."""
|
108
|
+
|
109
|
+
|
83
110
|
class PymitterConfig(BaseModel):
|
84
111
|
"""Pymitter configuration class.
|
85
112
|
|
@@ -140,8 +167,8 @@ class TemplateConfig(BaseModel):
|
|
140
167
|
template_suffix: str = Field(default="hbs", frozen=True)
|
141
168
|
"""The suffix of the templates."""
|
142
169
|
|
143
|
-
|
144
|
-
"""The name of the
|
170
|
+
create_json_obj_template: str = Field(default="create_json_obj")
|
171
|
+
"""The name of the create json object template which will be used to create a json object."""
|
145
172
|
|
146
173
|
draft_tool_usage_code_template: str = Field(default="draft_tool_usage_code")
|
147
174
|
"""The name of the draft tool usage code template which will be used to draft tool usage code."""
|
@@ -179,6 +206,15 @@ class TemplateConfig(BaseModel):
|
|
179
206
|
retrieved_display_template: str = Field(default="retrieved_display")
|
180
207
|
"""The name of the retrieved display template which will be used to display retrieved documents."""
|
181
208
|
|
209
|
+
liststr_template: str = Field(default="liststr")
|
210
|
+
"""The name of the liststr template which will be used to display a list of strings."""
|
211
|
+
|
212
|
+
refined_query_template: str = Field(default="refined_query")
|
213
|
+
"""The name of the refined query template which will be used to refine a query."""
|
214
|
+
|
215
|
+
pathstr_template: str = Field(default="pathstr")
|
216
|
+
"""The name of the pathstr template which will be used to acquire a path of strings."""
|
217
|
+
|
182
218
|
|
183
219
|
class MagikaConfig(BaseModel):
|
184
220
|
"""Magika configuration class."""
|
@@ -222,6 +258,8 @@ class RagConfig(BaseModel):
|
|
222
258
|
"""The timeout of the Milvus server."""
|
223
259
|
milvus_token: Optional[SecretStr] = Field(default=None)
|
224
260
|
"""The token of the Milvus server."""
|
261
|
+
milvus_dimensions: Optional[PositiveInt] = Field(default=None)
|
262
|
+
"""The dimensions of the Milvus server."""
|
225
263
|
|
226
264
|
|
227
265
|
class Settings(BaseSettings):
|
@@ -249,6 +287,9 @@ class Settings(BaseSettings):
|
|
249
287
|
llm: LLMConfig = Field(default_factory=LLMConfig)
|
250
288
|
"""LLM Configuration"""
|
251
289
|
|
290
|
+
embedding: EmbeddingConfig = Field(default_factory=EmbeddingConfig)
|
291
|
+
"""Embedding Configuration"""
|
292
|
+
|
252
293
|
debug: DebugConfig = Field(default_factory=DebugConfig)
|
253
294
|
"""Debug Configuration"""
|
254
295
|
|
fabricatio/fs/__init__.py
CHANGED
@@ -1,5 +1,27 @@
|
|
1
1
|
"""FileSystem manipulation module for Fabricatio."""
|
2
2
|
|
3
|
-
from fabricatio.fs.
|
3
|
+
from fabricatio.fs.curd import (
|
4
|
+
absolute_path,
|
5
|
+
copy_file,
|
6
|
+
create_directory,
|
7
|
+
delete_directory,
|
8
|
+
delete_file,
|
9
|
+
dump_text,
|
10
|
+
move_file,
|
11
|
+
tree,
|
12
|
+
)
|
13
|
+
from fabricatio.fs.readers import magika, safe_json_read, safe_text_read
|
4
14
|
|
5
|
-
__all__ = [
|
15
|
+
__all__ = [
|
16
|
+
"absolute_path",
|
17
|
+
"copy_file",
|
18
|
+
"create_directory",
|
19
|
+
"delete_directory",
|
20
|
+
"delete_file",
|
21
|
+
"dump_text",
|
22
|
+
"magika",
|
23
|
+
"move_file",
|
24
|
+
"safe_json_read",
|
25
|
+
"safe_text_read",
|
26
|
+
"tree",
|
27
|
+
]
|
fabricatio/fs/curd.py
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
|
3
3
|
import shutil
|
4
4
|
import subprocess
|
5
|
+
from os import PathLike
|
5
6
|
from pathlib import Path
|
6
7
|
from typing import Union
|
7
8
|
|
8
|
-
from fabricatio.decorators import depend_on_external_cmd
|
9
|
+
from fabricatio.decorators import depend_on_external_cmd
|
9
10
|
from fabricatio.journal import logger
|
10
11
|
|
11
12
|
|
12
|
-
@logging_execution_info
|
13
13
|
def dump_text(path: Union[str, Path], text: str) -> None:
|
14
14
|
"""Dump text to a file. you need to make sure the file's parent directory exists.
|
15
15
|
|
@@ -23,7 +23,6 @@ def dump_text(path: Union[str, Path], text: str) -> None:
|
|
23
23
|
Path(path).write_text(text, encoding="utf-8", errors="ignore")
|
24
24
|
|
25
25
|
|
26
|
-
@logging_execution_info
|
27
26
|
def copy_file(src: Union[str, Path], dst: Union[str, Path]) -> None:
|
28
27
|
"""Copy a file from source to destination.
|
29
28
|
|
@@ -43,7 +42,6 @@ def copy_file(src: Union[str, Path], dst: Union[str, Path]) -> None:
|
|
43
42
|
raise
|
44
43
|
|
45
44
|
|
46
|
-
@logging_execution_info
|
47
45
|
def move_file(src: Union[str, Path], dst: Union[str, Path]) -> None:
|
48
46
|
"""Move a file from source to destination.
|
49
47
|
|
@@ -63,7 +61,6 @@ def move_file(src: Union[str, Path], dst: Union[str, Path]) -> None:
|
|
63
61
|
raise
|
64
62
|
|
65
63
|
|
66
|
-
@logging_execution_info
|
67
64
|
def delete_file(file_path: Union[str, Path]) -> None:
|
68
65
|
"""Delete a file.
|
69
66
|
|
@@ -82,7 +79,6 @@ def delete_file(file_path: Union[str, Path]) -> None:
|
|
82
79
|
raise
|
83
80
|
|
84
81
|
|
85
|
-
@logging_execution_info
|
86
82
|
def create_directory(dir_path: Union[str, Path], parents: bool = True, exist_ok: bool = True) -> None:
|
87
83
|
"""Create a directory.
|
88
84
|
|
@@ -99,7 +95,6 @@ def create_directory(dir_path: Union[str, Path], parents: bool = True, exist_ok:
|
|
99
95
|
raise
|
100
96
|
|
101
97
|
|
102
|
-
@logging_execution_info
|
103
98
|
@depend_on_external_cmd(
|
104
99
|
"erd",
|
105
100
|
"Please install `erd` using `cargo install erdtree` or `scoop install erdtree`.",
|
@@ -111,7 +106,6 @@ def tree(dir_path: Union[str, Path]) -> str:
|
|
111
106
|
return subprocess.check_output(("erd", dir_path.as_posix()), encoding="utf-8") # noqa: S603
|
112
107
|
|
113
108
|
|
114
|
-
@logging_execution_info
|
115
109
|
def delete_directory(dir_path: Union[str, Path]) -> None:
|
116
110
|
"""Delete a directory and its contents.
|
117
111
|
|
@@ -128,3 +122,15 @@ def delete_directory(dir_path: Union[str, Path]) -> None:
|
|
128
122
|
except OSError as e:
|
129
123
|
logger.error(f"Failed to delete directory {dir_path}: {e!s}")
|
130
124
|
raise
|
125
|
+
|
126
|
+
|
127
|
+
def absolute_path(path: str | Path | PathLike) -> str:
|
128
|
+
"""Get the absolute path of a file or directory.
|
129
|
+
|
130
|
+
Args:
|
131
|
+
path (str, Path, PathLike): The path to the file or directory.
|
132
|
+
|
133
|
+
Returns:
|
134
|
+
str: The absolute path of the file or directory.
|
135
|
+
"""
|
136
|
+
return Path(path).expanduser().resolve().as_posix()
|
fabricatio/fs/readers.py
CHANGED
@@ -7,6 +7,7 @@ from magika import Magika
|
|
7
7
|
from orjson import orjson
|
8
8
|
|
9
9
|
from fabricatio.config import configs
|
10
|
+
from fabricatio.journal import logger
|
10
11
|
|
11
12
|
magika = Magika(model_dir=configs.magika.model_dir)
|
12
13
|
|
@@ -23,7 +24,8 @@ def safe_text_read(path: Path | str) -> str:
|
|
23
24
|
path = Path(path)
|
24
25
|
try:
|
25
26
|
return path.read_text(encoding="utf-8")
|
26
|
-
except (UnicodeDecodeError, IsADirectoryError, FileNotFoundError):
|
27
|
+
except (UnicodeDecodeError, IsADirectoryError, FileNotFoundError) as e:
|
28
|
+
logger.error(f"Failed to read file {path}: {e!s}")
|
27
29
|
return ""
|
28
30
|
|
29
31
|
|
@@ -39,5 +41,6 @@ def safe_json_read(path: Path | str) -> Dict:
|
|
39
41
|
path = Path(path)
|
40
42
|
try:
|
41
43
|
return orjson.loads(path.read_text(encoding="utf-8"))
|
42
|
-
except (orjson.JSONDecodeError, IsADirectoryError, FileNotFoundError):
|
44
|
+
except (orjson.JSONDecodeError, IsADirectoryError, FileNotFoundError) as e:
|
45
|
+
logger.error(f"Failed to read file {path}: {e!s}")
|
43
46
|
return {}
|
fabricatio/models/action.py
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
import traceback
|
4
4
|
from abc import abstractmethod
|
5
5
|
from asyncio import Queue, create_task
|
6
|
-
from typing import Any, Dict, Self, Tuple, Type, Union, Unpack
|
6
|
+
from typing import Any, Dict, Self, Tuple, Type, Union, Unpack, final
|
7
7
|
|
8
8
|
from fabricatio.capabilities.rating import GiveRating
|
9
9
|
from fabricatio.capabilities.task import HandleTask, ProposeTask
|
@@ -17,11 +17,25 @@ from pydantic import Field, PrivateAttr
|
|
17
17
|
class Action(HandleTask, ProposeTask, GiveRating):
|
18
18
|
"""Class that represents an action to be executed in a workflow."""
|
19
19
|
|
20
|
+
name: str = Field(default="")
|
21
|
+
"""The name of the action."""
|
22
|
+
description: str = Field(default="")
|
23
|
+
"""The description of the action."""
|
20
24
|
personality: str = Field(default="")
|
21
25
|
"""The personality of whom the action belongs to."""
|
22
26
|
output_key: str = Field(default="")
|
23
27
|
"""The key of the output data."""
|
24
28
|
|
29
|
+
@final
|
30
|
+
def model_post_init(self, __context: Any) -> None:
|
31
|
+
"""Initialize the action by setting the name if not provided.
|
32
|
+
|
33
|
+
Args:
|
34
|
+
__context: The context to be used for initialization.
|
35
|
+
"""
|
36
|
+
self.name = self.name or self.__class__.__name__
|
37
|
+
self.description = self.description or self.__class__.__doc__ or ""
|
38
|
+
|
25
39
|
@abstractmethod
|
26
40
|
async def _execute(self, **cxt: Unpack) -> Any:
|
27
41
|
"""Execute the action with the provided arguments.
|
@@ -34,6 +48,7 @@ class Action(HandleTask, ProposeTask, GiveRating):
|
|
34
48
|
"""
|
35
49
|
pass
|
36
50
|
|
51
|
+
@final
|
37
52
|
async def act(self, cxt: Dict[str, Any]) -> Dict[str, Any]:
|
38
53
|
"""Perform the action by executing it and setting the output data.
|
39
54
|
|
@@ -46,6 +61,7 @@ class Action(HandleTask, ProposeTask, GiveRating):
|
|
46
61
|
cxt[self.output_key] = ret
|
47
62
|
return cxt
|
48
63
|
|
64
|
+
@property
|
49
65
|
def briefing(self) -> str:
|
50
66
|
"""Return a brief description of the action."""
|
51
67
|
if self.personality:
|
@@ -91,9 +107,8 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
|
|
91
107
|
Returns:
|
92
108
|
Self: The instance of the workflow with the injected personality.
|
93
109
|
"""
|
94
|
-
for a in self._instances:
|
95
|
-
|
96
|
-
a.personality = personality
|
110
|
+
for a in filter(lambda action: not action.personality, self._instances):
|
111
|
+
a.personality = personality
|
97
112
|
return self
|
98
113
|
|
99
114
|
async def serve(self, task: Task) -> None:
|
fabricatio/models/events.py
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
from typing import List, Self, Union
|
4
4
|
|
5
5
|
from fabricatio.config import configs
|
6
|
+
from fabricatio.models.utils import TaskStatus
|
6
7
|
from pydantic import BaseModel, ConfigDict, Field
|
7
8
|
|
8
9
|
type EventLike = Union[str, List[str], "Event"]
|
@@ -33,6 +34,21 @@ class Event(BaseModel):
|
|
33
34
|
|
34
35
|
return cls(segments=event)
|
35
36
|
|
37
|
+
@classmethod
|
38
|
+
def quick_instantiate(cls, event: EventLike) -> Self:
|
39
|
+
"""Create an Event instance from a string or list of strings or an Event instance and push a wildcard and pending segment.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
event (EventLike): The event to instantiate from.
|
43
|
+
|
44
|
+
Returns:
|
45
|
+
Event: The Event instance.
|
46
|
+
|
47
|
+
Notes:
|
48
|
+
This method is used to create an Event instance from a string or list of strings or an Event instance and push a wildcard and pending segment.
|
49
|
+
"""
|
50
|
+
return cls.instantiate_from(event).push_wildcard().push_pending()
|
51
|
+
|
36
52
|
def derive(self, event: EventLike) -> Self:
|
37
53
|
"""Derive a new event from this event and another event or a string."""
|
38
54
|
return self.clone().concat(event)
|
@@ -59,6 +75,26 @@ class Event(BaseModel):
|
|
59
75
|
"""Push a wildcard segment to the event."""
|
60
76
|
return self.push("*")
|
61
77
|
|
78
|
+
def push_pending(self) -> Self:
|
79
|
+
"""Push a pending segment to the event."""
|
80
|
+
return self.push(TaskStatus.Pending.value)
|
81
|
+
|
82
|
+
def push_running(self) -> Self:
|
83
|
+
"""Push a running segment to the event."""
|
84
|
+
return self.push(TaskStatus.Running.value)
|
85
|
+
|
86
|
+
def push_finished(self) -> Self:
|
87
|
+
"""Push a finished segment to the event."""
|
88
|
+
return self.push(TaskStatus.Finished.value)
|
89
|
+
|
90
|
+
def push_failed(self) -> Self:
|
91
|
+
"""Push a failed segment to the event."""
|
92
|
+
return self.push(TaskStatus.Failed.value)
|
93
|
+
|
94
|
+
def push_cancelled(self) -> Self:
|
95
|
+
"""Push a cancelled segment to the event."""
|
96
|
+
return self.push(TaskStatus.Cancelled.value)
|
97
|
+
|
62
98
|
def pop(self) -> str:
|
63
99
|
"""Pop a segment from the event."""
|
64
100
|
return self.segments.pop()
|
@@ -0,0 +1,168 @@
|
|
1
|
+
"""Extra models for built-in actions."""
|
2
|
+
|
3
|
+
from typing import List
|
4
|
+
|
5
|
+
from fabricatio.models.generic import Base, Display, FinalizedDumpAble, PrepareVectorization, ProposedAble
|
6
|
+
from pydantic import Field
|
7
|
+
|
8
|
+
|
9
|
+
class Equation(Base):
|
10
|
+
"""Structured representation of mathematical equations (including their physical or conceptual meanings)."""
|
11
|
+
|
12
|
+
description: str = Field(...)
|
13
|
+
"""A concise explanation of the equation's meaning, purpose, and relevance in the context of the research."""
|
14
|
+
|
15
|
+
latex_code: str = Field(...)
|
16
|
+
"""The LaTeX code used to represent the equation in a publication-ready format."""
|
17
|
+
|
18
|
+
|
19
|
+
class Figure(Base):
|
20
|
+
"""Structured representation of figures (including their academic significance and explanatory captions)."""
|
21
|
+
|
22
|
+
description: str = Field(...)
|
23
|
+
"""A detailed explanation of the figure's content and its role in conveying key insights."""
|
24
|
+
|
25
|
+
figure_caption: str = Field(...)
|
26
|
+
"""The caption accompanying the figure, summarizing its main points and academic value."""
|
27
|
+
|
28
|
+
figure_path: str = Field(...)
|
29
|
+
"""The file path to the figure"""
|
30
|
+
|
31
|
+
|
32
|
+
class Highlightings(Base):
|
33
|
+
"""Structured representation of highlighted elements in an academic paper (including equations, algorithms, figures, and tables)."""
|
34
|
+
|
35
|
+
# Academic Achievements Showcase
|
36
|
+
highlighted_equations: List[Equation] = Field(default_factory=list)
|
37
|
+
"""Core mathematical equations that represent breakthroughs in the field, accompanied by explanations of their physical or conceptual significance."""
|
38
|
+
|
39
|
+
highlighted_algorithms: List[str] = Field(default_factory=list)
|
40
|
+
"""Pseudocode for key algorithms, annotated to highlight innovative components."""
|
41
|
+
|
42
|
+
highlighted_figures: List[Figure] = Field(default_factory=list)
|
43
|
+
"""Critical diagrams or illustrations, each accompanied by a caption explaining their academic importance."""
|
44
|
+
|
45
|
+
highlighted_tables: List[str] = Field(default_factory=list)
|
46
|
+
"""Important data tables, annotated to indicate statistical significance or other notable findings."""
|
47
|
+
|
48
|
+
|
49
|
+
class ArticleEssence(ProposedAble, Display, PrepareVectorization):
|
50
|
+
"""Structured representation of the core elements of an academic paper(providing a comprehensive digital profile of the paper's essential information)."""
|
51
|
+
|
52
|
+
# Basic Metadata
|
53
|
+
title: str = Field(...)
|
54
|
+
"""The full title of the paper, including any subtitles if applicable."""
|
55
|
+
|
56
|
+
authors: List[str] = Field(default_factory=list)
|
57
|
+
"""A list of the paper's authors, typically in the order of contribution."""
|
58
|
+
|
59
|
+
keywords: List[str] = Field(default_factory=list)
|
60
|
+
"""A list of keywords that summarize the paper's focus and facilitate indexing."""
|
61
|
+
|
62
|
+
publication_year: int = Field(None)
|
63
|
+
"""The year in which the paper was published."""
|
64
|
+
|
65
|
+
# Core Content Elements
|
66
|
+
domain: List[str] = Field(default_factory=list)
|
67
|
+
"""The research domains or fields addressed by the paper (e.g., ['Natural Language Processing', 'Computer Vision'])."""
|
68
|
+
|
69
|
+
abstract: str = Field(...)
|
70
|
+
"""A structured abstract that outlines the research problem, methodology, and conclusions in three distinct sections."""
|
71
|
+
|
72
|
+
core_contributions: List[str] = Field(default_factory=list)
|
73
|
+
"""Key academic contributions that distinguish the paper from prior work in the field."""
|
74
|
+
|
75
|
+
technical_novelty: List[str] = Field(default_factory=list)
|
76
|
+
"""Specific technical innovations introduced by the research, listed as individual points."""
|
77
|
+
|
78
|
+
# Academic Discussion Dimensions
|
79
|
+
research_problem: str = Field("")
|
80
|
+
"""A clearly defined research question or problem addressed by the study."""
|
81
|
+
|
82
|
+
limitations: List[str] = Field(default_factory=list)
|
83
|
+
"""An analysis of the methodological or experimental limitations of the research."""
|
84
|
+
|
85
|
+
future_work: List[str] = Field(default_factory=list)
|
86
|
+
"""Suggestions for potential directions or topics for follow-up studies."""
|
87
|
+
|
88
|
+
impact_analysis: str = Field("")
|
89
|
+
"""An assessment of the paper's potential influence on the development of the field."""
|
90
|
+
|
91
|
+
def _prepare_vectorization_inner(self) -> str:
|
92
|
+
return self.model_dump_json()
|
93
|
+
|
94
|
+
|
95
|
+
class ArticleProposal(ProposedAble, Display):
|
96
|
+
"""Structured representation of the proposal for an academic paper."""
|
97
|
+
|
98
|
+
title: str = Field(...)
|
99
|
+
"""The proposed title of the paper."""
|
100
|
+
|
101
|
+
focused_problem: List[str] = Field(default_factory=list)
|
102
|
+
"""The specific research problem or question that the paper aims to address."""
|
103
|
+
research_aim: List[str] = Field(default_factory=list)
|
104
|
+
"""The main objective or goal of the research, outlining what the study aims to achieve."""
|
105
|
+
research_methods: List[str] = Field(default_factory=list)
|
106
|
+
"""The methods used in the research, including the approach, techniques, and tools employed."""
|
107
|
+
|
108
|
+
|
109
|
+
class ArticleSubsectionOutline(Base):
|
110
|
+
"""Structured representation of the subsections of an academic paper."""
|
111
|
+
|
112
|
+
title: str = Field(...)
|
113
|
+
"""The title of the subsection."""
|
114
|
+
|
115
|
+
description: str = Field(...)
|
116
|
+
"""A brief description of the subsection's content should be, how it fits into the overall structure of the paper, and its significance in the context of the research."""
|
117
|
+
|
118
|
+
|
119
|
+
class ArticleSectionOutline(Base):
|
120
|
+
"""Structured representation of the sections of an academic paper."""
|
121
|
+
|
122
|
+
title: str = Field(...)
|
123
|
+
"""The title of the section."""
|
124
|
+
description: str = Field(...)
|
125
|
+
"""A brief description of the section's content should be, how it fits into the overall structure of the paper, and its significance in the context of the research."""
|
126
|
+
subsections: List[ArticleSubsectionOutline] = Field(default_factory=list)
|
127
|
+
"""The subsections of the section, outlining their content and significance."""
|
128
|
+
|
129
|
+
|
130
|
+
class ArticleChapterOutline(Base):
|
131
|
+
"""Structured representation of the chapters of an academic paper."""
|
132
|
+
|
133
|
+
title: str = Field(...)
|
134
|
+
"""The title of the chapter."""
|
135
|
+
description: str = Field(...)
|
136
|
+
"""A brief description of the chapter's content should be, how it fits into the overall structure of the paper, and its significance in the context of the research."""
|
137
|
+
sections: List[ArticleSectionOutline] = Field(default_factory=list)
|
138
|
+
"""The sections of the chapter, outlining their content and significance."""
|
139
|
+
|
140
|
+
|
141
|
+
class ArticleOutline(ProposedAble, Display, FinalizedDumpAble):
|
142
|
+
"""Structured representation of the outline for an academic paper."""
|
143
|
+
|
144
|
+
title: str = Field(...)
|
145
|
+
"""The proposed title of the paper."""
|
146
|
+
|
147
|
+
prospect: str = Field(...)
|
148
|
+
"""A brief description of the research problem or question that the paper aims to address manipulating methods or techniques"""
|
149
|
+
|
150
|
+
chapters: List[ArticleChapterOutline] = Field(default_factory=list)
|
151
|
+
"""The chapters of the paper, outlining their content and significance."""
|
152
|
+
|
153
|
+
def finalized_dump(self) -> str:
|
154
|
+
"""Finalized dump of the article outline.
|
155
|
+
|
156
|
+
Returns:
|
157
|
+
str: The finalized dump of the article outline.
|
158
|
+
"""
|
159
|
+
lines: List[str] = []
|
160
|
+
|
161
|
+
for chapter in self.chapters:
|
162
|
+
lines.append(f"= {chapter.title}")
|
163
|
+
for section in chapter.sections:
|
164
|
+
lines.append(f"== {section.title}")
|
165
|
+
for subsection in section.subsections:
|
166
|
+
lines.append(f"=== {subsection.title}")
|
167
|
+
|
168
|
+
return "\n\n".join(lines)
|