fabricatio 0.2.3.dev3__cp312-cp312-win_amd64.whl → 0.2.4.dev1__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/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."""
@@ -179,6 +206,9 @@ 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
+
182
212
 
183
213
  class MagikaConfig(BaseModel):
184
214
  """Magika configuration class."""
@@ -222,6 +252,8 @@ class RagConfig(BaseModel):
222
252
  """The timeout of the Milvus server."""
223
253
  milvus_token: Optional[SecretStr] = Field(default=None)
224
254
  """The token of the Milvus server."""
255
+ milvus_dimensions: Optional[PositiveInt] = Field(default=None)
256
+ """The dimensions of the Milvus server."""
225
257
 
226
258
 
227
259
  class Settings(BaseSettings):
@@ -249,6 +281,9 @@ class Settings(BaseSettings):
249
281
  llm: LLMConfig = Field(default_factory=LLMConfig)
250
282
  """LLM Configuration"""
251
283
 
284
+ embedding: EmbeddingConfig = Field(default_factory=EmbeddingConfig)
285
+ """Embedding Configuration"""
286
+
252
287
  debug: DebugConfig = Field(default_factory=DebugConfig)
253
288
  """Debug Configuration"""
254
289
 
@@ -46,6 +46,7 @@ class Action(HandleTask, ProposeTask, GiveRating):
46
46
  cxt[self.output_key] = ret
47
47
  return cxt
48
48
 
49
+ @property
49
50
  def briefing(self) -> str:
50
51
  """Return a brief description of the action."""
51
52
  if self.personality:
@@ -91,9 +92,8 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
91
92
  Returns:
92
93
  Self: The instance of the workflow with the injected personality.
93
94
  """
94
- for a in self._instances:
95
- if not a.personality:
96
- a.personality = personality
95
+ for a in filter(lambda action: not action.personality, self._instances):
96
+ a.personality = personality
97
97
  return self
98
98
 
99
99
  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,96 @@
