fabricatio 0.2.6.dev5__cp312-cp312-manylinux_2_34_x86_64.whl → 0.2.6.dev6__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.
@@ -93,10 +93,11 @@ class CorrectProposal(Action):
93
93
  f"{task_input.briefing}\nExtract the path of file, which contains the article briefing that I need to read."
94
94
  )
95
95
 
96
- rprint(article_proposal.display())
97
96
  ret = None
98
97
  while await confirm("Do you want to correct the Proposal?").ask_async():
99
- topic = await text("What is the topic of the proposal?").ask_async()
98
+ rprint(article_proposal.display())
99
+ while not (topic := await text("What is the topic of the proposal reviewing?").ask_async()):
100
+ ...
100
101
  ret = await self.correct_obj(
101
102
  article_proposal,
102
103
  safe_text_read(input_path),
@@ -115,11 +116,13 @@ class CorrectOutline(Action):
115
116
  self,
116
117
  article_outline: ArticleOutline,
117
118
  article_proposal: ArticleProposal,
119
+
118
120
  **_,
119
121
  ) -> Optional[str]:
120
- rprint(article_outline.finalized_dump())
121
122
  ret = None
122
123
  while await confirm("Do you want to correct the outline?").ask_async():
123
- topic = await text("What is the topic of the outline?").ask_async()
124
+ rprint(article_outline.finalized_dump())
125
+ while not (topic := await text("What is the topic of the outline reviewing?").ask_async()):
126
+ ...
124
127
  ret = await self.correct_obj(article_outline, article_proposal.display(), topic=topic)
125
128
  return ret or article_outline
@@ -21,7 +21,7 @@ from fabricatio.models.kwargs_types import (
21
21
  LLMKwargs,
22
22
  )
23
23
  from fabricatio.models.usages import EmbeddingUsage
24
- from fabricatio.models.utils import MilvusData
24
+ from fabricatio.models.utils import MilvusData, ok
25
25
  from more_itertools.recipes import flatten, unique
26
26
  from pydantic import Field, PrivateAttr
27
27
 
@@ -60,7 +60,7 @@ class RAG(EmbeddingUsage):
60
60
  ) -> Self:
61
61
  """Initialize the Milvus client."""
62
62
  self._client = create_client(
63
- uri=milvus_uri or (self.milvus_uri or configs.rag.milvus_uri).unicode_string(),
63
+ uri=milvus_uri or ok(self.milvus_uri or configs.rag.milvus_uri).unicode_string(),
64
64
  token=milvus_token
65
65
  or (token.get_secret_value() if (token := (self.milvus_token or configs.rag.milvus_token)) else ""),
66
66
  timeout=milvus_timeout or self.milvus_timeout,
@@ -315,7 +315,7 @@ class RAG(EmbeddingUsage):
315
315
  **kwargs,
316
316
  )
317
317
 
318
- async def arefined_query(self, question: List[str] | str, **kwargs: Unpack[ChooseKwargs]) -> List[str]:
318
+ async def arefined_query(self, question: List[str] | str, **kwargs: Unpack[ChooseKwargs]) -> Optional[List[str]]:
319
319
  """Refines the given question using a template.
320
320
 
321
321
  Args:
fabricatio/config.py CHANGED
@@ -66,7 +66,7 @@ class LLMConfig(BaseModel):
66
66
  temperature: Optional[NonNegativeFloat] = Field(default=1.0)
67
67
  """The temperature of the LLM model. Controls randomness in generation. Set to 1.0 as per request."""
68
68
 
69
- stop_sign: Optional[str | List[str]] = Field(default="")
69
+ stop_sign: Optional[str | List[str]] = Field(default=None)
70
70
  """The stop sign of the LLM model. No default stop sign specified."""
71
71
 
72
72
  top_p: Optional[NonNegativeFloat] = Field(default=0.35)
@@ -78,7 +78,7 @@ class LLMConfig(BaseModel):
78
78
  stream: Optional[bool] = Field(default=False)
79
79
  """Whether to stream the LLM model's response. Default is False."""
80
80
 
81
- max_tokens: Optional[PositiveInt] = Field(default=8192)
81
+ max_tokens: Optional[PositiveInt] = Field(default=None)
82
82
  """The maximum number of tokens to generate. Set to 8192 as per request."""
83
83
 
84
84
  rpm: Optional[PositiveInt] = Field(default=100)
@@ -148,13 +148,13 @@ class DebugConfig(BaseModel):
148
148
  log_level: Literal["DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL"] = Field(default="INFO")
149
149
  """The log level of the application."""
150
150
 
151
- log_file: FilePath = Field(default=Path(rf"{ROAMING_DIR}\fabricatio.log"))
151
+ log_file: FilePath = Field(default=Path(rf"{ROAMING_DIR}\fabricatio.log"), frozen=True)
152
152
  """The log file of the application."""
153
153
 
154
- rotation: int = Field(default=1)
154
+ rotation: int = Field(default=1, frozen=True)
155
155
  """The rotation of the log file. in weeks."""
156
156
 
157
- retention: int = Field(default=2)
157
+ retention: int = Field(default=2, frozen=True)
158
158
  """The retention of the log file. in weeks."""
159
159
 
160
160
  streaming_visible: bool = Field(default=False)
@@ -10,7 +10,6 @@ from asyncio import Queue, create_task
10
10
  from typing import Any, Dict, Self, Tuple, Type, Union, final
11
11
 
12
12
  from fabricatio.capabilities.correct import Correct
13
- from fabricatio.capabilities.covalidate import CoValidate
14
13
  from fabricatio.capabilities.task import HandleTask, ProposeTask
15
14
  from fabricatio.journal import logger
16
15
  from fabricatio.models.generic import WithBriefing
@@ -19,7 +18,7 @@ from fabricatio.models.usages import ToolBoxUsage
19
18
  from pydantic import Field, PrivateAttr
20
19
 
21
20
 
22
- class Action(HandleTask, ProposeTask, Correct, CoValidate):
21
+ class Action(HandleTask, ProposeTask, Correct):
23
22
  """Class that represents an action to be executed in a workflow.
24
23
 
25
24
  Actions are the atomic units of work in a workflow. Each action performs
@@ -7,157 +7,325 @@ from pydantic import Field
7
7
 
8
8
 
9
9
  class Equation(Base):
10
- """Structured representation of mathematical equations (including their physical or conceptual meanings)."""
10
+ """Mathematical formalism specification for research contributions.
11
+
12
+ Encodes equations with dual representation: semantic meaning and typeset-ready notation.
13
+ """
11
14
 
12
15
  description: str
13
- """A concise explanation of the equation's meaning, purpose, and relevance in the context of the research."""
16
+ """Equation significance structured in three elements:
17
+ 1. Physical/conceptual meaning
18
+ 2. Role in technical workflow
19
+ 3. Relationship to paper's core contribution
20
+ Example: 'Defines constrained search space dimensionality reduction. Used in architecture optimization phase (Section 3.2). Enables 40% parameter reduction.'"""
14
21
 
15
22
  latex_code: str
