fabricatio 0.2.5.dev2__tar.gz → 0.2.5.dev3__tar.gz

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 (109) hide show
  1. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/PKG-INFO +1 -1
  2. fabricatio-0.2.5.dev3/examples/extract_and_review/.gitignore +1 -0
  3. fabricatio-0.2.5.dev3/examples/extract_and_review/extract_and_review.py +37 -0
  4. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/pyproject.toml +1 -1
  5. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/_rust.pyi +1 -1
  6. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/_rust_instances.py +0 -1
  7. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/capabilities/propose.py +3 -3
  8. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/capabilities/rating.py +15 -1
  9. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/capabilities/review.py +30 -4
  10. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/fs/__init__.py +2 -0
  11. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/fs/curd.py +13 -0
  12. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/journal.py +0 -1
  13. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/models/action.py +3 -4
  14. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/models/kwargs_types.py +50 -10
  15. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/models/usages.py +38 -35
  16. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/toolboxes/fs.py +2 -0
  17. fabricatio-0.2.5.dev3/templates.tar.gz +0 -0
  18. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/uv.lock +1 -1
  19. fabricatio-0.2.5.dev2/templates.tar.gz +0 -0
  20. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/.github/workflows/build-package.yaml +0 -0
  21. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/.github/workflows/ruff.yaml +0 -0
  22. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/.github/workflows/tests.yaml +0 -0
  23. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/.gitignore +0 -0
  24. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/.python-version +0 -0
  25. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/Cargo.lock +0 -0
  26. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/Cargo.toml +0 -0
  27. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/LICENSE +0 -0
  28. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/Makefile +0 -0
  29. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/README.md +0 -0
  30. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/extract_article/extract.py +0 -0
  31. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/llm_usages/llm_usage.py +0 -0
  32. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/make_a_rating/rating.py +0 -0
  33. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/make_diary/commits.json +0 -0
  34. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/make_diary/diary.py +0 -0
  35. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/minor/hello_fabricatio.py +0 -0
  36. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/propose_task/propose.py +0 -0
  37. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/reviewer/review.py +0 -0
  38. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/simple_chat/chat.py +0 -0
  39. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/simple_rag/simple_rag.py +0 -0
  40. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/task_handle/handle_task.py +0 -0
  41. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/write_outline/.gitignore +0 -0
  42. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/examples/write_outline/write_outline.py +0 -0
  43. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/__init__.py +0 -0
  44. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/actions/article.py +0 -0
  45. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/actions/output.py +0 -0
  46. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/actions/rag.py +0 -0
  47. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/capabilities/rag.py +0 -0
  48. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/capabilities/task.py +0 -0
  49. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/config.py +0 -0
  50. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/core.py +0 -0
  51. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/decorators.py +0 -0
  52. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/fs/readers.py +0 -0
  53. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/models/events.py +0 -0
  54. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/models/extra.py +0 -0
  55. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/models/generic.py +0 -0
  56. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/models/role.py +0 -0
  57. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/models/task.py +0 -0
  58. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/models/tool.py +0 -0
  59. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/models/utils.py +0 -0
  60. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/parser.py +0 -0
  61. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/py.typed +0 -0
  62. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/toolboxes/__init__.py +0 -0
  63. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/toolboxes/arithmetic.py +0 -0
  64. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/workflows/articles.py +0 -0
  65. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/python/fabricatio/workflows/rag.py +0 -0
  66. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/src/bib_tools.rs +0 -0
  67. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/src/hash.rs +0 -0
  68. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/src/hbs_helpers.rs +0 -0
  69. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/src/lib.rs +0 -0
  70. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/src/templates.rs +0 -0
  71. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/binary-exploitation-ctf-solver.hbs +0 -0
  72. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/claude-xml.hbs +0 -0
  73. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/clean-up-code.hbs +0 -0
  74. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/create_json_obj.hbs +0 -0
  75. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/cryptography-ctf-solver.hbs +0 -0
  76. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/dependencies.hbs +0 -0
  77. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/document-the-code.hbs +0 -0
  78. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/draft_rating_criteria.hbs +0 -0
  79. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/draft_rating_manual.hbs +0 -0
  80. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/draft_rating_weights_klee.hbs +0 -0
  81. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/draft_tool_usage_code.hbs +0 -0
  82. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/extract_criteria_from_reasons.hbs +0 -0
  83. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/extract_reasons_from_examples.hbs +0 -0
  84. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/find-security-vulnerabilities.hbs +0 -0
  85. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/fix-bugs.hbs +0 -0
  86. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/improve-performance.hbs +0 -0
  87. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/liststr.hbs +0 -0
  88. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/make_choice.hbs +0 -0
  89. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/make_judgment.hbs +0 -0
  90. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/pathstr.hbs +0 -0
  91. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/rate_fine_grind.hbs +0 -0
  92. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/refactor.hbs +0 -0
  93. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/refined_query.hbs +0 -0
  94. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/retrieved_display.hbs +0 -0
  95. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/reverse-engineering-ctf-solver.hbs +0 -0
  96. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/review_string.hbs +0 -0
  97. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/task_briefing.hbs +0 -0
  98. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/web-ctf-solver.hbs +0 -0
  99. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/write-git-commit.hbs +0 -0
  100. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/write-github-pull-request.hbs +0 -0
  101. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/templates/built-in/write-github-readme.hbs +0 -0
  102. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/tests/test_config.py +0 -0
  103. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/tests/test_models/test_action.py +0 -0
  104. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/tests/test_models/test_advanced.py +0 -0
  105. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/tests/test_models/test_generic.py +0 -0
  106. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/tests/test_models/test_role.py +0 -0
  107. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/tests/test_models/test_task.py +0 -0
  108. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/tests/test_models/test_tool.py +0 -0
  109. {fabricatio-0.2.5.dev2 → fabricatio-0.2.5.dev3}/tests/test_models/test_usages.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fabricatio
