fabricatio 0.2.11.dev2__tar.gz → 0.2.12.dev1__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 (166) hide show
  1. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/.gitignore +2 -0
  2. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/PKG-INFO +4 -2
  3. fabricatio-0.2.12.dev1/examples/write_article/.gitignore +4 -0
  4. fabricatio-0.2.12.dev1/examples/write_article/write_article.py +196 -0
  5. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/pyproject.toml +7 -3
  6. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/actions/article.py +20 -4
  7. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/actions/article_rag.py +161 -53
  8. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/actions/output.py +35 -3
  9. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/config.py +3 -3
  10. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/fs/curd.py +1 -1
  11. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/action.py +18 -13
  12. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/aricle_rag.py +42 -19
  13. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/article_base.py +55 -26
  14. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/article_main.py +56 -4
  15. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/generic.py +10 -6
  16. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/kwargs_types.py +1 -1
  17. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/role.py +5 -4
  18. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/task.py +13 -1
  19. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/usages.py +1 -1
  20. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/utils.py +5 -5
  21. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/src/typst_tools.rs +8 -3
  22. fabricatio-0.2.12.dev1/templates.tar.gz +0 -0
  23. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/tests/test_models/test_problem.py +17 -37
  24. fabricatio-0.2.12.dev1/uv.lock +1706 -0
  25. fabricatio-0.2.11.dev2/examples/write_article/.gitignore +0 -3
  26. fabricatio-0.2.11.dev2/examples/write_article/write_article.py +0 -90
  27. fabricatio-0.2.11.dev2/templates.tar.gz +0 -0
  28. fabricatio-0.2.11.dev2/uv.lock +0 -1673
  29. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/.github/workflows/build-package.yaml +0 -0
  30. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/.github/workflows/ruff.yaml +0 -0
  31. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/.github/workflows/tests.yaml +0 -0
  32. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/.python-version +0 -0
  33. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/Cargo.lock +0 -0
  34. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/Cargo.toml +0 -0
  35. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/LICENSE +0 -0
  36. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/Makefile +0 -0
  37. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/README.md +0 -0
  38. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/correct/correct.py +0 -0
  39. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/correct/correct_loop.py +0 -0
  40. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/extract_and_inject/.gitignore +0 -0
  41. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/extract_and_inject/article_rag.py +0 -0
  42. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/extract_and_inject/ask.py +0 -0
  43. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/extract_and_inject/chunk_article.py +0 -0
  44. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/extract_and_inject/extract_and_inject.py +0 -0
  45. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/extract_article/extract.py +0 -0
  46. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/llm_usages/llm_usage.py +0 -0
  47. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/make_a_rating/rating.py +0 -0
  48. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/make_diary/commits.json +0 -0
  49. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/make_diary/diary.py +0 -0
  50. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/minor/hello_fabricatio.py +0 -0
  51. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/minor/write_a_poem.py +0 -0
  52. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/propose_task/.gitignore +0 -0
  53. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/propose_task/propose.py +0 -0
  54. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/reviewer/censor.py +0 -0
  55. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/reviewer/review.py +0 -0
  56. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/rules/.gitignore +0 -0
  57. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/rules/draft_ruleset.py +0 -0
  58. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/search_bibtex/.gitignore +0 -0
  59. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/search_bibtex/search.py +0 -0
  60. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/simple_chat/chat.py +0 -0
  61. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/simple_rag/simple_rag.py +0 -0
  62. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/task_handle/handle_task.py +0 -0
  63. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/write_article/article_rag.py +0 -0
  64. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/write_article/post_process.py +0 -0
  65. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/write_outline/.gitignore +0 -0
  66. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/write_outline/write_outline.py +0 -0
  67. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/examples/write_outline/write_outline_corrected.py +0 -0
  68. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/__init__.py +0 -0
  69. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/actions/__init__.py +0 -0
  70. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/actions/fs.py +0 -0
  71. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/actions/rag.py +0 -0
  72. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/actions/rules.py +0 -0
  73. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/__init__.py +0 -0
  74. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/advanced_judge.py +0 -0
  75. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/censor.py +0 -0
  76. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/check.py +0 -0
  77. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/correct.py +0 -0
  78. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/extract.py +0 -0
  79. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/propose.py +0 -0
  80. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/rag.py +0 -0
  81. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/rating.py +0 -0
  82. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/review.py +0 -0
  83. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/capabilities/task.py +0 -0
  84. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/constants.py +0 -0
  85. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/core.py +0 -0
  86. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/decorators.py +0 -0
  87. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/fs/__init__.py +0 -0
  88. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/fs/readers.py +0 -0
  89. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/journal.py +0 -0
  90. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/adv_kwargs_types.py +0 -0
  91. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/events.py +0 -0
  92. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/__init__.py +0 -0
  93. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/advanced_judge.py +0 -0
  94. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/article_essence.py +0 -0
  95. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/article_outline.py +0 -0
  96. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/article_proposal.py +0 -0
  97. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/patches.py +0 -0
  98. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/problem.py +0 -0
  99. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/rag.py +0 -0
  100. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/extra/rule.py +0 -0
  101. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/models/tool.py +0 -0
  102. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/parser.py +0 -0
  103. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/py.typed +0 -0
  104. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/rust.pyi +0 -0
  105. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/rust_instances.py +0 -0
  106. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/toolboxes/__init__.py +0 -0
  107. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/toolboxes/arithmetic.py +0 -0
  108. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/toolboxes/fs.py +0 -0
  109. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/workflows/__init__.py +0 -0
  110. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/workflows/articles.py +0 -0
  111. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/python/fabricatio/workflows/rag.py +0 -0
  112. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/src/bib_tools.rs +0 -0
  113. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/src/hash.rs +0 -0
  114. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/src/hbs_helpers.rs +0 -0
  115. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/src/language.rs +0 -0
  116. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/src/lib.rs +0 -0
  117. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/src/templates.rs +0 -0
  118. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/src/word_split.rs +0 -0
  119. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/as_prompt.hbs +0 -0
  120. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/binary-exploitation-ctf-solver.hbs +0 -0
  121. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/check_string.hbs +0 -0
  122. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/claude-xml.hbs +0 -0
  123. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/clean-up-code.hbs +0 -0
  124. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/co_validation.hbs +0 -0
  125. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/create_json_obj.hbs +0 -0
  126. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/cryptography-ctf-solver.hbs +0 -0
  127. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/dependencies.hbs +0 -0
  128. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/document-the-code.hbs +0 -0
  129. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/draft_rating_criteria.hbs +0 -0
  130. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/draft_rating_manual.hbs +0 -0
  131. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/draft_rating_weights_klee.hbs +0 -0
  132. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/draft_tool_usage_code.hbs +0 -0
  133. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/extract.hbs +0 -0
  134. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/extract_criteria_from_reasons.hbs +0 -0
  135. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/extract_reasons_from_examples.hbs +0 -0
  136. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/find-security-vulnerabilities.hbs +0 -0
  137. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/fix-bugs.hbs +0 -0
  138. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/fix_troubled_obj.hbs +0 -0
  139. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/fix_troubled_string.hbs +0 -0
  140. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/generic_string.hbs +0 -0
  141. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/improve-performance.hbs +0 -0
  142. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/liststr.hbs +0 -0
  143. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/make_choice.hbs +0 -0
  144. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/make_judgment.hbs +0 -0
  145. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/pathstr.hbs +0 -0
  146. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/rate_fine_grind.hbs +0 -0
  147. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/refactor.hbs +0 -0
  148. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/refined_query.hbs +0 -0
  149. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/retrieved_display.hbs +0 -0
  150. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/reverse-engineering-ctf-solver.hbs +0 -0
  151. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/review_string.hbs +0 -0
  152. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/rule_requirement.hbs +0 -0
  153. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/ruleset_requirement_breakdown.hbs +0 -0
  154. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/task_briefing.hbs +0 -0
  155. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/web-ctf-solver.hbs +0 -0
  156. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/write-git-commit.hbs +0 -0
  157. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/write-github-pull-request.hbs +0 -0
  158. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/templates/built-in/write-github-readme.hbs +0 -0
  159. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/tests/test_config.py +0 -0
  160. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/tests/test_models/test_action.py +0 -0
  161. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/tests/test_models/test_advanced.py +0 -0
  162. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/tests/test_models/test_generic.py +0 -0
  163. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/tests/test_models/test_role.py +0 -0
  164. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/tests/test_models/test_task.py +0 -0
  165. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/tests/test_models/test_tool.py +0 -0
  166. {fabricatio-0.2.11.dev2 → fabricatio-0.2.12.dev1}/tests/test_models/test_usages.py +0 -0
