fabricatio 0.2.3.dev2__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.
Files changed (38) hide show
  1. fabricatio/__init__.py +24 -3
  2. fabricatio/_rust.cp312-win_amd64.pyd +0 -0
  3. fabricatio/actions/article.py +81 -0
  4. fabricatio/actions/output.py +21 -0
  5. fabricatio/actions/rag.py +25 -0
  6. fabricatio/capabilities/propose.py +55 -0
  7. fabricatio/capabilities/rag.py +241 -54
  8. fabricatio/capabilities/rating.py +12 -36
  9. fabricatio/capabilities/task.py +6 -23
  10. fabricatio/config.py +46 -2
  11. fabricatio/fs/__init__.py +24 -2
  12. fabricatio/fs/curd.py +14 -8
  13. fabricatio/fs/readers.py +5 -2
  14. fabricatio/models/action.py +19 -4
  15. fabricatio/models/events.py +36 -0
  16. fabricatio/models/extra.py +168 -0
  17. fabricatio/models/generic.py +218 -7
  18. fabricatio/models/kwargs_types.py +15 -0
  19. fabricatio/models/task.py +11 -43
  20. fabricatio/models/tool.py +3 -2
  21. fabricatio/models/usages.py +153 -184
  22. fabricatio/models/utils.py +19 -0
  23. fabricatio/parser.py +35 -8
  24. fabricatio/toolboxes/__init__.py +1 -3
  25. fabricatio/toolboxes/fs.py +15 -1
  26. fabricatio/workflows/articles.py +15 -0
  27. fabricatio/workflows/rag.py +11 -0
  28. fabricatio-0.2.4.data/scripts/tdown.exe +0 -0
  29. {fabricatio-0.2.3.dev2.dist-info → fabricatio-0.2.4.dist-info}/METADATA +40 -148
  30. fabricatio-0.2.4.dist-info/RECORD +40 -0
  31. fabricatio/actions/__init__.py +0 -5
  32. fabricatio/actions/communication.py +0 -15
  33. fabricatio/actions/transmission.py +0 -23
  34. fabricatio/toolboxes/task.py +0 -6
  35. fabricatio-0.2.3.dev2.data/scripts/tdown.exe +0 -0
  36. fabricatio-0.2.3.dev2.dist-info/RECORD +0 -37
  37. {fabricatio-0.2.3.dev2.dist-info → fabricatio-0.2.4.dist-info}/WHEEL +0 -0
  38. {fabricatio-0.2.3.dev2.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.convert_with(response, orjson.loads)) is not None
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
- (json_data := JsonCapture.convert_with(response, orjson.loads)) is not None
177
- and isinstance(json_data, list)
178
- and all(isinstance(v, str) for v in json_data)
179
- and (criteria_count == 0 or len(json_data) == criteria_count)
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=_reasons_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=_criteria_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=_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]
@@ -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 LLMUsage, ToolBoxUsage
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, LLMUsage):
19
+ class ProposeTask(WithBriefing, Propose):
20
20
  """A class that proposes a task based on a prompt."""
21
21
 
22
- async def propose[T](
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 = f"{self.name}: Prompt must be provided."
38
- logger.error(err)
37
+ logger.error(err := f"{self.name}: Prompt must be provided.")
39
38
  raise ValueError(err)
40
39
 
41
- def _validate_json(response: str) -> None | Task:
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
- propose_task_template: str = Field(default="propose_task")
144
- """The name of the propose task template which will be used to propose a task."""
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."""
@@ -176,6 +203,18 @@ class TemplateConfig(BaseModel):
176
203
  draft_rating_weights_klee_template: str = Field(default="draft_rating_weights_klee")
177
204
  """The name of the draft rating weights klee template which will be used to draft rating weights with Klee method."""
178
205
 
206
+ retrieved_display_template: str = Field(default="retrieved_display")
207
+ """The name of the retrieved display template which will be used to display retrieved documents."""
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
+
179
218
 
180
219
  class MagikaConfig(BaseModel):
181
220
  """Magika configuration class."""
@@ -219,6 +258,8 @@ class RagConfig(BaseModel):
219
258
  """The timeout of the Milvus server."""
220
259
  milvus_token: Optional[SecretStr] = Field(default=None)
221
260
  """The token of the Milvus server."""
261
+ milvus_dimensions: Optional[PositiveInt] = Field(default=None)
262
+ """The dimensions of the Milvus server."""
222
263
 
223
264
 
224
265
  class Settings(BaseSettings):
@@ -246,6 +287,9 @@ class Settings(BaseSettings):
246
287
  llm: LLMConfig = Field(default_factory=LLMConfig)
247
288
  """LLM Configuration"""
248
289
 
290
+ embedding: EmbeddingConfig = Field(default_factory=EmbeddingConfig)
291
+ """Embedding Configuration"""
292
+
249
293
  debug: DebugConfig = Field(default_factory=DebugConfig)
250
294
  """Debug Configuration"""
251
295
 
fabricatio/fs/__init__.py CHANGED
@@ -1,5 +1,27 @@
1
1
  """FileSystem manipulation module for Fabricatio."""
2
2
 
3
- from fabricatio.fs.readers import magika
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__ = ["magika"]
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, logging_execution_info
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 {}
@@ -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
- if not a.personality:
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:
@@ -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)