fabricatio 0.2.8.dev2__tar.gz → 0.2.8.dev4__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 (148) hide show
  1. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/PKG-INFO +2 -1
  2. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/extract_and_inject/ask.py +1 -1
  3. fabricatio-0.2.8.dev4/examples/extract_and_inject/extract_and_inject.py +66 -0
  4. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/write_article/write_article.py +10 -11
  5. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/pyproject.toml +2 -1
  6. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/_rust.pyi +1 -1
  7. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/actions/article.py +112 -121
  8. fabricatio-0.2.8.dev4/python/fabricatio/actions/article_rag.py +100 -0
  9. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/actions/output.py +4 -3
  10. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/actions/rag.py +3 -3
  11. fabricatio-0.2.8.dev4/python/fabricatio/capabilities/censor.py +87 -0
  12. fabricatio-0.2.8.dev4/python/fabricatio/capabilities/check.py +194 -0
  13. fabricatio-0.2.8.dev4/python/fabricatio/capabilities/correct.py +209 -0
  14. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/capabilities/propose.py +20 -4
  15. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/capabilities/rag.py +3 -2
  16. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/capabilities/rating.py +67 -22
  17. fabricatio-0.2.8.dev4/python/fabricatio/capabilities/review.py +112 -0
  18. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/capabilities/task.py +8 -9
  19. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/config.py +11 -3
  20. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/action.py +8 -5
  21. fabricatio-0.2.8.dev4/python/fabricatio/models/adv_kwargs_types.py +25 -0
  22. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/extra/advanced_judge.py +10 -7
  23. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/extra/article_base.py +47 -27
  24. fabricatio-0.2.8.dev4/python/fabricatio/models/extra/article_essence.py +99 -0
  25. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/extra/article_main.py +3 -4
  26. fabricatio-0.2.8.dev4/python/fabricatio/models/extra/patches.py +7 -0
  27. fabricatio-0.2.8.dev4/python/fabricatio/models/extra/problem.py +153 -0
  28. fabricatio-0.2.8.dev4/python/fabricatio/models/extra/rule.py +21 -0
  29. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/generic.py +71 -37
  30. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/kwargs_types.py +23 -17
  31. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/role.py +4 -1
  32. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/usages.py +17 -20
  33. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/utils.py +0 -46
  34. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/parser.py +7 -8
  35. fabricatio-0.2.8.dev4/python/fabricatio/utils.py +54 -0
  36. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/src/bib_tools.rs +1 -1
  37. fabricatio-0.2.8.dev4/templates/built-in/check_string.hbs +19 -0
  38. fabricatio-0.2.8.dev4/templates/built-in/fix_troubled_obj.hbs +14 -0
  39. fabricatio-0.2.8.dev4/templates/built-in/fix_troubled_string.hbs +19 -0
  40. fabricatio-0.2.8.dev4/templates/built-in/ruleset_requirement_breakdown.hbs +7 -0
  41. fabricatio-0.2.8.dev4/templates.tar.gz +0 -0
  42. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/uv.lock +114 -78
  43. fabricatio-0.2.8.dev2/examples/extract_and_inject/extract_and_inject.py +0 -54
  44. fabricatio-0.2.8.dev2/python/fabricatio/actions/article_rag.py +0 -90
  45. fabricatio-0.2.8.dev2/python/fabricatio/capabilities/correct.py +0 -165
  46. fabricatio-0.2.8.dev2/python/fabricatio/capabilities/review.py +0 -281
  47. fabricatio-0.2.8.dev2/python/fabricatio/models/extra/article_essence.py +0 -268
  48. fabricatio-0.2.8.dev2/templates/built-in/correct.hbs +0 -15
  49. fabricatio-0.2.8.dev2/templates.tar.gz +0 -0
  50. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/.github/workflows/build-package.yaml +0 -0
  51. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/.github/workflows/ruff.yaml +0 -0
  52. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/.github/workflows/tests.yaml +0 -0
  53. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/.gitignore +0 -0
  54. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/.python-version +0 -0
  55. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/Cargo.lock +0 -0
  56. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/Cargo.toml +0 -0
  57. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/LICENSE +0 -0
  58. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/Makefile +0 -0
  59. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/README.md +0 -0
  60. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/correct/correct.py +0 -0
  61. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/correct/correct_loop.py +0 -0
  62. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/extract_and_inject/.gitignore +0 -0
  63. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/extract_and_inject/article_rag.py +0 -0
  64. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/extract_article/extract.py +0 -0
  65. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/llm_usages/llm_usage.py +0 -0
  66. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/make_a_rating/rating.py +0 -0
  67. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/make_diary/commits.json +0 -0
  68. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/make_diary/diary.py +0 -0
  69. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/minor/hello_fabricatio.py +0 -0
  70. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/minor/write_a_poem.py +0 -0
  71. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/propose_task/propose.py +0 -0
  72. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/reviewer/review.py +0 -0
  73. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/search_bibtex/.gitignore +0 -0
  74. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/search_bibtex/search.py +0 -0
  75. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/simple_chat/chat.py +0 -0
  76. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/simple_rag/simple_rag.py +0 -0
  77. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/task_handle/handle_task.py +0 -0
  78. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/write_article/.gitignore +0 -0
  79. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/write_article/article_rag.py +0 -0
  80. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/write_outline/.gitignore +0 -0
  81. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/write_outline/write_outline.py +0 -0
  82. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/examples/write_outline/write_outline_corrected.py +0 -0
  83. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/__init__.py +0 -0
  84. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/_rust_instances.py +0 -0
  85. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/capabilities/advanced_judge.py +0 -0
  86. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/core.py +0 -0
  87. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/decorators.py +0 -0
  88. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/fs/__init__.py +0 -0
  89. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/fs/curd.py +0 -0
  90. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/fs/readers.py +0 -0
  91. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/journal.py +0 -0
  92. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/events.py +0 -0
  93. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/extra/article_outline.py +0 -0
  94. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/extra/article_proposal.py +0 -0
  95. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/task.py +0 -0
  96. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/models/tool.py +0 -0
  97. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/py.typed +0 -0
  98. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/toolboxes/__init__.py +0 -0
  99. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/toolboxes/arithmetic.py +0 -0
  100. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/toolboxes/fs.py +0 -0
  101. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/workflows/articles.py +0 -0
  102. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/python/fabricatio/workflows/rag.py +0 -0
  103. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/src/hash.rs +0 -0
  104. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/src/hbs_helpers.rs +0 -0
  105. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/src/lib.rs +0 -0
  106. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/src/templates.rs +0 -0
  107. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/as_prompt.hbs +0 -0
  108. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/binary-exploitation-ctf-solver.hbs +0 -0
  109. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/claude-xml.hbs +0 -0
  110. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/clean-up-code.hbs +0 -0
  111. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/co_validation.hbs +0 -0
  112. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/create_json_obj.hbs +0 -0
  113. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/cryptography-ctf-solver.hbs +0 -0
  114. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/dependencies.hbs +0 -0
  115. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/document-the-code.hbs +0 -0
  116. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/draft_rating_criteria.hbs +0 -0
  117. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/draft_rating_manual.hbs +0 -0
  118. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/draft_rating_weights_klee.hbs +0 -0
  119. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/draft_tool_usage_code.hbs +0 -0
  120. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/extract_criteria_from_reasons.hbs +0 -0
  121. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/extract_reasons_from_examples.hbs +0 -0
  122. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/find-security-vulnerabilities.hbs +0 -0
  123. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/fix-bugs.hbs +0 -0
  124. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/generic_string.hbs +0 -0
  125. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/improve-performance.hbs +0 -0
  126. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/liststr.hbs +0 -0
  127. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/make_choice.hbs +0 -0
  128. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/make_judgment.hbs +0 -0
  129. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/pathstr.hbs +0 -0
  130. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/rate_fine_grind.hbs +0 -0
  131. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/refactor.hbs +0 -0
  132. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/refined_query.hbs +0 -0
  133. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/retrieved_display.hbs +0 -0
  134. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/reverse-engineering-ctf-solver.hbs +0 -0
  135. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/review_string.hbs +0 -0
  136. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/task_briefing.hbs +0 -0
  137. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/web-ctf-solver.hbs +0 -0
  138. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/write-git-commit.hbs +0 -0
  139. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/write-github-pull-request.hbs +0 -0
  140. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/templates/built-in/write-github-readme.hbs +0 -0
  141. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/tests/test_config.py +0 -0
  142. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/tests/test_models/test_action.py +0 -0
  143. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/tests/test_models/test_advanced.py +0 -0
  144. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/tests/test_models/test_generic.py +0 -0
  145. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/tests/test_models/test_role.py +0 -0
  146. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/tests/test_models/test_task.py +0 -0
  147. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/tests/test_models/test_tool.py +0 -0
  148. {fabricatio-0.2.8.dev2 → fabricatio-0.2.8.dev4}/tests/test_models/test_usages.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fabricatio