16
- """The LaTeX code used to represent the equation in a publication-ready format."""
23
+ """LaTeX representation following academic typesetting standards:
24
+ - Must use equation environment
25
+ - Multiline equations aligned at '='
26
+ - Unit annotations where applicable
27
+ Example: r'\begin{equation} \\mathcal{L}_{NAS} = \alpha \\|\theta\\|_2 + \beta H(p) \\end{equation}'"""
17
28
 
18
29
 
19
30
  class Figure(Base):
20
- """Structured representation of figures (including their academic significance and explanatory captions)."""
31
+ """Visual component specification for technical communication.
32
+
33
+ Combines graphical assets with structured academic captioning.
34
+ """
21
35
 
22
36
  description: str
23
- """A detailed explanation of the figure's content and its role in conveying key insights."""
37
+ """Figure interpretation guide containing:
38
+ 1. Key visual elements mapping
39
+ 2. Data representation methodology
40
+ 3. Connection to research findings
41
+ Example: 'Architecture search space topology (left) vs. convergence curves (right). Demonstrates NAS efficiency gains through constrained search.'"""
24
42
 
25
43
  figure_caption: str
26
- """The caption accompanying the figure, summarizing its main points and academic value."""
44
+ """Complete caption following Nature-style guidelines:
45
+ 1. Brief overview statement (首句总结)
46
+ 2. Technical detail layer
47
+ 3. Result implication
48
+ Example: 'Figure 3: Differentiable NAS framework. (a) Search space topology with constrained dimensions. (b) Training convergence across language pairs. Dashed lines indicate baseline methods.'"""
27
49
 
28
50
  figure_path: str
29
- """The exact path to the figure file, must exist in the file system, SHALL never be a PLACEHOLDER."""
51
+ """Filesystem path to high-resolution vector graphic (PDF/EPS/SVG).
52
+ Strict validation requirements:
53
+ - Absolute path under /assets/figures/
54
+ - Naming convention: fig[chapter]-[section]_[description].pdf
55
+ Example: '/assets/figures/fig3-2_nas_convergence.pdf'"""
30
56
 
31
57
 
32
58
  class Highlightings(Base):
33
- """Structured representation of highlighted elements in an academic paper (including equations, algorithms, figures, and tables)."""
59
+ """Technical showcase aggregator for research artifacts.
60
+
61
+ Curates core scientific components with machine-parseable annotations.
62
+ """
34
63
 
35
- # Academic Achievements Showcase
36
64
  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,Should always be in LaTeX format wrapped in $ or $$ signs."""
65
+ """3-5 pivotal equations representing theoretical contributions.
66
+ Each must:
67
+ - Use $$ wrapping for display math
68
+ - Contain at least one novel operator/symbol
69
+ - Reference in Methods/Results sections
70
+ Example: Equation describing proposed loss function"""
38
71
 
39
72
  highlighted_algorithms: List[str] = Field(default_factory=list)
40
- """Pseudocode for key algorithms, annotated to highlight innovative components."""
73
+ """Algorithm pseudocode following ACM style:
74
+ 1. Numbered steps with bold keywords
75
+ 2. Complexity analysis subsection
76
+ 3. Novel components marked with ※
77
+ Example:
78
+ 'Algorithm 1: Constrained NAS
79
+ 1. Initialize search space with §3.1 constraints ※
80
+ 2. While not converged:
81
+ a. Compute gradient ▽θ
82
+ b. Update architecture parameters...'"""
41
83
 
42
84
  highlighted_figures: List[Figure] = Field(default_factory=list)
43
- """Critical diagrams or illustrations, each accompanied by a caption explaining their academic importance."""
85
+ """4-6 key figures demonstrating:
86
+ 1. Framework overview (1 required)
87
+ 2. Quantitative results (2-3 required)
88
+ 3. Ablation studies (1 optional)
89
+ Each must appear in Results/Discussion chapters."""
44
90
 
45
91
  highlighted_tables: List[str] = Field(default_factory=list)
46
- """Important data tables, annotated to indicate statistical significance or other notable findings."""
92
+ """Critical data presentations using booktabs format:
93
+ - Minimum 3 comparison baselines
94
+ - Statistical significance markers (*/†/‡)
95
+ - Standard deviation in parentheses
96
+ Example:
97
+ \begin{tabular}{lcc}
98
+ \toprule
99
+ Method & BLEU & Δ Params \\
100
+ \\midrule
101
+ Ours & 32.4 & -41\\%† \\
102
+ \bottomrule
103
+ \\end{tabular}"""
47
104
 
48
105
 
49
106
  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)."""
107
+ """Semantic fingerprint of academic paper for structured analysis.
108
+
109
+ Encodes research artifacts with dual human-machine interpretability.
110
+ """
51
111
 
52
- # Basic Metadata
53
112
  title: str = Field(...)
54
- """The full title of the paper, including any subtitles if applicable."""
113
+ """Complete title with technical specificity (12-18 words).
114
+ Must contain:
115
+ 1. Methodology focus
116
+ 2. Application domain
117
+ 3. Performance metric
118
+ Example: 'EfficientViT: Multi-Scale Linear Attention for High-Resolution Dense Prediction'"""
55
119
 
56
120
  authors: List[str]
57
- """A list of the paper's authors, typically in the order of contribution."""
121
+ """Author list with institutional annotations.
122
+ Format: [First Last¹, First Last²]
123
+ Superscripts mapping to affiliations.
124
+ Example: ['Yuanhao Zhou¹', 'Lei Chen²']"""
58
125
 
59
126
  keywords: List[str]
60
- """A list of keywords that summarize the paper's focus and facilitate indexing."""
127
+ """5-8 ACM CCS concepts in camel case.
128
+ Example: ['Computing methodologies~Neural networks', 'Hardware~Emerging technologies']"""
61
129
 
62
130
  publication_year: int
63
- """The year in which the paper was published."""
131
+ """Publication timestamp in ISO 8601 (YYYY format).
132
+ Constraint: 2017 ≤ year ≤ current_year"""
64
133
 
65
- # Core Content Elements
66
134
  highlightings: Highlightings = Field(default_factory=Highlightings)
67
- """A collection of highlighted elements in the paper, including equations, algorithms, figures, and tables."""
135
+ """Technical highlight reel containing:
136
+ - Core equations (Theory)
137
+ - Key algorithms (Implementation)
138
+ - Critical figures (Results)
139
+ - Benchmark tables (Evaluation)"""
68
140
 
69
141
  domain: List[str]
70
- """The research domains or fields addressed by the paper (e.g., ['Natural Language Processing', 'Computer Vision'])."""
142
+ """Primary research domains from ACM CCS 2023 taxonomy.
143
+ Exactly 2-3 categories required.
144
+ Example: ['Computing methodologies → Machine learning']"""
71
145
 
72
146
  abstract: str = Field(...)
73
- """A structured abstract that outlines the research problem, methodology, and conclusions in three distinct sections."""
147
+ """Three-paragraph structured abstract:
148
+ Paragraph 1: Problem & Motivation (2-3 sentences)
149
+ Paragraph 2: Methodology & Innovations (3-4 sentences)
150
+ Paragraph 3: Results & Impact (2-3 sentences)
151
+ Total length: 150-250 words"""
74
152
 
75
153
  core_contributions: List[str]