1
+ """Extra models for built-in actions."""
2
+
3
+ from typing import List
4
+
5
+ from fabricatio.models.generic import Display, PrepareVectorization, ProposedAble
6
+ from pydantic import BaseModel, ConfigDict, Field
7
+
8
+
9
+ class Equation(BaseModel):
10
+ """Structured representation of mathematical equations (including their physical or conceptual meanings)."""
11
+
12
+ model_config = ConfigDict(use_attribute_docstrings=True)
13
+
14
+ description: str = Field(...)
15
+ """A concise explanation of the equation's meaning, purpose, and relevance in the context of the research."""
16
+
17
+ latex_code: str = Field(...)
18
+ """The LaTeX code used to represent the equation in a publication-ready format."""
19
+
20
+
21
+ class Figure(BaseModel):
22
+ """Structured representation of figures (including their academic significance and explanatory captions)."""
23
+
24
+ model_config = ConfigDict(use_attribute_docstrings=True)
25
+
26
+ description: str = Field(...)
27
+ """A detailed explanation of the figure's content and its role in conveying key insights."""
28
+
29
+ figure_caption: str = Field(...)
30
+ """The caption accompanying the figure, summarizing its main points and academic value."""
31
+
32
+ figure_path: str = Field(...)
33
+ """The file path to the figure"""
34
+
35
+
36
+ class Highlightings(BaseModel):
37
+ """Structured representation of highlighted elements in an academic paper (including equations, algorithms, figures, and tables)."""
38
+
39
+ # Academic Achievements Showcase
40
+ highlighted_equations: List[Equation] = Field(default_factory=list)
41
+ """Core mathematical equations that represent breakthroughs in the field, accompanied by explanations of their physical or conceptual significance."""
42
+
43
+ highlighted_algorithms: List[str] = Field(default_factory=list)
44
+ """Pseudocode for key algorithms, annotated to highlight innovative components."""
45
+
46
+ highlighted_figures: List[Figure] = Field(default_factory=list)
47
+ """Critical diagrams or illustrations, each accompanied by a caption explaining their academic importance."""
48
+
49
+ highlighted_tables: List[str] = Field(default_factory=list)
50
+ """Important data tables, annotated to indicate statistical significance or other notable findings."""
51
+
52
+
53
+ class ArticleEssence(ProposedAble, Display, PrepareVectorization):
54
+ """Structured representation of the core elements of an academic paper(providing a comprehensive digital profile of the paper's essential information)."""
55
+
56
+ # Basic Metadata
57
+ title: str = Field(...)
58
+ """The full title of the paper, including any subtitles if applicable."""
59
+
60
+ authors: List[str] = Field(default_factory=list)
61
+ """A list of the paper's authors, typically in the order of contribution."""
62
+
63
+ keywords: List[str] = Field(default_factory=list)
64
+ """A list of keywords that summarize the paper's focus and facilitate indexing."""
65
+
66
+ publication_year: int = Field(None)
67
+ """The year in which the paper was published."""
68
+
69
+ # Core Content Elements
70
+ domain: List[str] = Field(default_factory=list)
71
+ """The research domains or fields addressed by the paper (e.g., ['Natural Language Processing', 'Computer Vision'])."""
72
+
73
+ abstract: str = Field(...)
74
+ """A structured abstract that outlines the research problem, methodology, and conclusions in three distinct sections."""
75
+
76
+ core_contributions: List[str] = Field(default_factory=list)
77
+ """Key academic contributions that distinguish the paper from prior work in the field."""
78
+
79
+ technical_novelty: List[str] = Field(default_factory=list)
80
+ """Specific technical innovations introduced by the research, listed as individual points."""
81
+
82
+ # Academic Discussion Dimensions
83
+ research_problem: str = Field("")
84
+ """A clearly defined research question or problem addressed by the study."""
85
+
86
+ limitations: List[str] = Field(default_factory=list)
87
+ """An analysis of the methodological or experimental limitations of the research."""
88
+
89
+ future_work: List[str] = Field(default_factory=list)
90
+ """Suggestions for potential directions or topics for follow-up studies."""
91
+
92
+ impact_analysis: str = Field("")
93
+ """An assessment of the paper's potential influence on the development of the field."""
94
+
95
+ def _prepare_vectorization_inner(self) -> str:
96
+ return self.model_dump_json()
@@ -1,17 +1,25 @@
1
1
  """This module defines generic classes for models in the Fabricatio library."""
2
2
 
3
+ from abc import abstractmethod
3
4
  from pathlib import Path
4
- from typing import Callable, List, Self
5
+ from typing import Callable, Iterable, List, Optional, Self, Union, final
5
6
 
6
7
  import orjson
7
8
  from fabricatio._rust import blake3_hash
8
9
  from fabricatio._rust_instances import template_manager
9
10
  from fabricatio.config import configs
10
11
  from fabricatio.fs.readers import magika, safe_text_read
12
+ from fabricatio.journal import logger
13
+ from fabricatio.parser import JsonCapture
11
14
  from pydantic import (
12
15
  BaseModel,
13
16
  ConfigDict,
14
17
  Field,
18
+ HttpUrl,
19
+ NonNegativeFloat,
20
+ PositiveFloat,
21
+ PositiveInt,
22
+ SecretStr,
15
23
  )
16
24
 
17
25
 
@@ -21,6 +29,18 @@ class Base(BaseModel):
21
29
  model_config = ConfigDict(use_attribute_docstrings=True)
22
30
 
23
31
 
32
+ class Display(Base):
33
+ """Class that provides a method to display the model in a formatted JSON string."""
34
+
35
+ def display(self) -> str:
36
+ """Display the model in a formatted JSON string.
37
+
38
+ Returns:
39
+ str: The formatted JSON string of the model.
40
+ """
41
+ return self.model_dump_json(indent=1)
42
+
43
+
24
44
  class Named(Base):