3
- Version: 0.2.8.dev2
3
+ Version: 0.2.8.dev4
4
4
  Classifier: License :: OSI Approved :: MIT License
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -23,6 +23,7 @@ Requires-Dist: pymitter>=1.0.0
23
23
  Requires-Dist: questionary>=2.1.0
24
24
  Requires-Dist: regex>=2024.11.6
25
25
  Requires-Dist: rich>=13.9.4
26
+ Requires-Dist: rtoml>=0.12.0
26
27
  Requires-Dist: pymilvus>=2.5.4 ; extra == 'rag'
27
28
  Requires-Dist: fabricatio[calc,plot,rag] ; extra == 'full'
28
29
  Requires-Dist: sympy>=1.13.3 ; extra == 'calc'
@@ -4,7 +4,7 @@ import asyncio
4
4
 
5
5
  from fabricatio import RAG, Action, Role, Task, WorkFlow, logger
6
6
  from fabricatio.models.events import Event
7
- from fabricatio.models.utils import ok
7
+ from fabricatio.utils import ok
8
8
  from questionary import text
9
9
 
10
10
 
@@ -0,0 +1,66 @@
1
+ """Example of proposing a task to a role."""
2
+
3
+ import asyncio
4
+ from typing import Optional
5
+
6
+ from fabricatio import BibManager, Event, Role, Task, WorkFlow, logger
7
+ from fabricatio.actions.article import ExtractArticleEssence, FixArticleEssence
8
+ from fabricatio.actions.output import PersistentAll
9
+ from fabricatio.actions.rag import InjectToDB
10
+ from fabricatio.fs import safe_text_read
11
+ from fabricatio.fs.curd import gather_files
12
+ from litellm.utils import token_counter
13
+
14
+ MAX_TOKEN = 64000
15
+
16
+
17
+ def _reader(path:str)->Optional[str]:
18
+ string=safe_text_read(path)
19
+ string=string.split("References\n")[0]
20
+ string=string.split("参考文献\n")[0]
21
+ if (leng:=token_counter(text=string))> MAX_TOKEN:
22
+ logger.warning(f'{path} is too long, got {leng} tokens, skip.')
23
+ return None
24
+ logger.info(f'Read {path} get {leng} tokens.')
25
+ return string
26
+ async def main() -> None:
27
+ """Main function."""
28
+ Role(
29
+ name="Researcher",
30
+ description="Extract article essence",
31
+ llm_model="openai/deepseek-v3-250324",
32
+ registry={
33
+ Event.quick_instantiate("article"): WorkFlow(
34
+ name="extract",
35
+ steps=(
36
+ ExtractArticleEssence(output_key="article_essence"),
37
+ FixArticleEssence(output_key="to_inject"),
38
+ PersistentAll,
39
+ InjectToDB(output_key="task_output"),
40
+ ),
41
+ ).update_init_context(
42
+ override_inject=True,
43
+ collection_name="article_essence_0324",
44
+ persist_dir="output_0324",
45
+ bib_mgr=BibManager("ref.bib"),
46
+ reader=_reader
47
+ )
48
+ },
49
+ )
50
+
51
+ task: Task[str] = Task(
52
+ name="Extract Article Essence",
53
+ description="Extract the essence of the article from the files in './bpdf_out'",
54
+ dependencies=gather_files("bpdf_out", "md"),
55
+ )
56
+
57
+ col_name = await task.delegate("article")
58
+
59
+ if col_name is None:
60
+ logger.error("No essence found")
61
+ return
62
+ logger.success(f"Injected to collection: {col_name}")
63
+
64
+
65
+ if __name__ == "__main__":
66
+ asyncio.run(main())
@@ -23,11 +23,10 @@ async def main() -> None:
23
23
  Role(
24
24
  name="Undergraduate Researcher",
25
25
  description="Write an outline for an article in typst format.",
26
- llm_top_p=0.8,
27
26
  llm_temperature=1.15,
28
- llm_model="openai/qwen-max",
27
+ llm_model="openai/deepseek-v3-250324",
29
28
  llm_rpm=1000,
30
- llm_tpm=10000000,
29
+ llm_tpm=3000000,
31
30
  llm_max_tokens=8190,
32
31
  registry={
33
32
  Event.quick_instantiate(ns := "article"): WorkFlow(
@@ -35,15 +34,15 @@ async def main() -> None:
35
34
  description="Generate an outline for an article. dump the outline to the given path. in typst format.",
36
35
  steps=(
37
36
  GenerateArticleProposal(llm_temperature=1.18),
38
- GenerateInitialOutline(output_key="article_outline",llm_temperature=1.21, llm_top_p=0.3),
39
- FixIntrospectedErrors(output_key="article_outline"),
40
- FixIllegalReferences(output_key="article_outline"),
41
- TweakOutlineBackwardRef(output_key="article_outline"),
42
- TweakOutlineForwardRef(output_key="article_outline"),
43
- FixIllegalReferences(output_key="article_outline"),
44
- GenerateArticle(output_key="article", llm_temperature=1.2, llm_top_p=0.45),
37
+ GenerateInitialOutline(output_key="article_outline",llm_temperature=1.21),
38
+ FixIntrospectedErrors(output_key="article_outline",),
39
+ FixIllegalReferences(output_key="article_outline",),
40
+ TweakOutlineBackwardRef(output_key="article_outline",),
41
+ TweakOutlineForwardRef(output_key="article_outline",),
42
+ FixIllegalReferences(output_key="article_outline",),
43
+ GenerateArticle(output_key="article", llm_temperature=1.2),
45
44
  PersistentAll,
46
- TweakArticleRAG(output_key="to_dump", llm_temperature=1.2, llm_top_p=0.45),
45
+ TweakArticleRAG(output_key="to_dump", llm_temperature=1.2),
47
46
  DumpFinalizedOutput(output_key="task_output"),
48
47
  PersistentAll,
49
48
  ),
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fabricatio"
3
- version = "0.2.8-dev2"
3
+ version = "0.2.8-dev4"
4
4
  description = "A LLM multi-agent framework."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -42,6 +42,7 @@ dependencies = [
42
42
  "questionary>=2.1.0",
43
43
  "regex>=2024.11.6",
44
44
  "rich>=13.9.4",
45
+ "rtoml>=0.12.0",
45
46
  ]
46
47
 
47
48
  [project.urls]
@@ -171,4 +171,4 @@ class BibManager:
171
171
 
172
172
  Returns:
173
173
  Field value if found, None otherwise
174
- """
174
+ """
@@ -5,20 +5,24 @@ from pathlib import Path
5
5
  from typing import Any, Callable, List, Optional
6
6
 
7
7
  from fabricatio._rust import BibManager
8
- from fabricatio.capabilities.advanced_judge import AdvancedJudge
8
+ from fabricatio.capabilities.censor import Censor
9
+ from fabricatio.capabilities.correct import Correct
10
+ from fabricatio.capabilities.propose import Propose
9
11
  from fabricatio.fs import safe_text_read
10
12
  from fabricatio.journal import logger
11
13
  from fabricatio.models.action import Action
12
- from fabricatio.models.extra.article_base import ArticleRefPatch
14
+ from fabricatio.models.extra.article_base import ArticleRefSequencePatch
13
15
  from fabricatio.models.extra.article_essence import ArticleEssence
14
16
  from fabricatio.models.extra.article_main import Article
15
17
  from fabricatio.models.extra.article_outline import ArticleOutline
16
18
  from fabricatio.models.extra.article_proposal import ArticleProposal
19
+ from fabricatio.models.extra.rule import RuleSet
17
20
  from fabricatio.models.task import Task
18
- from fabricatio.models.utils import ok
21
+ from fabricatio.utils import ok
22
+ from more_itertools import filter_map
19
23
 
20
24
 
21
- class ExtractArticleEssence(Action):
25
+ class ExtractArticleEssence(Action, Propose):
22
26
  """Extract the essence of article(s) in text format from the paths specified in the task dependencies.
23
27
 
24
28
  Notes:
@@ -32,39 +36,65 @@ class ExtractArticleEssence(Action):
32
36
  async def _execute(
33
37
  self,
34
38
  task_input: Task,
35
- reader: Callable[[str], str] = lambda p: Path(p).read_text(encoding="utf-8"),
39
+ reader: Callable[[str], Optional[str]] = lambda p: Path(p).read_text(encoding="utf-8"),
36
40
  **_,
37
- ) -> Optional[List[ArticleEssence]]:
41
+ ) -> List[ArticleEssence]:
38
42
  if not task_input.dependencies:
39
43
  logger.info(err := "Task not approved, since no dependencies are provided.")
40
44
  raise RuntimeError(err)
41
-
45
+ logger.info(f"Extracting article essence from {len(task_input.dependencies)} files.")
42
46
  # trim the references
43
- contents = ["References".join(c.split("References")[:-1]) for c in map(reader, task_input.dependencies)]
44
- return await self.propose(ArticleEssence, contents, **self.prepend_sys_msg())
47
+ contents = list(filter_map(reader, task_input.dependencies))
48
+ logger.info(f"Read {len(task_input.dependencies)} to get {len(contents)} contents.")
49
+
50
+ out = []
51
+
52
+ for ess in await self.propose(
53
+ ArticleEssence,
54
+ [
55
+ f"{c}\n\n\nBased the provided academic article above, you need to extract the essence from it."
56
+ for c in contents
57
+ ],
58
+ ):
59
+ if ess is None:
60
+ logger.warning("Could not extract article essence")
61
+ else:
62
+ out.append(ess)
63
+ logger.info(f"Extracted {len(out)} article essence from {len(task_input.dependencies)} files.")
64
+ return out
45
65
 
46
66
 
47
67
  class FixArticleEssence(Action):
48
68
  """Fix the article essence based on the bibtex key."""
49
69
 
70
+ output_key: str = "fixed_article_essence"
71
+ """The key of the output data."""
72
+
50
73
  async def _execute(
51
74
  self,
52
75
  bib_mgr: BibManager,
53
76
  article_essence: List[ArticleEssence],
54
77
  **_,
55
- ) -> None:
78
+ ) -> List[ArticleEssence]:
79
+ out = []
80
+ count = 0
56
81
  for a in article_essence:
57
82
  if key := (bib_mgr.get_cite_key(a.title) or bib_mgr.get_cite_key_fuzzy(a.title)):
58
83
  a.title = bib_mgr.get_title_by_key(key) or a.title
59
84
  a.authors = bib_mgr.get_author_by_key(key) or a.authors
60
85
  a.publication_year = bib_mgr.get_year_by_key(key) or a.publication_year
61
86
  a.bibtex_cite_key = key
62
- logger.info(f'Updated {a.title} with {key}')
87
+ logger.info(f"Updated {a.title} with {key}")
88
+ out.append(a)
63
89
  else:
64
90
  logger.warning(f"No key found for {a.title}")
91
+ count += 1
92
+ if count:
93
+ logger.warning(f"{count} articles have no key")
94
+ return out
65
95
 
66
96
 
67
- class GenerateArticleProposal(Action):
97
+ class GenerateArticleProposal(Action, Propose):
68
98
  """Generate an outline for the article based on the extracted essence."""
69
99
 
70
100
  output_key: str = "article_proposal"
@@ -97,7 +127,6 @@ class GenerateArticleProposal(Action):
97
127
  )
98
128
  )
99
129
  ),
100
- **self.prepend_sys_msg(),
101
130
  ),
102
131
  "Could not generate the proposal.",
103
132
  ).update_ref(briefing)
@@ -107,7 +136,7 @@ class GenerateArticleProposal(Action):
107
136
  return proposal
108
137
 
109
138
 
110
- class GenerateInitialOutline(Action):
139
+ class GenerateInitialOutline(Action, Propose):
111
140
  """Generate the initial article outline based on the article proposal."""
112
141
 
113
142
  output_key: str = "initial_article_outline"
@@ -122,44 +151,34 @@ class GenerateInitialOutline(Action):
122
151
  await self.propose(
123
152
  ArticleOutline,
124
153
  article_proposal.as_prompt(),
125
- **self.prepend_sys_msg(),
126
154
  ),
127
155
  "Could not generate the initial outline.",
128
156
  ).update_ref(article_proposal)
129
157
 
130
158
 
131
- class FixIntrospectedErrors(Action):
159
+ class FixIntrospectedErrors(Action, Censor):
132
160
  """Fix introspected errors in the article outline."""
133
161
 
134
162
  output_key: str = "introspected_errors_fixed_outline"
135
163
  """The key of the output data."""
136
164
 
165
+ ruleset: Optional[RuleSet] = None
166
+ """The ruleset to use to fix the introspected errors."""
167
+
137
168
  async def _execute(
138
169
  self,
139
170
  article_outline: ArticleOutline,
140
- supervisor_check: bool = False,
171
+ ruleset: Optional[RuleSet] = None,
141
172
  **_,
142
173
  ) -> Optional[ArticleOutline]:
143
- introspect_manual = ok(
144
- await self.draft_rating_manual(
145
- topic=(
146
- intro_topic
147
- := "Fix the error in the article outline, make sure there is no more error in the article outline."
148
- ),
149
- ),
150
- "Could not generate the rating manual.",
151
- )
152
-
153
174
  while pack := article_outline.find_introspected():
154
175
  component, err = ok(pack)
155
176
  logger.warning(f"Found introspected error: {err}")
156
177
  corrected = ok(
157
- await self.correct_obj(
178
+ await self.censor_obj(
158
179
  component,
159
- reference=f"# Original Article Outline\n{article_outline.display()}\n# Error Need to be fixed\n{err}",
160
- topic=intro_topic,
161
- rating_manual=introspect_manual,
162
- supervisor_check=supervisor_check,
180
+ ruleset=ok(ruleset or self.ruleset, "No ruleset provided"),
181
+ reference=f"# Original Article Outline\n{article_outline.display()}\n# Some Basic errors found from `{component.title}` that need to be fixed\n{err}",
163
182
  ),
164
183
  "Could not correct the component.",
165
184
  )
@@ -168,141 +187,117 @@ class FixIntrospectedErrors(Action):
168
187
  return article_outline
169
188
 
170
189
 
171
- class FixIllegalReferences(Action):
190
+ class FixIllegalReferences(Action, Censor):
172
191
  """Fix illegal references in the article outline."""
173
192
 
174
193
  output_key: str = "illegal_references_fixed_outline"
175
194
  """The key of the output data."""
176
195
 
196
+ ruleset: Optional[RuleSet] = None
197
+ """Ruleset to use to fix the illegal references."""
198
+
177
199
  async def _execute(
178
200
  self,
179
201
  article_outline: ArticleOutline,
180
- supervisor_check: bool = False,
202
+ ruleset: Optional[RuleSet] = None,
181
203
  **_,
182
204
  ) -> Optional[ArticleOutline]:
183
- ref_manual = ok(
184
- await self.draft_rating_manual(
185
- topic=(
186
- ref_topic
187
- := "Fix the internal referring error, make sure there is no more `ArticleRef` pointing to a non-existing article component."
188
- ),
189
- ),
190
- "Could not generate the rating manual.",
191
- )
192
-
193
- while pack := article_outline.find_illegal_ref():
194
- ref, err = ok(pack)
205
+ while pack := article_outline.find_illegal_ref(gather_identical=True):
206
+ refs, err = ok(pack)
195
207
  logger.warning(f"Found illegal referring error: {err}")
196
- ok(
197
- await self.correct_obj_inplace(
198
- ref,
199
- reference=f"# Original Article Outline\n{article_outline.display()}\n# Error Need to be fixed\n{err}",
200
- topic=ref_topic,
201
- rating_manual=ref_manual,
202
- supervisor_check=supervisor_check,
208
+ corrected_ref = ok(
209
+ await self.censor_obj(
210
+ refs[0], # pyright: ignore [reportIndexIssue]
211
+ ruleset=ok(ruleset or self.ruleset, "No ruleset provided"),
212
+ reference=f"# Original Article Outline\n{article_outline.display()}\n# Some Basic errors found that need to be fixed\n{err}",
203
213
  )
204
214
  )
215
+ for ref in refs:
216
+ ref.update_from(corrected_ref) # pyright: ignore [reportAttributeAccessIssue]
217
+
205
218
  return article_outline.update_ref(article_outline)
206
219
 
207
220
 
208
- class TweakOutlineBackwardRef(Action, AdvancedJudge):
209
- """Tweak the backward references in the article outline.
221
+ class TweakOutlineForwardRef(Action, Censor):
222
+ """Tweak the forward references in the article outline.
210
223
 
211
- Ensures that the prerequisites of the current chapter are correctly referenced in the `depend_on` field.
224
+ Ensures that the conclusions of the current chapter effectively support the analysis of subsequent chapters.
212
225
  """
213
226
 
214
- output_key: str = "article_outline_bw_ref_checked"
227
+ output_key: str = "article_outline_fw_ref_checked"
228
+ ruleset: Optional[RuleSet] = None
229
+ """Ruleset to use to fix the illegal references."""
215
230
 
216
- async def _execute(self, article_outline: ArticleOutline, supervisor_check: bool = False, **cxt) -> ArticleOutline:
217
- tweak_depend_on_manual = ok(
218
- await self.draft_rating_manual(
219
- topic := "Ensure prerequisites are correctly referenced in the `depend_on` field."
220
- ),
221
- "Could not generate the rating manual.",
231
+ async def _execute(
232
+ self, article_outline: ArticleOutline, ruleset: Optional[RuleSet] = None, **cxt
233
+ ) -> ArticleOutline:
234
+ return await self._inner(
235
+ article_outline,
236
+ ruleset=ok(ruleset or self.ruleset, "No ruleset provided"),
237
+ field_name="support_to",
222
238
  )
223
239
 
240
+ async def _inner(self, article_outline: ArticleOutline, ruleset: RuleSet, field_name: str) -> ArticleOutline:
224
241
  for a in article_outline.iter_dfs():
225
- if await self.evidently_judge(
242
+ if judge := await self.evidently_judge(
226
243
  f"{article_outline.as_prompt()}\n\n{a.display()}\n"
227
- f"Does the `{a.__class__.__name__}`'s `depend_on` field need to be extended or tweaked?"
244
+ f"Does the `{a.__class__.__name__}`'s `{field_name}` field need to be extended or tweaked?"
228
245
  ):
229
- patch = ArticleRefPatch.default()
230
- patch.tweaked = a.depend_on
246
+ patch = ArticleRefSequencePatch.default()
247
+ patch.tweaked = getattr(a, field_name)
231
248
 
232
- await self.correct_obj_inplace(
249
+ await self.censor_obj_inplace(
233
250
  patch,
234
- topic=topic,
235
- reference=f"{article_outline.as_prompt()}\nThe Article component whose `depend_on` field needs to be extended or tweaked",
236
- rating_manual=tweak_depend_on_manual,
237
- supervisor_check=supervisor_check,
251
+ ruleset=ruleset,
252
+ reference=f"{article_outline.as_prompt()}\n"
253
+ f"The Article component titled `{a.title}` whose `{field_name}` field needs to be extended or tweaked.\n"
254
+ f"# Judgement\n{judge.display()}",
238
255
  )
239
-
240
256
  return article_outline
241
257
 
242
258
 
243
- class TweakOutlineForwardRef(Action, AdvancedJudge):
244
- """Tweak the forward references in the article outline.
259
+ class TweakOutlineBackwardRef(TweakOutlineForwardRef):
260
+ """Tweak the backward references in the article outline.
245
261
 
246
- Ensures that the conclusions of the current chapter effectively support the analysis of subsequent chapters.
262
+ Ensures that the prerequisites of the current chapter are correctly referenced in the `depend_on` field.
247
263
  """
248
264
 
249
- output_key: str = "article_outline_fw_ref_checked"
265
+ output_key: str = "article_outline_bw_ref_checked"
266
+ ruleset: Optional[RuleSet] = None
250
267
 
251
- async def _execute(self, article_outline: ArticleOutline, supervisor_check: bool = False, **cxt) -> ArticleOutline:
252
- tweak_support_to_manual = ok(
253
- await self.draft_rating_manual(
254
- topic := "Ensure conclusions support the analysis of subsequent chapters, sections or subsections."
255
- ),
256
- "Could not generate the rating manual.",
268
+ async def _execute(
269
+ self, article_outline: ArticleOutline, ruleset: Optional[RuleSet] = None, **cxt
270
+ ) -> ArticleOutline:
271
+ return await self._inner(
272
+ article_outline,
273
+ ruleset=ok(ruleset or self.ruleset, "No ruleset provided"),
274
+ field_name="depend_on",
257
275
  )
258
276
 
259
- for a in article_outline.iter_dfs():
260
- if await self.evidently_judge(
261
- f"{article_outline.as_prompt()}\n\n{a.display()}\n"
262
- f"Does the `{a.__class__.__name__}`'s `support_to` field need to be extended or tweaked?"
263
- ):
264
- patch = ArticleRefPatch.default()
265
- patch.tweaked = a.support_to
266
-
267
- await self.correct_obj_inplace(
268
- patch,
269
- topic=topic,
270
- reference=f"{article_outline.as_prompt()}\nThe Article component whose `support_to` field needs to be extended or tweaked",
271
- rating_manual=tweak_support_to_manual,
272
- supervisor_check=supervisor_check,
273
- )
274
-
275
- return article_outline
276
277
 
277
-
278
- class GenerateArticle(Action):
278
+ class GenerateArticle(Action, Censor):
279
279
  """Generate the article based on the outline."""
280
280
 
281
281
  output_key: str = "article"
282
282
  """The key of the output data."""
283
+ ruleset: Optional[RuleSet] = None
283
284
 
284
285
  async def _execute(
285
286
  self,
286
287
  article_outline: ArticleOutline,
287
- supervisor_check: bool = False,
288
+ ruleset: Optional[RuleSet] = None,
288
289
  **_,
289
290
  ) -> Optional[Article]:
290
291
  article: Article = Article.from_outline(ok(article_outline, "Article outline not specified.")).update_ref(
291
292
  article_outline
292
293
  )
293
294
 
294
- write_para_manual = ok(
295
- await self.draft_rating_manual(w_topic := "write the following paragraph in the subsection.")
296
- )
297
-
298
295
  await gather(
299
296
  *[
300
- self.correct_obj_inplace(
297
+ self.censor_obj_inplace(
301
298
  subsec,
299
+ ruleset=ok(ruleset or self.ruleset, "No ruleset provided"),
302
300
  reference=f"# Original Article Outline\n{article_outline.display()}\n# Error Need to be fixed\n{err}",
303
- topic=w_topic,
304
- rating_manual=write_para_manual,
305
- supervisor_check=supervisor_check,
306
301
  )
307
302
  for _, __, subsec in article.iter_subsections()
308
303
  if (err := subsec.introspect())
@@ -313,18 +308,16 @@ class GenerateArticle(Action):
313
308
  return article
314
309
 
315
310
 
316
- class CorrectProposal(Action):
311
+ class CorrectProposal(Action, Censor):
317
312
  """Correct the proposal of the article."""
318
313
 
319
314
  output_key: str = "corrected_proposal"
320
315
 
321
316
  async def _execute(self, article_proposal: ArticleProposal, **_) -> Any:
322
- return (await self.censor_obj(article_proposal, reference=article_proposal.referenced)).update_ref(
323
- article_proposal
324
- )
317
+ raise NotImplementedError("Not implemented.")
325
318
 
326
319
 
327
- class CorrectOutline(Action):
320
+ class CorrectOutline(Action, Correct):
328
321
  """Correct the outline of the article."""
329
322
 
330
323
  output_key: str = "corrected_outline"
@@ -335,12 +328,10 @@ class CorrectOutline(Action):
335
328
  article_outline: ArticleOutline,
336
329
  **_,
337
330
  ) -> ArticleOutline:
338
- return (await self.censor_obj(article_outline, reference=article_outline.referenced.as_prompt())).update_ref(
339
- article_outline
340
- )
331
+ raise NotImplementedError("Not implemented.")
341
332
 
342
333
 
343
- class CorrectArticle(Action):
334
+ class CorrectArticle(Action, Correct):
344
335
  """Correct the article based on the outline."""
345
336
 
346
337
  output_key: str = "corrected_article"
@@ -352,4 +343,4 @@ class CorrectArticle(Action):
352
343
  article_outline: ArticleOutline,
353
344
  **_,
354
345
  ) -> Article:
355
- return await self.censor_obj(article, reference=article_outline.referenced.as_prompt())
346
+ raise NotImplementedError("Not implemented.")
@@ -0,0 +1,100 @@
1
+ """A module for writing articles using RAG (Retrieval-Augmented Generation) capabilities."""
2
+
3
+ from asyncio import gather
4
+ from typing import Optional
5
+
6
+ from fabricatio.capabilities.censor import Censor
7
+ from fabricatio.capabilities.rag import RAG
8
+ from fabricatio.models.action import Action
9
+ from fabricatio.models.extra.article_main import Article, ArticleParagraphSequencePatch, ArticleSubsection
10
+ from fabricatio.models.extra.rule import RuleSet
11
+ from fabricatio.utils import ok
12
+
13
+
14
+ class TweakArticleRAG(Action, RAG, Censor):
15
+ """Write an article based on the provided outline.
16
+
17
+ This class inherits from `Action`, `RAG`, and `Censor` to provide capabilities for writing and refining articles
18
+ using Retrieval-Augmented Generation (RAG) techniques. It processes an article outline, enhances subsections by
19
+ searching for related references, and applies censoring rules to ensure compliance with the provided ruleset.
20
+
21
+ Attributes:
22
+ output_key (str): The key used to store the output of the action.
23
+ ruleset (Optional[RuleSet]): The ruleset to be used for censoring the article.
24
+ """
25
+
26
+ output_key: str = "rag_tweaked_article"
27
+ """The key used to store the output of the action."""
28
+
29
+ ruleset: Optional[RuleSet] = None
30
+ """The ruleset to be used for censoring the article."""
31
+
32
+ async def _execute(
33
+ self,
34
+ article: Article,
35
+ collection_name: str = "article_essence",
36
+ ruleset: Optional[RuleSet] = None,
37
+ parallel: bool = False,
38
+ **cxt,
39
+ ) -> Optional[Article]:
40
+ """Write an article based on the provided outline.
41
+
42
+ This method processes the article outline, either in parallel or sequentially, by enhancing each subsection
43
+ with relevant references and applying censoring rules.
44
+
45
+ Args:
46
+ article (Article): The article to be processed.
47
+ collection_name (str): The name of the collection to view for processing.
48
+ ruleset (Optional[RuleSet]): The ruleset to apply for censoring. If not provided, the class's ruleset is used.
49
+ parallel (bool): If True, process subsections in parallel. Otherwise, process them sequentially.
50
+ **cxt: Additional context parameters.
51
+
52
+ Returns:
53
+ Optional[Article]: The processed article with enhanced subsections and applied censoring rules.
54
+ """
55
+ self.view(collection_name)
56
+
57
+ if parallel:
58
+ await gather(
59
+ *[
60
+ self._inner(article, subsec, ok(ruleset or self.ruleset, "No ruleset provided!"))
61
+ for _, __, subsec in article.iter_subsections()
62
+ ],
63
+ return_exceptions=True,
64
+ )
65
+ else:
66
+ for _, __, subsec in article.iter_subsections():
67
+ await self._inner(article, subsec, ok(ruleset or self.ruleset, "No ruleset provided!"))
68
+ return article
69
+
70
+ async def _inner(self, article: Article, subsec: ArticleSubsection, ruleset: RuleSet) -> None:
71
+ """Enhance a subsection of the article with references and apply censoring rules.
72
+
73
+ This method refines the query for the subsection, retrieves related references, and applies censoring rules
74
+ to the subsection's paragraphs.
75
+
76
+ Args:
77
+ article (Article): The article containing the subsection.
78
+ subsec (ArticleSubsection): The subsection to be enhanced.
79
+ ruleset (RuleSet): The ruleset to apply for censoring.
80
+
81
+ Returns:
82
+ None
83
+ """
84
+ refind_q = ok(
85
+ await self.arefined_query(
86
+ f"{article.referenced.as_prompt()}\n"
87
+ f"# Subsection requiring reference enhancement\n"
88
+ f"{subsec.display()}\n"
89
+ f"# Requirement\n"
90
+ f"Search related articles in the base to find reference candidates, "
91
+ f"prioritizing both original article language and English usage",
92
+ )
93
+ )
94
+ patch = ArticleParagraphSequencePatch.default()
95
+ patch.tweaked = subsec.paragraphs
96
+ await self.censor_obj_inplace(
97
+ patch,
98
+ ruleset=ruleset,
99
+ reference=await self.aretrieve_compact(refind_q, final_limit=30),
100
+ )