76
- """Key academic contributions that distinguish the paper from prior work in the field."""
154
+ """3-5 technical contributions using CRediT taxonomy verbs.
155
+ Each item starts with action verb.
156
+ Example:
157
+ - 'Developed constrained NAS framework'
158
+ - 'Established cross-lingual transfer metrics'"""
77
159
 
78
160
  technical_novelty: List[str]
79
- """Specific technical innovations introduced by the research, listed as individual points."""
161
+ """Patent-style claims with technical specificity.
162
+ Format: 'A [system/method] comprising [novel components]...'
163
+ Example:
164
+ 'A neural architecture search system comprising:
165
+ a differentiable constrained search space;
166
+ multi-lingual transferability predictors...'"""
80
167
 
81
- # Academic Discussion Dimensions
82
168
  research_problems: List[str]
83
- """A clearly defined research question or problem addressed by the study."""
169
+ """Problem statements as how/why questions.
170
+ Example:
171
+ - 'How to reduce NAS computational overhead while maintaining search diversity?'
172
+ - 'Why do existing architectures fail in low-resource cross-lingual transfer?'"""
84
173
 
85
174
  limitations: List[str]
86
- """An analysis of the methodological or experimental limitations of the research."""
175
+ """Technical limitations analysis containing:
176
+ 1. Constraint source (data/method/theory)
177
+ 2. Impact quantification
178
+ 3. Mitigation pathway
179
+ Example:
180
+ 'Methodology constraint: Single-objective optimization (affects 5% edge cases),
181
+ mitigated through future multi-task extension'"""
87
182
 
88
183
  future_work: List[str]
89
- """Suggestions for potential directions or topics for follow-up studies."""
184
+ """Research roadmap items with 3 horizons:
185
+ 1. Immediate extensions (1 year)
186
+ 2. Mid-term directions (2-3 years)
187
+ 3. Long-term vision (5+ years)
188
+ Example:
189
+ 'Short-term: Adapt framework for vision transformers (ongoing with CVPR submission)'"""
90
190
 
91
191
  impact_analysis: List[str]
92
- """An assessment of the paper's potential influence on the development of the field."""
192
+ """Bibliometric impact projections:
193
+ - Expected citation counts (next 3 years)
194
+ - Target application domains
195
+ - Standard adoption potential
196
+ Example:
197
+ 'Predicted 150+ citations via integration into MMEngine (Alibaba OpenMMLab)'"""
93
198
 
94
199
  def _prepare_vectorization_inner(self) -> str:
95
200
  return self.model_dump_json()
96
201
 
97
202
 
98
203
  class ArticleProposal(ProposedAble, Display):
99
- """Structured representation of the proposal for an academic paper."""
204
+ """Structured proposal for academic paper development with core research elements.
205
+
206
+ Guides LLM in generating comprehensive research proposals with clearly defined components.
207
+ """
100
208
 
101
209
  title: str = Field(...)
102
- """The proposed title of the paper."""
210
+ """Paper title in academic style (Title Case, 8-15 words). Example: 'Exploring Neural Architecture Search for Low-Resource Machine Translation'"""
103
211
 
104
212
  focused_problem: List[str] = Field(default_factory=list)
105
- """The specific research problem or question that the paper aims to address."""
213
+ """Specific research problem(s) or question(s) addressed (list of 1-3 concise statements).
214
+ Example: ['NAS computational overhead in low-resource settings', 'Architecture transferability across language pairs']"""
215
+
106
216
  research_aim: List[str] = Field(default_factory=list)
107
- """The main objective or goal of the research, outlining what the study aims to achieve."""
217
+ """Primary research objectives (list of 2-4 measurable goals).
218
+ Example: ['Develop parameter-efficient NAS framework', 'Establish cross-lingual architecture transfer metrics']"""
219
+
108
220
  research_methods: List[str] = Field(default_factory=list)
109
- """The methods used in the research, including the approach, techniques, and tools employed."""
221
+ """Methodological components (list of techniques/tools).
222
+ Example: ['Differentiable architecture search', 'Transformer-based search space', 'Multi-lingual perplexity evaluation']"""
110
223
 
111
224
 
112
225
  class ArticleSubsectionOutline(Base):
113
- """Structured representation of the subsections of an academic paper."""
226
+ """Atomic content unit within academic paper sections.
227
+
228
+ Provides structured content specification for LLM-generated subsections.
229
+ """
114
230
 
115
231
  title: str = Field(...)
116
- """The title of the subsection."""
232
+ """Subsection title reflecting specific content focus (Title Case, 3-8 words).
233
+ Example: 'Differentiable Search Space Design'"""
117
234
 
118
235
  description: str = Field(...)
119
- """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."""
236
+ """Content specification with three required elements:
237
+ 1. Core technical content
238
+ 2. Structural purpose in section
239
+ 3. Research significance
240
+ Example: 'Introduces continuous relaxation method for search space, enabling gradient-based optimization. Forms technical foundation for Section 3. Critical for reducing search complexity.'"""
120
241
 
121
242
 
122
243
  class ArticleSectionOutline(Base):
123
- """Structured representation of the sections of an academic paper."""
244
+ """Primary organizational unit within paper chapters.
245
+
246
+ Defines section-level structure with nested subsections for hierarchical content organization.
247
+ """
124
248
 
125
249
  title: str = Field(...)
126
- """The title of the section."""
250
+ """Section title indicating methodological phase or conceptual component (Title Case).
251
+ Example: 'Architecture Search Methodology'"""
252
+
127
253
  description: str = Field(...)
128
- """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."""
254
+ """Functional description covering:
255
+ 1. Section's research stage
256
+ 2. Key contributions
257
+ 3. Flow relationship with adjacent sections
258
+ Example: 'Presents core NAS framework building on literature from Section 2. Introduces novel constrained search space. Leads to implementation details in Section 4.'"""
259
+
129
260
  subsections: List[ArticleSubsectionOutline]
130
- """The subsections of the section, outlining their content and significance."""
261
+ """Ordered sequence of 3-5 subsections implementing IMRaD structure within section. Maintains logical flow from problem statement to technical solution."""
131
262
 
132
263
 
133
264
  class ArticleChapterOutline(Base):
134
- """Structured representation of the chapters of an academic paper."""
265
+ """Macro-level paper organization unit.
266
+
267
+ Represents major paper divisions (Introduction, Methodology, etc.) with hierarchical section structure.
268
+ """
135
269
 
136
270
  title: str = Field(...)
137
- """The title of the chapter."""
271
+ """Chapter title reflecting standard academic sections (Title Case).
272
+ Example: 'Experimental Evaluation', 'Theoretical Framework'"""
273
+
138
274
  description: str = Field(...)
139
- """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."""
275
+ """Chapter role specification containing:
276
+ 1. Research phase covered
277
+ 2. Chapter-specific objectives
278
+ 3. Relationship to overall paper thesis
279
+ Example: 'Validates NAS framework through multilingual experiments. Demonstrates method effectiveness across 10 language pairs. Supports core thesis of parameter-efficient architecture search.'"""
280
+
140
281
  sections: List[ArticleSectionOutline]
