quantalogic 0.50.26__tar.gz → 0.50.29__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 (167) hide show
  1. {quantalogic-0.50.26 → quantalogic-0.50.29}/PKG-INFO +1 -1
  2. {quantalogic-0.50.26 → quantalogic-0.50.29}/pyproject.toml +1 -1
  3. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/agent.py +71 -107
  4. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/model_info_litellm.py +15 -4
  5. quantalogic-0.50.29/quantalogic/prompts/memory_compaction_prompt.j2 +16 -0
  6. quantalogic-0.50.29/quantalogic/prompts/observation_response_format.j2 +55 -0
  7. quantalogic-0.50.29/quantalogic/prompts/repeated_tool_call_error.j2 +10 -0
  8. quantalogic-0.50.26/quantalogic/prompts.py → quantalogic-0.50.29/quantalogic/prompts/system_prompt.j2 +5 -13
  9. quantalogic-0.50.29/quantalogic/prompts/task_prompt.j2 +12 -0
  10. quantalogic-0.50.29/quantalogic/prompts/task_summary_prompt.j2 +10 -0
  11. quantalogic-0.50.29/quantalogic/prompts/tools_prompt.j2 +13 -0
  12. quantalogic-0.50.29/quantalogic/prompts/variables_prompt.j2 +6 -0
  13. quantalogic-0.50.29/quantalogic/prompts.py +38 -0
  14. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/quantlitellm.py +5 -2
  15. {quantalogic-0.50.26 → quantalogic-0.50.29}/LICENSE +0 -0
  16. {quantalogic-0.50.26 → quantalogic-0.50.29}/README.md +0 -0
  17. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/__init__.py +0 -0
  18. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/agent_config.py +0 -0
  19. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/agent_factory.py +0 -0
  20. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/coding_agent.py +0 -0
  21. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/config.py +0 -0
  22. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/console_print_events.py +0 -0
  23. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/console_print_token.py +0 -0
  24. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/create_custom_agent.py +0 -0
  25. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/docs_cli.py +0 -0
  26. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/event_emitter.py +0 -0
  27. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/flow/__init__.py +0 -0
  28. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/flow/flow.py +0 -0
  29. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/flow/flow_extractor.py +0 -0
  30. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/flow/flow_generator.py +0 -0
  31. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/flow/flow_manager.py +0 -0
  32. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/flow/flow_manager_schema.py +0 -0
  33. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/flow/flow_yaml.md +0 -0
  34. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/generative_model.py +0 -0
  35. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/get_model_info.py +0 -0
  36. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/interactive_text_editor.py +0 -0
  37. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/main.py +0 -0
  38. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/memory.py +0 -0
  39. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/model_info.py +0 -0
  40. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/model_info_list.py +0 -0
  41. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/model_names.py +0 -0
  42. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/search_agent.py +0 -0
  43. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/server/__init__.py +0 -0
  44. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/server/agent_server.py +0 -0
  45. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/server/models.py +0 -0
  46. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/server/routes.py +0 -0
  47. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/server/state.py +0 -0
  48. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/server/static/js/event_visualizer.js +0 -0
  49. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/server/static/js/quantalogic.js +0 -0
  50. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/server/templates/index.html +0 -0
  51. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/task_file_reader.py +0 -0
  52. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/task_runner.py +0 -0
  53. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tool_manager.py +0 -0
  54. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/__init__.py +0 -0
  55. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/agent_tool.py +0 -0
  56. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/composio/__init__.py +0 -0
  57. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/composio/composio.py +0 -0
  58. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/database/__init__.py +0 -0
  59. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/database/generate_database_report_tool.py +0 -0
  60. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/database/sql_query_tool_advanced.py +0 -0
  61. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/document_tools/__init__.py +0 -0
  62. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/document_tools/markdown_to_docx_tool.py +0 -0
  63. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/document_tools/markdown_to_epub_tool.py +0 -0
  64. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/document_tools/markdown_to_html_tool.py +0 -0
  65. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/document_tools/markdown_to_ipynb_tool.py +0 -0
  66. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/document_tools/markdown_to_latex_tool.py +0 -0
  67. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/document_tools/markdown_to_pdf_tool.py +0 -0
  68. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/document_tools/markdown_to_pptx_tool.py +0 -0
  69. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/download_http_file_tool.py +0 -0
  70. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/duckduckgo_search_tool.py +0 -0
  71. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/edit_whole_content_tool.py +0 -0
  72. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/elixir_tool.py +0 -0
  73. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/execute_bash_command_tool.py +0 -0
  74. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/finance/__init__.py +0 -0
  75. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/finance/alpha_vantage_tool.py +0 -0
  76. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/finance/ccxt_tool.py +0 -0
  77. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/finance/finance_llm_tool.py +0 -0
  78. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/finance/google_finance.py +0 -0
  79. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/finance/market_intelligence_tool.py +0 -0
  80. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/finance/technical_analysis_tool.py +0 -0
  81. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/finance/tradingview_tool.py +0 -0
  82. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/finance/yahoo_finance.py +0 -0
  83. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/git/__init__.py +0 -0
  84. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/git/bitbucket_clone_repo_tool.py +0 -0
  85. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/git/bitbucket_operations_tool.py +0 -0
  86. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/git/clone_repo_tool.py +0 -0
  87. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/git/git_operations_tool.py +0 -0
  88. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/google_packages/__init__.py +0 -0
  89. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/google_packages/google_news_tool.py +0 -0
  90. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/grep_app_tool.py +0 -0
  91. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/image_generation/__init__.py +0 -0
  92. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/image_generation/dalle_e.py +0 -0
  93. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/input_question_tool.py +0 -0
  94. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/jinja_tool.py +0 -0
  95. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/language_handlers/__init__.py +0 -0
  96. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/language_handlers/c_handler.py +0 -0
  97. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/language_handlers/cpp_handler.py +0 -0
  98. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/language_handlers/go_handler.py +0 -0
  99. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/language_handlers/java_handler.py +0 -0
  100. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/language_handlers/javascript_handler.py +0 -0
  101. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/language_handlers/python_handler.py +0 -0
  102. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/language_handlers/rust_handler.py +0 -0
  103. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/language_handlers/scala_handler.py +0 -0
  104. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/language_handlers/typescript_handler.py +0 -0
  105. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/list_directory_tool.py +0 -0
  106. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/llm_tool.py +0 -0
  107. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/llm_vision_tool.py +0 -0
  108. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/markitdown_tool.py +0 -0
  109. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/nasa_packages/__init__.py +0 -0
  110. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/nasa_packages/models.py +0 -0
  111. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/nasa_packages/nasa_apod_tool.py +0 -0
  112. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/nasa_packages/nasa_neows_tool.py +0 -0
  113. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/nasa_packages/services.py +0 -0
  114. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/nodejs_tool.py +0 -0
  115. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/presentation_tools/__init__.py +0 -0
  116. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/presentation_tools/presentation_llm_tool.py +0 -0
  117. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/product_hunt/__init__.py +0 -0
  118. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/product_hunt/product_hunt_tool.py +0 -0
  119. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/product_hunt/services.py +0 -0
  120. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/python_tool.py +0 -0
  121. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/rag_tool/__init__.py +0 -0
  122. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/rag_tool/document_metadata.py +0 -0
  123. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/rag_tool/query_response.py +0 -0
  124. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/rag_tool/rag_tool.py +0 -0
  125. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/rag_tool/rag_tool_beta.py +0 -0
  126. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/read_file_block_tool.py +0 -0
  127. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/read_file_tool.py +0 -0
  128. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/read_html_tool.py +0 -0
  129. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/replace_in_file_tool.py +0 -0
  130. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/ripgrep_tool.py +0 -0
  131. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/safe_python_interpreter_tool.py +0 -0
  132. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/search_definition_names.py +0 -0
  133. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/sequence_tool.py +0 -0
  134. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/serpapi_search_tool.py +0 -0
  135. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/sql_query_tool.py +0 -0
  136. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/task_complete_tool.py +0 -0
  137. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/tool.py +0 -0
  138. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/unified_diff_tool.py +0 -0
  139. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/utilities/__init__.py +0 -0
  140. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/utilities/csv_processor_tool.py +0 -0
  141. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/utilities/download_file_tool.py +0 -0
  142. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/utilities/mermaid_validator_tool.py +0 -0
  143. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/utils/__init__.py +0 -0
  144. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/utils/create_sample_database.py +0 -0
  145. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/utils/generate_database_report.py +0 -0
  146. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/wikipedia_search_tool.py +0 -0
  147. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/tools/write_file_tool.py +0 -0
  148. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/__init__.py +0 -0
  149. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/ask_user_validation.py +0 -0
  150. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/async_utils.py +0 -0
  151. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/check_version.py +0 -0
  152. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/download_http_file.py +0 -0
  153. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/get_all_models.py +0 -0
  154. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/get_coding_environment.py +0 -0
  155. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/get_environment.py +0 -0
  156. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/get_quantalogic_rules_content.py +0 -0
  157. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/git_ls.py +0 -0
  158. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/lm_studio_model_info.py +0 -0
  159. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/python_interpreter.py +0 -0
  160. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/read_file.py +0 -0
  161. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/read_http_text_content.py +0 -0
  162. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/utils/xml_utility.py +0 -0
  163. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/version.py +0 -0
  164. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/version_check.py +0 -0
  165. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/welcome_message.py +0 -0
  166. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/xml_parser.py +0 -0
  167. {quantalogic-0.50.26 → quantalogic-0.50.29}/quantalogic/xml_tool_parser.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantalogic
3
- Version: 0.50.26
3
+ Version: 0.50.29
4
4
  Summary: QuantaLogic ReAct Agents
5
5
  Author: Raphaël MANSUY
6
6
  Author-email: raphael.mansuy@gmail.com
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "quantalogic"
3
- version = "0.50.26"
3
+ version = "0.50.29"
4
4
  description = "QuantaLogic ReAct Agents"
5
5
  authors = ["Raphaël MANSUY <raphael.mansuy@gmail.com>"]
6
6
  readme = "README.md"
@@ -1,10 +1,13 @@
1
1
  """Enhanced QuantaLogic agent implementing the ReAct framework."""
2
2
 
3
3
  import asyncio
4
+ import os
4
5
  from collections.abc import Callable
5
6
  from datetime import datetime
7
+ from pathlib import Path
6
8
  from typing import Any
7
9
 
10
+ from jinja2 import Environment, FileSystemLoader
8
11
  from loguru import logger
9
12
  from pydantic import BaseModel, ConfigDict, PrivateAttr
10
13
 
@@ -559,17 +562,7 @@ class Agent(BaseModel):
559
562
  Returns:
560
563
  Generated summary text
561
564
  """
562
- prompt_summary = (
563
- "Summarize the conversation concisely:\n"
564
- "format in markdown:\n"
565
- "<thinking>\n"
566
- " - 1. **Completed Steps**: Briefly describe the steps.\n"
567
- " - 2. **Variables Used**: List the variables.\n"
568
- " - 3. **Progress Analysis**: Assess progress.\n"
569
- "</thinking>\n"
570
- "Keep the summary clear and actionable.\n"
571
- )
572
-
565
+ # Format conversation history for the template
573
566
  memory_copy = self.memory.memory.copy()
574
567
 
575
568
  if len(memory_copy) < 3:
@@ -578,6 +571,14 @@ class Agent(BaseModel):
578
571
 
579
572
  user_message = memory_copy.pop()
580
573
  assistant_message = memory_copy.pop()
574
+
575
+ # Create summarization prompt using template
576
+ prompt_summary = self._render_template('memory_compaction_prompt.j2',
577
+ conversation_history="\n\n".join(
578
+ f"[{msg.role.upper()}]: {msg.content}"
579
+ for msg in memory_copy
580
+ ))
581
+
581
582
  summary = await self.model.async_generate_with_history(messages_history=memory_copy, prompt=prompt_summary)
582
583
 
583
584
  # Remove last system message if present
@@ -620,15 +621,7 @@ class Agent(BaseModel):
620
621
  if len(content) < 1024 * 4:
621
622
  return content
622
623
 
623
- prompt = (
624
- "Create a task summary that captures ONLY: \n"
625
- "1. Primary objective/purpose\n"
626
- "2. Core actions/requirements\n"
627
- "3. Desired end-state/outcome\n\n"
628
- "Guidelines:\n"
629
- "- Use imperative voice\n"
630
- f"Input Task Description:\n{content}\n\n"
631
- )
624
+ prompt = self._render_template('task_summary_prompt.j2', content=content)
632
625
  result = await self.model.async_generate(prompt=prompt)
633
626
  logger.debug(f"Generated summary: {result.response}")
634
627
  return result.response.strip() + "\n🚨 The FULL task is in <task> tag in the previous messages.\n"
@@ -785,16 +778,11 @@ class Agent(BaseModel):
785
778
  Tuple of (executed_tool_name, error_message)
786
779
  """
787
780
  repeat_count = self.last_tool_call.get("count", 0)
788
- error_message = (
789
- "Error: Detected repeated identical tool call pattern.\n"
790
- f"Tool: {tool_name}\n"
791
- f"Arguments: {arguments_with_values}\n"
792
- f"Repeated {repeat_count} times\n\n"
793
- "PLEASE:\n"
794
- "1. Review your previous steps\n"
795
- "2. Consider a different approach\n"
796
- "3. Use a different tool or modify the arguments\n"
797
- "4. Ensure you're making progress towards the goal"
781
+ error_message = self._render_template(
782
+ 'repeated_tool_call_error.j2',
783
+ tool_name=tool_name,
784
+ arguments_with_values=arguments_with_values,
785
+ repeat_count=repeat_count
798
786
  )
799
787
  return tool_name, error_message
800
788
 
@@ -850,46 +838,19 @@ class Agent(BaseModel):
850
838
  f"... content was truncated full content available by interpolation in variable {variable_name}"
851
839
  )
852
840
 
853
- formatted_response = (
854
- "# Analysis and Next Action Decision Point\n\n"
855
- f"📊 Progress: Iteration {iteration}/{self.max_iterations}\n\n"
856
- "## Global Task summary:\n"
857
- f"```\n\n{self.task_to_solve_summary}```\n\n"
858
- "## Available Resources\n"
859
- f"🛠️ Tools:\n{self._get_tools_names_prompt()}\n\n"
860
- f"📦 Variables:\n{self._get_variable_prompt()}\n\n"
861
- "## Your Task\n"
862
- "1. Analyze the execution result and progress, formalize if the current step is solved according to the task.\n"
863
- "2. Determine the most effective next step\n"
864
- "3. Select exactly ONE tool from the available list\n"
865
- "4. Utilize variable interpolation where needed\n"
866
- "## Response Requirements\n"
867
- "Provide TWO markdown-formatted XML blocks:\n"
868
- "1. Your analysis of the progression resulting from the execution of the tool in <thinking> tags, don't include <context_analysis/>\n"
869
- "2. Your tool execution plan in <tool_name> tags\n\n"
870
- "## Last executed action result\n"
871
- f"Last executed tool {last_executed_tool} Execution Result:\n"
872
- f"\n<{variable_name}>\n{response_display}\n</{variable_name}>\n"
873
- "## Response Format\n"
874
- "```xml\n"
875
- "<thinking>\n"
876
- "[Detailed analysis of progress, and reasoning for next step]\n"
877
- "</thinking>\n"
878
- "```\n"
879
- "```xml\n"
880
- "<action>\n"
881
- "<selected_tool_name>\n"
882
- "[Precise instruction for tool execution]\n"
883
- "</selected_tool_name>\n"
884
- "</action>\n"
885
- "```\n\n"
886
- "⚠️ Important:\n"
887
- "- Respond ONLY with the two XML blocks\n"
888
- "- No additional commentary\n"
889
- "- If previous step failed, revise approach\n"
890
- "- Use interpolated variables ($variable_name$) where required in tool calls, to minimize token usage, if possible\n"
891
- "- strictly follow the required arguments for each tool as defined in system prompt\n"
892
- "- Utilize <action><task_complete><answer>...</answer></task_complete><action> to indicate task completion, display the result or if the task is deemed unfeasible."
841
+ tools_prompt = self._get_tools_names_prompt()
842
+ variables_prompt = self._get_variable_prompt()
843
+
844
+ formatted_response = self._render_template(
845
+ 'observation_response_format.j2',
846
+ iteration=iteration,
847
+ max_iterations=self.max_iterations,
848
+ task_to_solve_summary=self.task_to_solve_summary,
849
+ tools_prompt=tools_prompt,
850
+ variables_prompt=variables_prompt,
851
+ last_executed_tool=last_executed_tool,
852
+ variable_name=variable_name,
853
+ response_display=response_display
893
854
  )
894
855
 
895
856
  return formatted_response
@@ -903,16 +864,14 @@ class Agent(BaseModel):
903
864
  Returns:
904
865
  The formatted task prompt
905
866
  """
906
- prompt_task: str = (
907
- "## Your task to solve:\n"
908
- f"<task>\n{task}\n</task>\n"
909
- "\n### Tools:\n"
910
- "-----------------------------\n"
911
- f"{self._get_tools_names_prompt()}\n"
912
- "\n"
913
- "### Variables:\n"
914
- "-----------------------------\n"
915
- f"{self._get_variable_prompt()}\n"
867
+ tools_prompt = self._get_tools_names_prompt()
868
+ variables_prompt = self._get_variable_prompt()
869
+
870
+ prompt_task = self._render_template(
871
+ 'task_prompt.j2',
872
+ task=task,
873
+ tools_prompt=tools_prompt,
874
+ variables_prompt=variables_prompt
916
875
  )
917
876
  return prompt_task
918
877
 
@@ -922,21 +881,8 @@ class Agent(BaseModel):
922
881
  Returns:
923
882
  Formatted tools prompt
924
883
  """
925
- prompt_use_tools: str = (
926
- "To accomplish this task, you have access to these tools:\n"
927
- "\n"
928
- f"{', '.join(self.tools.tool_names())}\n\n"
929
- "Instructions:\n"
930
- "\n"
931
- "1. Select ONE tool per message\n"
932
- "2. You will receive the tool's output in the next user response\n"
933
- "3. Choose the most appropriate tool for each step\n"
934
- "4. If it's not asked to write on files, don't use write_file tool\n"
935
- "5. If files are written, then use tool to display the prepared download link\n"
936
- "6. Give the final full answer using all the variables\n"
937
- "7. Use task_complete tool to confirm task completion with the full content of the final answer\n"
938
- )
939
- return prompt_use_tools
884
+ tool_names = ', '.join(self.tools.tool_names())
885
+ return self._render_template('tools_prompt.j2', tool_names=tool_names)
940
886
 
941
887
  def _get_variable_prompt(self) -> str:
942
888
  """Construct a prompt that explains how to use variables.
@@ -944,17 +890,8 @@ class Agent(BaseModel):
944
890
  Returns:
945
891
  Formatted variables prompt
946
892
  """
947
- prompt_use_variables: str = (
948
- "To use a variable interpolation, use the format $variable_name$ in function arguments.\n"
949
- "Example: <write_file><file_path>/path/to/file.txt</file_path><content>$var1$</content></write_file>\n"
950
- "\n"
951
- "Available variables:\n"
952
- "\n"
953
- f"{', '.join(self.variable_store.keys())}\n"
954
- if len(self.variable_store.keys()) > 0
955
- else "None\n"
956
- )
957
- return prompt_use_variables
893
+ variable_names = ', '.join(self.variable_store.keys()) if len(self.variable_store.keys()) > 0 else "None"
894
+ return self._render_template('variables_prompt.j2', variable_names=variable_names)
958
895
 
959
896
  def _calculate_context_occupancy(self) -> float:
960
897
  """Calculate the number of tokens in percentages for prompt and completion.
@@ -1063,4 +1000,31 @@ class Agent(BaseModel):
1063
1000
  tools_markdown=self.tools.to_markdown(),
1064
1001
  system_prompt=self.config.system_prompt,
1065
1002
  )
1066
- logger.debug(f"Set {len(tools)} tools")
1003
+ logger.debug(f"Set {len(tools)} tools")
1004
+
1005
+ def _render_template(self, template_name: str, **kwargs) -> str:
1006
+ """Render a Jinja2 template with the provided variables.
1007
+
1008
+ Args:
1009
+ template_name: Name of the template file (without directory path)
1010
+ **kwargs: Variables to pass to the template
1011
+
1012
+ Returns:
1013
+ str: The rendered template
1014
+ """
1015
+ try:
1016
+ # Get the directory where this file is located
1017
+ current_dir = Path(os.path.dirname(os.path.abspath(__file__)))
1018
+
1019
+ # Set up Jinja2 environment
1020
+ template_dir = current_dir / 'prompts'
1021
+ env = Environment(loader=FileSystemLoader(template_dir))
1022
+
1023
+ # Load the template
1024
+ template = env.get_template(template_name)
1025
+
1026
+ # Render the template with the provided variables
1027
+ return template.render(**kwargs)
1028
+ except Exception as e:
1029
+ logger.error(f"Error rendering template {template_name}: {str(e)}")
1030
+ raise
@@ -1,7 +1,19 @@
1
1
  import functools
2
2
 
3
- import litellm
3
+ # litellm will be imported lazily when needed
4
+ _litellm = None
4
5
 
6
+ def _get_litellm():
7
+ """Lazy load litellm module.
8
+
9
+ Returns:
10
+ The litellm module
11
+ """
12
+ global _litellm
13
+ if _litellm is None:
14
+ import litellm
15
+ _litellm = litellm
16
+ return _litellm
5
17
 
6
18
  @functools.lru_cache(maxsize=32)
7
19
  def litellm_get_model_info(model_name: str) -> dict | None:
@@ -16,6 +28,7 @@ def litellm_get_model_info(model_name: str) -> dict | None:
16
28
  Raises:
17
29
  ValueError: If model info cannot be found after prefix fallbacks
18
30
  """
31
+ litellm = _get_litellm()
19
32
  tried_models = [model_name]
20
33
 
21
34
  while True:
@@ -37,7 +50,6 @@ def litellm_get_model_info(model_name: str) -> dict | None:
37
50
 
38
51
  return None
39
52
 
40
-
41
53
  def litellm_get_model_max_input_tokens(model_name: str) -> int | None:
42
54
  """Get maximum input tokens for a model using litellm.
43
55
 
@@ -53,7 +65,6 @@ def litellm_get_model_max_input_tokens(model_name: str) -> int | None:
53
65
  except Exception:
54
66
  return 8192 # Default for many modern models
55
67
 
56
-
57
68
  def litellm_get_model_max_output_tokens(model_name: str) -> int | None:
58
69
  """Get maximum output tokens for a model using litellm.
59
70
 
@@ -67,4 +78,4 @@ def litellm_get_model_max_output_tokens(model_name: str) -> int | None:
67
78
  info = litellm_get_model_info(model_name)
68
79
  return info.get("max_output_tokens", 4096)
69
80
  except Exception:
70
- return 4096 # Conservative default
81
+ return 4096 # Conservative default
@@ -0,0 +1,16 @@
1
+ You are an AI assistant tasked with summarizing a conversation history.
2
+
3
+ Create a concise summary that captures the essential information from the conversation, focusing on:
4
+ 1. The main task or problem being solved
5
+ 2. Key information discovered or shared
6
+ 3. Important decisions made
7
+ 4. Current status or progress
8
+
9
+ Guidelines:
10
+ - Be factual and objective
11
+ - Preserve critical details and context
12
+ - Focus on information that would be needed to continue the task
13
+ - Aim for a summary that is about 20% of the original length
14
+
15
+ Conversation History:
16
+ {{ conversation_history }}
@@ -0,0 +1,55 @@
1
+ # Analysis and Next Action Decision Point
2
+
3
+ 📊 Progress: Iteration {{ iteration }}/{{ max_iterations }}
4
+
5
+ ## Global Task summary:
6
+ ```
7
+
8
+ {{ task_to_solve_summary }}```
9
+
10
+ ## Available Resources
11
+ 🛠️ Tools:
12
+ {{ tools_prompt }}
13
+
14
+ 📦 Variables:
15
+ {{ variables_prompt }}
16
+
17
+ ## Your Task
18
+ 1. Analyze the execution result and progress, formalize if the current step is solved according to the task.
19
+ 2. Determine the most effective next step
20
+ 3. Select exactly ONE tool from the available list
21
+ 4. Utilize variable interpolation where needed
22
+
23
+ ## Response Requirements
24
+ Provide TWO markdown-formatted XML blocks:
25
+ 1. Your analysis of the progression resulting from the execution of the tool in <thinking> tags, don't include <context_analysis/>
26
+ 2. Your tool execution plan in <tool_name> tags
27
+
28
+ ## Last executed action result
29
+ Last executed tool {{ last_executed_tool }} Execution Result:
30
+
31
+ <{{ variable_name }}>
32
+ {{ response_display }}
33
+ </{{ variable_name }}>
34
+
35
+ ## Response Format
36
+ ```xml
37
+ <thinking>
38
+ [Detailed analysis of progress, and reasoning for next step]
39
+ </thinking>
40
+ ```
41
+ ```xml
42
+ <action>
43
+ <selected_tool_name>
44
+ [Precise instruction for tool execution]
45
+ </selected_tool_name>
46
+ </action>
47
+ ```
48
+
49
+ ⚠️ Important:
50
+ - Respond ONLY with the two XML blocks
51
+ - No additional commentary
52
+ - If previous step failed, revise approach
53
+ - Use interpolated variables ($variable_name$) where required in tool calls, to minimize token usage, if possible
54
+ - strictly follow the required arguments for each tool as defined in system prompt
55
+ - Utilize <action><task_complete><answer>...</answer></task_complete><action> to indicate task completion, display the result or if the task is deemed unfeasible.
@@ -0,0 +1,10 @@
1
+ Error: Detected repeated identical tool call pattern.
2
+ Tool: {{ tool_name }}
3
+ Arguments: {{ arguments_with_values }}
4
+ Repeated {{ repeat_count }} times
5
+
6
+ PLEASE:
7
+ 1. Review your previous steps
8
+ 2. Consider a different approach
9
+ 3. Use a different tool or modify the arguments
10
+ 4. Ensure you're making progress towards the goal
@@ -1,14 +1,8 @@
1
- from quantalogic.version import get_version
2
-
3
-
4
- def system_prompt(tools: str, environment: str, expertise: str = ""):
5
- """System prompt for the ReAct chatbot with enhanced cognitive architecture."""
6
- return f"""
7
- ### Agent Identity: QuantaLogic {get_version()}
1
+ ### Agent Identity: QuantaLogic {{ version }}
8
2
  Expert ReAct AI Agent implementing OODA (Observe-Orient-Decide-Act) loop with advanced problem-solving capabilities.
9
3
 
10
4
  ### Domain Expertise
11
- {expertise}
5
+ {{ expertise }}
12
6
 
13
7
  ### Input Protocol
14
8
  Task Format: <task>task_description</task>
@@ -76,14 +70,14 @@ Task Format: <task>task_description</task>
76
70
  ```xml
77
71
  <action>
78
72
  <task_complete>
79
- <result>$final_output$</result>
73
+ <r>$final_output$</r>
80
74
  </task_complete>
81
75
  </action>
82
76
  ```
83
77
 
84
78
  ### Operational Parameters
85
- 🛠️ Tools: {tools}
86
- 🌐 Environment: {environment}
79
+ 🛠️ Tools: {{ tools }}
80
+ 🌐 Environment: {{ environment }}
87
81
 
88
82
  ### Execution Guidelines
89
83
  1. 🎯 Maintain laser focus on task objectives
@@ -94,5 +88,3 @@ Task Format: <task>task_description</task>
94
88
  6. 🛑 Fail fast and adapt when encountering blockers
95
89
  7. ✅ Verify completion criteria rigorously
96
90
  8. ✅ Return complete, full and usable results.
97
-
98
- """
@@ -0,0 +1,12 @@
1
+ ## Your task to solve:
2
+ <task>
3
+ {{ task }}
4
+ </task>
5
+
6
+ ### Tools:
7
+ -----------------------------
8
+ {{ tools_prompt }}
9
+
10
+ ### Variables:
11
+ -----------------------------
12
+ {{ variables_prompt }}
@@ -0,0 +1,10 @@
1
+ Create a task summary that captures ONLY:
2
+ 1. Primary objective/purpose
3
+ 2. Core actions/requirements
4
+ 3. Desired end-state/outcome
5
+
6
+ Guidelines:
7
+ - Use imperative voice
8
+
9
+ Input Task Description:
10
+ {{ content }}
@@ -0,0 +1,13 @@
1
+ To accomplish this task, you have access to these tools:
2
+
3
+ {{ tool_names }}
4
+
5
+ Instructions:
6
+
7
+ 1. Select ONE tool per message
8
+ 2. You will receive the tool's output in the next user response
9
+ 3. Choose the most appropriate tool for each step
10
+ 4. If it's not asked to write on files, don't use write_file tool
11
+ 5. If files are written, then use tool to display the prepared download link
12
+ 6. Give the final full answer using all the variables
13
+ 7. Use task_complete tool to confirm task completion with the full content of the final answer
@@ -0,0 +1,6 @@
1
+ To use a variable interpolation, use the format $variable_name$ in function arguments.
2
+ Example: <write_file><file_path>/path/to/file.txt</file_path><content>$var1$</content></write_file>
3
+
4
+ Available variables:
5
+
6
+ {{ variable_names }}
@@ -0,0 +1,38 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ from jinja2 import Environment, FileSystemLoader
5
+
6
+ from quantalogic.version import get_version
7
+
8
+
9
+ def system_prompt(tools: str, environment: str, expertise: str = ""):
10
+ """System prompt for the ReAct chatbot with enhanced cognitive architecture.
11
+
12
+ Uses a Jinja2 template from the prompts directory.
13
+
14
+ Args:
15
+ tools: Available tools for the agent
16
+ environment: Environment information
17
+ expertise: Domain expertise information
18
+
19
+ Returns:
20
+ str: The rendered system prompt
21
+ """
22
+ # Get the directory where this file is located
23
+ current_dir = Path(os.path.dirname(os.path.abspath(__file__)))
24
+
25
+ # Set up Jinja2 environment
26
+ template_dir = current_dir / 'prompts'
27
+ env = Environment(loader=FileSystemLoader(template_dir))
28
+
29
+ # Load the template
30
+ template = env.get_template('system_prompt.j2')
31
+
32
+ # Render the template with the provided variables
33
+ return template.render(
34
+ version=get_version(),
35
+ tools=tools,
36
+ environment=environment,
37
+ expertise=expertise
38
+ )
@@ -38,7 +38,10 @@ PROVIDERS = {
38
38
  env_var="DASHSCOPE_API_KEY",
39
39
  ),
40
40
  "nvidia": ModelProviderConfig(
41
- prefix="nvidia/", provider="openai", base_url="https://integrate.api.nvidia.com/v1", env_var="NVIDIA_API_KEY"
41
+ prefix="nvidia/",
42
+ provider="openai",
43
+ base_url="https://integrate.api.nvidia.com/v1",
44
+ env_var="NVIDIA_API_KEY",
42
45
  ),
43
46
  "ovh": ModelProviderConfig(
44
47
  prefix="ovh/",
@@ -160,4 +163,4 @@ def get_model_max_output_tokens(model_name: str) -> int | None:
160
163
 
161
164
  def get_model_info(model_name: str) -> dict | None:
162
165
  """Get model information for a given model name."""
163
- return model_info.get(model_name, None)
166
+ return model_info.get(model_name, None)
File without changes
File without changes