3
- Version: 0.2.5.dev2
3
+ Version: 0.2.5.dev3
4
4
  Classifier: License :: OSI Approved :: MIT License
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -0,0 +1,37 @@
1
+ """Example of proposing a task to a role."""
2
+
3
+ import asyncio
4
+ from pathlib import Path
5
+ from typing import List
6
+
7
+ from fabricatio import ArticleEssence, Event, ExtractArticleEssence, Role, Task, WorkFlow, logger
8
+ from fabricatio.fs.curd import dump_text, gather_files
9
+
10
+
11
+ async def main() -> None:
12
+ """Main function."""
13
+ role = Role(
14
+ name="Researcher",
15
+ description="Extract article essence",
16
+ registry={
17
+ Event.quick_instantiate("article"): WorkFlow(
18
+ name="extract",
19
+ steps=(ExtractArticleEssence(output_key="task_output"),),
20
+ )
21
+ },
22
+ )
23
+
24
+ task: Task[List[ArticleEssence]] = await role.propose_task(
25
+ "Extract the essence of the article from the files in './bpdf_out'",
26
+ )
27
+
28
+ ess = await task.override_dependencies(gather_files("bpdf_out", "md")).delegate("article")
29
+ logger.success(f"Essence Count:{len(ess)}")
30
+
31
+ Path("output").mkdir(exist_ok=True)
32
+ for i, e in enumerate(ess):
33
+ dump_text(f"output/{i}.json", e.display())
34
+
35
+
36
+ if __name__ == "__main__":
37
+ asyncio.run(main())
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fabricatio"
3
- version = "0.2.5-dev2"
3
+ version = "0.2.5-dev3"
4
4
  description = "A LLM multi-agent framework."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -99,4 +99,4 @@ class BibManager:
99
99
  Notes:
100
100
  Uses nucleo_matcher for high-quality fuzzy text searching
101
101
  See: https://crates.io/crates/nucleo-matcher
102
- """
102
+ """
@@ -1,7 +1,6 @@
1
1
  """Some necessary instances."""
2
2
 
3
3
  from fabricatio._rust import TemplateManager
4
-
5
4
  from fabricatio.config import configs
6
5
 
7
6
  template_manager = TemplateManager(
@@ -15,7 +15,7 @@ class Propose[M: ProposedAble](LLMUsage):
15
15
  self,
16
16
  cls: Type[M],
17
17
  prompt: List[str],
18
- **kwargs: Unpack[GenerateKwargs],
18
+ **kwargs: Unpack[GenerateKwargs[M]],
19
19
  ) -> List[M]: ...
20
20
 
21
21
  @overload