141
- """The sections of the chapter, outlining their content and significance."""
282
+ """3-5 sections implementing chapter's main function. Ordered to maintain academic paper logic:
283
+ Introduction → Related Work → Methods → Experiments → Analysis"""
142
284
 
143
285
 
144
286
  class ArticleOutline(ProposedAble, Display, FinalizedDumpAble):
145
- """Structured representation of the outline for an academic paper."""
287
+ """Complete hierarchical structure for academic paper generation.
288
+
289
+ Provides multi-level outline specification for LLM-based paper drafting with strict academic conventions.
290
+ """
146
291
 
147
292
  title: str = Field(...)
148
- """The proposed title of the paper."""
293
+ """Full paper title with technical specificity (Title Case, 12-18 words).
294
+ Example: 'Parameter-Efficient Neural Architecture Search for Low-Resource Machine Translation: A Cross-Lingual Transfer Approach'"""
149
295
 
150
296
  prospect: str = Field(...)
151
- """A brief description of the research problem or question that the paper aims to address manipulating methods or techniques"""
297
+ """Unified problem-solution statement combining:
298
+ 1. Core research gap
299
+ 2. Proposed methodology
300
+ 3. Expected contribution
301
+ Example: 'Addressing NAS computational barriers in low-resource NLP through differentiable constrained search spaces and cross-lingual transfer metrics, enabling efficient architecture discovery for 50+ languages.'"""
152
302
 
153
303
  chapters: List[ArticleChapterOutline]
154
- """The chapters of the paper, outlining their content and significance."""
304
+ """Standard academic structure (5-8 chapters):
305
+ 1. Introduction
306
+ 2. Related Work
307
+ 3. Methodology
308
+ 4. Experiments
309
+ 5. Results
310
+ 6. Discussion
311
+ 7. Conclusion
312
+ Maintains IMRaD logical flow with clear inter-chapter transitions."""
155
313
 
156
314
  def finalized_dump(self) -> str:
157
- """Finalized dump of the article outline.
315
+ """Generates standardized hierarchical markup for paper drafting systems.
158
316
 
159
317
  Returns:
160
- str: The finalized dump of the article outline.
318
+ str: Multi-level outline using academic markup conventions:
319
+ = Chapter Title
320
+ == Section Title
321
+ === Subsection Title
322
+ ==== Subsubsection Title (if needed)
323
+
324
+ Example:
325
+ = Methodology
326
+ == Neural Architecture Search Framework
327
+ === Differentiable Search Space
328
+ === Constrained Optimization Approach
161
329
  """
162
330
  lines: List[str] = []
163
331
 
@@ -81,6 +81,7 @@ class ValidateKwargs[T](GenerateKwargs, total=False):
81
81
 
82
82
  default: T
83
83
  max_validations: int
84
+ co_extractor: GenerateKwargs
84
85
 
85
86
 
86
87
  # noinspection PyTypedDict
fabricatio/models/role.py CHANGED
@@ -3,7 +3,6 @@
3
3
  from typing import Any, Self, Set
4
4
 
5
5
  from fabricatio.capabilities.correct import Correct
6
- from fabricatio.capabilities.covalidate import CoValidate
7
6
  from fabricatio.capabilities.task import HandleTask, ProposeTask
8
7
  from fabricatio.core import env
9
8
  from fabricatio.journal import logger
@@ -13,7 +12,7 @@ from fabricatio.models.tool import ToolBox
13
12
  from pydantic import Field
14
13
 
15
14
 
16
- class Role(ProposeTask, HandleTask, Correct, CoValidate):
15
+ class Role(ProposeTask, HandleTask, Correct):
17
16
  """Class that represents a role with a registry of events and workflows.
18
17
 
19
18
  A Role serves as a container for workflows, managing their registration to events
@@ -12,9 +12,9 @@ from fabricatio.models.generic import ScopedConfig, WithBriefing
12
12
  from fabricatio.models.kwargs_types import ChooseKwargs, EmbeddingKwargs, GenerateKwargs, LLMKwargs, ValidateKwargs
13
13
  from fabricatio.models.task import Task
14
14
  from fabricatio.models.tool import Tool, ToolBox
15
- from fabricatio.models.utils import Messages
15
+ from fabricatio.models.utils import Messages, ok
16
16
  from fabricatio.parser import GenericCapture, JsonCapture
17
- from litellm import Router, stream_chunk_builder
17
+ from litellm import Router, stream_chunk_builder # pyright: ignore [reportPrivateImportUsage]
18
18
  from litellm.types.router import Deployment, LiteLLM_Params, ModelInfo