@@ -166,3 +166,5 @@ cython_debug/
166
166
  extra/scripts/*
167
167
  output/
168
168
  .vscode/
169
+ templates/customed
170
+ *.typ
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fabricatio
3
- Version: 0.2.11.dev2
3
+ Version: 0.2.12.dev1
4
4
  Classifier: License :: OSI Approved :: MIT License
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -20,18 +20,20 @@ Requires-Dist: pydantic-settings>=2.7.1
20
20
  Requires-Dist: pymitter>=1.0.0
21
21
  Requires-Dist: rich>=13.9.4
22
22
  Requires-Dist: ujson>=5.10.0
23
- Requires-Dist: fabricatio[calc,ftd,plot,qa,rag] ; extra == 'full'
23
+ Requires-Dist: fabricatio[calc,ftd,plot,qa,rag,cli] ; extra == 'full'
24
24
  Requires-Dist: pymilvus>=2.5.4 ; extra == 'rag'
25
25
  Requires-Dist: sympy>=1.13.3 ; extra == 'calc'
26
26
  Requires-Dist: matplotlib>=3.10.1 ; extra == 'plot'
27
27
  Requires-Dist: questionary>=2.1.0 ; extra == 'qa'
28
28
  Requires-Dist: magika>=0.6.1 ; extra == 'ftd'
29
+ Requires-Dist: typer-slim[standard]>=0.15.2 ; extra == 'cli'
29
30
  Provides-Extra: full
30
31
  Provides-Extra: rag
31
32
  Provides-Extra: calc
32
33
  Provides-Extra: plot
33
34
  Provides-Extra: qa
34
35
  Provides-Extra: ftd
36
+ Provides-Extra: cli
35
37
  License-File: LICENSE
36
38
  Summary: A LLM multi-agent framework.
37
39
  Keywords: ai,agents,multi-agent,llm,pyo3
@@ -0,0 +1,4 @@
1
+ article_briefing.txt
2
+ article_outline_raw.txt
3
+ out.typ
4
+ persistent*
@@ -0,0 +1,196 @@
1
+ """Example of using the library."""
2
+
3
+ import asyncio
4
+ from pathlib import Path
5
+
6
+ import typer
7
+ from fabricatio import Event, Role, WorkFlow, logger
8
+ from fabricatio.actions.article import ExtractOutlineFromRaw, GenerateArticleProposal, GenerateInitialOutline
9
+ from fabricatio.actions.article_rag import ArticleConsultRAG, WriteArticleContentRAG
10
+ from fabricatio.actions.output import DumpFinalizedOutput, PersistentAll
11
+ from fabricatio.models.extra.article_outline import ArticleOutline
12
+ from fabricatio.models.task import Task
13
+ from fabricatio.utils import ok
14
+ from typer import Typer
15
+
16
+ # from pydantic import HttpUrl
17
+
18
+ Role(
19
+ name="Undergraduate Researcher",
20
+ description="Write an outline for an article in typst format.",
21
+ llm_model="openai/qwen-plus",
22
+ llm_temperature=0.35,
23
+ # llm_api_endpoint=HttpUrl("https://dashscope.aliyuncs.com/compatible-mode/v1"),
24
+ llm_top_p=0.95,
25
+ llm_max_tokens=8191,
26
+ llm_stream=True,
27
+ llm_rpm=600,
28
+ llm_tpm=1000000,
29
+ llm_timeout=600,
30
+ registry={
31
+ Event.quick_instantiate(ns := "article"): WorkFlow(
32
+ name="Generate Article",
33
+ description="Generate an article. dump the outline to the given path. in typst format.",
34
+ steps=(
35
+ GenerateArticleProposal,
36
+ GenerateInitialOutline(output_key="article_outline"),
37
+ PersistentAll,
38
+ (
39
+ a := WriteArticleContentRAG(
40
+ output_key="to_dump",
41
+ ref_limit=18,
42
+ threshold=0.58,
43
+ result_per_query=2,
44
+ llm_model="openai/qwq-plus",
45
+ extractor_model="openai/qwen-max",
46
+ query_model="openai/qwen-turbo",
47
+ )
48
+ ),
49
+ DumpFinalizedOutput(output_key="task_output"),
50
+ PersistentAll,
51
+ ),
52
+ ),
53
+ Event.quick_instantiate(ns2 := "complete"): WorkFlow(
54
+ name="Generate Article",
55
+ description="Generate an article with given raw article outline. dump the outline to the given path. in typst format.",
56
+ steps=(
57
+ ExtractOutlineFromRaw(output_key="article_outline"),
58
+ PersistentAll,
59
+ a,
60
+ DumpFinalizedOutput(output_key="task_output"),
61
+ PersistentAll,
62
+ ),
63
+ ),
64
+ Event.quick_instantiate(ns3 := "finish"): WorkFlow(
65
+ name="Finish Article",
66
+ description="Finish an article with given article outline. dump the outline to the given path. in typst format.",
67
+ steps=(
68
+ a,
69
+ DumpFinalizedOutput(output_key="task_output"),
70
+ PersistentAll,
71
+ ),
72
+ ),
73
+ Event.quick_instantiate(ns4 := "consult"): WorkFlow(
74
+ name="Consult Article",
75
+ description="Consult an article with given article outline. dump the outline to the given path. in typst format.",
76
+ steps=(ArticleConsultRAG().to_task_output(),),
77
+ ),
78
+ },
79
+ )
80
+
81
+
82
+ app = Typer()
83
+
84
+
85
+ @app.command()
86
+ def consult(
87
+ collection_name: str = typer.Option("article_chunks", "-c", "--collection-name", help="Name of the collection."),
88
+ ) -> None:
89
+ """Consult an article based on a given article outline."""
90
+ _ = asyncio.run(
91
+ Task(name="Answer Question")
92
+ .update_init_context(
93
+ collection_name=collection_name,
94
+ )
95
+ .delegate(ns4)
96
+ )
97
+
98
+ logger.info("Finished")
99
+
100
+
101
+ @app.command()
102
+ def finish(
103
+ article_outline_path: Path = typer.Argument( # noqa: B008
104
+ help="Path to the article outline raw file."
105
+ ),
106
+ dump_path: Path = typer.Option(Path("out.typ"), "-d", "--dump-path", help="Path to dump the final output."), # noqa: B008
107
+ persist_dir: Path = typer.Option( # noqa: B008
108
+ Path("persistent"), "-p", "--persist-dir", help="Directory to persist the output."
109
+ ),
110
+ collection_name: str = typer.Option("article_chunks", "-c", "--collection-name", help="Name of the collection."),
111
+ supervisor: bool = typer.Option(False, "-s", "--supervisor", help="Whether to use the supervisor mode."),
112
+ ) -> None:
113
+ """Finish an article based on a given article outline."""
114
+ path = ok(
115
+ asyncio.run(
116
+ Task(name="write an article")
117
+ .update_init_context(
118
+ article_outline=ArticleOutline.from_persistent(article_outline_path),
119
+ dump_path=dump_path,
120
+ persist_dir=persist_dir,
121
+ collection_name=collection_name,
122
+ supervisor=supervisor,
123
+ )
124
+ .delegate(ns3)
125
+ ),
126
+ "Failed to generate an article ",
127
+ )
128
+ logger.success(f"The outline is saved in:\n{path}")
129
+
130
+
131
+ @app.command()
132
+ def completion(
133
+ article_outline_raw_path: Path = typer.Option( # noqa: B008
134
+ Path("article_outline_raw.txt"), "-a", "--article-outline-raw", help="Path to the article outline raw file."
135
+ ),
136
+ dump_path: Path = typer.Option(Path("out.typ"), "-d", "--dump-path", help="Path to dump the final output."), # noqa: B008
137
+ persist_dir: Path = typer.Option( # noqa: B008
138
+ Path("persistent"), "-p", "--persist-dir", help="Directory to persist the output."
139
+ ),
140
+ collection_name: str = typer.Option("article_chunks", "-c", "--collection-name", help="Name of the collection."),
141
+ supervisor: bool = typer.Option(False, "-s", "--supervisor", help="Whether to use the supervisor mode."),
142
+ ) -> None:
143
+ """Write an article based on a raw article outline."""
144
+ path = ok(
145
+ asyncio.run(
146
+ Task(name="write an article")
147
+ .update_init_context(
148
+ article_outline_raw_path=article_outline_raw_path,
149
+ dump_path=dump_path,
150
+ persist_dir=persist_dir,
151
+ collection_name=collection_name,
152
+ supervisor=supervisor,
153
+ )
154
+ .delegate(ns2)
155
+ ),
156
+ "Failed to generate an article ",
157
+ )
158
+ logger.success(f"The outline is saved in:\n{path}")
159
+
160
+
161
+ @app.command()
162
+ def write(
163
+ article_briefing: Path = typer.Option( # noqa: B008
164
+ Path("article_briefing.txt"), "-a", "--article-briefing", help="Path to the article briefing file."
165
+ ),
166
+ dump_path: Path = typer.Option(Path("out.typ"), "-d", "--dump-path", help="Path to dump the final output."), # noqa: B008
167
+ persist_dir: Path = typer.Option( # noqa: B008
168
+ Path("persistent"), "-p", "--persist-dir", help="Directory to persist the output."
169
+ ),
170
+ collection_name: str = typer.Option("article_chunks", "-c", "--collection-name", help="Name of the collection."),
171
+ supervisor: bool = typer.Option(False, "-s", "--supervisor", help="Whether to use the supervisor mode."),
172
+ ) -> None:
173
+ """Write an article based on a briefing.
174
+
175
+ This function generates an article outline and content based on the provided briefing.
176
+ The outline and content are then dumped to the specified path and persisted in the given directory.
177
+ """
178
+ path = ok(
179
+ asyncio.run(
180
+ Task(name="write an article")
181
+ .update_init_context(
182
+ article_briefing=article_briefing.read_text(),
183
+ dump_path=dump_path,
184
+ persist_dir=persist_dir,
185
+ collection_name=collection_name,
186
+ supervisor=supervisor,
187
+ )
188
+ .delegate(ns)
189
+ ),
190
+ "Failed to generate an article ",
191
+ )
192
+ logger.success(f"The outline is saved in:\n{path}")
193
+
194
+
195
+ if __name__ == "__main__":
196
+ app()
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fabricatio"
3
- version = "0.2.11-dev2"
3
+ version = "0.2.12-dev1"
4
4
  description = "A LLM multi-agent framework."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -74,7 +74,7 @@ dev = [
74
74
 
75
75
  [project.optional-dependencies]
76
76
  full = [
77
- "fabricatio[calc,ftd,plot,qa,rag]",
77
+ "fabricatio[calc,ftd,plot,qa,rag,cli]",
78
78
  ]
79
79
  rag = [
80
80
  "pymilvus>=2.5.4",
@@ -92,6 +92,9 @@ qa = [
92
92
  ftd = [
93
93
  "magika>=0.6.1",
94
94
  ]
95
+ cli = [
96
+ "typer-slim[standard]>=0.15.2",
97
+ ]
95
98
 
96
99
  [tool.ruff]
97
100
  include = ["pyproject.toml", "python/fabricatio/*.py", "python/fabricatio/*.pyi", "examples/*.py"]
@@ -134,7 +137,8 @@ ignore = [
134
137
  "PYI063",
135
138
  "PYI021",
136
139
  "ASYNC109",
137
- "RUF001"
140
+ "RUF001",
141
+ "PYI019"
138
142
  ]
139
143
  [tool.ruff.lint.pydocstyle]
140
144
  convention = "google"
@@ -149,10 +149,10 @@ class GenerateInitialOutline(Action, Extract):
149
149
  async def _execute(
150
150
  self,
151
151
  article_proposal: ArticleProposal,
152
+ supervisor: Optional[bool] = None,
152
153
  **_,
153
154
  ) -> Optional[ArticleOutline]:
154
- raw_outline = await self.aask(
155
- f"{(article_proposal.as_prompt())}\n"
155
+ req = (
156
156
  f"Design each chapter of a proper and academic and ready for release manner.\n"
157
157
  f"You Must make sure every chapter have sections, and every section have subsections.\n"
158
158
  f"Make the chapter and sections and subsections bing divided into a specific enough article component.\n"
@@ -160,14 +160,16 @@ class GenerateInitialOutline(Action, Extract):
160
160
  f"Note that you SHALL use `{article_proposal.language}` as written language",
161
161
  )
162
162
 
163
- if self.supervisor:
163
+ raw_outline = await self.aask(f"{(article_proposal.as_prompt())}\n{req}")
164
+
165
+ if supervisor or (supervisor is None and self.supervisor):
164
166
  from questionary import confirm, text
165
167
 
166
168
  r_print(raw_outline)
167
169
  while not await confirm("Accept this version and continue?", default=True).ask_async():
168
170
  imp = await text("Enter the improvement:").ask_async()
169
171
  raw_outline = await self.aask(
170
- f"{article_proposal.as_prompt()}\n{wrapp_in_block(raw_outline, 'Previous ArticleOutline')}\n{imp}"
172
+ f"{article_proposal.as_prompt()}\n{wrapp_in_block(raw_outline, 'Previous ArticleOutline')}\n{req}\n{wrapp_in_block(imp, title='Improvement')}"
171
173
  )
172
174
  r_print(raw_outline)
173
175
 
@@ -177,6 +179,20 @@ class GenerateInitialOutline(Action, Extract):
177
179
  ).update_ref(article_proposal)
178
180
 
179
181
 
182
+ class ExtractOutlineFromRaw(Action, Extract):
183
+ """Extract the outline from the raw outline."""
184
+
185
+ output_key: str = "article_outline_from_raw"
186
+
187
+ async def _execute(self, article_outline_raw_path: str | Path, **cxt) -> ArticleOutline:
188
+ logger.info(f"Extracting outline from raw: {Path(article_outline_raw_path).as_posix()}")
189
+
190
+ return ok(
191
+ await self.extract(ArticleOutline, safe_text_read(article_outline_raw_path)),
192
+ "Could not extract the outline from raw.",
193
+ )
194
+
195
+
180
196
  class FixIntrospectedErrors(Action, Censor):
181
197
  """Fix introspected errors in the article outline."""
182
198
 
@@ -4,6 +4,8 @@ from asyncio import gather
4
4
  from pathlib import Path
5
5
  from typing import List, Optional
6
6
 
7
+ from pydantic import PositiveInt
8
+
7
9
  from fabricatio import BibManager
8
10
  from fabricatio.capabilities.censor import Censor
9
11
  from fabricatio.capabilities.extract import Extract
@@ -18,13 +20,35 @@ from fabricatio.models.extra.article_outline import ArticleOutline
18
20
  from fabricatio.models.extra.rule import RuleSet
19
21
  from fabricatio.utils import ask_retain, ok
20
22
 
23
+ TYPST_CITE_USAGE = (
24
+ "citation number is REQUIRED to cite any reference!,for example in Auther Pattern: 'Doe et al.[[1]], Jack et al.[[2]]' or in Sentence Suffix Sattern: 'Global requirement is incresing[[1]].'\n"
25
+ "Everything is build upon the typst language, which is similar to latex, \n"
26
+ "Legal citing syntax examples(seperated by |): [[1]]|[[1,2]]|[[1-3]]|[[12,13-15]]|[[1-3,5-7]]\n"
27
+ "Illegal citing syntax examples(seperated by |): [[1],[2],[3]]|[[1],[1-2]]\n"
28
+ "Those reference mark shall not be omitted during the extraction\n"
29
+ "It's recommended to cite multiple references that supports your conclusion at a time.\n"
30
+ "Wrapp inline expression using $ $,like '$>5m$' '$89%$' , and wrapp block equation using $$ $$. if you are using '$' as the money unit, you should add a '\\' before it to avoid being interpreted as a inline equation. For example 'The pants worths 5\\$.'\n"
31
+ "In addition to that, you can add a label outside the block equation which can be used as a cross reference identifier, the label is a string wrapped in `<` and `>` like `<energy-release-rate-equation>`.Note that the label string should be a summarizing title for the equation being labeled.\n"
32
+ "you can refer to that label by using the syntax with prefix of `@eqt:`, which indicate that this notation is citing a label from the equations. For example ' @eqt:energy-release-rate-equation ' DO remember that the notation shall have both suffixed and prefixed space char which enable the compiler to distinguish the notation from the plaintext."
33
+ "Below is a usage example:\n"
34
+ "```typst\n"
35
+ "See @eqt:mass-energy-equation , it's the foundation of physics.\n"
36
+ "$$\n"
37
+ "E = m c^2\n"
38
+ "$$ <mass-energy-equation>\n\n\n"
39
+ "In @eqt:mass-energy-equation , $m$ stands for mass, $c$ stands for speed of light, and $E$ stands for energy. \n"
40
+ "```"
41
+ )
42
+
21
43
 
22
44
  class WriteArticleContentRAG(Action, RAG, Extract):
23
45
  """Write an article based on the provided outline."""
24
46
 
47
+ search_increment_multiplier: float = 1.6
48
+ """The increment multiplier of the search increment."""
25
49
  ref_limit: int = 35
26
50
  """The limit of references to be retrieved"""
27
- threshold: float = 0.55
51
+ threshold: float = 0.62
28
52
  """The threshold of relevance"""
29
53
  extractor_model: str
30
54
  """The model to use for extracting the content from the retrieved references."""
@@ -32,43 +56,24 @@ class WriteArticleContentRAG(Action, RAG, Extract):
32
56
  """The model to use for querying the database"""
33
57
  supervisor: bool = False
34
58
  """Whether to use supervisor mode"""
35
- req: str = (
36
- "citation number is REQUIRED to cite any reference!\n"
37
- "Everything is build upon the typst language, which is similar to latex, \n"
38
- "Legal citing syntax examples(seperated by |): [[1]]|[[1,2]]|[[1-3]]|[[12,13-15]]|[[1-3,5-7]]\n"
39
- "Illegal citing syntax examples(seperated by |): [[1],[2],[3]]|[[1],[1-2]]\n"
40
- "Those reference mark shall not be omitted during the extraction\n"
41
- "It's recommended to cite multiple references that supports your conclusion at a time.\n"
42
- "Wrapp inline expression using $ $, and wrapp block equation using $$ $$."
43
- "In addition to that, you can add a label outside the block equation which can be used as a cross reference identifier, the label is a string wrapped in `<` and `>`,"
44
- "you can refer to that label by using the syntax with prefix of `@eqt:`"
45
- "Below is a usage example:\n"
46
- "```typst\n"
47
- "See @eqt:mass-energy-equation , it's the foundation of physics.\n"
48
- "$$\n"
49
- "E = m c^2"
50
- "$$\n"
51
- "<mass-energy-equation>\n\n"
52
- "In @eqt:mass-energy-equation , $m$ stands for mass, $c$ stands for speed of light, and $E$ stands for energy. \n"
53
- "```"
54
- )
59
+ result_per_query: PositiveInt = 4
60
+ """The number of results to be returned per query."""
61
+ req: str = TYPST_CITE_USAGE
62
+ """The req of the write article content."""
55
63
 
56
64
  async def _execute(
57
65
  self,
58
66
  article_outline: ArticleOutline,
59
- writing_ruleset: RuleSet,
60
- collection_name: str = "article_chunks",
67
+ collection_name: Optional[str] = None,
68
+ supervisor: Optional[bool] = None,
61
69
  **cxt,
62
70
  ) -> Article:
63
71
  article = Article.from_outline(article_outline).update_ref(article_outline)
72
+ self.target_collection = collection_name or self.safe_target_collection
73
+ if supervisor or (supervisor is None and self.supervisor):
74
+ for chap, sec, subsec in article.iter_subsections():
75
+ await self._supervisor_inner(article, article_outline, chap, sec, subsec)
64
76
 
65
- if self.supervisor:
66
- await gather(
67
- *[
68
- self._supervisor_inner(article, article_outline, chap, sec, subsec)
69
- for chap, sec, subsec in article.iter_subsections()
70
- ]
71
- )
72
77
  else:
73
78
  await gather(
74
79
  *[
@@ -92,21 +97,29 @@ class WriteArticleContentRAG(Action, RAG, Extract):
92
97
  from questionary import confirm, text
93
98
  from rich import print as r_print
94
99
 
95
- ret = await self.search_database(article, article_outline, chap, sec, subsec)
96
-
97
- cm = CitationManager(article_chunks=await ask_retain([r.chunk for r in ret], ret)).set_cite_number_all()
100
+ cm = CitationManager()
101
+ await self.search_database(article, article_outline, chap, sec, subsec, cm)
98
102
 
99
103
  raw = await self.write_raw(article, article_outline, chap, sec, subsec, cm)
100
104
  r_print(raw)
105
+
101
106
  while not await confirm("Accept this version and continue?").ask_async():
102
- if await confirm("Search for more refs?").ask_async():
103
- new_refs = await self.search_database(article, article_outline, chap, sec, subsec)
104
- cm.add_chunks(await ask_retain([r.chunk for r in new_refs], new_refs))
107
+ if inst := await text("Search for more refs for additional spec.").ask_async():
108
+ await self.search_database(
109
+ article,
110
+ article_outline,
111
+ chap,
112
+ sec,
113
+ subsec,
114
+ cm,
115
+ supervisor=True,
116
+ extra_instruction=inst,
117
+ )
105
118
 
106
- instruction = await text("Enter the instructions to improve").ask_async()
107
- raw = await self.write_raw(article, article_outline, chap, sec, subsec, cm, instruction)
108
- if await confirm("Edit it?").ask_async():
109
- raw = await text("Edit", default=raw).ask_async() or raw
119
+ if instruction := await text("Enter the instructions to improve").ask_async():
120
+ raw = await self.write_raw(article, article_outline, chap, sec, subsec, cm, instruction)
121
+ if edt := await text("Edit", default=raw).ask_async():
122
+ raw = edt
110
123
 
111
124
  r_print(raw)
112
125
 
@@ -120,11 +133,14 @@ class WriteArticleContentRAG(Action, RAG, Extract):
120
133
  sec: ArticleSection,
121
134
  subsec: ArticleSubsection,
122
135
  ) -> ArticleSubsection:
123
- ret = await self.search_database(article, article_outline, chap, sec, subsec)
124
- cm = CitationManager(article_chunks=ret).set_cite_number_all()
136
+ cm = CitationManager()
137
+
138
+ await self.search_database(article, article_outline, chap, sec, subsec, cm)
125
139
 
126
140
  raw_paras = await self.write_raw(article, article_outline, chap, sec, subsec, cm)
127
141
 
142
+ raw_paras = "\n".join(p for p in raw_paras.splitlines() if p and not p.endswith("**") and not p.startswith("#"))
143
+
128
144
  return await self.extract_new_subsec(subsec, raw_paras, cm)
129
145
 
130
146
  async def extract_new_subsec(
@@ -138,6 +154,7 @@ class WriteArticleContentRAG(Action, RAG, Extract):
138
154
  f"Above is the subsection titled `{subsec.title}`.\n"
139
155
  f"I need you to extract the content to update my subsection obj provided below.\n{self.req}"
140
156
  f"{subsec.display()}\n",
157
+ model=self.extractor_model,
141
158
  ),
142
159
  "Failed to propose new subsection.",
143
160
  )
@@ -161,12 +178,15 @@ class WriteArticleContentRAG(Action, RAG, Extract):
161
178
  return (
162
179
  (
163
180
  await self.aask(
164
- f"{cm.as_prompt()}\nAbove is some related reference retrieved for you."
181
+ f"{cm.as_prompt()}\nAbove is some related reference from other auther retrieved for you."
165
182
  f"{article_outline.finalized_dump()}\n\nAbove is my article outline, I m writing graduate thesis titled `{article.title}`. "
166
183
  f"More specifically, i m witting the Chapter `{chap.title}` >> Section `{sec.title}` >> Subsection `{subsec.title}`.\n"
167
184
  f"Please help me write the paragraphs of the subsec mentioned above, which is `{subsec.title}`.\n"
168
185
  f"{self.req}\n"
169
- f"You SHALL use `{article.language}` as writing language.\n{extra_instruction}"
186
+ f"You SHALL use `{article.language}` as writing language.\n{extra_instruction}\n"
187
+ f"Do not use numbered list to display the outcome, you should regard you are writing the main text of the thesis.\n"
188
+ f"You should not copy others' works from the references directly on to my thesis, we can only harness the conclusion they have drawn.\n"
189
+ f"No extra explanation is allowed."
170
190
  )
171
191
  )
172
192
  .replace(r" \( ", "$")
@@ -174,7 +194,9 @@ class WriteArticleContentRAG(Action, RAG, Extract):
174
194
  .replace(r"\(", "$")
175
195
  .replace(r"\)", "$")
176
196
  .replace("\\[\n", "$$\n")
197
+ .replace("\\[ ", "$$\n")
177
198
  .replace("\n\\]", "\n$$")
199
+ .replace(" \\]", "\n$$")
178
200
  )
179
201
 
180
202
  async def search_database(
@@ -184,27 +206,113 @@ class WriteArticleContentRAG(Action, RAG, Extract):
184
206
  chap: ArticleChapter,
185
207
  sec: ArticleSection,
186
208
  subsec: ArticleSubsection,
209
+ cm: CitationManager,
187
210
  extra_instruction: str = "",
188
- ) -> List[ArticleChunk]:
211
+ supervisor: bool = False,
212
+ ) -> None:
189
213
  """Search database for related references."""
214
+ search_req = (
215
+ f"{article_outline.finalized_dump()}\n\nAbove is my article outline, I m writing graduate thesis titled `{article.title}`. "
216
+ f"More specifically, i m witting the Chapter `{chap.title}` >> Section `{sec.title}` >> Subsection `{subsec.title}`.\n"
217
+ f"I need to search related references to build up the content of the subsec mentioned above, which is `{subsec.title}`.\n"
218
+ f"provide 10~16 queries as possible, to get best result!\n"
219
+ f"You should provide both English version and chinese version of the refined queries!\n{extra_instruction}\n"
220
+ )
221
+
190
222
  ref_q = ok(
191
223
  await self.arefined_query(
192
- f"{article_outline.finalized_dump()}\n\nAbove is my article outline, I m writing graduate thesis titled `{article.title}`. "
193
- f"More specifically, i m witting the Chapter `{chap.title}` >> Section `{sec.title}` >> Subsection `{subsec.title}`.\n"
194
- f"I need to search related references to build up the content of the subsec mentioned above, which is `{subsec.title}`.\n"
195
- f"provide 10~16 queries as possible, to get best result!\n"
196
- f"You should provide both English version and chinese version of the refined queries!\n{extra_instruction}\n",
224
+ search_req,
197
225
  model=self.query_model,
198
226
  ),
199
227
  "Failed to refine query.",
200
228
  )
201
229
 
202
- if self.supervisor:
230
+ if supervisor:
231
+ ref_q = await ask_retain(ref_q)
232
+ ret = await self.aretrieve(
233
+ ref_q,
234
+ ArticleChunk,
235
+ final_limit=self.ref_limit,
236
+ result_per_query=self.result_per_query,
237
+ similarity_threshold=self.threshold,
238
+ )
239
+
240
+ cm.add_chunks(ok(ret))
241
+ ref_q = await self.arefined_query(
242
+ f"{cm.as_prompt()}\n\nAbove is the retrieved references in the first RAG, now we need to perform the second RAG.\n\n{search_req}",
243
+ model=self.query_model,
244
+ )
245
+
246
+ if ref_q is None:
247
+ logger.warning("Second refine query is None, skipping.")
248
+ return
249
+ if supervisor:
203
250
  ref_q = await ask_retain(ref_q)
204
251
 
205
- return await self.aretrieve(
206
- ref_q, ArticleChunk, final_limit=self.ref_limit, result_per_query=3, similarity_threshold=self.threshold
252
+ ret = await self.aretrieve(
253
+ ref_q,
254
+ ArticleChunk,
255
+ final_limit=int(self.ref_limit * self.search_increment_multiplier),
256
+ result_per_query=int(self.result_per_query * self.search_increment_multiplier),
257
+ similarity_threshold=self.threshold,
207
258
  )
259
+ if ret is None:
260
+ logger.warning("Second retrieve is None, skipping.")
261
+ return
262
+ cm.add_chunks(ret)
263
+
264
+
265
+ class ArticleConsultRAG(Action, RAG):
266
+ """Write an article based on the provided outline."""
267
+
268
+ output_key: str = "consult_count"
269
+
270
+ ref_limit: int = 20
271
+ """The final limit of references."""
272
+ ref_per_q: int = 3
273
+ """The limit of references to retrieve per query."""
274
+ similarity_threshold: float = 0.62
275
+ """The similarity threshold of references to retrieve."""
276
+ ref_q_model: Optional[str] = None
277
+ """The model to use for refining query."""
278
+ req: str = TYPST_CITE_USAGE
279
+ """The request for the rag model."""
280
+
281
+ @precheck_package(
282
+ "questionary", "`questionary` is required for supervisor mode, please install it by `fabricatio[qa]`"
283
+ )
284
+ async def _execute(self, collection_name: Optional[str] = None, **cxt) -> int:
285
+ from questionary import confirm, text
286
+ from rich import print as r_print
287
+
288
+ from fabricatio.rust import convert_all_block_tex, convert_all_inline_tex
289
+
290
+ self.target_collection = collection_name or self.safe_target_collection
291
+
292
+ cm = CitationManager()
293
+
294
+ counter = 0
295
+ while (req := await text("User: ").ask_async()) is not None:
296
+ if await confirm("Empty the cm?").ask_async():
297
+ cm.empty()
298
+ ref_q = await self.arefined_query(req, model=self.ref_q_model)
299
+ refs = await self.aretrieve(
300
+ ok(ref_q, "Failed to refine query."),
301
+ ArticleChunk,
302
+ final_limit=self.ref_limit,
303
+ result_per_query=self.ref_per_q,
304
+ similarity_threshold=self.similarity_threshold,
305
+ )
306
+
307
+ ret = await self.aask(f"{cm.add_chunks(refs).as_prompt()}\n{self.req}\n{req}")
308
+ ret = convert_all_inline_tex(ret)
309
+ ret = convert_all_block_tex(ret)
310
+ ret = cm.apply(ret)
311
+
312
+ r_print(ret)
313
+ counter += 1
314
+ logger.info(f"{counter} rounds of conversation.")
315
+ return counter
208
316
 
209
317
 
210
318
  class TweakArticleRAG(Action, RAG, Censor):