fabricatio 0.2.7.dev1__tar.gz → 0.2.7.dev3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. fabricatio-0.2.7.dev3/Makefile +27 -0
  2. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/PKG-INFO +1 -1
  3. fabricatio-0.2.7.dev3/examples/extract_and_inject/ask.py +59 -0
  4. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/extract_and_inject/extract_and_inject.py +1 -1
  5. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/extract_article/extract.py +1 -1
  6. fabricatio-0.2.7.dev3/examples/write_article/write_article.py +46 -0
  7. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/pyproject.toml +1 -1
  8. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/actions/article.py +70 -16
  9. fabricatio-0.2.7.dev3/python/fabricatio/actions/article_rag.py +35 -0
  10. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/capabilities/rating.py +11 -2
  11. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/capabilities/review.py +6 -3
  12. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/decorators.py +32 -0
  13. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/models/action.py +9 -7
  14. fabricatio-0.2.7.dev3/python/fabricatio/models/extra/article_essence.py +226 -0
  15. fabricatio-0.2.7.dev3/python/fabricatio/models/extra/article_main.py +359 -0
  16. fabricatio-0.2.7.dev3/python/fabricatio/models/extra/article_outline.py +276 -0
  17. fabricatio-0.2.7.dev3/python/fabricatio/models/extra/article_proposal.py +37 -0
  18. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/models/generic.py +36 -1
  19. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/models/kwargs_types.py +2 -1
  20. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/models/usages.py +4 -1
  21. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/models/utils.py +6 -4
  22. fabricatio-0.2.7.dev3/templates.tar.gz +0 -0
  23. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/uv.lock +1 -1
  24. fabricatio-0.2.7.dev1/Makefile +0 -27
  25. fabricatio-0.2.7.dev1/python/fabricatio/models/extra.py +0 -712
  26. fabricatio-0.2.7.dev1/templates.tar.gz +0 -0
  27. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/.github/workflows/build-package.yaml +0 -0
  28. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/.github/workflows/ruff.yaml +0 -0
  29. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/.github/workflows/tests.yaml +0 -0
  30. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/.gitignore +0 -0
  31. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/.python-version +0 -0
  32. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/Cargo.lock +0 -0
  33. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/Cargo.toml +0 -0
  34. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/LICENSE +0 -0
  35. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/README.md +0 -0
  36. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/correct/correct.py +0 -0
  37. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/correct/correct_loop.py +0 -0
  38. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/extract_and_inject/.gitignore +0 -0
  39. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/extract_and_inject/article_rag.py +0 -0
  40. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/llm_usages/llm_usage.py +0 -0
  41. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/make_a_rating/rating.py +0 -0
  42. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/make_diary/commits.json +0 -0
  43. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/make_diary/diary.py +0 -0
  44. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/minor/hello_fabricatio.py +0 -0
  45. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/minor/write_a_poem.py +0 -0
  46. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/propose_task/propose.py +0 -0
  47. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/reviewer/review.py +0 -0
  48. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/search_bibtex/.gitignore +0 -0
  49. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/search_bibtex/search.py +0 -0
  50. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/simple_chat/chat.py +0 -0
  51. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/simple_rag/simple_rag.py +0 -0
  52. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/task_handle/handle_task.py +0 -0
  53. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/write_article/.gitignore +0 -0
  54. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/write_outline/.gitignore +0 -0
  55. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/write_outline/write_outline.py +0 -0
  56. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/examples/write_outline/write_outline_corrected.py +0 -0
  57. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/__init__.py +0 -0
  58. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/_rust.pyi +0 -0
  59. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/_rust_instances.py +0 -0
  60. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/actions/output.py +0 -0
  61. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/actions/rag.py +0 -0
  62. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/capabilities/correct.py +0 -0
  63. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/capabilities/propose.py +0 -0
  64. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/capabilities/rag.py +0 -0
  65. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/capabilities/task.py +0 -0
  66. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/config.py +0 -0
  67. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/core.py +0 -0
  68. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/fs/__init__.py +0 -0
  69. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/fs/curd.py +0 -0
  70. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/fs/readers.py +0 -0
  71. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/journal.py +0 -0
  72. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/models/events.py +0 -0
  73. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/models/role.py +0 -0
  74. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/models/task.py +0 -0
  75. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/models/tool.py +0 -0
  76. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/parser.py +0 -0
  77. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/py.typed +0 -0
  78. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/toolboxes/__init__.py +0 -0
  79. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/toolboxes/arithmetic.py +0 -0
  80. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/toolboxes/fs.py +0 -0
  81. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/workflows/articles.py +0 -0
  82. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/python/fabricatio/workflows/rag.py +0 -0
  83. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/src/bib_tools.rs +0 -0
  84. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/src/hash.rs +0 -0
  85. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/src/hbs_helpers.rs +0 -0
  86. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/src/lib.rs +0 -0
  87. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/src/templates.rs +0 -0
  88. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/as_prompt.hbs +0 -0
  89. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/binary-exploitation-ctf-solver.hbs +0 -0
  90. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/claude-xml.hbs +0 -0
  91. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/clean-up-code.hbs +0 -0
  92. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/co_validation.hbs +0 -0
  93. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/correct.hbs +0 -0
  94. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/create_json_obj.hbs +0 -0
  95. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/cryptography-ctf-solver.hbs +0 -0
  96. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/dependencies.hbs +0 -0
  97. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/document-the-code.hbs +0 -0
  98. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/draft_rating_criteria.hbs +0 -0
  99. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/draft_rating_manual.hbs +0 -0
  100. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/draft_rating_weights_klee.hbs +0 -0
  101. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/draft_tool_usage_code.hbs +0 -0
  102. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/extract_criteria_from_reasons.hbs +0 -0
  103. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/extract_reasons_from_examples.hbs +0 -0
  104. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/find-security-vulnerabilities.hbs +0 -0
  105. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/fix-bugs.hbs +0 -0
  106. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/generic_string.hbs +0 -0
  107. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/improve-performance.hbs +0 -0
  108. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/liststr.hbs +0 -0
  109. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/make_choice.hbs +0 -0
  110. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/make_judgment.hbs +0 -0
  111. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/pathstr.hbs +0 -0
  112. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/rate_fine_grind.hbs +0 -0
  113. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/refactor.hbs +0 -0
  114. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/refined_query.hbs +0 -0
  115. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/retrieved_display.hbs +0 -0
  116. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/reverse-engineering-ctf-solver.hbs +0 -0
  117. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/review_string.hbs +0 -0
  118. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/task_briefing.hbs +0 -0
  119. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/web-ctf-solver.hbs +0 -0
  120. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/write-git-commit.hbs +0 -0
  121. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/write-github-pull-request.hbs +0 -0
  122. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/templates/built-in/write-github-readme.hbs +0 -0
  123. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/tests/test_config.py +0 -0
  124. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/tests/test_models/test_action.py +0 -0
  125. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/tests/test_models/test_advanced.py +0 -0
  126. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/tests/test_models/test_generic.py +0 -0
  127. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/tests/test_models/test_role.py +0 -0
  128. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/tests/test_models/test_task.py +0 -0
  129. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/tests/test_models/test_tool.py +0 -0
  130. {fabricatio-0.2.7.dev1 → fabricatio-0.2.7.dev3}/tests/test_models/test_usages.py +0 -0