19
19
  from litellm.types.utils import (
20
20
  Choices,
@@ -70,14 +70,22 @@ class LLMUsage(ScopedConfig):
70
70
  """
71
71
  # Call the underlying asynchronous completion function with the provided and default parameters
72
72
  # noinspection PyTypeChecker,PydanticTypeChecker
73
-
74
73
  return await self._deploy(
75
74
  Deployment(
76
- model_name=(m_name := kwargs.get("model") or self.llm_model or configs.llm.model),
75
+ model_name=(
76
+ m_name := ok(
77
+ kwargs.get("model") or self.llm_model or configs.llm.model, "model name is not set at any place"
78
+ )
79
+ ), # pyright: ignore [reportCallIssue]
77
80
  litellm_params=(
78
81
  p := LiteLLM_Params(
79
- api_key=(self.llm_api_key or configs.llm.api_key).get_secret_value(),
80
- api_base=(self.llm_api_endpoint or configs.llm.api_endpoint).unicode_string(),
82
+ api_key=ok(
83
+ self.llm_api_key or configs.llm.api_key, "llm api key is not set at any place"
84
+ ).get_secret_value(),
85
+ api_base=ok(
86
+ self.llm_api_endpoint or configs.llm.api_endpoint,
87
+ "llm api endpoint is not set at any place",
88
+ ).unicode_string(),
81
89
  model=m_name,
82
90
  tpm=self.llm_tpm or configs.llm.tpm,
83
91
  rpm=self.llm_rpm or configs.llm.rpm,
@@ -88,14 +96,14 @@ class LLMUsage(ScopedConfig):
88
96
  model_info=ModelInfo(id=hash(m_name + p.model_dump_json(exclude_none=True))),
89
97
  )
90
98
  ).acompletion(
91
- messages=messages,
99
+ messages=messages, # pyright: ignore [reportArgumentType]
92
100
  n=n or self.llm_generation_count or configs.llm.generation_count,
93
101
  model=m_name,
94
102
  temperature=kwargs.get("temperature") or self.llm_temperature or configs.llm.temperature,
95
103
  stop=kwargs.get("stop") or self.llm_stop_sign or configs.llm.stop_sign,
96
104
  top_p=kwargs.get("top_p") or self.llm_top_p or configs.llm.top_p,
97
105
  max_tokens=kwargs.get("max_tokens") or self.llm_max_tokens or configs.llm.max_tokens,
98
- stream=kwargs.get("stream") or self.llm_stream or configs.llm.stream,
106
+ stream=ok(kwargs.get("stream") or self.llm_stream or configs.llm.stream, "stream is not set at any place"),
99
107
  cache={
100
108
  "no-cache": kwargs.get("no_cache"),
101
109
  "no-store": kwargs.get("no_store"),
@@ -196,15 +204,15 @@ class LLMUsage(ScopedConfig):
196
204
  for q, sm in zip(q_seq, sm_seq, strict=True)
197
205
  ]
198
206
  )
199
- return [r[0].message.content for r in res]
207
+ return [r[0].message.content for r in res] # pyright: ignore [reportReturnType, reportAttributeAccessIssue]
200
208
  case (list(q_seq), str(sm)):
201
209
  res = await gather(*[self.ainvoke(n=1, question=q, system_message=sm, **kwargs) for q in q_seq])
202
- return [r[0].message.content for r in res]
210
+ return [r[0].message.content for r in res] # pyright: ignore [reportReturnType, reportAttributeAccessIssue]
203
211
  case (str(q), list(sm_seq)):
204
212
  res = await gather(*[self.ainvoke(n=1, question=q, system_message=sm, **kwargs) for sm in sm_seq])
205
- return [r[0].message.content for r in res]
213
+ return [r[0].message.content for r in res] # pyright: ignore [reportReturnType, reportAttributeAccessIssue]
206
214
  case (str(q), str(sm)):
207
- return ((await self.ainvoke(n=1, question=q, system_message=sm, **kwargs))[0]).message.content
215
+ return ((await self.ainvoke(n=1, question=q, system_message=sm, **kwargs))[0]).message.content # pyright: ignore [reportReturnType, reportAttributeAccessIssue]
208
216
  case _:
209
217
  raise RuntimeError("Should not reach here.")
210
218
 
@@ -215,6 +223,7 @@ class LLMUsage(ScopedConfig):
215
223
  validator: Callable[[str], T | None],
216
224
  default: T = ...,
217
225
  max_validations: PositiveInt = 2,
226
+ co_extractor: Optional[GenerateKwargs] = None,
218
227
  **kwargs: Unpack[GenerateKwargs],
219
228
  ) -> T: ...
220
229
  @overload
@@ -224,6 +233,7 @@ class LLMUsage(ScopedConfig):
224
233
  validator: Callable[[str], T | None],
225
234
  default: T = ...,
226
235
  max_validations: PositiveInt = 2,
236
+ co_extractor: Optional[GenerateKwargs] = None,
227
237
  **kwargs: Unpack[GenerateKwargs],
228
238
  ) -> List[T]: ...
229
239
  @overload
@@ -233,6 +243,7 @@ class LLMUsage(ScopedConfig):
233
243
  validator: Callable[[str], T | None],
234
244
  default: None = None,
235
245
  max_validations: PositiveInt = 2,
246
+ co_extractor: Optional[GenerateKwargs] = None,
236
247
  **kwargs: Unpack[GenerateKwargs],
237
248
  ) -> Optional[T]: ...
238
249
 
@@ -243,6 +254,7 @@ class LLMUsage(ScopedConfig):
243
254
  validator: Callable[[str], T | None],
244
255
  default: None = None,
245
256
  max_validations: PositiveInt = 2,
257
+ co_extractor: Optional[GenerateKwargs] = None,
246
258
  **kwargs: Unpack[GenerateKwargs],
247
259
  ) -> List[Optional[T]]: ...
248
260
 
@@ -252,6 +264,7 @@ class LLMUsage(ScopedConfig):
252
264
  validator: Callable[[str], T | None],
253
265
  default: Optional[T] = None,
254
266
  max_validations: PositiveInt = 2,
267
+ co_extractor: Optional[GenerateKwargs] = None,
255
268
  **kwargs: Unpack[GenerateKwargs],
256
269
  ) -> Optional[T] | List[Optional[T]] | List[T] | T:
257
270
  """Asynchronously asks a question and validates the response using a given validator.
@@ -261,6 +274,7 @@ class LLMUsage(ScopedConfig):
261
274
  validator (Callable[[str], T | None]): A function to validate the response.
262
275
  default (T | None): Default value to return if validation fails. Defaults to None.
263
276
  max_validations (PositiveInt): Maximum number of validation attempts. Defaults to 2.
277
+ co_extractor (Optional[GenerateKwargs]): Keyword arguments for the co-extractor, if provided will enable co-extraction.
264
278
  **kwargs (Unpack[LLMKwargs]): Additional keyword arguments for the LLM usage.
265
279
 
266
280
  Returns:
@@ -274,6 +288,23 @@ class LLMUsage(ScopedConfig):
274
288
  if (response := await self.aask(question=q, **kwargs)) and (validated := validator(response)):
275
289
  logger.debug(f"Successfully validated the response at {lap}th attempt.")
276
290
  return validated
291
+
292
+ if co_extractor and (
293
+ (
294
+ co_response := await self.aask(
295
+ question=(
296
+ TEMPLATE_MANAGER.render_template(
297
+ configs.templates.co_validation_template,
298
+ {"original_q": q, "original_a": response},
299
+ )
300
+ ),
301
+ **co_extractor,
302
+ )
303
+ )
304
+ and (validated := validator(co_response))
305
+ ):
306
+ logger.debug(f"Successfully validated the co-response at {lap}th attempt.")
307
+ return validated
277
308
  except Exception as e: # noqa: BLE001
278
309
  logger.error(f"Error during validation: \n{e}")
279
310
  break
@@ -291,7 +322,7 @@ class LLMUsage(ScopedConfig):
291
322
 
292
323
  async def aliststr(
293
324
  self, requirement: str, k: NonNegativeInt = 0, **kwargs: Unpack[ValidateKwargs[List[str]]]
294
- ) -> List[str]:
325
+ ) -> Optional[List[str]]:
295
326
  """Asynchronously generates a list of strings based on a given requirement.
296
327
 
297
328
  Args:
@@ -311,7 +342,7 @@ class LLMUsage(ScopedConfig):
311
342
  **kwargs,
312
343
  )
313
344
 
314
- async def apathstr(self, requirement: str, **kwargs: Unpack[ChooseKwargs[List[str]]]) -> List[str]:
345
+ async def apathstr(self, requirement: str, **kwargs: Unpack[ChooseKwargs[List[str]]]) -> Optional[List[str]]:
315
346
  """Asynchronously generates a list of strings based on a given requirement.
316
347
 
317
348
  Args:
@@ -339,7 +370,7 @@ class LLMUsage(ScopedConfig):
339
370
  Returns:
340
371
  str: The validated response as a single string.
341
372
  """
342
- return (
373
+ return ok(
343
374
  await self.apathstr(
344
375
  requirement,
345
376
  k=1,
@@ -347,7 +378,7 @@ class LLMUsage(ScopedConfig):
347
378
  )
348
379
  ).pop()
349
380
 
350
- async def ageneric_string(self, requirement: str, **kwargs: Unpack[ValidateKwargs[str]]) -> str:
381
+ async def ageneric_string(self, requirement: str, **kwargs: Unpack[ValidateKwargs[str]]) -> Optional[str]:
351
382
  """Asynchronously generates a generic string based on a given requirement.
352
383
 
353
384
  Args:
@@ -357,7 +388,7 @@ class LLMUsage(ScopedConfig):
357
388
  Returns:
358
389
  str: The generated string.
