fabricatio 0.2.7.dev0__tar.gz → 0.2.7.dev2__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 (129) hide show
  1. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/.gitignore +1 -0
  2. fabricatio-0.2.7.dev2/Makefile +27 -0
  3. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/PKG-INFO +6 -2
  4. fabricatio-0.2.7.dev2/examples/extract_and_inject/ask.py +59 -0
  5. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/extract_and_inject/extract_and_inject.py +1 -2
  6. fabricatio-0.2.7.dev2/examples/write_article/write_article.py +46 -0
  7. fabricatio-0.2.7.dev2/examples/write_outline/.gitignore +2 -0
  8. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/pyproject.toml +11 -2
  9. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/_rust.pyi +11 -2
  10. fabricatio-0.2.7.dev2/python/fabricatio/actions/article.py +209 -0
  11. fabricatio-0.2.7.dev2/python/fabricatio/actions/output.py +34 -0
  12. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/capabilities/correct.py +34 -4
  13. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/capabilities/rag.py +41 -5
  14. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/capabilities/rating.py +15 -6
  15. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/capabilities/review.py +6 -3
  16. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/capabilities/task.py +2 -2
  17. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/config.py +3 -0
  18. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/decorators.py +32 -0
  19. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/models/action.py +9 -7
  20. fabricatio-0.2.7.dev2/python/fabricatio/models/extra.py +811 -0
  21. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/models/generic.py +60 -9
  22. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/models/kwargs_types.py +22 -3
  23. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/models/usages.py +48 -37
  24. fabricatio-0.2.7.dev2/src/templates.rs +111 -0
  25. fabricatio-0.2.7.dev2/templates/built-in/as_prompt.hbs +3 -0
  26. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/refined_query.hbs +15 -4
  27. fabricatio-0.2.7.dev2/templates.tar.gz +0 -0
  28. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/uv.lock +136 -3
  29. fabricatio-0.2.7.dev0/Makefile +0 -27
  30. fabricatio-0.2.7.dev0/python/fabricatio/actions/article.py +0 -131
  31. fabricatio-0.2.7.dev0/python/fabricatio/actions/output.py +0 -19
  32. fabricatio-0.2.7.dev0/python/fabricatio/models/extra.py +0 -685
  33. fabricatio-0.2.7.dev0/src/templates.rs +0 -104
  34. fabricatio-0.2.7.dev0/templates.tar.gz +0 -0
  35. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/.github/workflows/build-package.yaml +0 -0
  36. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/.github/workflows/ruff.yaml +0 -0
  37. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/.github/workflows/tests.yaml +0 -0
  38. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/.python-version +0 -0
  39. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/Cargo.lock +0 -0
  40. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/Cargo.toml +0 -0
  41. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/LICENSE +0 -0
  42. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/README.md +0 -0
  43. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/correct/correct.py +0 -0
  44. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/correct/correct_loop.py +0 -0
  45. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/extract_and_inject/.gitignore +0 -0
  46. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/extract_and_inject/article_rag.py +0 -0
  47. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/extract_article/extract.py +0 -0
  48. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/llm_usages/llm_usage.py +0 -0
  49. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/make_a_rating/rating.py +0 -0
  50. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/make_diary/commits.json +0 -0
  51. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/make_diary/diary.py +0 -0
  52. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/minor/hello_fabricatio.py +0 -0
  53. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/minor/write_a_poem.py +0 -0
  54. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/propose_task/propose.py +0 -0
  55. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/reviewer/review.py +0 -0
  56. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/search_bibtex/.gitignore +0 -0
  57. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/search_bibtex/search.py +0 -0
  58. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/simple_chat/chat.py +0 -0
  59. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/simple_rag/simple_rag.py +0 -0
  60. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/task_handle/handle_task.py +0 -0
  61. {fabricatio-0.2.7.dev0/examples/write_outline → fabricatio-0.2.7.dev2/examples/write_article}/.gitignore +0 -0
  62. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/write_outline/write_outline.py +0 -0
  63. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/examples/write_outline/write_outline_corrected.py +0 -0
  64. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/__init__.py +0 -0
  65. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/_rust_instances.py +0 -0
  66. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/actions/rag.py +0 -0
  67. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/capabilities/propose.py +0 -0
  68. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/core.py +0 -0
  69. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/fs/__init__.py +0 -0
  70. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/fs/curd.py +0 -0
  71. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/fs/readers.py +0 -0
  72. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/journal.py +0 -0
  73. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/models/events.py +0 -0
  74. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/models/role.py +0 -0
  75. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/models/task.py +0 -0
  76. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/models/tool.py +0 -0
  77. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/models/utils.py +0 -0
  78. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/parser.py +0 -0
  79. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/py.typed +0 -0
  80. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/toolboxes/__init__.py +0 -0
  81. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/toolboxes/arithmetic.py +0 -0
  82. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/toolboxes/fs.py +0 -0
  83. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/workflows/articles.py +0 -0
  84. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/python/fabricatio/workflows/rag.py +0 -0
  85. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/src/bib_tools.rs +0 -0
  86. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/src/hash.rs +0 -0
  87. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/src/hbs_helpers.rs +0 -0
  88. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/src/lib.rs +0 -0
  89. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/binary-exploitation-ctf-solver.hbs +0 -0
  90. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/claude-xml.hbs +0 -0
  91. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/clean-up-code.hbs +0 -0
  92. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/co_validation.hbs +0 -0
  93. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/correct.hbs +0 -0
  94. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/create_json_obj.hbs +0 -0
  95. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/cryptography-ctf-solver.hbs +0 -0
  96. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/dependencies.hbs +0 -0
  97. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/document-the-code.hbs +0 -0
  98. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/draft_rating_criteria.hbs +0 -0
  99. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/draft_rating_manual.hbs +0 -0
  100. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/draft_rating_weights_klee.hbs +0 -0
  101. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/draft_tool_usage_code.hbs +0 -0
  102. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/extract_criteria_from_reasons.hbs +0 -0
  103. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/extract_reasons_from_examples.hbs +0 -0
  104. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/find-security-vulnerabilities.hbs +0 -0
  105. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/fix-bugs.hbs +0 -0
  106. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/generic_string.hbs +0 -0
  107. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/improve-performance.hbs +0 -0
  108. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/liststr.hbs +0 -0
  109. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/make_choice.hbs +0 -0
  110. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/make_judgment.hbs +0 -0
  111. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/pathstr.hbs +0 -0
  112. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/rate_fine_grind.hbs +0 -0
  113. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/refactor.hbs +0 -0
  114. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/retrieved_display.hbs +0 -0
  115. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/reverse-engineering-ctf-solver.hbs +0 -0
  116. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/review_string.hbs +0 -0
  117. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/task_briefing.hbs +0 -0
  118. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/web-ctf-solver.hbs +0 -0
  119. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/write-git-commit.hbs +0 -0
  120. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/write-github-pull-request.hbs +0 -0
  121. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/templates/built-in/write-github-readme.hbs +0 -0
  122. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/tests/test_config.py +0 -0
  123. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/tests/test_models/test_action.py +0 -0
  124. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/tests/test_models/test_advanced.py +0 -0
  125. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/tests/test_models/test_generic.py +0 -0
  126. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/tests/test_models/test_role.py +0 -0
  127. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/tests/test_models/test_task.py +0 -0
  128. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/tests/test_models/test_tool.py +0 -0
  129. {fabricatio-0.2.7.dev0 → fabricatio-0.2.7.dev2}/tests/test_models/test_usages.py +0 -0
@@ -165,3 +165,4 @@ cython_debug/
165
165
 
166
166
  extra/scripts/*
167
167
  output/
168
+ .vscode/
@@ -0,0 +1,27 @@
1
+ DIST:=dist
2
+ DATA:=extra
3
+ PY:=3.12
4
+
5
+
6
+ all:bdist
7
+
8
+ tools:
9
+ cargo build --all --bins -Z unstable-options --artifact-dir $(DATA)/scripts --release
10
+ mkdir -p $(DATA)/scripts
11
+ rm $(DATA)/scripts/*.pdb || true
12
+ rm $(DATA)/scripts/*.dwarf || true
13
+
14
+ dev: tools
15
+ uvx -p $(PY) --project . maturin develop --uv -r
16
+
17
+ bdist:clean tools
18
+ uvx -p $(PY) --project . maturin sdist -o $(DIST)
19
+ uvx -p $(PY) --project . maturin build -r -o $(DIST)
20
+
21
+ clean:
22
+ rm -rf $(DIST) $(DATA)
23
+
24
+ publish:tools
25
+ uvx -p $(PY) --project . maturin publish --skip-existing
26
+ uvx -p $(PY) --project . maturin upload --skip-existing $(DIST)/*
27
+ .PHONY: tools dev bdist clean publish
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fabricatio
3
- Version: 0.2.7.dev0
3
+ Version: 0.2.7.dev2
4
4
  Classifier: License :: OSI Approved :: MIT License
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -24,9 +24,13 @@ Requires-Dist: questionary>=2.1.0
24
24
  Requires-Dist: regex>=2024.11.6
25
25
  Requires-Dist: rich>=13.9.4
26
26
  Requires-Dist: pymilvus>=2.5.4 ; extra == 'rag'
27
- Requires-Dist: fabricatio[rag] ; extra == 'full'
27
+ Requires-Dist: fabricatio[calc,plot,rag] ; extra == 'full'
28
+ Requires-Dist: sympy>=1.13.3 ; extra == 'calc'
29
+ Requires-Dist: matplotlib>=3.10.1 ; extra == 'plot'
28
30
  Provides-Extra: rag
29
31
  Provides-Extra: full
32
+ Provides-Extra: calc
33
+ Provides-Extra: plot
30
34
  License-File: LICENSE
31
35
  Summary: A LLM multi-agent framework.
32
36
  Keywords: ai,agents,multi-agent,llm,pyo3
@@ -0,0 +1,59 @@
1
+ """Simple chat example."""
2
+
3
+ import asyncio
4
+
5
+ from fabricatio import RAG, Action, Role, Task, WorkFlow, logger
6
+ from fabricatio.models.events import Event
7
+ from fabricatio.models.utils import ok
8
+ from questionary import text
9
+
10
+
11
+ class Talk(Action, RAG):
12
+ """Action that says hello to the world."""
13
+
14
+ output_key: str = "task_output"
15
+
16
+ async def _execute(self, task_input: Task[str], **_) -> int:
17
+ counter = 0
18
+
19
+ self.init_client()
20
+
21
+ try:
22
+ while True:
23
+ user_say = await text("User: ").ask_async()
24
+ if user_say is None:
25
+ break
26
+ gpt_say = await self.aask_refined(
27
+ user_say,
28
+ "article_essence_max",
29
+ extra_system_message=f"You have to answer to user obeying task assigned to you:\n{task_input.briefing}\nYou should explicitly say write a label if you draw a conclusion from the references, the label shall contain names.",
30
+ result_per_query=16,
31
+ final_limit=40,
32
+ similarity_threshold=0.31,
33
+ )
34
+ print(f"GPT: {gpt_say}") # noqa: T201
35
+ counter += 1
36
+ except KeyboardInterrupt:
37
+ logger.info(f"executed talk action {counter} times")
38
+ return counter
39
+
40
+
41
+ async def main() -> None:
42
+ """Main function."""
43
+ role = Role(
44
+ name="talker",
45
+ description="talker role but with rag",
46
+ registry={Event.instantiate_from("talk").push_wildcard().push("pending"): WorkFlow(name="talk", steps=(Talk,))},
47
+ )
48
+
49
+ task = ok(
50
+ await role.propose_task(
51
+ "you have to act as a helpful assistant, answer to all user questions properly and patiently"
52
+ ),
53
+ "Failed to propose task",
54
+ )
55
+ _ = await task.delegate("talk")
56
+
57
+
58
+ if __name__ == "__main__":
59
+ asyncio.run(main())
@@ -4,14 +4,13 @@ import asyncio
4
4
  from pathlib import Path
5
5
  from typing import List, Optional
6
6
 
7
- from pydantic import HttpUrl
8
-
9
7
  from fabricatio import Action, Event, Role, Task, WorkFlow, logger
10
8
  from fabricatio.actions.article import ExtractArticleEssence
11
9
  from fabricatio.actions.rag import InjectToDB
12
10
  from fabricatio.fs.curd import dump_text, gather_files
13
11
  from fabricatio.models.extra import ArticleEssence
14
12
  from fabricatio.models.utils import ok
13
+ from pydantic import HttpUrl
15
14
 
16
15
 
17
16
  class SaveToFS(Action):
@@ -0,0 +1,46 @@
1
+ """Example of using the library."""
2
+
3
+ import asyncio
4
+ from pathlib import Path
5
+
6
+ from fabricatio import Event, Role, WorkFlow, logger
7
+ from fabricatio.actions.article import (
8
+ GenerateArticle,
9
+ GenerateArticleProposal,
10
+ GenerateOutline,
11
+ )
12
+ from fabricatio.actions.output import DumpFinalizedOutput
13
+ from fabricatio.models.task import Task
14
+
15
+
16
+ async def main() -> None:
17
+ """Main function."""
18
+ Role(
19
+ name="Undergraduate Researcher",
20
+ description="Write an outline for an article in typst format.",
21
+ llm_top_p=0.8,
22
+ llm_temperature=1.15,
23
+ llm_max_tokens=8192,
24
+ llm_model="openai/qwen-max",
25
+ llm_stream=True,
26
+ registry={
27
+ Event.quick_instantiate(ns := "article"): WorkFlow(
28
+ name="Generate Article Outline",
29
+ description="Generate an outline for an article. dump the outline to the given path. in typst format.",
30
+ steps=(
31
+ GenerateArticleProposal(llm_temperature=1.18),
32
+ GenerateOutline(llm_temperature=1.21, llm_top_p=0.3),
33
+ GenerateArticle(output_key="to_dump", llm_temperature=1.2, llm_top_p=0.45),
34
+ DumpFinalizedOutput(output_key="task_output"),
35
+ ),
36
+ ).update_init_context(article_briefing=Path("./article_briefing.txt").read_text(), dump_path="out.typ")
37
+ },
38
+ )
39
+
40
+ proposed_task = Task(name="write an article")
41
+ path = await proposed_task.delegate(ns)
42
+ logger.success(f"The outline is saved in:\n{path}")
43
+
44
+
45
+ if __name__ == "__main__":
46
+ asyncio.run(main())
@@ -0,0 +1,2 @@
1
+ article_briefing.txt
2
+ out.typ
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fabricatio"
3
- version = "0.2.7-dev0"
3
+ version = "0.2.7-dev2"
4
4
  description = "A LLM multi-agent framework."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -81,7 +81,13 @@ rag = [
81
81
  ]
82
82
 
83
83
  full = [
84
- "fabricatio[rag]",
84
+ "fabricatio[calc,plot,rag]",
85
+ ]
86
+ calc = [
87
+ "sympy>=1.13.3",
88
+ ]
89
+ plot = [
90
+ "matplotlib>=3.10.1",
85
91
  ]
86
92
 
87
93
  [tool.ruff]
@@ -140,6 +146,9 @@ testpaths = [
140
146
  asyncio_mode = "auto"
141
147
  asyncio_default_fixture_loop_scope = "function"
142
148
 
149
+ [tool.uv.sources]
150
+ fabricatio = { workspace = true }
151
+
143
152
  [[tool.uv.index]]
144
153
  url = "https://mirrors.bfsu.edu.cn/pypi/web/simple"
145
154
  default = true
@@ -11,7 +11,7 @@ class TemplateManager:
11
11
  """
12
12
 
13
13
  def __init__(
14
- self, template_dirs: List[Path], suffix: Optional[str] = None, active_loading: Optional[bool] = None
14
+ self, template_dirs: List[Path], suffix: Optional[str] = None, active_loading: Optional[bool] = None
15
15
  ) -> None:
16
16
  """Initialize the template manager.
17
17
 
@@ -55,6 +55,16 @@ class TemplateManager:
55
55
  RuntimeError: If template rendering fails
56
56
  """
57
57
 
58
+ def render_template_raw(self, template: str, data: Dict[str, Any]) -> str:
59
+ """Render a template with context data.
60
+
61
+ Args:
62
+ template: The template string
63
+ data: Context dictionary to provide variables to the template
64
+
65
+ Returns:
66
+ Rendered template content as string
67
+ """
58
68
 
59
69
  def blake3_hash(content: bytes) -> str:
60
70
  """Calculate the BLAKE3 cryptographic hash of data.
@@ -66,7 +76,6 @@ def blake3_hash(content: bytes) -> str:
66
76
  Hex-encoded BLAKE3 hash string
67
77
  """
68
78
 
69
-
70
79
  class BibManager:
71
80
  """BibTeX bibliography manager for parsing and querying citation data."""
72
81
 
@@ -0,0 +1,209 @@
1
+ """Actions for transmitting tasks to targets."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any, Callable, List, Optional
5
+
6
+ from fabricatio.fs import safe_text_read
7
+ from fabricatio.journal import logger
8
+ from fabricatio.models.action import Action
9
+ from fabricatio.models.extra import Article, ArticleEssence, ArticleOutline, ArticleProposal
10
+ from fabricatio.models.task import Task
11
+ from fabricatio.models.utils import ok
12
+
13
+
14
+ class ExtractArticleEssence(Action):
15
+ """Extract the essence of article(s) in text format from the paths specified in the task dependencies.
16
+
17
+ Notes:
18
+ This action is designed to extract vital information from articles with Markdown format, which is pure text, and
19
+ which is converted from pdf files using `magic-pdf` from the `MinerU` project, see https://github.com/opendatalab/MinerU
20
+ """
21
+
22
+ output_key: str = "article_essence"
23
+ """The key of the output data."""
24
+
25
+ async def _execute(
26
+ self,
27
+ task_input: Task,
28
+ reader: Callable[[str], str] = lambda p: Path(p).read_text(encoding="utf-8"),
29
+ **_,
30
+ ) -> Optional[List[ArticleEssence]]:
31
+ if not task_input.dependencies:
32
+ logger.info(err := "Task not approved, since no dependencies are provided.")
33
+ raise RuntimeError(err)
34
+
35
+ # trim the references
36
+ contents = ["References".join(c.split("References")[:-1]) for c in map(reader, task_input.dependencies)]
37
+ return await self.propose(
38
+ ArticleEssence,
39
+ contents,
40
+ system_message=f"# your personal briefing: \n{self.briefing}",
41
+ )
42
+
43
+
44
+ class GenerateArticleProposal(Action):
45
+ """Generate an outline for the article based on the extracted essence."""
46
+
47
+ output_key: str = "article_proposal"
48
+ """The key of the output data."""
49
+
50
+ async def _execute(
51
+ self,
52
+ task_input: Optional[Task] = None,
53
+ article_briefing: Optional[str] = None,
54
+ article_briefing_path: Optional[str] = None,
55
+ **_,
56
+ ) -> Optional[ArticleProposal]:
57
+ if article_briefing is None and article_briefing_path is None and task_input is None:
58
+ logger.error("Task not approved, since all inputs are None.")
59
+ return None
60
+
61
+ return (
62
+ await self.propose(
63
+ ArticleProposal,
64
+ briefing := (
65
+ article_briefing
66
+ or safe_text_read(
67
+ ok(
68
+ article_briefing_path
69
+ or await self.awhich_pathstr(
70
+ f"{task_input.briefing}\nExtract the path of file which contains the article briefing."
71
+ ),
72
+ "Could not find the path of file to read.",
73
+ )
74
+ )
75
+ ),
76
+ **self.prepend_sys_msg(),
77
+ )
78
+ ).update_ref(briefing)
79
+
80
+
81
+ class GenerateOutline(Action):
82
+ """Generate the article based on the outline."""
83
+
84
+ output_key: str = "article_outline"
85
+ """The key of the output data."""
86
+
87
+ async def _execute(
88
+ self,
89
+ article_proposal: ArticleProposal,
90
+ **_,
91
+ ) -> Optional[ArticleOutline]:
92
+ out = await self.propose(
93
+ ArticleOutline,
94
+ article_proposal.as_prompt(),
95
+ **self.prepend_sys_msg(),
96
+ )
97
+
98
+ manual = await self.draft_rating_manual(
99
+ topic=(
100
+ topic
101
+ := "Fix the internal referring error, make sure there is no more `ArticleRef` pointing to a non-existing article component."
102
+ ),
103
+ )
104
+ while err := out.resolve_ref_error():
105
+ logger.warning(f"Found error in the outline: \n{err}")
106
+ out = await self.correct_obj(
107
+ out,
108
+ reference=f"# Referring Error\n{err}",
109
+ topic=topic,
110
+ rating_manual=manual,
111
+ supervisor_check=False,
112
+ )
113
+ return out.update_ref(article_proposal)
114
+
115
+
116
+ class CorrectProposal(Action):
117
+ """Correct the proposal of the article."""
118
+
119
+ output_key: str = "corrected_proposal"
120
+
121
+ async def _execute(self, article_proposal: ArticleProposal, **_) -> Any:
122
+ return (await self.censor_obj(article_proposal, reference=article_proposal.referenced)).update_ref(
123
+ article_proposal
124
+ )
125
+
126
+
127
+ class CorrectOutline(Action):
128
+ """Correct the outline of the article."""
129
+
130
+ output_key: str = "corrected_outline"
131
+ """The key of the output data."""
132
+
133
+ async def _execute(
134
+ self,
135
+ article_outline: ArticleOutline,
136
+ **_,
137
+ ) -> ArticleOutline:
138
+ return (await self.censor_obj(article_outline, reference=article_outline.referenced.as_prompt())).update_ref(
139
+ article_outline
140
+ )
141
+
142
+
143
+ class GenerateArticle(Action):
144
+ """Generate the article based on the outline."""
145
+
146
+ output_key: str = "article"
147
+ """The key of the output data."""
148
+
149
+ async def _execute(
150
+ self,
151
+ article_outline: ArticleOutline,
152
+ **_,
153
+ ) -> Optional[Article]:
154
+ article: Article = Article.from_outline(article_outline).update_ref(article_outline)
155
+
156
+ writing_manual = await self.draft_rating_manual(
157
+ topic=(
158
+ topic_1
159
+ := "improve the content of the subsection to fit the outline. SHALL never add or remove any section or subsection, you can only add or delete paragraphs within the subsection."
160
+ ),
161
+ )
162
+ err_resolve_manual = await self.draft_rating_manual(
163
+ topic=(topic_2 := "this article component has violated the constrain, please correct it.")
164
+ )
165
+ for c, deps in article.iter_dfs_with_deps(chapter=False):
166
+ logger.info(f"Updating the article component: \n{c.display()}")
167
+
168
+ out = ok(
169
+ await self.correct_obj(
170
+ c,
171
+ reference=(
172
+ ref := f"{article_outline.referenced.as_prompt()}\n" + "\n".join(d.display() for d in deps)
173
+ ),
174
+ topic=topic_1,
175
+ rating_manual=writing_manual,
176
+ supervisor_check=False,
177
+ ),
178
+ "Could not correct the article component.",
179
+ )
180
+ while err := c.resolve_update_error(out):
181
+ logger.warning(f"Found error in the article component: \n{err}")
182
+ out = ok(
183
+ await self.correct_obj(
184
+ out,
185
+ reference=f"{ref}\n\n# Violated Error\n{err}",
186
+ topic=topic_2,
187
+ rating_manual=err_resolve_manual,
188
+ supervisor_check=False,
189
+ ),
190
+ "Could not correct the article component.",
191
+ )
192
+
193
+ c.update_from(out)
194
+ return article
195
+
196
+
197
+ class CorrectArticle(Action):
198
+ """Correct the article based on the outline."""
199
+
200
+ output_key: str = "corrected_article"
201
+ """The key of the output data."""
202
+
203
+ async def _execute(
204
+ self,
205
+ article: Article,
206
+ article_outline: ArticleOutline,
207
+ **_,
208
+ ) -> Article:
209
+ return await self.censor_obj(article, reference=article_outline.referenced.as_prompt())
@@ -0,0 +1,34 @@
1
+ """Dump the finalized output to a file."""
2
+
3
+ from pathlib import Path
4
+ from typing import Optional
5
+
6
+ from fabricatio.models.action import Action
7
+ from fabricatio.models.generic import FinalizedDumpAble
8
+ from fabricatio.models.task import Task
9
+ from fabricatio.models.utils import ok
10
+
11
+
12
+ class DumpFinalizedOutput(Action):
13
+ """Dump the finalized output to a file."""
14
+
15
+ output_key: str = "dump_path"
16
+
17
+ async def _execute(
18
+ self,
19
+ to_dump: FinalizedDumpAble,
20
+ task_input: Optional[Task] = None,
21
+ dump_path: Optional[str | Path] = None,
22
+ **_,
23
+ ) -> str:
24
+ dump_path = Path(
25
+ dump_path
26
+ or ok(
27
+ await self.awhich_pathstr(
28
+ f"{ok(task_input, 'Neither `task_input` and `dump_path` is provided.').briefing}\n\nExtract a single path of the file, to which I will dump the data."
29
+ ),
30
+ "Could not find the path of file to dump the data.",
31
+ )
32
+ )
33
+ ok(to_dump, "Could not dump the data since the path is not specified.").finalized_dump_to(dump_path)
34
+ return dump_path.as_posix()
@@ -10,9 +10,11 @@ from typing import Optional, Unpack, cast
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
- from fabricatio.models.generic import Display, ProposedAble, WithBriefing
14
- from fabricatio.models.kwargs_types import CorrectKwargs, ReviewKwargs
13
+ from fabricatio.models.generic import CensoredAble, Display, ProposedAble, WithBriefing
14
+ from fabricatio.models.kwargs_types import CensoredCorrectKwargs, CorrectKwargs, ReviewKwargs
15
15
  from fabricatio.models.task import Task
16
+ from questionary import confirm, text
17
+ from rich import print as rprint
16
18
 
17
19
 
18
20
  class Correct(Review):
@@ -55,7 +57,7 @@ class Correct(Review):
55
57
  if supervisor_check:
56
58
  await review_res.supervisor_check()
57
59
  if "default" in kwargs:
58
- cast('ReviewKwargs[None]', kwargs)["default"] = None
60
+ cast("ReviewKwargs[None]", kwargs)["default"] = None
59
61
  return await self.propose(
60
62
  obj.__class__,
61
63
  TEMPLATE_MANAGER.render_template(
@@ -89,7 +91,7 @@ class Correct(Review):
89
91
  await review_res.supervisor_check()
90
92
 
91
93
  if "default" in kwargs:
92
- cast('ReviewKwargs[None]', kwargs)["default"] = None
94
+ cast("ReviewKwargs[None]", kwargs)["default"] = None
93
95
  return await self.ageneric_string(
94
96
  TEMPLATE_MANAGER.render_template(
95
97
  configs.templates.correct_template, {"content": input_text, "review": review_res.display()}
@@ -113,3 +115,31 @@ class Correct(Review):
113
115
  Optional[Task[T]]: The corrected task, or None if correction fails.
114
116
  """
115
117
  return await self.correct_obj(task, **kwargs)
118
+
119
+ async def censor_obj[M: CensoredAble](
120
+ self, obj: M, **kwargs: Unpack[CensoredCorrectKwargs[ReviewResult[str]]]
121
+ ) -> M:
122
+ """Censor and correct an object based on defined criteria and templates.
123
+
124
+ Args:
125
+ obj (M): The object to be reviewed and corrected.
126
+ **kwargs (Unpack[CensoredCorrectKwargs]): Additional keyword
127
+
128
+ Returns:
129
+ M: The censored and corrected object.
130
+ """
131
+ last_modified_obj = obj
132
+ modified_obj = None
133
+ rprint(obj.finalized_dump())
134
+ while await confirm("Begin to correct obj above with human censorship?").ask_async():
135
+ while (topic := await text("What is the topic of the obj reviewing?").ask_async()) is not None and topic:
136
+ ...
137
+ if (modified_obj := await self.correct_obj(
138
+ last_modified_obj,
139
+ topic=topic,
140
+ **kwargs,
141
+ )) is None:
142
+ break
143
+ last_modified_obj = modified_obj
144
+ rprint(last_modified_obj.finalized_dump())
145
+ return modified_obj or last_modified_obj
@@ -19,6 +19,7 @@ from fabricatio.models.kwargs_types import (
19
19
  EmbeddingKwargs,
20
20
  FetchKwargs,
21
21
  LLMKwargs,
22
+ RetrievalKwargs,
22
23
  )
23
24
  from fabricatio.models.usages import EmbeddingUsage
24
25
  from fabricatio.models.utils import MilvusData, ok
@@ -213,6 +214,25 @@ class RAG(EmbeddingUsage):
213
214
  self.add_document(await self.pack(text), collection_name or self.safe_target_collection, flush=True)
214
215
  return self
215
216
 
217
+ @overload
218
+ async def afetch_document[V: (int, str, float, bytes)](
219
+ self,
220
+ vecs: List[List[float]],
221
+ desired_fields: List[str],
222
+ collection_name: Optional[str] = None,
223
+ similarity_threshold: float = 0.37,
224
+ result_per_query: int = 10,
225
+ ) -> List[Dict[str, V]]: ...
226
+
227
+ @overload
228
+ async def afetch_document[V: (int, str, float, bytes)](
229
+ self,
230
+ vecs: List[List[float]],
231
+ desired_fields: str,
232
+ collection_name: Optional[str] = None,
233
+ similarity_threshold: float = 0.37,
234
+ result_per_query: int = 10,
235
+ ) -> List[V]: ...
216
236
  async def afetch_document[V: (int, str, float, bytes)](
217
237
  self,
218
238
  vecs: List[List[float]],
@@ -275,7 +295,7 @@ class RAG(EmbeddingUsage):
275
295
  if isinstance(query, str):
276
296
  query = [query]
277
297
  return cast(
278
- 'List[str]',
298
+ "List[str]",
279
299
  await self.afetch_document(
280
300
  vecs=(await self.vectorize(query)),
281
301
  desired_fields="text",
@@ -283,6 +303,24 @@ class RAG(EmbeddingUsage):
283
303
  ),
284
304
  )[:final_limit]
285
305
 
306
+ async def aretrieve_compact(
307
+ self,
308
+ query: List[str] | str,
309
+ **kwargs: Unpack[RetrievalKwargs],
310
+ ) -> str:
311
+ """Retrieve data from the collection and format it for display.
312
+
313
+ Args:
314
+ query (List[str] | str): The query to be used for retrieval.
315
+ **kwargs (Unpack[RetrievalKwargs]): Additional keyword arguments for retrieval.
316
+
317
+ Returns:
318
+ str: A formatted string containing the retrieved data.
319
+ """
320
+ return TEMPLATE_MANAGER.render_template(
321
+ configs.templates.retrieved_display_template, {"docs": (await self.aretrieve(query, **kwargs))}
322
+ )
323
+
286
324
  async def aask_retrieved(
287
325
  self,
288
326
  question: str,
@@ -313,16 +351,14 @@ class RAG(EmbeddingUsage):
313
351
  Returns:
314
352
  str: A string response generated after asking with the context of retrieved documents.
315
353
  """
316
- docs = await self.aretrieve(
354
+ rendered = await self.aretrieve_compact(
317
355
  query or question,
318
- final_limit,
356
+ final_limit=final_limit,
319
357
  collection_name=collection_name,
320
358
  result_per_query=result_per_query,
321
359
  similarity_threshold=similarity_threshold,
322
360
  )
323
361
 
324
- rendered = TEMPLATE_MANAGER.render_template(configs.templates.retrieved_display_template, {"docs": docs[::-1]})
325
-
326
362
  logger.debug(f"Retrieved Documents: \n{rendered}")
327
363
  return await self.aask(
328
364
  question,