25
45
  """Class that includes a name attribute."""
26
46
 
@@ -48,22 +68,63 @@ class WithBriefing(Named, Described):
48
68
  return f"{self.name}: {self.description}" if self.description else self.name
49
69
 
50
70
 
51
- class WithJsonExample(Base):
52
- """Class that provides a JSON schema for the model."""
71
+ class WithFormatedJsonSchema(Base):
72
+ """Class that provides a formatted JSON schema of the model."""
53
73
 
54
74
  @classmethod
55
- def json_example(cls) -> str:
56
- """Return a JSON example for the model.
75
+ def formated_json_schema(cls) -> str:
76
+ """Get the JSON schema of the model in a formatted string.
57
77
 
58
78
  Returns:
59
- str: A JSON example for the model.
79
+ str: The JSON schema of the model in a formatted string.
60
80
  """
61
81
  return orjson.dumps(
62
- {field_name: field_info.description for field_name, field_info in cls.model_fields.items()},
82
+ cls.model_json_schema(),
63
83
  option=orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS,
64
84
  ).decode()
65
85
 
66
86
 
87
+ class CreateJsonObjPrompt(WithFormatedJsonSchema):
88
+ """Class that provides a prompt for creating a JSON object."""
89
+
90
+ @classmethod
91
+ def create_json_prompt(cls, requirement: str) -> str:
92
+ """Create the prompt for creating a JSON object with given requirement.
93
+
94
+ Args:
95
+ requirement (str): The requirement for the JSON object.
96
+
97
+ Returns:
98
+ str: The prompt for creating a JSON object with given requirement.
99
+ """
100
+ return template_manager.render_template(
101
+ configs.templates.create_json_obj_template,
102
+ {"requirement": requirement, "json_schema": cls.formated_json_schema()},
103
+ )
104
+
105
+
106
+ class InstantiateFromString(Base):
107
+ """Class that provides a method to instantiate the class from a string."""
108
+
109
+ @classmethod
110
+ def instantiate_from_string(cls, string: str) -> Self | None:
111
+ """Instantiate the class from a string.
112
+
113
+ Args:
114
+ string (str): The string to instantiate the class from.
115
+
116
+ Returns:
117
+ Self | None: The instance of the class or None if the string is not valid.
118
+ """
119
+ return JsonCapture.convert_with(string, cls.model_validate_json)
120
+
121
+
122
+ class ProposedAble(CreateJsonObjPrompt, InstantiateFromString):
123
+ """Class that provides methods for proposing a task."""
124
+
125
+ pass
126
+
127
+
67
128
  class WithDependency(Base):
68
129
  """Class that manages file dependencies."""
69
130
 
@@ -150,3 +211,129 @@ class WithDependency(Base):
150
211
  for p in self.dependencies
151
212
  },
152
213
  )
214
+
215
+
216
+ class PrepareVectorization(Base):
217
+ """Class that prepares the vectorization of the model."""
218
+
219
+ @abstractmethod
220
+ def _prepare_vectorization_inner(self) -> str:
221
+ """Prepare the vectorization of the model."""
222
+
223
+ def prepare_vectorization(self, max_length: Optional[int] = None) -> str:
224
+ """Prepare the vectorization of the model.
225
+
226
+ Returns:
227
+ str: The prepared vectorization of the model.
228
+ """
229
+ max_length = max_length or configs.embedding.max_sequence_length
230
+ chunk = self._prepare_vectorization_inner()
231
+ if len(chunk) > max_length:
232
+ logger.error(err := f"Chunk exceeds maximum sequence length {max_length}.")
233
+ raise ValueError(err)
234
+
235
+ return chunk
236
+
237
+
238
+ class ScopedConfig(Base):
239
+ """Class that manages a scoped configuration."""
240
+
241
+ llm_api_endpoint: Optional[HttpUrl] = None
242
+ """The OpenAI API endpoint."""
243
+
244
+ llm_api_key: Optional[SecretStr] = None
245
+ """The OpenAI API key."""
246
+
247
+ llm_timeout: Optional[PositiveInt] = None
248
+ """The timeout of the LLM model."""
249
+
250
+ llm_max_retries: Optional[PositiveInt] = None
251
+ """The maximum number of retries."""
252
+
253
+ llm_model: Optional[str] = None
254
+ """The LLM model name."""
255
+
256
+ llm_temperature: Optional[NonNegativeFloat] = None
257
+ """The temperature of the LLM model."""
258
+
259
+ llm_stop_sign: Optional[str | List[str]] = None
260
+ """The stop sign of the LLM model."""
261
+
262
+ llm_top_p: Optional[NonNegativeFloat] = None
263
+ """The top p of the LLM model."""
264
+
265
+ llm_generation_count: Optional[PositiveInt] = None
266
+ """The number of generations to generate."""
267
+
268
+ llm_stream: Optional[bool] = None
269
+ """Whether to stream the LLM model's response."""
270
+
271
+ llm_max_tokens: Optional[PositiveInt] = None
272
+ """The maximum number of tokens to generate."""
273
+
274
+ embedding_api_endpoint: Optional[HttpUrl] = None
275
+ """The OpenAI API endpoint."""
276
+
277
+ embedding_api_key: Optional[SecretStr] = None
278
+ """The OpenAI API key."""
279
+
280
+ embedding_timeout: Optional[PositiveInt] = None
281
+ """The timeout of the LLM model."""
282
+
283
+ embedding_model: Optional[str] = None
284
+ """The LLM model name."""
285
+
286
+ embedding_max_sequence_length: Optional[PositiveInt] = None
287
+ """The maximum sequence length."""
288
+
289
+ embedding_dimensions: Optional[PositiveInt] = None
290
+ """The dimensions of the embedding."""
291
+ embedding_caching: Optional[bool] = False
292
+ """Whether to cache the embedding result."""
293
+
294
+ milvus_uri: Optional[HttpUrl] = Field(default=None)
295
+ """The URI of the Milvus server."""
296
+ milvus_token: Optional[SecretStr] = Field(default=None)
297
+ """The token for the Milvus server."""
298
+ milvus_timeout: Optional[PositiveFloat] = Field(default=None)
299
+ """The timeout for the Milvus server."""
300
+ milvus_dimensions: Optional[PositiveInt] = Field(default=None)
301
+ """The dimensions of the Milvus server."""
302
+
303
+ @final
304
+ def fallback_to(self, other: "ScopedConfig") -> Self:
305
+ """Fallback to another instance's attribute values if the current instance's attributes are None.
306
+
307
+ Args:
308
+ other (LLMUsage): Another instance from which to copy attribute values.
309
+
310
+ Returns:
311
+ Self: The current instance, allowing for method chaining.
312
+ """
313
+ # Iterate over the attribute names and copy values from 'other' to 'self' where applicable
314
+ # noinspection PydanticTypeChecker,PyTypeChecker
315
+ for attr_name in ScopedConfig.model_fields:
316
+ # Copy the attribute value from 'other' to 'self' only if 'self' has None and 'other' has a non-None value
317
+ if getattr(self, attr_name) is None and (attr := getattr(other, attr_name)) is not None:
318
+ setattr(self, attr_name, attr)
319
+
320
+ # Return the current instance to allow for method chaining
321
+ return self
322
+
323
+ @final
324
+ def hold_to(self, others: Union["ScopedConfig", Iterable["ScopedConfig"]]) -> Self:
325
+ """Hold to another instance's attribute values if the current instance's attributes are None.
326
+
327
+ Args:
328
+ others (LLMUsage | Iterable[LLMUsage]): Another instance or iterable of instances from which to copy attribute values.
329
+
330
+ Returns:
331
+ Self: The current instance, allowing for method chaining.
332
+ """
333
+ if not isinstance(others, Iterable):
334
+ others = [others]
335
+ for other in others:
336
+ # noinspection PyTypeChecker,PydanticTypeChecker
337
+ for attr_name in ScopedConfig.model_fields:
338
+ if (attr := getattr(self, attr_name)) is not None and getattr(other, attr_name) is None:
339
+ setattr(other, attr_name, attr)
@@ -5,6 +5,20 @@ from typing import List, NotRequired, TypedDict
5
5
  from pydantic import NonNegativeFloat, NonNegativeInt, PositiveInt
6
6
 
7
7
 
8
+ class CollectionSimpleConfigKwargs(TypedDict):
9
+ """A type representing the configuration for a collection."""
10
+
11
+ dimension: NotRequired[int]
12
+ timeout: NotRequired[float]
13
+
14
+
15
+ class FetchKwargs(TypedDict):
16
+ """A type representing the keyword arguments for the fetch method."""
17
+
18
+ similarity_threshold: NotRequired[float]
19
+ result_per_query: NotRequired[int]
20
+
21
+
8
22
  class EmbeddingKwargs(TypedDict):
9
23
  """A type representing the keyword arguments for the embedding method."""
10
24
 
fabricatio/models/task.py CHANGED
@@ -4,7 +4,6 @@ It includes methods to manage the task's lifecycle, such as starting, finishing,
4
4
  """
5
5
 
6
6
  from asyncio import Queue
7
- from enum import Enum
8
7
  from typing import Any, List, Optional, Self
9
8
 
10
9
  from fabricatio._rust_instances import template_manager
@@ -12,35 +11,18 @@ from fabricatio.config import configs
12
11
  from fabricatio.core import env
13
12
  from fabricatio.journal import logger
14
13
  from fabricatio.models.events import Event, EventLike
15
- from fabricatio.models.generic import WithBriefing, WithDependency, WithJsonExample
14
+ from fabricatio.models.generic import ProposedAble, WithBriefing, WithDependency
15
+ from fabricatio.models.utils import TaskStatus
16
16
  from pydantic import Field, PrivateAttr
17
17
 
18
18
 
19
- class TaskStatus(Enum):
20
- """An enumeration representing the status of a task.
21
-
22
- Attributes:
23
- Pending: The task is pending.
24
- Running: The task is currently running.
25
- Finished: The task has been successfully completed.
26
- Failed: The task has failed.
27
- Cancelled: The task has been cancelled.
28
- """
29
-
30
- Pending = "pending"
31
- Running = "running"
32
- Finished = "finished"
33
- Failed = "failed"
34
- Cancelled = "cancelled"
35
-
36
-
37
- class Task[T](WithBriefing, WithJsonExample, WithDependency):
19
+ class Task[T](WithBriefing, ProposedAble, WithDependency):
38
20
  """A class representing a task with a status and output.
39
21
 
40
22
  Attributes:
41
23
  name (str): The name of the task.
42
24
  description (str): The description of the task.
43
- goal (str): The goal of the task.
25
+ goals (str): The goal of the task.
44
26
  dependencies (List[str]): The file dependencies of the task, a list of file paths.
45
27
  namespace (List[str]): The namespace of the task, a list of namespace segment, as string.
46
28
  """
@@ -58,7 +40,7 @@ class Task[T](WithBriefing, WithJsonExample, WithDependency):
58
40
  """A list of string segments that identify the task's location in the system. If not specified, defaults to an empty list."""
59
41
 
60
42
  dependencies: List[str] = Field(default_factory=list)
61
- """A list of file paths that are needed (either reading or writing) to complete this task. If not specified, defaults to an empty list."""
43
+ """A list of file paths that are needed or mentioned in the task's description (either reading or writing) to complete this task. If not specified, defaults to an empty list."""
62
44
 
63
45
  _output: Queue[T | None] = PrivateAttr(default_factory=Queue)
64
46
  """The output queue of the task."""