359
390
  """
360
- return await self.aask_validate(
391
+ return await self.aask_validate( # pyright: ignore [reportReturnType]
361
392
  TEMPLATE_MANAGER.render_template(
362
393
  configs.templates.generic_string_template,
363
394
  {"requirement": requirement, "language": GenericCapture.capture_type},
@@ -372,7 +403,7 @@ class LLMUsage(ScopedConfig):
372
403
  choices: List[T],
373
404
  k: NonNegativeInt = 0,
374
405
  **kwargs: Unpack[ValidateKwargs[List[T]]],
375
- ) -> List[T]:
406
+ ) -> Optional[List[T]]:
376
407
  """Asynchronously executes a multi-choice decision-making process, generating a prompt based on the instruction and options, and validates the returned selection results.
377
408
 
378
409
  Args:
@@ -437,13 +468,13 @@ class LLMUsage(ScopedConfig):
437
468
  Raises:
438
469
  ValueError: If validation fails after maximum attempts or if no valid selection is made.
439
470
  """
440
- return (
471
+ return ok(
441
472
  await self.achoose(
442
473
  instruction=instruction,
443
474
  choices=choices,
444
475
  k=1,
445
476
  **kwargs,
446
- )
477
+ ),
447
478
  )[0]
448
479
 
449
480
  async def ajudge(
@@ -500,7 +531,7 @@ class EmbeddingUsage(LLMUsage):
500
531
  """
501
532
  # check seq length
502
533
  max_len = self.embedding_max_sequence_length or configs.embedding.max_sequence_length
503
- if any(len(t) > max_len for t in input_text):
534
+ if max_len and any(len(t) > max_len for t in input_text):
504
535
  logger.error(err := f"Input text exceeds maximum sequence length {max_len}.")
505
536
  raise ValueError(err)
506
537
 
@@ -514,10 +545,10 @@ class EmbeddingUsage(LLMUsage):
514
545
  or configs.embedding.timeout
515
546
  or self.llm_timeout
516
547
  or configs.llm.timeout,
517
- api_key=(
548
+ api_key=ok(
518
549
  self.embedding_api_key or configs.embedding.api_key or self.llm_api_key or configs.llm.api_key
519
550
  ).get_secret_value(),
520
- api_base=(
551
+ api_base=ok(
521
552
  self.embedding_api_endpoint
522
553
  or configs.embedding.api_endpoint
523
554
  or self.llm_api_endpoint
@@ -566,7 +597,7 @@ class ToolBoxUsage(LLMUsage):
566
597
  self,
567
598
  task: Task,
568
599
  **kwargs: Unpack[ChooseKwargs[List[ToolBox]]],
569
- ) -> List[ToolBox]:
600
+ ) -> Optional[List[ToolBox]]:
570
601
  """Asynchronously executes a multi-choice decision-making process to choose toolboxes.
571
602
 
572
603
  Args:
@@ -591,7 +622,7 @@ class ToolBoxUsage(LLMUsage):
591
622
  task: Task,
592
623
  toolbox: ToolBox,
593
624
  **kwargs: Unpack[ChooseKwargs[List[Tool]]],
594
- ) -> List[Tool]:
625
+ ) -> Optional[List[Tool]]:
595
626
  """Asynchronously executes a multi-choice decision-making process to choose tools.
596
627
 
597
628
  Args:
@@ -631,11 +662,11 @@ class ToolBoxUsage(LLMUsage):
631
662
  tool_choose_kwargs = tool_choose_kwargs or {}
632
663
 
633
664
  # Choose the toolboxes
634
- chosen_toolboxes = await self.choose_toolboxes(task, **box_choose_kwargs)
665
+ chosen_toolboxes = ok(await self.choose_toolboxes(task, **box_choose_kwargs))
635
666
  # Choose the tools
636
667
  chosen_tools = []
637
668
  for toolbox in chosen_toolboxes:
638
- chosen_tools.extend(await self.choose_tools(task, toolbox, **tool_choose_kwargs))
669
+ chosen_tools.extend(ok(await self.choose_tools(task, toolbox, **tool_choose_kwargs)))
639
670
  return chosen_tools
640
671
 
641
672
  async def gather_tools(self, task: Task, **kwargs: Unpack[ChooseKwargs]) -> List[Tool]:
@@ -165,3 +165,24 @@ async def ask_edit(
165
165
  if edited:
166
166
  res.append(edited)
167
167
  return res
168
+
169
+
170
+ def override_kwargs[T](kwargs: Dict[str, T], **overrides) -> Dict[str, T]:
171
+ """Override the values in kwargs with the provided overrides."""
172
+ kwargs.update({k: v for k, v in overrides.items() if v is not None})
173
+ return kwargs
174
+
175
+
176
+ def ok[T](val: Optional[T], msg:str="Value is None") -> T:
177
+ """Check if a value is None and raise a ValueError with the provided message if it is.
178
+
179
+ Args:
180
+ val: The value to check.
181
+ msg: The message to include in the ValueError if val is None.
182
+
183
+ Returns:
184
+ T: The value if it is not None.
185
+ """
186
+ if val is None:
187
+ raise ValueError(msg)
188
+ return val
fabricatio/parser.py CHANGED
@@ -52,6 +52,7 @@ class Capture(BaseModel):
52
52
  case _:
53
53
  return text
54
54
 
55
+
55
56
  def capture(self, text: str) -> Tuple[str, ...] | str | None:
56
57
  """Capture the first occurrence of the pattern in the given text.
57
58
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fabricatio
3
- Version: 0.2.6.dev5
3
+ Version: 0.2.6.dev6
4
4
  Classifier: License :: OSI Approved :: MIT License
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -1,18 +1,18 @@
1
- fabricatio-0.2.6.dev5.dist-info/METADATA,sha256=fDyrjLOMA7hb-NFEGY3jM5sMjkDDfHQ-PIYRHqjQvO0,13693
2
- fabricatio-0.2.6.dev5.dist-info/WHEEL,sha256=RIvmwLDYujv60MYBx2jxyP4vdn1DD7X0kBgz1TQvZuc,108
3
- fabricatio-0.2.6.dev5.dist-info/licenses/LICENSE,sha256=yDZaTLnOi03bi3Dk6f5IjhLUc5old2yOsihHWU0z-i0,1067
1
+ fabricatio-0.2.6.dev6.dist-info/METADATA,sha256=9pqI0pxZslMJl25ehrBbGfOGeCikqwFGDVWNYwaAYXs,13693
2
+ fabricatio-0.2.6.dev6.dist-info/WHEEL,sha256=7FgAcpQES0h1xhfN9Ugve9FTUilU6sRAr1WJ5ph2cuw,108
3
+ fabricatio-0.2.6.dev6.dist-info/licenses/LICENSE,sha256=yDZaTLnOi03bi3Dk6f5IjhLUc5old2yOsihHWU0z-i0,1067
4
4
  fabricatio/decorators.py,sha256=cJHsxxbnMhc4SzPl4454CPLuDP3H0qbTrzV_U2rLPrs,6372
5
5
  fabricatio/core.py,sha256=MaEKZ6DDmbdScAY-7F1gwGA6fr7ADX6Mz5rNVi2msFA,6277
6
6
  fabricatio/models/generic.py,sha256=WxT4KBGGZTpqGPSPVwD5mkmhYBjxggZ7n-HKi-Hed4M,13619
7
7
  fabricatio/models/tool.py,sha256=ATwbOyvOTzrfAKcbOmCqdG3je4-T5jrM6FIw4cDPRDY,6863
8
- fabricatio/models/role.py,sha256=m-orT8xtiI9t0MvCzwVnfnPXPoocS2z6Twaim_nSmNE,2780
9
- fabricatio/models/extra.py,sha256=2TyrlYOfTe-Z-9eZxV8K7lXQLHz3y5Ze97JYZnnqg9U,7219
10
- fabricatio/models/kwargs_types.py,sha256=7MjoTtGfSUx4jws_DlvK2ud7au6Y2z50Umr3PFtmSTc,4435
11
- fabricatio/models/utils.py,sha256=KmsTQcBCTYgnsZz7U1ECSfLRdswWPkKtGg8mBMaXrwA,4850
12
- fabricatio/models/usages.py,sha256=SvfASbO_nqbZ1fvn-dTMldjQetFcin3ADwVC8xmN-nQ,28019
8
+ fabricatio/models/role.py,sha256=UgIfGdfIBu4cOug8Nm1a04JCEwjXR_MDZUQhumwMptk,2710
9
+ fabricatio/models/extra.py,sha256=tP58nLHlwgkM9F9EzVoDV7JP2n_1h-10uo2WRFouXuw,13448
10
+ fabricatio/models/kwargs_types.py,sha256=VB_2X2cUdhD0syVl_5vPi0GU3qH5MjO7GiS44we9OO8,4468
11
+ fabricatio/models/utils.py,sha256=snRuH81CQfTr9GZMSV_cW0JZocwfttgsKAqFWPk_Vc8,5480
12
+ fabricatio/models/usages.py,sha256=ovuvDab9wvn9no4_a93HVcdo8Da1kF_eOnMoqph7LcY,30145
13
13
  fabricatio/models/events.py,sha256=UvOc6V3vfjKuvh7irDezJ8EGpsNo5yzLdq4xQexVonw,4063
14
14
  fabricatio/models/task.py,sha256=-EnzpEyM6Z687gF1lPcmA2szEUw6dFpu3lOtseaz95o,10193
15
- fabricatio/models/action.py,sha256=C8zyrZbJdMmspJFFbsoXK1B5R0WCbY46G3CLAarxnWo,8062
15
+ fabricatio/models/action.py,sha256=Y8fYLWi28edtmi9KZIlE9E7M9_G4GcWMeraTLPVjp_c,7992
16
16
  fabricatio/toolboxes/fs.py,sha256=OQMdeokYxSNVrCZJAweJ0cYiK4k2QuEiNdIbS5IHIV8,705
17
17
  fabricatio/toolboxes/__init__.py,sha256=dYm_Gd8XolSU_h4wnkA09dlaLDK146eeFz0CUgPZ8_c,380
18
18
  fabricatio/toolboxes/arithmetic.py,sha256=sSTPkKI6-mb278DwQKFO9jKyzc9kCx45xNH7V6bGBpE,1307
@@ -20,24 +20,23 @@ fabricatio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  fabricatio/fs/readers.py,sha256=5bLlpqcdhIwWfysh7gvfVv0PPPVAeDlTPGwNTio6j9M,1156
21
21
  fabricatio/fs/curd.py,sha256=FuG75qco4dX8vhIK27gKz9rKUXbWHOFg5yK3nGLB25s,4469
22
22
  fabricatio/fs/__init__.py,sha256=hTuYtzmvIGtbg7PTdoqLEQJ0E63hOzZltCIrLlDKaSE,559
23
- fabricatio/config.py,sha256=vRCDnCyBgQoNCiwMEVdlD8_ij9Q7rykdpsod3XHtD-8,16191
23
+ fabricatio/config.py,sha256=6BXaIUZsfxuIvNOt74lmlBYoS_uBQhcCwGAmmxdvKZk,16232
24
24
  fabricatio/journal.py,sha256=Op0wC-JlZumnAc_aDmYM4ljnSNLoKEEMfcIRbCF69ow,455
25
25
  fabricatio/__init__.py,sha256=6EjK4SxbnvFxdO9ftkXD9rxSuoPEIITNzUkuMO9s3yU,1092
26
26
  fabricatio/actions/output.py,sha256=wNyLNxjqBlms0hyxap8XUPgN53izipJrCOtpX6aluFQ,626
27
27
  fabricatio/actions/rag.py,sha256=xCCNPM4pgjGlKaIl1J4SpWoNx3oWlSMxq6pQRSquXmc,788
28
- fabricatio/actions/article.py,sha256=dQ0Ca83v8yhO2n-IGtm4gIojXfsYD8s-HWRpPO5a7a4,4338
28
+ fabricatio/actions/article.py,sha256=m3ejPgLX7WXcg-CfqRjQmanc5qSvCsT_u02wW9Jb23w,4435
29
29
  fabricatio/_rust_instances.py,sha256=bQmlhUCcxTmRgvw1SfzYzNNpgW_UCjmkYw5f-VPAyg8,304
30
30
  fabricatio/workflows/articles.py,sha256=oHNV5kNKEcOKP55FA7I1SlxQRlk6N26cpem_QYu05g0,1021
31
31
  fabricatio/workflows/rag.py,sha256=uOZXprD479fUhLA6sYvEM8RWcVcUZXXtP0xRbTMPdHE,509
32
- fabricatio/parser.py,sha256=Jr2ELtcmiRNAyz76TCWoJuUpG7zrJoRn3GfaX9vZSJM,6099
32
+ fabricatio/parser.py,sha256=OV6bIAfLJ-GfaKoTeIOqS3X3GqCgyvzSJsgYMO3ogj4,6100
33
33
  fabricatio/capabilities/correct.py,sha256=BiLEAk6e1KbwUMhTexmDfgtlPUct_bG0igDK7CwHqao,5107
34
- fabricatio/capabilities/rag.py,sha256=ghctqjIf6KDe6PP8-SDzKN1zxh94rXk5Y5hHFtG_46Y,15404
35
- fabricatio/capabilities/covalidate.py,sha256=uEpZNpzsQoIM5ZP4sntUhBveNhhqrAzQ6Q9-2WDlpPg,6461
34
+ fabricatio/capabilities/rag.py,sha256=hyQMgpFrefwMT84Huh728xsVQXNEYkUH2-98KJyfOas,15420
36
35
  fabricatio/capabilities/rating.py,sha256=ZQrKKmmIgnN4zgNnG_GmWa5Nyxpk03JYW32RJ4R5vvQ,14067
37
36
  fabricatio/capabilities/review.py,sha256=TX7av4b2N7MRDHMowsIZfiujXRRNxjUMNHtCFVA1UTM,10824
38
37
  fabricatio/capabilities/propose.py,sha256=4QvONVVUp1rs34Te2Rjams6NioEt6FhEAxDWiveQnSg,1544
39
38
  fabricatio/capabilities/task.py,sha256=llFFKh8MAaTjsp8DtAGD_UUONROfFNxorh6NLys973U,4496
40
39
  fabricatio/_rust.pyi,sha256=1TvnaXK_QKM8Et05LkZ_vOGR4WISVd9X8lU6OTwFFaU,3376
41
40
  fabricatio/_rust.cpython-312-x86_64-linux-gnu.so,sha256=Qv4F28dducNx2GS8L8TmMWuk3MgBivQbzH_UmC-1P2w,1911376
42
- fabricatio-0.2.6.dev5.data/scripts/tdown,sha256=h7dazHQEgymw8fXo1ROyyUfwLMMw7l4JyMlt2xJyN-4,4576688
43
- fabricatio-0.2.6.dev5.dist-info/RECORD,,
41
+ fabricatio-0.2.6.dev6.data/scripts/tdown,sha256=h7dazHQEgymw8fXo1ROyyUfwLMMw7l4JyMlt2xJyN-4,4576688
42
+ fabricatio-0.2.6.dev6.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: maturin (1.8.2)
2
+ Generator: maturin (1.8.3)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp312-cp312-manylinux_2_34_x86_64
@@ -1,160 +0,0 @@
1
- """Co-validation capability for LLMs."""
2
-
3
- from asyncio import gather
4
- from typing import Callable, List, Optional, Union, Unpack, overload
5
-
6
- from fabricatio import TEMPLATE_MANAGER
7
- from fabricatio.config import configs
8
- from fabricatio.journal import logger
9
- from fabricatio.models.kwargs_types import GenerateKwargs
10
- from fabricatio.models.usages import LLMUsage
11
-
12
-
13
- class CoValidate(LLMUsage):
14
- """Class that represents a co-validation capability using multiple LLMs.
15
-
16
- This class provides methods to validate responses by attempting multiple approaches:
17
- 1. Using the primary LLM to generate a response
18
- 2. Using a secondary (co-) model to refine responses that fail validation
19
- 3. Trying multiple times if needed
20
- """
21
-
22
- @overload
23
- async def aask_covalidate[T](
24
- self,
25
- question: str,
26
- validator: Callable[[str], T | None],
27
- co_model: Optional[str] = None,
28
- co_temperature: Optional[float] = None,
29
- co_top_p: Optional[float] = None,
30
- co_max_tokens: Optional[int] = None,
31
- max_validations: int = 2,
32
- default: None = None,
33
- **kwargs: Unpack[GenerateKwargs],
34
- ) -> T | None: ...
35
-
36
- @overload
37
- async def aask_covalidate[T](
38
- self,
39
- question: str,
40
- validator: Callable[[str], T | None],
41
- co_model: Optional[str] = None,
42
- co_temperature: Optional[float] = None,
43
- co_top_p: Optional[float] = None,
44
- co_max_tokens: Optional[int] = None,
45
- max_validations: int = 2,
46
- default: T = ...,
47
- **kwargs: Unpack[GenerateKwargs],
48
- ) -> T: ...
49
-
50
- @overload
51
- async def aask_covalidate[T](
52
- self,
53
- question: List[str],
54
- validator: Callable[[str], T | None],
55
- co_model: Optional[str] = None,
56
- co_temperature: Optional[float] = None,
57
- co_top_p: Optional[float] = None,
58
- co_max_tokens: Optional[int] = None,
59
- max_validations: int = 2,
60
- default: None = None,
61
- **kwargs: Unpack[GenerateKwargs],
62
- ) -> List[T | None]: ...
63
-
64
- @overload
65
- async def aask_covalidate[T](
66
- self,
67
- question: List[str],
68
- validator: Callable[[str], T | None],
69
- co_model: Optional[str] = None,
70
- co_temperature: Optional[float] = None,
71
- co_top_p: Optional[float] = None,
72
- co_max_tokens: Optional[int] = None,
73
- max_validations: int = 2,
74
- default: T = ...,
75
- **kwargs: Unpack[GenerateKwargs],
76
- ) -> List[T]: ...
77
-
78
- async def aask_covalidate[T](
79
- self,
80
- question: Union[str, List[str]],
81
- validator: Callable[[str], T | None],
82
- co_model: Optional[str] = None,
83
- co_temperature: Optional[float] = None,
84
- co_top_p: Optional[float] = None,
85
- co_max_tokens: Optional[int] = None,
86
- max_validations: int = 2,
87
- default: Optional[T] = None,
88
- **kwargs: Unpack[GenerateKwargs],
89
- ) -> Union[T | None, List[T | None]]:
90
- """Ask the LLM with co-validation to obtain a validated response.
91
-
92
- This method attempts to generate a response that passes validation using two approaches:
93
- 1. First, it asks the primary LLM using the original question
94
- 2. If validation fails, it uses a secondary (co-) model with a template to improve the response
95
- 3. The process repeats up to max_validations times
96
-
97
- Args:
98
- question: String question or list of questions to ask
99
- validator: Function that validates responses, returns result or None if invalid
100
- co_model: Optional model name for the co-validator
101
- co_temperature: Optional temperature setting for the co-validator
102
- co_top_p: Optional top_p setting for the co-validator
103
- co_max_tokens: Optional maximum tokens for the co-validator response
104
- max_validations: Maximum number of validation attempts
105
- default: Default value to return if validation fails
106
- **kwargs: Additional keyword arguments passed to aask method
107
-
108
- Returns:
109
- The validated result (T) or default if validation fails.
110
- If input is a list of questions, returns a list of results.
111
- """
112
-
113
- async def validate_single_question(q: str) -> Optional[T]:
114
- """Process a single question with validation attempts."""
115
- validation_kwargs = kwargs.copy()
116
-
117
- for lap in range(max_validations):
118
- try:
119
- # First attempt: direct question to primary model
120
- response = await self.aask(question=q, **validation_kwargs)
121
- if response and (validated := validator(response)):
122
- logger.debug(f"Successfully validated the primary response at {lap}th attempt.")
123
- return validated
124
-
125
- # Second attempt: use co-model with validation template
126
- co_prompt = TEMPLATE_MANAGER.render_template(
127
- configs.templates.co_validation_template,
128
- {"original_q": q, "original_a": response},
129
- )
130
- co_response = await self.aask(
131
- question=co_prompt,
132
- model=co_model,
133
- temperature=co_temperature,
134
- top_p=co_top_p,
135
- max_tokens=co_max_tokens,
136
- )
137
-
138
- if co_response and (validated := validator(co_response)):
139
- logger.debug(f"Successfully validated the co-response at {lap}th attempt.")
140
- return validated
141
-
142
- except Exception as e: # noqa: BLE001
143
- logger.error(f"Error during validation: \n{e}")
144
- break
145
-
146
- # Disable caching for subsequent attempts
147
- if not validation_kwargs.get("no_cache"):
148
- validation_kwargs["no_cache"] = True
149
- logger.debug("Disabled cache for the next attempt")
150
-
151
- if default is None:
152
- logger.error(f"Failed to validate the response after {max_validations} attempts.")
153
- return default
154
-
155
- # Handle single question or list of questions
156
- if isinstance(question, str):
157
- return await validate_single_question(question)
158
-
159
- # Process multiple questions in parallel
160
- return await gather(*[validate_single_question(q) for q in question])