@@ -23,14 +23,14 @@ class Propose[M: ProposedAble](LLMUsage):
23
23
  self,
24
24
  cls: Type[M],
25
25
  prompt: str,
26
- **kwargs: Unpack[GenerateKwargs],
26
+ **kwargs: Unpack[GenerateKwargs[M]],
27
27
  ) -> M: ...
28
28
 
29
29
  async def propose(
30
30
  self,
31
31
  cls: Type[M],
32
32
  prompt: List[str] | str,
33
- **kwargs: Unpack[GenerateKwargs],
33
+ **kwargs: Unpack[GenerateKwargs[M]],
34
34
  ) -> List[M] | M:
35
35
  """Asynchronously proposes a task based on a given prompt and parameters.
36
36
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  from asyncio import gather
4
4
  from itertools import permutations
5
+ from random import sample
5
6
  from typing import Dict, List, Set, Tuple, Union, Unpack, overload
6
7
 
7
8
  from fabricatio._rust_instances import template_manager
@@ -16,7 +17,11 @@ from pydantic import NonNegativeInt, PositiveInt
16
17
 
17
18
 
18
19
  class GiveRating(WithBriefing, LLMUsage):
19
- """A class that provides functionality to rate tasks based on a rating manual and score range."""
20
+ """A class that provides functionality to rate tasks based on a rating manual and score range.
21
+
22
+ References:
23
+ Lu X, Li J, Takeuchi K, et al. AHP-powered LLM reasoning for multi-criteria evaluation of open-ended responses[A/OL]. arXiv, 2024. DOI: 10.48550/arXiv.2410.01246.
24
+ """
20
25
 
21
26
  async def rate_fine_grind(
22
27
  self,
@@ -187,6 +192,7 @@ class GiveRating(WithBriefing, LLMUsage):
187
192
  self,
188
193
  topic: str,
189
194
  examples: List[str],
195
+ m: NonNegativeInt = 0,
190
196
  reasons_count: PositiveInt = 2,
191
197
  criteria_count: PositiveInt = 5,
192
198
  **kwargs: Unpack[ValidateKwargs],
@@ -199,13 +205,21 @@ class GiveRating(WithBriefing, LLMUsage):
199
205
  Parameters:
200
206
  topic (str): The subject topic for the rating criteria.
201
207
  examples (List[str]): A list of example texts to analyze.
208
+ m (NonNegativeInt, optional): The number of examples to sample from the provided list. Defaults to 0 (no sampling).
202
209
  reasons_count (PositiveInt, optional): The number of reasons to extract from each pair of examples. Defaults to 2.
203
210
  criteria_count (PositiveInt, optional): The final number of rating criteria to draft. Defaults to 5.
204
211
  **kwargs (Unpack[ValidateKwargs]): Additional keyword arguments for validation.
205
212
 
206
213
  Returns:
207
214
  Set[str]: A set of drafted rating criteria.
215
+
216
+ Warnings:
217
+ Since this function uses pairwise comparisons, it may not be suitable for large lists of examples.
218
+ For that reason, consider using a smaller list of examples or setting `m` to a non-zero value smaller than the length of the examples.
208
219
  """
220
+ if m:
221
+ examples = sample(examples, m)
222
+
209
223
  kwargs = GenerateKwargs(system_message=f"# your personal briefing: \n{self.briefing}", **kwargs)
210
224
  # extract reasons from the comparison of ordered pairs of extracted from examples