@@ -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.dev1
3
+ Version: 0.2.7.dev3
4
4
  Classifier: License :: OSI Approved :: MIT License
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -0,0 +1,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())
@@ -8,7 +8,7 @@ from fabricatio import Action, Event, Role, Task, WorkFlow, logger
8
8
  from fabricatio.actions.article import ExtractArticleEssence
9
9
  from fabricatio.actions.rag import InjectToDB
10
10
  from fabricatio.fs.curd import dump_text, gather_files
11
- from fabricatio.models.extra import ArticleEssence
11
+ from fabricatio.models.extra.article_essence import ArticleEssence
12
12
  from fabricatio.models.utils import ok
13
13
  from pydantic import HttpUrl
14
14
 
@@ -7,7 +7,7 @@ from fabricatio import Event, Role, Task, WorkFlow, logger
7
7
  from fabricatio.actions.article import ExtractArticleEssence
8
8
 
9
9
  if TYPE_CHECKING:
10
- from fabricatio.models.extra import ArticleEssence
10
+ from fabricatio.models.extra.article_essence import ArticleEssence
11
11
 
12
12
 
13
13
  async def main() -> None:
@@ -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())
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fabricatio"
3
- version = "0.2.7-dev1"
3
+ version = "0.2.7-dev3"
4
4
  description = "A LLM multi-agent framework."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -6,7 +6,10 @@ from typing import Any, Callable, List, Optional
