fabricatio 0.2.6.dev1__cp312-cp312-manylinux_2_34_x86_64.whl → 0.2.6.dev2__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.
@@ -5,13 +5,13 @@ to provide mechanisms for reviewing, validating, and correcting various objects
5
5
  based on predefined criteria and templates.
6
6
  """
7
7
 
8
- from typing import Optional, Unpack
8
+ from typing import Optional, Unpack, cast
9
9
 
10
10
  from fabricatio._rust_instances import TEMPLATE_MANAGER
11
11
  from fabricatio.capabilities.review import Review, ReviewResult
12
12
  from fabricatio.config import configs
13
13
  from fabricatio.models.generic import Display, ProposedAble, WithBriefing
14
- from fabricatio.models.kwargs_types import ReviewKwargs
14
+ from fabricatio.models.kwargs_types import CorrectKwargs, ReviewKwargs
15
15
  from fabricatio.models.task import Task
16
16
 
17
17
 
@@ -25,7 +25,11 @@ class Correct(Review):
25
25
  """
26
26
 
27
27
  async def correct_obj[M: ProposedAble](
28
- self, obj: M, **kwargs: Unpack[ReviewKwargs[ReviewResult[str]]]
28
+ self,
29
+ obj: M,
30
+ reference: str = "",
31
+ supervisor_check: bool = True,
32
+ **kwargs: Unpack[ReviewKwargs[ReviewResult[str]]],
29
33
  ) -> Optional[M]:
30
34
  """Review and correct an object based on defined criteria and templates.
31
35
 
@@ -34,6 +38,8 @@ class Correct(Review):
34
38
 
35
39
  Args:
36
40
  obj (M): The object to be reviewed and corrected. Must implement ProposedAble.
41
+ reference (str): A reference or contextual information for the object.
42
+ supervisor_check (bool, optional): Whether to perform a supervisor check on the review results. Defaults to True.
37
43
  **kwargs: Review configuration parameters including criteria and review options.
38
44
 
39
45
  Returns:
@@ -44,23 +50,27 @@ class Correct(Review):
44
50
  """
45
51
  if not isinstance(obj, (Display, WithBriefing)):
46
52
  raise TypeError(f"Expected Display or WithBriefing, got {type(obj)}")
53
+
47
54
  review_res = await self.review_obj(obj, **kwargs)
48
- await review_res.supervisor_check()
55
+ if supervisor_check:
56
+ await review_res.supervisor_check()
49
57
  if "default" in kwargs:
50
- kwargs["default"] = None
58
+ cast(ReviewKwargs[None], kwargs)["default"] = None
51
59
  return await self.propose(
52
60
  obj.__class__,
53
61
  TEMPLATE_MANAGER.render_template(
54
62
  configs.templates.correct_template,
55
63
  {
56
- "content": obj.display() if isinstance(obj, Display) else obj.briefing,
64
+ "content": f"{(reference + '\n\nAbove is referencing material') if reference else ''}{obj.display() if isinstance(obj, Display) else obj.briefing}",
57
65
  "review": review_res.display(),
58
66
  },
59
67
  ),
60
68
  **kwargs,
61
69
  )
62
70
 
63
- async def correct_string(self, input_text: str, **kwargs: Unpack[ReviewKwargs[ReviewResult[str]]]) -> Optional[str]:
71
+ async def correct_string(
72
+ self, input_text: str, supervisor_check: bool = True, **kwargs: Unpack[ReviewKwargs[ReviewResult[str]]]
73
+ ) -> Optional[str]:
64
74
  """Review and correct a string based on defined criteria and templates.
65
75
 
66
76
  This method applies the review process to the input text and generates
@@ -68,16 +78,18 @@ class Correct(Review):
68
78
 
69
79
  Args:
70
80
  input_text (str): The text content to be reviewed and corrected.
81
+ supervisor_check (bool, optional): Whether to perform a supervisor check on the review results. Defaults to True.
71
82
  **kwargs: Review configuration parameters including criteria and review options.
72
83
 
73
84
  Returns:
74
85
  Optional[str]: The corrected text content, or None if correction fails.
75
86
  """
76
87
  review_res = await self.review_string(input_text, **kwargs)
77
- await review_res.supervisor_check()
88
+ if supervisor_check:
89
+ await review_res.supervisor_check()
78
90
 
79
91
  if "default" in kwargs:
80
- kwargs["default"] = None
92
+ cast(ReviewKwargs[None], kwargs)["default"] = None
81
93
  return await self.ageneric_string(
82
94
  TEMPLATE_MANAGER.render_template(
83
95
  configs.templates.correct_template, {"content": input_text, "review": review_res.display()}
@@ -86,7 +98,7 @@ class Correct(Review):
86
98
  )
87
99
 
88
100
  async def correct_task[T](
89
- self, task: Task[T], **kwargs: Unpack[ReviewKwargs[ReviewResult[str]]]
101
+ self, task: Task[T], **kwargs: Unpack[CorrectKwargs[ReviewResult[str]]]
90
102
  ) -> Optional[Task[T]]:
91
103
  """Review and correct a task object based on defined criteria.
92
104
 
@@ -95,6 +95,17 @@ class ReviewKwargs[T](ValidateKwargs[T], total=False):
95
95
  criteria: set[str]
96
96
 
97
97
 
98
+ class CorrectKwargs[T](ReviewKwargs[T], total=False):
99
+ """Arguments for content correction operations.
100
+
101
+ Extends GenerateKwargs with parameters for correcting content based on
102
+ specific criteria and templates.
103
+ """
104
+
105
+ reference: str
106
+ supervisor_check: bool
107
+
108
+
98
109
  # noinspection PyTypedDict
99
110
  class ChooseKwargs[T](ValidateKwargs[T], total=False):
100
111
  """Arguments for selection operations.
@@ -0,0 +1,432 @@
1
+ Metadata-Version: 2.4
2
+ Name: fabricatio
3
+ Version: 0.2.6.dev2
4
+ Classifier: License :: OSI Approved :: MIT License
5
+ Classifier: Programming Language :: Rust
6
+ Classifier: Programming Language :: Python :: 3.12
7
+ Classifier: Programming Language :: Python :: Implementation :: CPython
8
+ Classifier: Framework :: AsyncIO
9
+ Classifier: Framework :: Pydantic :: 2
10
+ Classifier: Typing :: Typed
11
+ Requires-Dist: appdirs>=1.4.4
12
+ Requires-Dist: asyncio>=3.4.3
13
+ Requires-Dist: asyncstdlib>=3.13.0
14
+ Requires-Dist: json-repair>=0.39.1
15
+ Requires-Dist: litellm>=1.60.0
16
+ Requires-Dist: loguru>=0.7.3
17
+ Requires-Dist: magika>=0.5.1
18
+ Requires-Dist: more-itertools>=10.6.0
19
+ Requires-Dist: orjson>=3.10.15
20
+ Requires-Dist: pydantic>=2.10.6
21
+ Requires-Dist: pydantic-settings>=2.7.1
22
+ Requires-Dist: pymitter>=1.0.0
23
+ Requires-Dist: questionary>=2.1.0
24
+ Requires-Dist: regex>=2024.11.6
25
+ Requires-Dist: rich>=13.9.4
26
+ Requires-Dist: pymilvus>=2.5.4 ; extra == 'rag'
27
+ Requires-Dist: fabricatio[rag] ; extra == 'full'
28
+ Provides-Extra: rag
29
+ Provides-Extra: full
30
+ License-File: LICENSE
31
+ Summary: A LLM multi-agent framework.
32
+ Keywords: ai,agents,multi-agent,llm,pyo3
33
+ Author-email: Whth <zettainspector@foxmail.com>
34
+ Requires-Python: >=3.12, <3.13
35
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
36
+ Project-URL: Homepage, https://github.com/Whth/fabricatio
37
+ Project-URL: Repository, https://github.com/Whth/fabricatio
38
+ Project-URL: Issues, https://github.com/Whth/fabricatio/issues
39
+
40
+ # Fabricatio
41
+
42
+ ![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)
43
+ ![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)
44
+ ![Build Status](https://img.shields.io/badge/build-passing-brightgreen)
45
+
46
+ ## Overview
47
+
48
+ Fabricatio is a Python library designed for building LLM (Large Language Model) applications using an event-based agent structure. It integrates Rust for performance-critical tasks, utilizes Handlebars for templating, and employs PyO3 for Python bindings.
49
+
50
+ ## Features
51
+
52
+ - **Event-Based Architecture**: Utilizes an EventEmitter pattern for robust task management.
53
+ - **LLM Integration**: Supports interactions with large language models for intelligent task processing.
54
+ - **Templating Engine**: Uses Handlebars for dynamic content generation.
55
+ - **Toolboxes**: Provides predefined toolboxes for common operations like file manipulation and arithmetic.
56
+ - **Async Support**: Fully asynchronous for efficient execution.
57
+ - **Extensible**: Easy to extend with custom actions, workflows, and tools.
58
+
59
+ ## Installation
60
+
61
+ ### Using UV (Recommended)
62
+
63
+ To install Fabricatio using `uv` (a package manager for Python):
64
+
65
+ ```bash
66
+ # Install uv if not already installed
67
+ pip install uv
68
+
69
+ # Clone the repository
70
+ git clone https://github.com/Whth/fabricatio.git
71
+ cd fabricatio
72
+
73
+ # Install the package in development mode with uv
74
+ uv --with-editable . maturin develop --uv -r
75
+ ```
76
+
77
+ ### Building Distribution
78
+
79
+ For production builds:
80
+
81
+ ```bash
82
+ # Build distribution packages
83
+ make bdist
84
+ ```
85
+
86
+ This will generate distribution files in the `dist` directory.
87
+
88
+ ## Usage
89
+
90
+ ### Basic Example
91
+
92
+ #### Simple Hello World Program
93
+
94
+ ```python
95
+ import asyncio
96
+ from fabricatio import Action, Role, Task, logger, WorkFlow
97
+ from typing import Any
98
+
99
+ class Hello(Action):
100
+ name: str = "hello"
101
+ output_key: str = "task_output"
102
+
103
+ async def _execute(self, task_input: Task[str], **_) -> Any:
104
+ ret = "Hello fabricatio!"
105
+ logger.info("executing talk action")
106
+ return ret
107
+
108
+ async def main() -> None:
109
+ role = Role(
110
+ name="talker",
111
+ description="talker role",
112
+ registry={Task.pending_label: WorkFlow(name="talk", steps=(Hello,))}
113
+ )
114
+
115
+ task = Task(name="say hello", goals="say hello", description="say hello to the world")
116
+ result = await task.delegate()
117
+ logger.success(f"Result: {result}")
118
+
119
+ if __name__ == "__main__":
120
+ asyncio.run(main())
121
+ ```
122
+
123
+ ### Advanced Examples
124
+
125
+ #### Simple Chat
126
+
127
+ Demonstrates a basic chat application.
128
+
129
+ ```python
130
+ """Simple chat example."""
131
+ import asyncio
132
+ from fabricatio import Action, Role, Task, WorkFlow, logger
133
+ from fabricatio.models.events import Event
134
+ from questionary import text
135
+
136
+ class Talk(Action):
137
+ """Action that says hello to the world."""
138
+
139
+ output_key: str = "task_output"
140
+
141
+ async def _execute(self, task_input: Task[str], **_) -> int:
142
+ counter = 0
143
+ try:
144
+ while True:
145
+ user_say = await text("User: ").ask_async()
146
+ gpt_say = await self.aask(
147
+ user_say,
148
+ system_message=f"You have to answer to user obeying task assigned to you:\n{task_input.briefing}",
149
+ )
150
+ print(f"GPT: {gpt_say}") # noqa: T201
151
+ counter += 1
152
+ except KeyboardInterrupt:
153
+ logger.info(f"executed talk action {counter} times")
154
+ return counter
155
+
156
+ async def main() -> None:
157
+ """Main function."""
158
+ role = Role(
159
+ name="talker",
160
+ description="talker role",
161
+ registry={Event.instantiate_from("talk").push_wildcard().push("pending"): WorkFlow(name="talk", steps=(Talk,))},
162
+ )
163
+
164
+ task = await role.propose_task(
165
+ "you have to act as a helpful assistant, answer to all user questions properly and patiently"
166
+ )
167
+ _ = await task.delegate("talk")
168
+
169
+ if __name__ == "__main__":
170
+ asyncio.run(main())
171
+ ```
172
+
173
+ #### Simple RAG
174
+
175
+ Demonstrates Retrieval-Augmented Generation (RAG).
176
+
177
+ ```python
178
+ """Simple chat example."""
179
+ import asyncio
180
+ from fabricatio import RAG, Action, Role, Task, WorkFlow, logger
181
+ from fabricatio.models.events import Event
182
+ from questionary import text
183
+
184
+ class Talk(Action, RAG):
185
+ """Action that says hello to the world."""
186
+
187
+ output_key: str = "task_output"
188
+
189
+ async def _execute(self, task_input: Task[str], **_) -> int:
190
+ counter = 0
191
+
192
+ self.init_client().view("test_collection", create=True)
193
+ await self.consume_string(
194
+ [
195
+ "Company policy clearly stipulates that all employees must arrive at the headquarters building located at 88 Jianguo Road, Chaoyang District, Beijing before 9 AM daily.",
196
+ "According to the latest revised health and safety guidelines, employees must wear company-provided athletic gear when using the company gym facilities.",
197
+ "Section 3.2.1 of the employee handbook states that pets are not allowed in the office area under any circumstances.",
198
+ "To promote work efficiency, the company has quiet workspaces at 100 Century Avenue, Pudong New District, Shanghai, for employees who need high concentration for their work.",
199
+ "According to the company's remote work policy, employees can apply for a maximum of 5 days of working from home per month, but must submit the application one week in advance.",
200
+ "The company has strict regulations on overtime. Unless approved by direct supervisors, no form of work is allowed after 9 PM.",
201
+ "Regarding the new regulations for business travel reimbursement, all traveling personnel must submit detailed expense reports within five working days after returning.",
202
+ "Company address: 123 East Sports Road, Tianhe District, Guangzhou, Postal Code: 510620.",
203
+ "Annual team building activities will be held in the second quarter of each year, usually at a resort within a two-hour drive from the Guangzhou headquarters.",
204
+ "Employees who are late more than three times will receive a formal warning, which may affect their year-end performance evaluation.",
205
+ ]
206
+ )
207
+ try:
208
+ while True:
209
+ user_say = await text("User: ").ask_async()
210
+ if user_say is None:
211
+ break
212
+ gpt_say = await self.aask_retrieved(
213
+ user_say,
214
+ user_say,
215
+ extra_system_message=f"You have to answer to user obeying task assigned to you:\n{task_input.briefing}",
216
+ )
217
+ print(f"GPT: {gpt_say}") # noqa: T201
218
+ counter += 1
219
+ except KeyboardInterrupt:
220
+ logger.info(f"executed talk action {counter} times")
221
+ return counter
222
+
223
+ async def main() -> None:
224
+ """Main function."""
225
+ role = Role(
226
+ name="talker",
227
+ description="talker role but with rag",
228
+ registry={Event.instantiate_from("talk").push_wildcard().push("pending"): WorkFlow(name="talk", steps=(Talk,))},
229
+ )
230
+
231
+ task = await role.propose_task(
232
+ "you have to act as a helpful assistant, answer to all user questions properly and patiently"
233
+ )
234
+ _ = await task.delegate("talk")
235
+
236
+ if __name__ == "__main__":
237
+ asyncio.run(main())
238
+ ```
239
+
240
+ #### Extract Article
241
+
242
+ Demonstrates extracting the essence of an article from a file.
243
+
244
+ ```python
245
+ """Example of proposing a task to a role."""
246
+ import asyncio
247
+ from typing import List
248
+
249
+ from fabricatio import ArticleEssence, Event, ExtractArticleEssence, Role, Task, WorkFlow, logger
250
+
251
+ async def main() -> None:
252
+ """Main function."""
253
+ role = Role(
254
+ name="Researcher",
255
+ description="Extract article essence",
256
+ registry={
257
+ Event.quick_instantiate("article"): WorkFlow(
258
+ name="extract",
259
+ steps=(ExtractArticleEssence(output_key="task_output"),),
260
+ )
261
+ },
262
+ )
263
+ task: Task[List[ArticleEssence]] = await role.propose_task(
264
+ "Extract the essence of the article from the file at './7.md'"
265
+ )
266
+ ess = (await task.delegate("article")).pop()
267
+ logger.success(f"Essence:\n{ess.display()}")
268
+
269
+ if __name__ == "__main__":
270
+ asyncio.run(main())
271
+ ```
272
+
273
+ #### Propose Task
274
+
275
+ Demonstrates proposing a task to a role.
276
+
277
+ ```python
278
+ """Example of proposing a task to a role."""
279
+ import asyncio
280
+ from typing import Any
281
+
282
+ from fabricatio import Action, Event, Role, Task, WorkFlow, logger
283
+
284
+ class Talk(Action):
285
+ """Action that says hello to the world."""
286
+
287
+ output_key: str = "task_output"
288
+
289
+ async def _execute(self, **_) -> Any:
290
+ ret = "Hello fabricatio!"
291
+ logger.info("executing talk action")
292
+ return ret
293
+
294
+ async def main() -> None:
295
+ """Main function."""
296
+ role = Role(
297
+ name="talker",
298
+ description="talker role",
299
+ registry={Event.quick_instantiate("talk"): WorkFlow(name="talk", steps=(Talk,))},
300
+ )
301
+ logger.info(f"Task example:\n{Task.formated_json_schema()}")
302
+ logger.info(f"proposed task: {await role.propose_task('write a rust clap cli that can download a html page')}")
303
+
304
+ if __name__ == "__main__":
305
+ asyncio.run(main())
306
+ ```
307
+
308
+ #### Review
309
+
310
+ Demonstrates reviewing code.
311
+
312
+ ```python
313
+ """Example of review usage."""
314
+ import asyncio
315
+
316
+ from fabricatio import Role, logger
317
+
318
+ async def main() -> None:
319
+ """Main function."""
320
+ role = Role(
321
+ name="Reviewer",
322
+ description="A role that reviews the code.",
323
+ )
324
+
325
+ code = await role.aask(
326
+ "write a cli app using rust with clap which can generate a basic manifest of a standard rust project, output code only,no extra explanation"
327
+ )
328
+
329
+ logger.success(f"Code: \n{code}")
330
+ res = await role.review_string(code, "If the cli app is of good design")
331
+ logger.success(f"Review: \n{res.display()}")
332
+ await res.supervisor_check()
333
+ logger.success(f"Review: \n{res.display()}")
334
+
335
+ if __name__ == "__main__":
336
+ asyncio.run(main())
337
+ ```
338
+
339
+ #### Write Outline
340
+
341
+ Demonstrates writing an outline for an article in Typst format.
342
+
343
+ ```python
344
+ """Example of using the library."""
345
+ import asyncio
346
+
347
+ from fabricatio import Event, Role, WriteOutlineWorkFlow, logger
348
+
349
+ async def main() -> None:
350
+ """Main function."""
351
+ role = Role(
352
+ name="Undergraduate Researcher",
353
+ description="Write an outline for an article in typst format.",
354
+ registry={Event.quick_instantiate(ns := "article"): WriteOutlineWorkFlow},
355
+ )
356
+
357
+ proposed_task = await role.propose_task(
358
+ "You need to read the `./article_briefing.txt` file and write an outline for the article in typst format. The outline should be saved in the `./out.typ` file.",
359
+ )
360
+ path = await proposed_task.delegate(ns)
361
+ logger.success(f"The outline is saved in:\n{path}")
362
+
363
+ if __name__ == "__main__":
364
+ asyncio.run(main())
365
+ ```
366
+
367
+ ## Configuration
368
+
369
+ The configuration for Fabricatio is managed via environment variables or TOML files. The default configuration file (`config.toml`) can be overridden by specifying a custom path.
370
+
371
+ Example `config.toml`:
372
+
373
+ ```toml
374
+ [llm]
375
+ api_endpoint = "https://api.openai.com"
376
+ api_key = "your_openai_api_key"
377
+ timeout = 300
378
+ max_retries = 3
379
+ model = "gpt-3.5-turbo"
380
+ temperature = 1.0
381
+ stop_sign = ["\n\n\n", "User:"]
382
+ top_p = 0.35
383
+ generation_count = 1
384
+ stream = false
385
+ max_tokens = 8192
386
+ ```
387
+
388
+ ## Development Setup
389
+
390
+ To set up a development environment for Fabricatio:
391
+
392
+ 1. **Clone the Repository**:
393
+ ```bash
394
+ git clone https://github.com/Whth/fabricatio.git
395
+ cd fabricatio
396
+ ```
397
+
398
+ 2. **Install Dependencies**:
399
+ ```bash
400
+ uv --with-editable . maturin develop --uv -r
401
+ ```
402
+
403
+ 3. **Run Tests**:
404
+ ```bash
405
+ make test
406
+ ```
407
+
408
+ 4. **Build Documentation**:
409
+ ```bash
410
+ make docs
411
+ ```
412
+
413
+ ## Contributing
414
+
415
+ Contributions are welcome! Please follow these guidelines when contributing:
416
+
417
+ 1. Fork the repository.
418
+ 2. Create your feature branch (`git checkout -b feature/new-feature`).
419
+ 3. Commit your changes (`git commit -am 'Add new feature'`).
420
+ 4. Push to the branch (`git push origin feature/new-feature`).
421
+ 5. Create a new Pull Request.
422
+
423
+ ## License
424
+
425
+ Fabricatio is licensed under the MIT License. See [LICENSE](LICENSE) for more details.
426
+
427
+ ## Acknowledgments
428
+
429
+ Special thanks to the contributors and maintainers of:
430
+ - [PyO3](https://github.com/PyO3/pyo3)
431
+ - [Maturin](https://github.com/PyO3/maturin)
432
+ - [Handlebars.rs](https://github.com/sunng87/handlebars-rust)
@@ -1,13 +1,13 @@
1
- fabricatio-0.2.6.dev1.dist-info/METADATA,sha256=EAsdhUegSLfBx_7NiZpY2BL54yfY1uHPUZmtoH_yaVU,8624
2
- fabricatio-0.2.6.dev1.dist-info/WHEEL,sha256=RIvmwLDYujv60MYBx2jxyP4vdn1DD7X0kBgz1TQvZuc,108
3
- fabricatio-0.2.6.dev1.dist-info/licenses/LICENSE,sha256=yDZaTLnOi03bi3Dk6f5IjhLUc5old2yOsihHWU0z-i0,1067
1
+ fabricatio-0.2.6.dev2.dist-info/METADATA,sha256=Y6L-yF34GPs0csU6zdhZxzJ8OOsNxa26hT3iBaD7Jn8,13693
2
+ fabricatio-0.2.6.dev2.dist-info/WHEEL,sha256=RIvmwLDYujv60MYBx2jxyP4vdn1DD7X0kBgz1TQvZuc,108
3
+ fabricatio-0.2.6.dev2.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
8
  fabricatio/models/role.py,sha256=pQUHj5jx5OqbbDufhvoqqF72R0dJ6aIrREieASe96Ls,1794
9
9
  fabricatio/models/extra.py,sha256=ndK8EKzANT7sz_1f00PtJgs8922M9V3_G4JlORXySKk,7241
10
- fabricatio/models/kwargs_types.py,sha256=1i_R_FDElmRzBpNLBM8SuqzLt2aJSjjC9AS-NYUlWYg,4139
10
+ fabricatio/models/kwargs_types.py,sha256=30hREqUXw4_0fVl6-NPdnTN07hSBiCWcdVr5z6RH6jE,4415
11
11
  fabricatio/models/utils.py,sha256=KmsTQcBCTYgnsZz7U1ECSfLRdswWPkKtGg8mBMaXrwA,4850
12
12
  fabricatio/models/usages.py,sha256=DiCiS1_YsHyB1-cQJdevyVxAn5_B9x0717mis8DNG9s,27952
13
13
  fabricatio/models/events.py,sha256=UvOc6V3vfjKuvh7irDezJ8EGpsNo5yzLdq4xQexVonw,4063
@@ -30,7 +30,7 @@ fabricatio/_rust_instances.py,sha256=bQmlhUCcxTmRgvw1SfzYzNNpgW_UCjmkYw5f-VPAyg8
30
30
  fabricatio/workflows/articles.py,sha256=utvKDBFEJbcM76729-H2AvgMCNcsX1NquqMpHqGZq8E,565
31
31
  fabricatio/workflows/rag.py,sha256=uOZXprD479fUhLA6sYvEM8RWcVcUZXXtP0xRbTMPdHE,509
32
32
  fabricatio/parser.py,sha256=uewTtO5N_5FAX_4rVzysGJsVs75J0vR-Iz7_dvWfGQk,6045
33
- fabricatio/capabilities/correct.py,sha256=s2vXPkX-NKBO5Yt1qaMDbrXfrYBRxzI5bvWBXnbaaOw,4424
33
+ fabricatio/capabilities/correct.py,sha256=BiLEAk6e1KbwUMhTexmDfgtlPUct_bG0igDK7CwHqao,5107
34
34
  fabricatio/capabilities/rag.py,sha256=ghctqjIf6KDe6PP8-SDzKN1zxh94rXk5Y5hHFtG_46Y,15404
35
35
  fabricatio/capabilities/rating.py,sha256=ZQrKKmmIgnN4zgNnG_GmWa5Nyxpk03JYW32RJ4R5vvQ,14067
36
36
  fabricatio/capabilities/review.py,sha256=TX7av4b2N7MRDHMowsIZfiujXRRNxjUMNHtCFVA1UTM,10824
@@ -38,5 +38,5 @@ fabricatio/capabilities/propose.py,sha256=4QvONVVUp1rs34Te2Rjams6NioEt6FhEAxDWiv
38
38
  fabricatio/capabilities/task.py,sha256=uAp4tC9cbq3Ux-VQHjYdEzKLE3Jr8vhB6HKLPbhozIo,4494
39
39
  fabricatio/_rust.pyi,sha256=xXSaL7llihyFIyr9_k6e5RRJVNYk2jM-jrrheNvvaIA,3067
40
40
  fabricatio/_rust.cpython-312-x86_64-linux-gnu.so,sha256=74s_TC4HghV27dU5SlwPhHVbGQXAjB_tRTopjpIWjBI,1899904
41
- fabricatio-0.2.6.dev1.data/scripts/tdown,sha256=_ZohEMMAnhhlAKfxVua2YoN3LSsaWp1RVXCA6y1EBTg,4573488
42
- fabricatio-0.2.6.dev1.dist-info/RECORD,,
41
+ fabricatio-0.2.6.dev2.data/scripts/tdown,sha256=_ZohEMMAnhhlAKfxVua2YoN3LSsaWp1RVXCA6y1EBTg,4573488
42
+ fabricatio-0.2.6.dev2.dist-info/RECORD,,
@@ -1,312 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: fabricatio
3
- Version: 0.2.6.dev1
4
- Classifier: License :: OSI Approved :: MIT License
5
- Classifier: Programming Language :: Rust
6
- Classifier: Programming Language :: Python :: 3.12
7
- Classifier: Programming Language :: Python :: Implementation :: CPython
8
- Classifier: Framework :: AsyncIO
9
- Classifier: Framework :: Pydantic :: 2
10
- Classifier: Typing :: Typed
11
- Requires-Dist: appdirs>=1.4.4
12
- Requires-Dist: asyncio>=3.4.3
13
- Requires-Dist: asyncstdlib>=3.13.0
14
- Requires-Dist: json-repair>=0.39.1
15
- Requires-Dist: litellm>=1.60.0
16
- Requires-Dist: loguru>=0.7.3
17
- Requires-Dist: magika>=0.5.1
18
- Requires-Dist: more-itertools>=10.6.0
19
- Requires-Dist: orjson>=3.10.15
20
- Requires-Dist: pydantic>=2.10.6
21
- Requires-Dist: pydantic-settings>=2.7.1
22
- Requires-Dist: pymitter>=1.0.0
23
- Requires-Dist: questionary>=2.1.0
24
- Requires-Dist: regex>=2024.11.6
25
- Requires-Dist: rich>=13.9.4
26
- Requires-Dist: pymilvus>=2.5.4 ; extra == 'rag'
27
- Requires-Dist: fabricatio[rag] ; extra == 'full'
28
- Provides-Extra: rag
29
- Provides-Extra: full
30
- License-File: LICENSE
31
- Summary: A LLM multi-agent framework.
32
- Keywords: ai,agents,multi-agent,llm,pyo3
33
- Author-email: Whth <zettainspector@foxmail.com>
34
- Requires-Python: >=3.12, <3.13
35
- Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
36
- Project-URL: Homepage, https://github.com/Whth/fabricatio
37
- Project-URL: Repository, https://github.com/Whth/fabricatio
38
- Project-URL: Issues, https://github.com/Whth/fabricatio/issues
39
-
40
- # Fabricatio
41
-
42
- ![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)
43
- ![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)
44
- ![Build Status](https://img.shields.io/badge/build-passing-brightgreen)
45
-
46
- ## Overview
47
-
48
- Fabricatio is a Python library designed for building LLM (Large Language Model) applications using an event-based agent structure. It integrates Rust for performance-critical tasks, utilizes Handlebars for templating, and employs PyO3 for Python bindings.
49
-
50
- ## Features
51
-
52
- - **Event-Based Architecture**: Utilizes an EventEmitter pattern for robust task management.
53
- - **LLM Integration**: Supports interactions with large language models for intelligent task processing.
54
- - **Templating Engine**: Uses Handlebars for dynamic content generation.
55
- - **Toolboxes**: Provides predefined toolboxes for common operations like file manipulation and arithmetic.
56
- - **Async Support**: Fully asynchronous for efficient execution.
57
- - **Extensible**: Easy to extend with custom actions, workflows, and tools.
58
-
59
- ## Installation
60
-
61
- ### Using UV (Recommended)
62
-
63
- To install Fabricatio using `uv` (a package manager for Python):
64
-
65
- ```bash
66
- # Install uv if not already installed
67
- pip install uv
68
-
69
- # Clone the repository
70
- git clone https://github.com/Whth/fabricatio.git
71
- cd fabricatio
72
-
73
- # Install the package in development mode with uv
74
- uv --with-editable . maturin develop --uv -r
75
- ```
76
-
77
-
78
- ### Building Distribution
79
-
80
- For production builds:
81
-
82
- ```bash
83
- # Build distribution packages
84
- make bdist
85
- ```
86
-
87
-
88
- This will generate distribution files in the `dist` directory.
89
-
90
- ## Usage
91
-
92
- ### Basic Example
93
-
94
- #### Simple Hello World Program
95
-
96
- ```python
97
- import asyncio
98
- from fabricatio import Action, Role, Task, logger, WorkFlow
99
- from typing import Any
100
-
101
- class Hello(Action):
102
- name: str = "hello"
103
- output_key: str = "task_output"
104
-
105
- async def _execute(self, task_input: Task[str], **_) -> Any:
106
- ret = "Hello fabricatio!"
107
- logger.info("executing talk action")
108
- return ret
109
-
110
- async def main() -> None:
111
- role = Role(
112
- name="talker",
113
- description="talker role",
114
- registry={Task.pending_label: WorkFlow(name="talk", steps=(Hello,))}
115
- )
116
-
117
- task = Task(name="say hello", goals="say hello", description="say hello to the world")
118
- result = await task.delegate()
119
- logger.success(f"Result: {result}")
120
-
121
- if __name__ == "__main__":
122
- asyncio.run(main())
123
- ```
124
-
125
-
126
- ### Advanced Examples
127
-
128
- #### Writing and Dumping Code
129
-
130
- ```python
131
- import asyncio
132
- from fabricatio import Action, Event, PythonCapture, Role, Task, ToolBox, WorkFlow, fs_toolbox, logger
133
-
134
-
135
- class WriteCode(Action):
136
- name: str = "write code"
137
- output_key: str = "source_code"
138
-
139
- async def _execute(self, task_input: Task[str], **_) -> str:
140
- return await self.aask_validate(task_input.briefing, validator=PythonCapture.capture)
141
-
142
-
143
- class DumpCode(Action):
144
- name: str = "dump code"
145
- description: str = "Dump code to file system"
146
- toolboxes: set[ToolBox] = {fs_toolbox}
147
- output_key: str = "task_output"
148
-
149
- async def _execute(self, task_input: Task, source_code: str, **_) -> Any:
150
- path = await self.handle_fin_grind(task_input, {"source_code": source_code})
151
- return path[0] if path else None
152
-
153
-
154
- async def main() -> None:
155
- role = Role(
156
- name="Coder",
157
- description="A python coder who can write and document code",
158
- registry={
159
- Event.instantiate_from("coding.*").push("pending"): WorkFlow(
160
- name="write code", steps=(WriteCode, DumpCode)
161
- )
162
- }
163
- )
164
-
165
- prompt = "write a Python CLI app which prints 'hello world' n times with detailed Google-style docstring. Write the source code to `cli.py`."
166
- proposed_task = await role.propose_task(prompt)
167
- path = await proposed_task.move_to("coding").delegate()
168
- logger.success(f"Code Path: {path}")
169
-
170
-
171
- if __name__ == "__main__":
172
- asyncio.run(main())
173
- ```
174
-
175
-
176
- ### Template Management and Rendering
177
-
178
- ```python
179
- from fabricatio._rust_instances import TEMPLATE_MANAGER
180
-
181
- template_name = "claude-xml.hbs"
182
- data = {
183
- "absolute_code_path": "/path/to/project",
184
- "source_tree": "source tree content",
185
- "files": [{"path": "file1.py", "code": "print('Hello')"}],
186
- }
187
-
188
- rendered_template = TEMPLATE_MANAGER.render_template(template_name, data)
189
- print(rendered_template)
190
- ```
191
-
192
-
193
- ### Handling Security Vulnerabilities
194
-
195
- ```python
196
- from fabricatio.models.usages import ToolBoxUsage
197
- from fabricatio.models.task import Task
198
-
199
- toolbox_usage = ToolBoxUsage()
200
-
201
- async def handle_security_vulnerabilities():
202
- task = Task(
203
- name="Security Check",
204
- goals=["Identify security vulnerabilities"],
205
- description="Perform a thorough security review on the project.",
206
- dependencies=["./src/main.py"]
207
- )
208
-
209
- vulnerabilities = await toolbox_usage.gather_tools_fine_grind(task)
210
- for vulnerability in vulnerabilities:
211
- print(f"Found vulnerability: {vulnerability.name}")
212
- ```
213
-
214
-
215
- ### Managing CTF Challenges
216
-
217
- ```python
218
- import asyncio
219
-
220
- from fabricatio.models.usages import ToolBoxUsage
221
- from fabricatio.models.task import Task
222
-
223
- toolbox_usage = ToolBoxUsage()
224
-
225
- async def solve_ctf_challenge(challenge_name: str, challenge_description: str, files: list[str]):
226
- task = Task(
227
- name=challenge_name,
228
- goals=[f"Solve {challenge_name} challenge"],
229
- description=challenge_description,
230
- dependencies=files
231
- )
232
-
233
- solution = await toolbox_usage.gather_tools_fine_grind(task)
234
- print(f"Challenge Solved: {solution}")
235
-
236
- if __name__ == "__main__":
237
- asyncio.run(
238
- solve_ctf_challenge("Binary Exploitation", "CTF Binary Exploitation Challenge", ["./challenges/binary_exploit"]))
239
- ```
240
-
241
-
242
- ## Configuration
243
-
244
- The configuration for Fabricatio is managed via environment variables or TOML files. The default configuration file (`config.toml`) can be overridden by specifying a custom path.
245
-
246
- Example `config.toml`:
247
-
248
- ```toml
249
- [llm]
250
- api_endpoint = "https://api.openai.com"
251
- api_key = "your_openai_api_key"
252
- timeout = 300
253
- max_retries = 3
254
- model = "gpt-3.5-turbo"
255
- temperature = 1.0
256
- stop_sign = ["\n\n\n", "User:"]
257
- top_p = 0.35
258
- generation_count = 1
259
- stream = false
260
- max_tokens = 8192
261
- ```
262
-
263
-
264
- ## Development Setup
265
-
266
- To set up a development environment for Fabricatio:
267
-
268
- 1. **Clone the Repository**:
269
- ```bash
270
- git clone https://github.com/Whth/fabricatio.git
271
- cd fabricatio
272
- ```
273
-
274
-
275
- 2. **Install Dependencies**:
276
- ```bash
277
- uv --with-editable . maturin develop --uv -r
278
- ```
279
-
280
-
281
- 3. **Run Tests**:
282
- ```bash
283
- make test
284
- ```
285
-
286
-
287
- 4. **Build Documentation**:
288
- ```bash
289
- make docs
290
- ```
291
-
292
-
293
- ## Contributing
294
-
295
- Contributions are welcome! Please follow these guidelines when contributing:
296
-
297
- 1. Fork the repository.
298
- 2. Create your feature branch (`git checkout -b feature/new-feature`).
299
- 3. Commit your changes (`git commit -am 'Add new feature'`).
300
- 4. Push to the branch (`git push origin feature/new-feature`).
301
- 5. Create a new Pull Request.
302
-
303
- ## License
304
-
305
- Fabricatio is licensed under the MIT License. See [LICENSE](LICENSE) for more details.
306
-
307
- ## Acknowledgments
308
-
309
- Special thanks to the contributors and maintainers of:
310
- - [PyO3](https://github.com/PyO3/pyo3)
311
- - [Maturin](https://github.com/PyO3/maturin)
312
- - [Handlebars.rs](https://github.com/sunng87/handlebars-rust)