211
225
  reasons = flatten(
@@ -11,6 +11,7 @@ from fabricatio.models.kwargs_types import GenerateKwargs, ReviewKwargs
11
11
  from fabricatio.models.task import Task
12
12
  from pydantic import PrivateAttr
13
13
  from questionary import Choice, checkbox
14
+ from rich import print
14
15
 
15
16
 
16
17
  class ProblemSolutions(Base):
@@ -78,6 +79,18 @@ class ReviewResult[T](ProposedAble, Display):
78
79
  _ref: T = PrivateAttr(None)
79
80
  """Reference to the original object that was reviewed."""
80
81
 
82
+ def update_topic(self, topic: str) -> Self:
83
+ """Update the review topic.
84
+
85
+ Args:
86
+ topic (str): The new topic to be associated with this review.
87
+
88
+ Returns:
89
+ Self: The current instance with updated review topic.
90
+ """
91
+ self.review_topic = topic
92
+ return self
93
+
81
94
  def update_ref[K](self, ref: K) -> "ReviewResult[K]":
82
95
  """Update the reference to the reviewed object.
83
96
 
@@ -111,9 +124,18 @@ class ReviewResult[T](ProposedAble, Display):
111
124
  Returns:
112
125
  Self: The current instance with filtered problems and solutions.
113
126
  """
127
+ if isinstance(self._ref, str):
128
+ display = self._ref
129
+ elif isinstance(self._ref, WithBriefing):
130
+ display = self._ref.briefing
131
+ elif isinstance(self._ref, Display):
132
+ display = self._ref.display()
133
+ else:
134
+ raise TypeError(f"Unsupported type for review: {type(self._ref)}")
114
135
  # Choose the problems to retain
136
+ print(display)
115
137
  chosen_ones: List[ProblemSolutions] = await checkbox(
116
- f"Please choose the problems you want to retain, under the topic of `{self.review_topic}`.(Default: retain all)",
138
+ f"Please choose the problems you want to retain.(Default: retain all)\n\t`{self.review_topic}`",
117
139
  choices=[Choice(p.problem, p, checked=True) for p in self.problem_solutions],
118
140
  ).ask_async()
119
141
  if not check_solutions:
@@ -124,7 +146,7 @@ class ReviewResult[T](ProposedAble, Display):
124
146
  for to_exam in chosen_ones:
125
147
  to_exam.update_solutions(
126
148
  await checkbox(
127
- f"Please choose the solutions you want to retain, under the problem of `{to_exam.problem}`.(Default: retain all)",
149
+ f"Please choose the solutions you want to retain.(Default: retain all)\n\t`{to_exam.problem}`",
128
150
  choices=[Choice(s, s, checked=True) for s in to_exam.solutions],
129
151
  ).ask_async()
130
152
  )
@@ -159,7 +181,11 @@ class Review(GiveRating, Propose):
159
181
  return await self.review_obj(task, **kwargs)
160
182
 
161
183
  async def review_string(
162
- self, text: str, topic: str, criteria: Optional[Set[str]] = None, **kwargs: Unpack[GenerateKwargs]
184
+ self,
185
+ text: str,
186
+ topic: str,
187
+ criteria: Optional[Set[str]] = None,
188
+ **kwargs: Unpack[GenerateKwargs[ReviewResult[str]]],
163
189
  ) -> ReviewResult[str]:
164
190
  """Review a string based on specified topic and criteria.
165
191
 
@@ -186,7 +212,7 @@ class Review(GiveRating, Propose):
186
212
  ),
187
213
  **kwargs,
188
214
  )
189
- return res.update_ref(text)
215
+ return res.update_ref(text).update_topic(topic)
190
216
 
191
217
  async def review_obj[M: (Display, WithBriefing)](self, obj: M, **kwargs: Unpack[ReviewKwargs]) -> ReviewResult[M]:
192
218
  """Review an object that implements Display or WithBriefing interface.
@@ -7,6 +7,7 @@ from fabricatio.fs.curd import (
7
7
  delete_directory,
8
8
  delete_file,
9
9
  dump_text,
10
+ gather_files,
10
11
  move_file,
11
12
  tree,
12
13
  )
@@ -19,6 +20,7 @@ __all__ = [
19
20
  "delete_directory",
20
21
  "delete_file",
21
22
  "dump_text",
23
+ "gather_files",
22
24
  "magika",
23
25
  "move_file",
24
26
  "safe_json_read",
@@ -134,3 +134,16 @@ def absolute_path(path: str | Path | PathLike) -> str:
134
134
  str: The absolute path of the file or directory.
135
135
  """
136
136
  return Path(path).expanduser().resolve().as_posix()
137
+
138
+
139
+ def gather_files(directory: str | Path | PathLike, extension: str) -> list[str]:
140
+ """Gather all files with a specific extension in a directory.
141
+
142
+ Args:
143
+ directory (str, Path, PathLike): The directory to search in.
144
+ extension (str): The file extension to look for.
145
+
146
+ Returns:
147
+ list[str]: A list of file paths with the specified extension.
148
+ """
149
+ return [file.as_posix() for file in Path(directory).rglob(f"*.{extension}")]
@@ -18,7 +18,6 @@ logger.add(
18
18
  )
19
19
  logger.add(sys.stderr, level=configs.debug.log_level)
20
20
 
21
-
22
21
  if __name__ == "__main__":
23
22
  logger.debug("This is a trace message.")
24
23
  logger.info("This is an information message.")
@@ -122,17 +122,16 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
122
122
  current_action = None
123
123
  try:
124
124
  for step in self._instances:
125
- logger.debug(f"Executing step: {step.name}")
125
+ logger.debug(f"Executing step: {(current_action := step.name)}")
126
126
  act_task = create_task(step.act(await self._context.get()))
127
127
  if task.is_cancelled():
128
128
  act_task.cancel(f"Cancelled by task: {task.name}")
129
129
  break
130
130
  modified_ctx = await act_task
131
131
  await self._context.put(modified_ctx)
132
- current_action = step.name
133
132
  logger.info(f"Finished executing workflow: {self.name}")
134
- final_ctx = await self._context.get()
135
- if self.task_output_key not in final_ctx:
133
+
134
+ if self.task_output_key not in (final_ctx := await self._context.get()):
136
135
  logger.warning(
137
136
  f"Task output key: {self.task_output_key} not found in the context, None will be returned. You can check if `Action.output_key` is set the same as `WorkFlow.task_output_key`."
138
137
  )
@@ -8,14 +8,21 @@ from pydantic import NonNegativeFloat, NonNegativeInt, PositiveInt
8
8
 
9
9
 
10
10
  class CollectionSimpleConfigKwargs(TypedDict):
11
- """A type representing the configuration for a collection."""
11
+ """Configuration parameters for a vector collection.
12
+
13
+ These arguments are typically used when configuring connections to vector databases.
14
+ """
12
15
 
13
16
  dimension: NotRequired[int]
14
17
  timeout: NotRequired[float]
15
18
 
16
19
 
17
20
  class FetchKwargs(TypedDict):
18
- """A type representing the keyword arguments for the fetch method."""
21
+ """Arguments for fetching data from vector collections.
22
+
23
+ Controls how data is retrieved from vector databases, including filtering
24
+ and result limiting parameters.
25
+ """
19
26
 
20
27
  collection_name: NotRequired[str]
21
28
  similarity_threshold: NotRequired[float]
@@ -23,7 +30,11 @@ class FetchKwargs(TypedDict):
23
30
 
24
31
 
25
32
  class EmbeddingKwargs(TypedDict):
26
- """A type representing the keyword arguments for the embedding method."""
33
+ """Configuration parameters for text embedding operations.
34
+
35
+ These settings control the behavior of embedding models that convert text
36
+ to vector representations.
37
+ """
27
38
 
28
39
  model: NotRequired[str]
29
40
  dimensions: NotRequired[int]
@@ -32,7 +43,11 @@ class EmbeddingKwargs(TypedDict):
32
43
 
33
44
 
34
45
  class LLMKwargs(TypedDict):
35
- """A type representing the keyword arguments for the LLM (Large Language Model) usage."""
46
+ """Configuration parameters for language model inference.
47
+
48
+ These arguments control the behavior of large language model calls,
49
+ including generation parameters and caching options.
50
+ """
36
51
 
37
52
  model: NotRequired[str]
38
53
  temperature: NotRequired[NonNegativeFloat]
@@ -42,35 +57,60 @@ class LLMKwargs(TypedDict):
42
57
  stream: NotRequired[bool]
43
58
  timeout: NotRequired[PositiveInt]
44
59
  max_retries: NotRequired[PositiveInt]
60
+ no_cache: NotRequired[bool] # If use cache in this call
61
+ no_store: NotRequired[bool] # If store the response of this call to cache
62
+ cache_ttl: NotRequired[int] # how long the stored cache is alive, in seconds
63
+ s_maxage: NotRequired[int] # max accepted age of cached response, in seconds
64
+
45
65
 
66
+ class ValidateKwargs[T](LLMKwargs):
67
+ """Arguments for content validation operations.
46
68
 
47
- class ValidateKwargs(LLMKwargs):
48
- """A type representing the keyword arguments for the validate method."""
69
+ Extends LLMKwargs with additional parameters specific to validation tasks,
70
+ such as limiting the number of validation attempts.
71
+ """
49
72
 
73
+ default: NotRequired[T]
50
74
  max_validations: NotRequired[PositiveInt]
51
75
 
52
76
 
53
77
  class GenerateKwargs(ValidateKwargs):
54
- """A type representing the keyword arguments for the generate method."""
78
+ """Arguments for content generation operations.
79
+
80
+ Extends ValidateKwargs with parameters specific to text generation,
81
+ including system prompt configuration.
82
+ """
55
83
 
56
84
  system_message: NotRequired[str]
57
85
 
58
86
 
59
87
  class ReviewKwargs(GenerateKwargs):
60
- """A type representing the keyword arguments for the review method."""
88
+ """Arguments for content review operations.
89
+
90
+ Extends GenerateKwargs with parameters for evaluating content against
91
+ specific topics and review criteria.
92
+ """
61
93
 
62
94
  topic: str
63
95
  criteria: NotRequired[Set[str]]
64
96
 
65
97
 
66
98
  class ChooseKwargs(GenerateKwargs):
67
- """A type representing the keyword arguments for the choose method."""
99
+ """Arguments for selection operations.
100
+
101
+ Extends GenerateKwargs with parameters for selecting among options,
102
+ such as the number of items to choose.
103
+ """
68
104
 
69
105
  k: NotRequired[NonNegativeInt]
70
106
 
71
107
 
72
108
  class CacheKwargs(TypedDict, total=False):
73
- """A type representing the keyword arguments for the cache method."""
109
+ """Configuration parameters for the caching system.
110
+
111
+ These arguments control the behavior of various caching backends,
112
+ including in-memory, Redis, S3, and vector database caching options.
113
+ """
74
114
 
75
115
  mode: NotRequired[CacheMode] # when default_on cache is always on, when default_off cache is opt in
76
116
  host: NotRequired[str]
@@ -26,12 +26,8 @@ from more_itertools import duplicates_everseen
26
26
  from pydantic import Field, NonNegativeInt, PositiveInt
27
27
 
28
28
  if configs.cache.enabled:
29
- from litellm.caching import Cache
30
-
31
- if configs.cache.type is None:
32
- Cache(**configs.cache.params)
33
- else:
34
- Cache(type=configs.cache.type, **configs.cache.params)
29
+ litellm.enable_cache(type=configs.cache.type, **configs.cache.params)
30
+ logger.success(f"{configs.cache.type.name} Cache enabled")
35
31
 
36
32
 
37
33
  class LLMUsage(ScopedConfig):
@@ -71,6 +67,12 @@ class LLMUsage(ScopedConfig):
71
67
  max_retries=kwargs.get("max_retries") or self.llm_max_retries or configs.llm.max_retries,
72
68
  api_key=(self.llm_api_key or configs.llm.api_key).get_secret_value(),
73
69
  base_url=(self.llm_api_endpoint or configs.llm.api_endpoint).unicode_string(),
70
+ cache={
71
+ "no-cache": kwargs.get("no_cache"),
72
+ "no-store": kwargs.get("no_store"),
73
+ "cache-ttl": kwargs.get("cache_ttl"),
74
+ "s-maxage": kwargs.get("s_maxage"),
75
+ },
74
76
  )
75
77
 
76
78
  async def ainvoke(
@@ -176,19 +178,32 @@ class LLMUsage(ScopedConfig):
176
178
  case _:
177
179
  raise RuntimeError("Should not reach here.")
178
180
 
181
+ @overload
179
182
  async def aask_validate[T](
180
183
  self,
181
184
  question: str,
182
185
  validator: Callable[[str], T | None],
186
+ default: T,
183
187
  max_validations: PositiveInt = 2,
184
188
  system_message: str = "",
185
189
  **kwargs: Unpack[LLMKwargs],
186
- ) -> T:
190
+ ) -> T: ...
191
+
192
+ async def aask_validate[T](
193
+ self,
194
+ question: str,
195
+ validator: Callable[[str], T | None],
196
+ default: Optional[T] = None,
197
+ max_validations: PositiveInt = 2,
198
+ system_message: str = "",
199
+ **kwargs: Unpack[LLMKwargs],
200
+ ) -> Optional[T]:
187
201
  """Asynchronously asks a question and validates the response using a given validator.
188
202
 
189
203
  Args:
190
204
  question (str): The question to ask.
191
205
  validator (Callable[[str], T | None]): A function to validate the response.
206
+ default (T | None): Default value to return if validation fails. Defaults to None.
192
207
  max_validations (PositiveInt): Maximum number of validation attempts. Defaults to 2.
193
208
  system_message (str): System message to include in the request. Defaults to an empty string.
194
209
  **kwargs (Unpack[LLMKwargs]): Additional keyword arguments for the LLM usage.
@@ -196,8 +211,6 @@ class LLMUsage(ScopedConfig):
196
211
  Returns:
197
212
  T: The validated response.
198
213
 
199
- Raises:
200
- ValueError: If the response fails to validate after the maximum number of attempts.
201
214
  """
202
215
  for i in range(max_validations):
203
216
  if (
@@ -209,14 +222,17 @@ class LLMUsage(ScopedConfig):
209
222
  ) and (validated := validator(response)):
210
223
  logger.debug(f"Successfully validated the response at {i}th attempt.")
211
224
  return validated
212
- logger.error(err := f"Failed to validate the response after {max_validations} attempts.")
213
- raise ValueError(err)
225
+ kwargs["no_cache"] = True
226
+ logger.debug("Closed the cache for the next attempt")
227
+ if default is None:
228
+ logger.error(f"Failed to validate the response after {max_validations} attempts.")
229
+ return default
214
230
 
215
231
  async def aask_validate_batch[T](
216
232
  self,
217
233
  questions: List[str],
218
234
  validator: Callable[[str], T | None],
219
- **kwargs: Unpack[GenerateKwargs],
235
+ **kwargs: Unpack[GenerateKwargs[T]],
220
236
  ) -> List[T]:
221
237
  """Asynchronously asks a batch of questions and validates the responses using a given validator.
222
238
 
@@ -233,7 +249,9 @@ class LLMUsage(ScopedConfig):
233
249
  """
234
250
  return await gather(*[self.aask_validate(question, validator, **kwargs) for question in questions])
235
251
 
236
- async def aliststr(self, requirement: str, k: NonNegativeInt = 0, **kwargs: Unpack[GenerateKwargs]) -> List[str]:
252
+ async def aliststr(
253
+ self, requirement: str, k: NonNegativeInt = 0, **kwargs: Unpack[GenerateKwargs[List[str]]]
254
+ ) -> List[str]:
237
255
  """Asynchronously generates a list of strings based on a given requirement.
238
256
 
239
257
  Args:
@@ -253,7 +271,7 @@ class LLMUsage(ScopedConfig):
253
271
  **kwargs,
254
272
  )
255
273
 
256
- async def apathstr(self, requirement: str, **kwargs: Unpack[ChooseKwargs]) -> List[str]:
274
+ async def apathstr(self, requirement: str, **kwargs: Unpack[ChooseKwargs[List[str]]]) -> List[str]:
257
275
  """Asynchronously generates a list of strings based on a given requirement.
258
276
 
259
277
  Args:
@@ -271,7 +289,7 @@ class LLMUsage(ScopedConfig):
271
289
  **kwargs,
272
290
  )
273
291
 
274
- async def awhich_pathstr(self, requirement: str, **kwargs: Unpack[GenerateKwargs]) -> str:
292
+ async def awhich_pathstr(self, requirement: str, **kwargs: Unpack[GenerateKwargs[List[str]]]) -> str:
275
293
  """Asynchronously generates a single path string based on a given requirement.
276
294
 
277
295
  Args:
@@ -294,7 +312,7 @@ class LLMUsage(ScopedConfig):
294
312
  instruction: str,
295
313
  choices: List[T],
296
314
  k: NonNegativeInt = 0,
297
- **kwargs: Unpack[GenerateKwargs],
315
+ **kwargs: Unpack[GenerateKwargs[List[T]]],
298
316
  ) -> List[T]:
299
317
  """Asynchronously executes a multi-choice decision-making process, generating a prompt based on the instruction and options, and validates the returned selection results.
300
318
 
@@ -345,7 +363,7 @@ class LLMUsage(ScopedConfig):
345
363
  self,
346
364
  instruction: str,
347
365
  choices: List[T],
348
- **kwargs: Unpack[GenerateKwargs],
366
+ **kwargs: Unpack[GenerateKwargs[List[T]]],
349
367
  ) -> T:
350
368
  """Asynchronously picks a single choice from a list of options using AI validation.
351
369
 
@@ -374,7 +392,7 @@ class LLMUsage(ScopedConfig):
374
392
  prompt: str,
375
393
  affirm_case: str = "",
376
394
  deny_case: str = "",
377
- **kwargs: Unpack[GenerateKwargs],
395
+ **kwargs: Unpack[GenerateKwargs[bool]],
378
396
  ) -> bool:
379
397
  """Asynchronously judges a prompt using AI validation.
380
398
 
@@ -489,17 +507,13 @@ class ToolBoxUsage(LLMUsage):
489
507
  self,
490
508
  task: Task,
491
509
  system_message: str = "",
492
- k: NonNegativeInt = 0,
493
- max_validations: PositiveInt = 2,
494
- **kwargs: Unpack[LLMKwargs],
510
+ **kwargs: Unpack[ChooseKwargs[List[ToolBox]]],
495
511
  ) -> List[ToolBox]:
496
512
  """Asynchronously executes a multi-choice decision-making process to choose toolboxes.
497
513
 
498
514
  Args:
499
515
  task (Task): The task for which to choose toolboxes.
500
516
  system_message (str): Custom system-level prompt, defaults to an empty string.
501
- k (NonNegativeInt): The number of toolboxes to select, 0 means infinite. Defaults to 0.
502
- max_validations (PositiveInt): Maximum number of validation failures, default is 2.
503
517
  **kwargs (Unpack[LLMKwargs]): Additional keyword arguments for the LLM usage.
504
518
 
505
519
  Returns:
@@ -511,8 +525,6 @@ class ToolBoxUsage(LLMUsage):
511
525
  return await self.achoose(
512
526
  instruction=task.briefing,
513
527
  choices=list(self.toolboxes),
514
- k=k,
515
- max_validations=max_validations,
516
528
  system_message=system_message,
517
529
  **kwargs,
518
530
  )
@@ -521,19 +533,13 @@ class ToolBoxUsage(LLMUsage):
521
533
  self,
522
534
  task: Task,
523
535
  toolbox: ToolBox,
524
- system_message: str = "",
525
- k: NonNegativeInt = 0,
526
- max_validations: PositiveInt = 2,
527
- **kwargs: Unpack[LLMKwargs],
536
+ **kwargs: Unpack[ChooseKwargs[List[Tool]]],
528
537
  ) -> List[Tool]:
529
538
  """Asynchronously executes a multi-choice decision-making process to choose tools.
530
539
 
531
540
  Args:
532
541
  task (Task): The task for which to choose tools.
533
542
  toolbox (ToolBox): The toolbox from which to choose tools.
534
- system_message (str): Custom system-level prompt, defaults to an empty string.
535
- k (NonNegativeInt): The number of tools to select, 0 means infinite. Defaults to 0.
536
- max_validations (PositiveInt): Maximum number of validation failures, default is 2.
537
543
  **kwargs (Unpack[LLMKwargs]): Additional keyword arguments for the LLM usage.
538
544
 
539
545
  Returns:
@@ -545,9 +551,6 @@ class ToolBoxUsage(LLMUsage):
545
551
  return await self.achoose(
546
552
  instruction=task.briefing,
547
553
  choices=toolbox.tools,
548
- k=k,
549
- max_validations=max_validations,
550
- system_message=system_message,
551
554
  **kwargs,
552
555
  )
553
556
 
@@ -7,6 +7,7 @@ from fabricatio.fs import (
7
7
  delete_directory,
8
8
  delete_file,
9
9
  dump_text,
10
+ gather_files,
10
11
  move_file,
11
12
  safe_json_read,
12
13
  safe_text_read,
@@ -26,4 +27,5 @@ fs_toolbox = (
26
27
  .add_tool(absolute_path)
27
28
  .add_tool(safe_text_read)
28
29
  .add_tool(safe_json_read)
30
+ .add_tool(gather_files)
29
31
  )
Binary file
@@ -216,7 +216,7 @@ wheels = [
216
216
 
217
217
  [[package]]
218
218
  name = "fabricatio"
219
- version = "0.2.5.dev2"
219
+ version = "0.2.5.dev3"
220
220
  source = { editable = "." }
221
221
  dependencies = [
222
222
  { name = "appdirs" },
Binary file
File without changes