fabricatio 0.2.5.dev5__tar.gz → 0.2.6.dev0__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.dev5 → fabricatio-0.2.6.dev0}/PKG-INFO +1 -1
  2. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/extract_and_review/extract_and_review.py +3 -1
  3. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/minor/hello_fabricatio.py +1 -1
  4. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/pyproject.toml +6 -5
  5. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/actions/article.py +4 -4
  6. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/actions/output.py +1 -3
  7. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/actions/rag.py +2 -2
  8. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/capabilities/rag.py +17 -14
  9. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/capabilities/task.py +1 -1
  10. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/config.py +23 -1
  11. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/models/action.py +2 -2
  12. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/models/generic.py +28 -6
  13. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/models/kwargs_types.py +2 -2
  14. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/models/usages.py +44 -17
  15. fabricatio-0.2.6.dev0/templates.tar.gz +0 -0
  16. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/uv.lock +30 -3
  17. fabricatio-0.2.5.dev5/templates.tar.gz +0 -0
  18. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/.github/workflows/build-package.yaml +0 -0
  19. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/.github/workflows/ruff.yaml +0 -0
  20. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/.github/workflows/tests.yaml +0 -0
  21. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/.gitignore +0 -0
  22. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/.python-version +0 -0
  23. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/Cargo.lock +0 -0
  24. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/Cargo.toml +0 -0
  25. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/LICENSE +0 -0
  26. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/Makefile +0 -0
  27. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/README.md +0 -0
  28. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/extract_and_review/.gitignore +0 -0
  29. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/extract_article/extract.py +0 -0
  30. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/llm_usages/llm_usage.py +0 -0
  31. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/make_a_rating/rating.py +0 -0
  32. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/make_diary/commits.json +0 -0
  33. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/make_diary/diary.py +0 -0
  34. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/propose_task/propose.py +0 -0
  35. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/reviewer/review.py +0 -0
  36. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/simple_chat/chat.py +0 -0
  37. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/simple_rag/simple_rag.py +0 -0
  38. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/task_handle/handle_task.py +0 -0
  39. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/write_outline/.gitignore +0 -0
  40. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/examples/write_outline/write_outline.py +0 -0
  41. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/__init__.py +0 -0
  42. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/_rust.pyi +0 -0
  43. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/_rust_instances.py +0 -0
  44. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/capabilities/propose.py +0 -0
  45. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/capabilities/rating.py +0 -0
  46. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/capabilities/review.py +0 -0
  47. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/core.py +0 -0
  48. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/decorators.py +0 -0
  49. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/fs/__init__.py +0 -0
  50. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/fs/curd.py +0 -0
  51. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/fs/readers.py +0 -0
  52. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/journal.py +0 -0
  53. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/models/events.py +0 -0
  54. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/models/extra.py +0 -0
  55. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/models/role.py +0 -0
  56. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/models/task.py +0 -0
  57. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/models/tool.py +0 -0
  58. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/models/utils.py +0 -0
  59. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/parser.py +0 -0
  60. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/py.typed +0 -0
  61. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/toolboxes/__init__.py +0 -0
  62. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/toolboxes/arithmetic.py +0 -0
  63. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/toolboxes/fs.py +0 -0
  64. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/workflows/articles.py +0 -0
  65. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/python/fabricatio/workflows/rag.py +0 -0
  66. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/src/bib_tools.rs +0 -0
  67. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/src/hash.rs +0 -0
  68. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/src/hbs_helpers.rs +0 -0
  69. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/src/lib.rs +0 -0
  70. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/src/templates.rs +0 -0
  71. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/binary-exploitation-ctf-solver.hbs +0 -0
  72. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/claude-xml.hbs +0 -0
  73. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/clean-up-code.hbs +0 -0
  74. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/create_json_obj.hbs +0 -0
  75. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/cryptography-ctf-solver.hbs +0 -0
  76. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/dependencies.hbs +0 -0
  77. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/document-the-code.hbs +0 -0
  78. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/draft_rating_criteria.hbs +0 -0
  79. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/draft_rating_manual.hbs +0 -0
  80. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/draft_rating_weights_klee.hbs +0 -0
  81. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/draft_tool_usage_code.hbs +0 -0
  82. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/extract_criteria_from_reasons.hbs +0 -0
  83. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/extract_reasons_from_examples.hbs +0 -0
  84. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/find-security-vulnerabilities.hbs +0 -0
  85. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/fix-bugs.hbs +0 -0
  86. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/improve-performance.hbs +0 -0
  87. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/liststr.hbs +0 -0
  88. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/make_choice.hbs +0 -0
  89. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/make_judgment.hbs +0 -0
  90. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/pathstr.hbs +0 -0
  91. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/rate_fine_grind.hbs +0 -0
  92. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/refactor.hbs +0 -0
  93. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/refined_query.hbs +0 -0
  94. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/retrieved_display.hbs +0 -0
  95. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/reverse-engineering-ctf-solver.hbs +0 -0
  96. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/review_string.hbs +0 -0
  97. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/task_briefing.hbs +0 -0
  98. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/web-ctf-solver.hbs +0 -0
  99. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/write-git-commit.hbs +0 -0
  100. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/write-github-pull-request.hbs +0 -0
  101. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/templates/built-in/write-github-readme.hbs +0 -0
  102. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/tests/test_config.py +0 -0
  103. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/tests/test_models/test_action.py +0 -0
  104. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/tests/test_models/test_advanced.py +0 -0
  105. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/tests/test_models/test_generic.py +0 -0
  106. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/tests/test_models/test_role.py +0 -0
  107. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/tests/test_models/test_task.py +0 -0
  108. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/tests/test_models/test_tool.py +0 -0
  109. {fabricatio-0.2.5.dev5 → fabricatio-0.2.6.dev0}/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.dev5
3
+ Version: 0.2.6.dev0
4
4
  Classifier: License :: OSI Approved :: MIT License
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -27,8 +27,10 @@ async def main() -> None:
27
27
 
28
28
  unchecked_ess = await task.override_dependencies(gather_files("bpdf_out", "md")).delegate("article")
29
29
 
30
+ if unchecked_ess is None:
31
+ logger.error("No essence found")
32
+ return
30
33
  ess = list(filter(lambda x: x is not None, unchecked_ess))
31
-
32
34
  logger.success(f"Essence Count:{len(ess)}, invalid count: {len(unchecked_ess) - len(ess)}")
33
35
 
34
36
  Path("output").mkdir(exist_ok=True)
@@ -13,7 +13,7 @@ class Hello(Action):
13
13
 
14
14
  output_key: str = "task_output"
15
15
 
16
- async def _execute(self, task_input: Task[str], **_) -> Any:
16
+ async def _execute(self, **_) -> Any:
17
17
  ret = "Hello fabricatio!"
18
18
  logger.info("executing talk action")
19
19
  return ret
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fabricatio"
3
- version = "0.2.5-dev5"
3
+ version = "0.2.6-dev0"
4
4
  description = "A LLM multi-agent framework."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -72,6 +72,7 @@ dev = [
72
72
  "pytest-mock>=3.14.0",
73
73
  "pytest-rerunfailures>=15.0",
74
74
  "pytest-xdist>=3.6.1",
75
+ "viztracer>=1.0.2",
75
76
  ]
76
77
 
77
78
  [project.optional-dependencies]
@@ -139,6 +140,10 @@ testpaths = [
139
140
  asyncio_mode = "auto"
140
141
  asyncio_default_fixture_loop_scope = "function"
141
142
 
143
+ [[tool.uv.index]]
144
+ url = "https://mirrors.bfsu.edu.cn/pypi/web/simple"
145
+ default = true
146
+
142
147
  [[tool.uv.index]]
143
148
  url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
144
149
 
@@ -148,7 +153,3 @@ url = "https://mirrors.huaweicloud.com/repository/pypi/simple"
148
153
  [[tool.uv.index]]
149
154
  url = "https://mirrors.aliyun.com/pypi/simple/"
150
155
 
151
- [[tool.uv.index]]
152
- url = "https://mirrors.bfsu.edu.cn/pypi/web/simple"
153
- default = true
154
-
@@ -2,7 +2,7 @@
2
2
 
3
3
  from os import PathLike
4
4
  from pathlib import Path
5
- from typing import Callable, List
5
+ from typing import Callable, List, Optional
6
6
 
7
7
  from fabricatio.fs import safe_text_read
8
8
  from fabricatio.journal import logger
@@ -27,7 +27,7 @@ class ExtractArticleEssence(Action):
27
27
  task_input: Task,
28
28
  reader: Callable[[P], str] = lambda p: Path(p).read_text(encoding="utf-8"),
29
29
  **_,
30
- ) -> List[ArticleEssence]:
30
+ ) -> Optional[List[ArticleEssence]]:
31
31
  if not task_input.dependencies:
32
32
  logger.info(err := "Task not approved, since no dependencies are provided.")
33
33
  raise RuntimeError(err)
@@ -51,7 +51,7 @@ class GenerateArticleProposal(Action):
51
51
  self,
52
52
  task_input: Task,
53
53
  **_,
54
- ) -> ArticleProposal:
54
+ ) -> Optional[ArticleProposal]:
55
55
  input_path = await self.awhich_pathstr(
56
56
  f"{task_input.briefing}\nExtract the path of file, which contains the article briefing that I need to read."
57
57
  )
@@ -73,7 +73,7 @@ class GenerateOutline(Action):
73
73
  self,
74
74
  article_proposal: ArticleProposal,
75
75
  **_,
76
- ) -> ArticleOutline:
76
+ ) -> Optional[ArticleOutline]:
77
77
  return await self.propose(
78
78
  ArticleOutline,
79
79
  article_proposal.display(),
@@ -1,7 +1,5 @@
1
1
  """Dump the finalized output to a file."""
2
2
 
3
- from typing import Unpack
4
-
5
3
  from fabricatio.models.action import Action
6
4
  from fabricatio.models.generic import FinalizedDumpAble
7
5
  from fabricatio.models.task import Task
@@ -12,7 +10,7 @@ class DumpFinalizedOutput(Action):
12
10
 
13
11
  output_key: str = "dump_path"
14
12
 
15
- async def _execute(self, task_input: Task, to_dump: FinalizedDumpAble, **cxt: Unpack) -> str:
13
+ async def _execute(self, task_input: Task, to_dump: FinalizedDumpAble, **_) -> str:
16
14
  dump_path = await self.awhich_pathstr(
17
15
  f"{task_input.briefing}\n\nExtract a single path of the file, to which I will dump the data."
18
16
  )
@@ -1,6 +1,6 @@
1
1
  """Inject data into the database."""
2
2
 
3
- from typing import List, Optional, Unpack
3
+ from typing import List, Optional
4
4
 
5
5
  from fabricatio.capabilities.rag import RAG
6
6
  from fabricatio.models.action import Action
@@ -13,7 +13,7 @@ class InjectToDB(Action, RAG):
13
13
  output_key: str = "collection_name"
14
14
 
15
15
  async def _execute[T: PrepareVectorization](
16
- self, to_inject: T | List[T], collection_name: Optional[str] = "my_collection", **cxt: Unpack
16
+ self, to_inject: T | List[T], collection_name: Optional[str] = "my_collection", **_
17
17
  ) -> Optional[str]:
18
18
  if not isinstance(to_inject, list):
19
19
  to_inject = [to_inject]
@@ -8,7 +8,7 @@ from functools import lru_cache
8
8
  from operator import itemgetter
9
9
  from os import PathLike
10
10
  from pathlib import Path
11
- from typing import Any, Callable, Dict, List, Optional, Self, Union, Unpack, overload
11
+ from typing import Any, Callable, Dict, List, Optional, Self, Union, Unpack, cast, overload
12
12
 
13
13
  from fabricatio._rust_instances import template_manager
14
14
  from fabricatio.config import configs
@@ -111,9 +111,9 @@ class RAG(EmbeddingUsage):
111
111
  create (bool): Whether to create the collection if it does not exist.
112
112
  **kwargs (Unpack[CollectionSimpleConfigKwargs]): Additional keyword arguments for collection configuration.
113
113
  """
114
- if create and collection_name and not self._client.has_collection(collection_name):
114
+ if create and collection_name and self.client.has_collection(collection_name):
115
115
  kwargs["dimension"] = kwargs.get("dimension") or self.milvus_dimensions or configs.rag.milvus_dimensions
116
- self._client.create_collection(collection_name, auto_id=True, **kwargs)
116
+ self.client.create_collection(collection_name, auto_id=True, **kwargs)
117
117
  logger.info(f"Creating collection {collection_name}")
118
118
 
119
119
  self.target_collection = collection_name
@@ -152,15 +152,17 @@ class RAG(EmbeddingUsage):
152
152
  Self: The current instance, allowing for method chaining.
153
153
  """
154
154
  if isinstance(data, MilvusData):
155
- data = data.prepare_insertion()
156
- if isinstance(data, list):
157
- data = [d.prepare_insertion() if isinstance(d, MilvusData) else d for d in data]
155
+ prepared_data = data.prepare_insertion()
156
+ elif isinstance(data, list):
157
+ prepared_data = [d.prepare_insertion() if isinstance(d, MilvusData) else d for d in data]
158
+ else:
159
+ raise TypeError(f"Expected MilvusData or list of MilvusData, got {type(data)}")
158
160
  c_name = collection_name or self.safe_target_collection
159
- self._client.insert(c_name, data)
161
+ self.client.insert(c_name, prepared_data)
160
162
 
161
163
  if flush:
162
164
  logger.debug(f"Flushing collection {c_name}")
163
- self._client.flush(c_name)
165
+ self.client.flush(c_name)
164
166
  return self
165
167
 
166
168
  async def consume_file(
@@ -196,14 +198,14 @@ class RAG(EmbeddingUsage):
196
198
  self.add_document(await self.pack(text), collection_name or self.safe_target_collection, flush=True)
197
199
  return self
198
200
 
199
- async def afetch_document(
201
+ async def afetch_document[V: (int, str, float, bytes)](
200
202
  self,
201
203
  vecs: List[List[float]],
202
204
  desired_fields: List[str] | str,
203
205
  collection_name: Optional[str] = None,
204
206
  similarity_threshold: float = 0.37,
205
207
  result_per_query: int = 10,
206
- ) -> List[Dict[str, Any]] | List[Any]:
208
+ ) -> List[Dict[str, Any]] | List[V]:
207
209
  """Fetch data from the collection.
208
210
 
209
211
  Args:
@@ -217,7 +219,7 @@ class RAG(EmbeddingUsage):
217
219
  List[Dict[str, Any]] | List[Any]: The retrieved data.
218
220
  """
219
221
  # Step 1: Search for vectors
220
- search_results = self._client.search(
222
+ search_results = self.client.search(
221
223
  collection_name or self.safe_target_collection,
222
224
  vecs,
223
225
  search_params={"radius": similarity_threshold},
@@ -237,7 +239,7 @@ class RAG(EmbeddingUsage):
237
239
 
238
240
  if isinstance(desired_fields, list):
239
241
  return resp
240
- return [r.get(desired_fields) for r in resp]
242
+ return [r.get(desired_fields) for r in resp] # extract the single field as list
241
243
 
242
244
  async def aretrieve(
243
245
  self,
@@ -257,12 +259,13 @@ class RAG(EmbeddingUsage):
257
259
  """
258
260
  if isinstance(query, str):
259
261
  query = [query]
260
- return (
262
+ return cast(
263
+ List[str],
261
264
  await self.afetch_document(
262
265
  vecs=(await self.vectorize(query)),
263
266
  desired_fields="text",
264
267
  **kwargs,
265
- )
268
+ ),
266
269
  )[:final_limit]
267
270
 
268
271
  async def aask_retrieved(
@@ -7,13 +7,13 @@ import orjson
7
7
  from fabricatio._rust_instances import template_manager
8
8
  from fabricatio.capabilities.propose import Propose
9
9
  from fabricatio.config import configs
10
+ from fabricatio.journal import logger
10
11
  from fabricatio.models.generic import WithBriefing
11
12
  from fabricatio.models.kwargs_types import ChooseKwargs, ValidateKwargs
12
13
  from fabricatio.models.task import Task
13
14
  from fabricatio.models.tool import Tool, ToolExecutor
14
15
  from fabricatio.models.usages import ToolBoxUsage
15
16
  from fabricatio.parser import JsonCapture, PythonCapture
16
- from loguru import logger
17
17
 
18
18
 
19
19
  class ProposeTask(WithBriefing, Propose):
@@ -68,7 +68,7 @@ class LLMConfig(BaseModel):
68
68
  temperature: NonNegativeFloat = Field(default=1.0)
69
69
  """The temperature of the LLM model. Controls randomness in generation. Set to 1.0 as per request."""
70
70
 
71
- stop_sign: str | List[str] = Field(default_factory=lambda :["\n\n\n", "User:"])
71
+ stop_sign: str | List[str] = Field(default_factory=lambda: ["\n\n\n", "User:"])
72
72
  """The stop sign of the LLM model. No default stop sign specified."""
73
73
 
74
74
  top_p: NonNegativeFloat = Field(default=0.35)
@@ -83,6 +83,12 @@ class LLMConfig(BaseModel):
83
83
  max_tokens: PositiveInt = Field(default=8192)
84
84
  """The maximum number of tokens to generate. Set to 8192 as per request."""
85
85
 
86
+ rpm: Optional[PositiveInt] = Field(default=100)
87
+ """The rate limit of the LLM model in requests per minute. None means not checked."""
88
+
89
+ tpm: Optional[PositiveInt] = Field(default=1000000)
90
+ """The rate limit of the LLM model in tokens per minute. None means not checked."""
91
+
86
92
 
87
93
  class EmbeddingConfig(BaseModel):
88
94
  """Embedding configuration class."""
@@ -285,6 +291,19 @@ class CacheConfig(BaseModel):
285
291
  """Whether to enable cache."""
286
292
 
287
293
 
294
+ class RoutingConfig(BaseModel):
295
+ """Routing configuration class."""
296
+
297
+ model_config = ConfigDict(use_attribute_docstrings=True)
298
+
299
+ allowed_fails: Optional[int] = 1
300
+ """The number of allowed fails before the routing is considered failed."""
301
+ retry_after: int = 15
302
+ """The time in seconds to wait before retrying the routing after a fail."""
303
+ cooldown_time: Optional[int] = 120
304
+ """The time in seconds to wait before retrying the routing after a cooldown."""
305
+
306
+
288
307
  class Settings(BaseSettings):
289
308
  """Application settings class.
290
309
 
@@ -310,6 +329,9 @@ class Settings(BaseSettings):
310
329
  llm: LLMConfig = Field(default_factory=LLMConfig)
311
330
  """LLM Configuration"""
312
331
 
332
+ routing: RoutingConfig = Field(default_factory=RoutingConfig)
333
+ """Routing Configuration"""
334
+
313
335
  embedding: EmbeddingConfig = Field(default_factory=EmbeddingConfig)
314
336
  """Embedding Configuration"""
315
337
 
@@ -3,7 +3,7 @@
3
3
  import traceback
4
4
  from abc import abstractmethod
5
5
  from asyncio import Queue, create_task
6
- from typing import Any, Dict, Self, Tuple, Type, Union, Unpack, final
6
+ from typing import Any, Dict, Self, Tuple, Type, Union, final
7
7
 
8
8
  from fabricatio.capabilities.review import Review
9
9
  from fabricatio.capabilities.task import HandleTask, ProposeTask
@@ -37,7 +37,7 @@ class Action(HandleTask, ProposeTask, Review):
37
37
  self.description = self.description or self.__class__.__doc__ or ""
38
38
 
39
39
  @abstractmethod
40
- async def _execute(self, **cxt: Unpack) -> Any:
40
+ async def _execute(self, **cxt) -> Any:
41
41
  """Execute the action with the provided arguments.
42
42
 
43
43
  Args:
@@ -2,7 +2,7 @@
2
2
 
3
3
  from abc import abstractmethod
4
4
  from pathlib import Path
5
- from typing import Any, Callable, Dict, Iterable, List, Optional, Self, Union, final
5
+ from typing import Any, Callable, Dict, Iterable, List, Optional, Self, Union, final, overload
6
6
 
7
7
  import orjson
8
8
  from fabricatio._rust import blake3_hash
@@ -100,7 +100,15 @@ class CreateJsonObjPrompt(WithFormatedJsonSchema):
100
100
  """Class that provides a prompt for creating a JSON object."""
101
101
 
102
102
  @classmethod
103
- def create_json_prompt(cls, requirement: str) -> str:
103
+ @overload
104
+ def create_json_prompt(cls, requirement: List[str]) -> List[str]: ...
105
+
106
+ @classmethod
107
+ @overload
108
+ def create_json_prompt(cls, requirement: str) -> str: ...
109
+
110
+ @classmethod
111
+ def create_json_prompt(cls, requirement: str | List[str]) -> str | List[str]:
104
112
  """Create the prompt for creating a JSON object with given requirement.
105
113
 
106
114
  Args:
@@ -109,10 +117,18 @@ class CreateJsonObjPrompt(WithFormatedJsonSchema):
109
117
  Returns:
110
118
  str: The prompt for creating a JSON object with given requirement.
111
119
  """
112
- return template_manager.render_template(
113
- configs.templates.create_json_obj_template,
114
- {"requirement": requirement, "json_schema": cls.formated_json_schema()},
115
- )
120
+ if isinstance(requirement, str):
121
+ return template_manager.render_template(
122
+ configs.templates.create_json_obj_template,
123
+ {"requirement": requirement, "json_schema": cls.formated_json_schema()},
124
+ )
125
+ return [
126
+ template_manager.render_template(
127
+ configs.templates.create_json_obj_template,
128
+ {"requirement": r, "json_schema": cls.formated_json_schema()},
129
+ )
130
+ for r in requirement
131
+ ]
116
132
 
117
133
 
118
134
  class InstantiateFromString(Base):
@@ -307,6 +323,12 @@ class ScopedConfig(Base):
307
323
  llm_max_tokens: Optional[PositiveInt] = None
308
324
  """The maximum number of tokens to generate."""
309
325
 
326
+ llm_tpm: Optional[PositiveInt] = None
327
+ """The tokens per minute of the LLM model."""
328
+
329
+ llm_rpm: Optional[PositiveInt] = None
330
+ """The requests per minute of the LLM model."""
331
+
310
332
  embedding_api_endpoint: Optional[HttpUrl] = None
311
333
  """The OpenAI API endpoint."""
312
334
 
@@ -12,7 +12,7 @@ class CollectionSimpleConfigKwargs(TypedDict, total=False):
12
12
  These arguments are typically used when configuring connections to vector databases.
13
13
  """
14
14
 
15
- dimension: int
15
+ dimension: int|None
16
16
  timeout: float
17
17
 
18
18
 
@@ -23,7 +23,7 @@ class FetchKwargs(TypedDict, total=False):
23
23
  and result limiting parameters.
24
24
  """
25
25
 
26
- collection_name: str
26
+ collection_name: str|None
27
27
  similarity_threshold: float
28
28
  result_per_query: int
29
29
 
@@ -14,7 +14,8 @@ from fabricatio.models.task import Task
14
14
  from fabricatio.models.tool import Tool, ToolBox
15
15
  from fabricatio.models.utils import Messages
16
16
  from fabricatio.parser import JsonCapture
17
- from litellm import stream_chunk_builder
17
+ from litellm import Router, stream_chunk_builder
18
+ from litellm.types.router import Deployment, LiteLLM_Params, ModelInfo
18
19
  from litellm.types.utils import (
19
20
  Choices,
20
21
  EmbeddingResponse,
@@ -22,28 +23,40 @@ from litellm.types.utils import (
22
23
  StreamingChoices,
23
24
  TextChoices,
24
25
  )
25
- from litellm.utils import CustomStreamWrapper
26
+ from litellm.utils import CustomStreamWrapper # pyright: ignore [reportPrivateImportUsage]
26
27
  from more_itertools import duplicates_everseen
27
28
  from pydantic import Field, NonNegativeInt, PositiveInt
28
29
 
29
30
  if configs.cache.enabled and configs.cache.type:
30
31
  litellm.enable_cache(type=configs.cache.type, **configs.cache.params)
31
32
  logger.success(f"{configs.cache.type.name} Cache enabled")
33
+ ROUTER = Router(
34
+ routing_strategy="usage-based-routing-v2",
35
+ allowed_fails=configs.routing.allowed_fails,
36
+ retry_after=configs.routing.retry_after,
37
+ cooldown_time=configs.routing.cooldown_time,
38
+ )
32
39
 
33
40
 
34
41
  class LLMUsage(ScopedConfig):
35
42
  """Class that manages LLM (Large Language Model) usage parameters and methods."""
36
43
 
44
+ def _deploy(self, deployment: Deployment) -> Router:
45
+ """Add a deployment to the router."""
46
+ self._added_deployment = ROUTER.upsert_deployment(deployment)
47
+ return ROUTER
48
+
37
49
  @classmethod
38
50
  def _scoped_model(cls) -> Type["LLMUsage"]:
39
51
  return LLMUsage
40
52
 
53
+ # noinspection PyTypeChecker,PydanticTypeChecker
41
54
  async def aquery(
42
55
  self,
43
56
  messages: List[Dict[str, str]],
44
57
  n: PositiveInt | None = None,
45
58
  **kwargs: Unpack[LLMKwargs],
46
- ) -> ModelResponse:
59
+ ) -> ModelResponse | CustomStreamWrapper:
47
60
  """Asynchronously queries the language model to generate a response based on the provided messages and parameters.
48
61
 
49
62
  Args:
@@ -55,19 +68,33 @@ class LLMUsage(ScopedConfig):
55
68
  ModelResponse | CustomStreamWrapper: An object containing the generated response and other metadata from the model.
56
69
  """
57
70
  # Call the underlying asynchronous completion function with the provided and default parameters
58
- return await litellm.acompletion(
71
+ # noinspection PyTypeChecker,PydanticTypeChecker
72
+
73
+ return await self._deploy(
74
+ Deployment(
75
+ model_name=(m_name := kwargs.get("model") or self.llm_model or configs.llm.model),
76
+ litellm_params=(
77
+ p := LiteLLM_Params(
78
+ api_key=(self.llm_api_key or configs.llm.api_key).get_secret_value(),
79
+ api_base=(self.llm_api_endpoint or configs.llm.api_endpoint).unicode_string(),
80
+ model=m_name,
81
+ tpm=self.llm_tpm or configs.llm.tpm,
82
+ rpm=self.llm_rpm or configs.llm.rpm,
83
+ max_retries=kwargs.get("max_retries") or self.llm_max_retries or configs.llm.max_retries,
84
+ timeout=kwargs.get("timeout") or self.llm_timeout or configs.llm.timeout,
85
+ )
86
+ ),
87
+ model_info=ModelInfo(id=hash(m_name + p.model_dump_json(exclude_none=True))),
88
+ )
89
+ ).acompletion(
59
90
  messages=messages,
60
91
  n=n or self.llm_generation_count or configs.llm.generation_count,
61
- model=kwargs.get("model") or self.llm_model or configs.llm.model,
92
+ model=m_name,
62
93
  temperature=kwargs.get("temperature") or self.llm_temperature or configs.llm.temperature,
63
94
  stop=kwargs.get("stop") or self.llm_stop_sign or configs.llm.stop_sign,
64
95
  top_p=kwargs.get("top_p") or self.llm_top_p or configs.llm.top_p,
65
96
  max_tokens=kwargs.get("max_tokens") or self.llm_max_tokens or configs.llm.max_tokens,
66
97
  stream=kwargs.get("stream") or self.llm_stream or configs.llm.stream,
67
- timeout=kwargs.get("timeout") or self.llm_timeout or configs.llm.timeout,
68
- max_retries=kwargs.get("max_retries") or self.llm_max_retries or configs.llm.max_retries,
69
- api_key=(self.llm_api_key or configs.llm.api_key).get_secret_value(),
70
- base_url=(self.llm_api_endpoint or configs.llm.api_endpoint).unicode_string(),
71
98
  cache={
72
99
  "no-cache": kwargs.get("no_cache"),
73
100
  "no-store": kwargs.get("no_store"),
@@ -192,31 +219,31 @@ class LLMUsage(ScopedConfig):
192
219
  @overload
193
220
  async def aask_validate[T](
194
221
  self,
195
- question: str,
222
+ question: List[str],
196
223
  validator: Callable[[str], T | None],
197
- default: None = None,
224
+ default: T,
198
225
  max_validations: PositiveInt = 2,
199
226
  **kwargs: Unpack[GenerateKwargs],
200
- ) -> Optional[T]: ...
201
-
227
+ ) -> List[T]: ...
202
228
  @overload
203
229
  async def aask_validate[T](
204
230
  self,
205
- question: List[str],
231
+ question: str,
206
232
  validator: Callable[[str], T | None],
207
233
  default: None = None,
208
234
  max_validations: PositiveInt = 2,
209
235
  **kwargs: Unpack[GenerateKwargs],
210
- ) -> List[Optional[T]]: ...
236
+ ) -> Optional[T]: ...
237
+
211
238
  @overload
212
239
  async def aask_validate[T](
213
240
  self,
214
241
  question: List[str],
215
242
  validator: Callable[[str], T | None],
216
- default: T,
243
+ default: None = None,
217
244
  max_validations: PositiveInt = 2,
218
245
  **kwargs: Unpack[GenerateKwargs],
219
- ) -> List[T]: ...
246
+ ) -> List[Optional[T]]: ...
220
247
 
221
248
  async def aask_validate[T](
222
249
  self,
Binary file
@@ -1,5 +1,4 @@
1
1
  version = 1
2
- revision = 1
3
2
  requires-python = "==3.12.*"
4
3
 
5
4
  [[package]]
@@ -216,7 +215,7 @@ wheels = [
216
215
 
217
216
  [[package]]
218
217
  name = "fabricatio"
219
- version = "0.2.5.dev5"
218
+ version = "0.2.6.dev0"
220
219
  source = { editable = "." }
221
220
  dependencies = [
222
221
  { name = "appdirs" },
@@ -258,6 +257,7 @@ dev = [
258
257
  { name = "pytest-xdist" },
259
258
  { name = "ruff" },
260
259
  { name = "uv" },
260
+ { name = "viztracer" },
261
261
  ]
262
262
 
263
263
  [package.metadata]
@@ -280,7 +280,6 @@ requires-dist = [
280
280
  { name = "regex", specifier = ">=2024.11.6" },
281
281
  { name = "rich", specifier = ">=13.9.4" },
282
282
  ]
283
- provides-extras = ["rag", "full"]
284
283
 
285
284
  [package.metadata.requires-dev]
286
285
  dev = [
@@ -296,6 +295,7 @@ dev = [
296
295
  { name = "pytest-xdist", specifier = ">=3.6.1" },
297
296
  { name = "ruff", specifier = ">=0.9.4" },
298
297
  { name = "uv", specifier = ">=0.5.29" },
298
+ { name = "viztracer", specifier = ">=1.0.2" },
299
299
  ]
300
300
 
301
301
  [[package]]
@@ -750,6 +750,15 @@ wheels = [
750
750
  { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/16/2e/86f24451c2d530c88daf997cb8d6ac622c1d40d19f5a031ed68a4b73a374/numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818", size = 15517754 },
751
751
  ]
752
752
 
753
+ [[package]]
754
+ name = "objprint"
755
+ version = "0.3.0"
756
+ source = { registry = "https://mirrors.bfsu.edu.cn/pypi/web/simple" }
757
+ sdist = { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/81/b8/c10e96120f1585824a1992655334b49da3924edfb364e84a26cc0ecdb89b/objprint-0.3.0.tar.gz", hash = "sha256:b5d83f9d62db5b95353bb42959106e1cd43010dcaa3eed1ad8d7d0b2df9b2d5a", size = 47481 }
758
+ wheels = [
759
+ { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/ec/af/572825252f16f36eeecbc8e3b721913d2640d69b984fdb8907aa8b4b0975/objprint-0.3.0-py3-none-any.whl", hash = "sha256:489083bfc8baf0526f8fd6af74673799511532636f0ce4141133255ded773405", size = 41619 },
760
+ ]
761
+
753
762
  [[package]]
754
763
  name = "onnxruntime"
755
764
  version = "1.20.1"
@@ -1462,6 +1471,24 @@ wheels = [
1462
1471
  { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/94/5e/0132a00365066b058d096c008f8ef7dc36bb00a5676efae97dc919669c78/uv-0.5.29-py3-none-win_arm64.whl", hash = "sha256:e8a5e18487c33a0c29867da123ef0f035ee1ba880640fcbf8743ca80d7158ed0", size = 15693104 },
1463
1472
  ]
1464
1473
 
1474
+ [[package]]
1475
+ name = "viztracer"
1476
+ version = "1.0.2"
1477
+ source = { registry = "https://mirrors.bfsu.edu.cn/pypi/web/simple" }
1478
+ dependencies = [
1479
+ { name = "objprint" },
1480
+ ]
1481
+ sdist = { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/ab/20/c699e4c355fc63fa9a3516c000e6e0ea1fc12a8ac1fef3ccceeb4b4acc04/viztracer-1.0.2.tar.gz", hash = "sha256:83f3fbc9530808ac048942acaa684ffca3a850de0b098783f67de059bf460764", size = 14270242 }
1482
+ wheels = [
1483
+ { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/76/fc/5d32541bc6b758fccf59642103e29b9f039dd34c53b1c213eecba86bfbe1/viztracer-1.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:37f9bcc2bd42cde5c4b4fb1ee4c65b795a1c4ed2636876abb49cc6e67721d72e", size = 14437011 },
1484
+ { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/68/ed/63d051ffb12db1cf659e5ca5a0373b9d471c7d5525f763e0f59e9689db6f/viztracer-1.0.2-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:01feb66558942c6ac21d07400c95a6254709d5e050bb2cd9ace6bee989da413f", size = 14436844 },
1485
+ { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/c4/e3/7de2b047e27f4d98e04504654b63c24b878ede178e6631d5c81248336668/viztracer-1.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d7964ae404427c6feea6460a1bccd88fd9898b36bf256fd0a3b20c3ec556e92", size = 14556048 },
1486
+ { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/7e/cb/37863d6efdc65e89ab89e92a559c6c2736a7a5fe60d094175d17d407c4bf/viztracer-1.0.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2680b2bda7b8c42a1a32b391034d58e7ace81a4c601c727a333598bf70df794", size = 14552601 },
1487
+ { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/f3/e3/25f5ade889c92440cf279bd66e32965523513642a0e5f8ed58eb087e17ce/viztracer-1.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d5c412c2f3bf6d05a0bc5f50e4bce3642a863a001f0d3b290c6bd7085f045ca", size = 14564496 },
1488
+ { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/8d/b1/60ef00a773c631a068f3ef53a7d598408cce4bd60f19e8ef355a9012e77d/viztracer-1.0.2-cp312-cp312-win32.whl", hash = "sha256:f0ba07dff91cdb7a489376f35206594c90b211367abfcb109c7c59f5b6691c18", size = 14600798 },
1489
+ { url = "https://mirrors.bfsu.edu.cn/pypi/web/packages/5d/45/a53c0fe058780c8262c09a3c8279974e31cc54bc9aaa7d026c4a2f0289d2/viztracer-1.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:0c114f56839e78113f3721e013a6742aca74acfef987eae2ba7c670533950c82", size = 14603623 },
1490
+ ]
1491
+
1465
1492
  [[package]]
1466
1493
  name = "wcwidth"
1467
1494
  version = "0.2.13"
Binary file
File without changes