6
6
  from fabricatio.fs import safe_text_read
7
7
  from fabricatio.journal import logger
8
8
  from fabricatio.models.action import Action
9
- from fabricatio.models.extra import Article, ArticleEssence, ArticleOutline, ArticleProposal
9
+ from fabricatio.models.extra.article_essence import ArticleEssence
10
+ from fabricatio.models.extra.article_main import Article
11
+ from fabricatio.models.extra.article_outline import ArticleOutline
12
+ from fabricatio.models.extra.article_proposal import ArticleProposal
10
13
  from fabricatio.models.task import Task
11
14
  from fabricatio.models.utils import ok
12
15
 
@@ -55,19 +58,23 @@ class GenerateArticleProposal(Action):
55
58
  **_,
56
59
  ) -> Optional[ArticleProposal]:
57
60
  if article_briefing is None and article_briefing_path is None and task_input is None:
58
- logger.info("Task not approved, since ")
61
+ logger.error("Task not approved, since all inputs are None.")
59
62
  return None
60
- if article_briefing_path is None and task_input:
61
- article_briefing_path = await self.awhich_pathstr(
62
- f"{task_input.briefing}\nExtract the path of file which contains the article briefing."
63
- )
64
63
 
65
64
  return (
66
65
  await self.propose(
67
66
  ArticleProposal,
68
67
  briefing := (
69
68
  article_briefing
70
- or safe_text_read(ok(article_briefing_path, "Could not find the path of file to read."))
69
+ or safe_text_read(
70
+ ok(
71
+ article_briefing_path
72
+ or await self.awhich_pathstr(
73
+ f"{task_input.briefing}\nExtract the path of file which contains the article briefing."
74
+ ),
75
+ "Could not find the path of file to read.",
76
+ )
77
+ )
71
78
  ),
72
79
  **self.prepend_sys_msg(),
73
80
  )
@@ -85,13 +92,28 @@ class GenerateOutline(Action):
85
92
  article_proposal: ArticleProposal,
86
93
  **_,
87
94
  ) -> Optional[ArticleOutline]:
88
- return (
89
- await self.propose(
90
- ArticleOutline,
91
- article_proposal.as_prompt(),
92
- **self.prepend_sys_msg(),
95
+ out = await self.propose(
96
+ ArticleOutline,
97
+ article_proposal.as_prompt(),
98
+ **self.prepend_sys_msg(),
99
+ )
100
+
101
+ manual = await self.draft_rating_manual(
102
+ topic=(
103
+ topic
104
+ := "Fix the internal referring error, make sure there is no more `ArticleRef` pointing to a non-existing article component."
105
+ ),
106
+ )
107
+ while err := out.resolve_ref_error():
108
+ logger.warning(f"Found error in the outline: \n{err}")
109
+ out = await self.correct_obj(
110
+ out,
111
+ reference=f"# Referring Error\n{err}",
112
+ topic=topic,
113
+ rating_manual=manual,
114
+ supervisor_check=False,
93
115
  )
94
- ).update_ref(article_proposal)
116
+ return out.update_ref(article_proposal)
95
117
 
96
118
 
97
119
  class CorrectProposal(Action):
@@ -134,10 +156,42 @@ class GenerateArticle(Action):
134
156
  ) -> Optional[Article]:
135
157
  article: Article = Article.from_outline(article_outline).update_ref(article_outline)
136
158
 
137
- for c, deps in article.iter_dfs_with_deps():
138
- out = await self.correct_obj(
139
- c, reference=f"{article_outline.referenced.as_prompt()}\n" + "\n".join(d.display() for d in deps)
159
+ writing_manual = await self.draft_rating_manual(
160
+ topic=(
161
+ topic_1
162
+ := "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."
163
+ ),
164
+ )
165
+ err_resolve_manual = await self.draft_rating_manual(
166
+ topic=(topic_2 := "this article component has violated the constrain, please correct it.")
167
+ )
168
+ for c, deps in article.iter_dfs_with_deps(chapter=False):
169
+ logger.info(f"Updating the article component: \n{c.display()}")
170
+
171
+ out = ok(
172
+ await self.correct_obj(
173
+ c,
174
+ reference=(
175
+ ref := f"{article_outline.referenced.as_prompt()}\n" + "\n".join(d.display() for d in deps)
176
+ ),
177
+ topic=topic_1,
178
+ rating_manual=writing_manual,
179
+ supervisor_check=False,
180
+ ),
181
+ "Could not correct the article component.",
140
182
  )
183
+ while err := c.resolve_update_error(out):
184
+ logger.warning(f"Found error in the article component: \n{err}")
185
+ out = ok(
186
+ await self.correct_obj(
187
+ out,
188
+ reference=f"{ref}\n\n# Violated Error\n{err}",
189
+ topic=topic_2,
190
+ rating_manual=err_resolve_manual,
191
+ supervisor_check=False,
192
+ ),
193
+ "Could not correct the article component.",
194
+ )
141
195
 
142
196
  c.update_from(out)
143
197
  return article
@@ -0,0 +1,35 @@
1
+ """A module for writing articles using RAG (Retrieval-Augmented Generation) capabilities."""
2
+
3
+ from typing import Optional
4
+
5
+ from fabricatio.capabilities.rag import RAG
6
+ from fabricatio.journal import logger
7
+ from fabricatio.models.action import Action
8
+ from fabricatio.models.extra.article_main import Article
9
+ from fabricatio.models.extra.article_outline import ArticleOutline
10
+
11
+
12
+ class GenerateArticleRAG(Action, RAG):
13
+ """Write an article based on the provided outline."""
14
+
15
+ output_key: str = "article"
16
+
17
+ async def _execute(self, article_outline: ArticleOutline, **cxt) -> Optional[Article]:
18
+ """Write an article based on the provided outline."""
19
+ logger.info(f"Writing an article based on the outline:\n{article_outline.title}")
20
+ refined_q = await self.arefined_query(article_outline.display())
21
+ return await self.propose(
22
+ Article,
23
+ article_outline.display(),
24
+ **self.prepend_sys_msg(f"{await self.aretrieve_compact(refined_q)}\n{self.briefing}"),
25
+ )
26
+
27
+
28
+ class WriteArticleFineGrind(Action, RAG):
29
+ """Fine-grind an article based on the provided outline."""
30
+
31
+ output_key: str = "article"
32
+
33
+ async def _execute(self, article_outline: ArticleOutline, **cxt) -> Optional[Article]:
34
+ """Fine-grind an article based on the provided outline."""
35
+ logger.info(f"Fine-grinding an article based on the outline:\n{article_outline.title}")
@@ -10,6 +10,7 @@ from fabricatio.journal import logger
10
10
  from fabricatio.models.generic import WithBriefing
11
11
  from fabricatio.models.kwargs_types import ValidateKwargs
12
12
  from fabricatio.models.usages import LLMUsage
13
+ from fabricatio.models.utils import override_kwargs
13
14
  from fabricatio.parser import JsonCapture
14
15
  from more_itertools import flatten, windowed
15
16
  from pydantic import NonNegativeInt, PositiveInt
@@ -126,13 +127,13 @@ class GiveRating(WithBriefing, LLMUsage):
126
127
  return await self.rate_fine_grind(to_rate, manual, score_range, **kwargs)
127
128
 
128
129
  async def draft_rating_manual(
129
- self, topic: str, criteria: Set[str], **kwargs: Unpack[ValidateKwargs[Dict[str, str]]]
130
+ self, topic: str, criteria: Optional[Set[str]] = None, **kwargs: Unpack[ValidateKwargs[Dict[str, str]]]
130
131
  ) -> Optional[Dict[str, str]]:
131
132
  """Drafts a rating manual based on a topic and dimensions.
132
133
 
133
134
  Args:
134
135
  topic (str): The topic for the rating manual.
135
- criteria (Set[str]): A set of dimensions for the rating manual.
136
+ criteria (Optional[Set[str]], optional): A set of criteria for the rating manual. If not specified, then this method will draft the criteria automatically.
136
137
  **kwargs (Unpack[ValidateKwargs]): Additional keyword arguments for the LLM usage.
137
138
 
138
139
  Returns:
@@ -148,6 +149,14 @@ class GiveRating(WithBriefing, LLMUsage):
148
149
  return json_data
149
150
  return None
150
151
 
152
+ criteria = criteria or await self.draft_rating_criteria(
153
+ topic, **self.prepend_sys_msg(override_kwargs(dict(kwargs), default=None))
154
+ )
155
+
156
+ if criteria is None:
157
+ logger.error(f"Failed to draft rating criteria for topic {topic}")
158
+ return None
159
+
151
160
  return await self.aask_validate(
152
161
  question=(
153
162
  TEMPLATE_MANAGER.render_template(
@@ -1,6 +1,6 @@
1
1
  """A module that provides functionality to rate tasks based on a rating manual and score range."""
2
2
 
3
- from typing import List, Optional, Self, Set, Unpack, cast
3
+ from typing import Dict, List, Optional, Self, Set, Unpack, cast
4
4
 
5
5
  from fabricatio._rust_instances import TEMPLATE_MANAGER
6
6
  from fabricatio.capabilities.propose import Propose
@@ -200,13 +200,14 @@ class Review(GiveRating, Propose):
200
200
  ReviewResult[Task[T]]: A review result containing identified problems and proposed solutions,
201
201
  with a reference to the original task.
202
202
  """
203
- return cast('ReviewResult[Task[T]]', await self.review_obj(task, **kwargs))
203
+ return cast("ReviewResult[Task[T]]", await self.review_obj(task, **kwargs))
204
204
 
205
205
  async def review_string(
206
206
  self,
207
207
  input_text: str,
208
208
  topic: str,
209
209
  criteria: Optional[Set[str]] = None,
210
+ rating_manual: Optional[Dict[str, str]] = None,
210
211
  **kwargs: Unpack[ValidateKwargs[ReviewResult[str]]],
211
212
  ) -> ReviewResult[str]:
212
213
  """Review a string based on specified topic and criteria.
@@ -219,6 +220,7 @@ class Review(GiveRating, Propose):
219
220
  topic (str): The subject topic for the review criteria.
220
221
  criteria (Optional[Set[str]], optional): A set of criteria for the review.
221
222
  If not provided, criteria will be drafted automatically. Defaults to None.
223
+ rating_manual (Optional[Dict[str,str]], optional): A dictionary of rating criteria and their corresponding scores.
222
224
  **kwargs (Unpack[ValidateKwargs]): Additional keyword arguments for the LLM usage.
223
225
 
224
226
  Returns:
@@ -227,12 +229,13 @@ class Review(GiveRating, Propose):
227
229
  """
228
230
  default = None
229
231
  if "default" in kwargs:
232
+ # this `default` is the default for the `propose` method
230
233
  default = kwargs.pop("default")
231
234
 
232
235
  criteria = criteria or (await self.draft_rating_criteria(topic, **kwargs))
233
236
  if not criteria:
234
237
  raise ValueError("No criteria provided for review.")
235
- manual = await self.draft_rating_manual(topic, criteria, **kwargs)
238
+ manual = rating_manual or await self.draft_rating_manual(topic, criteria, **kwargs)
236
239
 
237
240
  if default is not None:
238
241
  kwargs["default"] = default
@@ -177,3 +177,35 @@ def use_temp_module[**P, R](modules: ModuleType | List[ModuleType]) -> Callable[
177
177
  return _wrapper
178
178
 
179
179
  return _decorator
180
+
181
+
182
+ def logging_exec_time[**P, R](func: Callable[P, R]) -> Callable[P, R]:
183
+ """Decorator to log the execution time of a function.
184
+
185
+ Args:
186
+ func (Callable): The function to be executed
187
+
188
+ Returns:
189
+ Callable: A decorator that wraps the function to log the execution time.
190
+ """
191
+ from time import time
192
+
193
+ if iscoroutinefunction(func):
194
+
195
+ @wraps(func)
196
+ async def _async_wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
197
+ start_time = time()
198
+ result = await func(*args, **kwargs)
199
+ logger.debug(f"Execution time of `{func.__name__}`: {time() - start_time:.2f} s")
200
+ return result
201
+
202
+ return _async_wrapper
203
+
204
+ @wraps(func)
205
+ def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
206
+ start_time = time()
207
+ result = func(*args, **kwargs)
208
+ logger.debug(f"Execution time of {func.__name__}: {(time() - start_time) * 1000:.2f} ms")
209
+ return result
210
+
211
+ return _wrapper
@@ -48,7 +48,7 @@ class Action(HandleTask, ProposeTask, Correct):
48
48
  self.description = self.description or self.__class__.__doc__ or ""
49
49
 
50
50
  @abstractmethod
51
- async def _execute(self,*_, **cxt) -> Any: # noqa: ANN002
51
+ async def _execute(self, *_, **cxt) -> Any: # noqa: ANN002
52
52
  """Execute the action logic with the provided context arguments.
53
53
 
54
54
  This method must be implemented by subclasses to define the actual behavior.
@@ -147,6 +147,8 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
147
147
  Args:
148
148
  task: The task to be processed.
149
149
  """
150
+ logger.info(f"Start execute workflow: {self.name}")
151
+
150
152
  await task.start()
151
153
  await self._init_context(task)
152
154
 
@@ -155,12 +157,11 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
155
157
  # Process each action in sequence
156
158
  for step in self._instances:
157
159
  current_action = step.name
158
- logger.debug(f"Executing step: {current_action}")
160
+ logger.info(f"Executing step: {current_action}")
159
161
 
160
162
  # Get current context and execute action
161
163
  context = await self._context.get()
162
164
  act_task = create_task(step.act(context))
163
-
164
165
  # Handle task cancellation
165
166
  if task.is_cancelled():
166
167
  act_task.cancel(f"Cancelled by task: {task.name}")
@@ -168,9 +169,10 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
168
169
 
169
170
  # Update context with modified values
170
171
  modified_ctx = await act_task
172
+ logger.success(f"Step execution finished: {current_action}")
171
173
  await self._context.put(modified_ctx)
172
174
 
173
- logger.info(f"Finished executing workflow: {self.name}")
175
+ logger.success(f"Workflow execution finished: {self.name}")
174
176
 
175
177
  # Get final context and extract result
176
178
  final_ctx = await self._context.get()
@@ -184,9 +186,9 @@ class WorkFlow(WithBriefing, ToolBoxUsage):
184
186
 
185
187
  await task.finish(result)
186
188
 
187
- except RuntimeError as e:
188
- logger.error(f"Error during task: {current_action} execution: {e}")
189
- logger.error(traceback.format_exc())
189
+ except Exception as e: # noqa: BLE001
190
+ logger.critical(f"Error during task: {current_action} execution: {e}")
191
+ logger.critical(traceback.format_exc())
190
192
  await task.fail()
191
193
 
192
194
  async def _init_context[T](self, task: Task[T]) -> None: