quantalogic 0.59.3__py3-none-any.whl → 0.61.0__py3-none-any.whl
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.
- quantalogic/agent.py +268 -24
- quantalogic/agent_config.py +5 -5
- quantalogic/agent_factory.py +2 -2
- quantalogic/codeact/__init__.py +0 -0
- quantalogic/codeact/agent.py +499 -0
- quantalogic/codeact/cli.py +232 -0
- quantalogic/codeact/constants.py +9 -0
- quantalogic/codeact/events.py +78 -0
- quantalogic/codeact/llm_util.py +76 -0
- quantalogic/codeact/prompts/error_format.j2 +11 -0
- quantalogic/codeact/prompts/generate_action.j2 +26 -0
- quantalogic/codeact/prompts/generate_program.j2 +39 -0
- quantalogic/codeact/prompts/response_format.j2 +11 -0
- quantalogic/codeact/tools_manager.py +135 -0
- quantalogic/codeact/utils.py +135 -0
- quantalogic/coding_agent.py +2 -2
- quantalogic/create_custom_agent.py +26 -78
- quantalogic/prompts/chat_system_prompt.j2 +10 -7
- quantalogic/prompts/code_2_system_prompt.j2 +190 -0
- quantalogic/prompts/code_system_prompt.j2 +142 -0
- quantalogic/prompts/doc_system_prompt.j2 +178 -0
- quantalogic/prompts/legal_2_system_prompt.j2 +218 -0
- quantalogic/prompts/legal_system_prompt.j2 +140 -0
- quantalogic/prompts/system_prompt.j2 +6 -2
- quantalogic/prompts/tools_prompt.j2 +2 -4
- quantalogic/prompts.py +23 -4
- quantalogic/python_interpreter/__init__.py +23 -0
- quantalogic/python_interpreter/assignment_visitors.py +63 -0
- quantalogic/python_interpreter/base_visitors.py +20 -0
- quantalogic/python_interpreter/class_visitors.py +22 -0
- quantalogic/python_interpreter/comprehension_visitors.py +172 -0
- quantalogic/python_interpreter/context_visitors.py +59 -0
- quantalogic/python_interpreter/control_flow_visitors.py +88 -0
- quantalogic/python_interpreter/exception_visitors.py +109 -0
- quantalogic/python_interpreter/exceptions.py +39 -0
- quantalogic/python_interpreter/execution.py +202 -0
- quantalogic/python_interpreter/function_utils.py +386 -0
- quantalogic/python_interpreter/function_visitors.py +209 -0
- quantalogic/python_interpreter/import_visitors.py +28 -0
- quantalogic/python_interpreter/interpreter_core.py +358 -0
- quantalogic/python_interpreter/literal_visitors.py +74 -0
- quantalogic/python_interpreter/misc_visitors.py +148 -0
- quantalogic/python_interpreter/operator_visitors.py +108 -0
- quantalogic/python_interpreter/scope.py +10 -0
- quantalogic/python_interpreter/visit_handlers.py +110 -0
- quantalogic/server/agent_server.py +1 -1
- quantalogic/tools/__init__.py +6 -3
- quantalogic/tools/action_gen.py +366 -0
- quantalogic/tools/duckduckgo_search_tool.py +1 -0
- quantalogic/tools/execute_bash_command_tool.py +114 -57
- quantalogic/tools/file_tracker_tool.py +49 -0
- quantalogic/tools/google_packages/google_news_tool.py +3 -0
- quantalogic/tools/image_generation/dalle_e.py +89 -137
- quantalogic/tools/python_tool.py +13 -0
- quantalogic/tools/rag_tool/__init__.py +2 -9
- quantalogic/tools/rag_tool/document_rag_sources_.py +728 -0
- quantalogic/tools/rag_tool/ocr_pdf_markdown.py +144 -0
- quantalogic/tools/replace_in_file_tool.py +1 -1
- quantalogic/tools/{search_definition_names.py → search_definition_names_tool.py} +2 -2
- quantalogic/tools/terminal_capture_tool.py +293 -0
- quantalogic/tools/tool.py +120 -22
- quantalogic/tools/utilities/__init__.py +2 -0
- quantalogic/tools/utilities/download_file_tool.py +3 -5
- quantalogic/tools/utilities/llm_tool.py +283 -0
- quantalogic/tools/utilities/selenium_tool.py +296 -0
- quantalogic/tools/utilities/vscode_tool.py +1 -1
- quantalogic/tools/web_navigation/__init__.py +5 -0
- quantalogic/tools/web_navigation/web_tool.py +145 -0
- quantalogic/tools/write_file_tool.py +72 -36
- quantalogic/utils/__init__.py +0 -1
- quantalogic/utils/test_python_interpreter.py +119 -0
- {quantalogic-0.59.3.dist-info → quantalogic-0.61.0.dist-info}/METADATA +7 -2
- {quantalogic-0.59.3.dist-info → quantalogic-0.61.0.dist-info}/RECORD +76 -35
- quantalogic/tools/rag_tool/document_metadata.py +0 -15
- quantalogic/tools/rag_tool/query_response.py +0 -20
- quantalogic/tools/rag_tool/rag_tool.py +0 -566
- quantalogic/tools/rag_tool/rag_tool_beta.py +0 -264
- quantalogic/utils/python_interpreter.py +0 -905
- {quantalogic-0.59.3.dist-info → quantalogic-0.61.0.dist-info}/LICENSE +0 -0
- {quantalogic-0.59.3.dist-info → quantalogic-0.61.0.dist-info}/WHEEL +0 -0
- {quantalogic-0.59.3.dist-info → quantalogic-0.61.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,135 @@
|
|
1
|
+
import ast
|
2
|
+
import inspect
|
3
|
+
from functools import wraps
|
4
|
+
from typing import Any, Callable, Tuple
|
5
|
+
|
6
|
+
from loguru import logger
|
7
|
+
from lxml import etree
|
8
|
+
|
9
|
+
|
10
|
+
def log_async_tool(verb: str):
|
11
|
+
"""Decorator factory for consistent async tool logging."""
|
12
|
+
def decorator(func: Callable) -> Callable:
|
13
|
+
@wraps(func)
|
14
|
+
async def wrapper(*args, **kwargs):
|
15
|
+
logger.info(f"Starting tool: {func.__name__}")
|
16
|
+
sig = inspect.signature(func)
|
17
|
+
bound_args = sig.bind(*args, **kwargs)
|
18
|
+
bound_args.apply_defaults()
|
19
|
+
logger.info(f"{verb} {', '.join(f'{k}={v}' for k, v in bound_args.arguments.items())}")
|
20
|
+
result = await func(*args, **kwargs)
|
21
|
+
logger.info(f"Finished tool: {func.__name__}")
|
22
|
+
return result
|
23
|
+
return wrapper
|
24
|
+
return decorator
|
25
|
+
|
26
|
+
|
27
|
+
def log_tool_method(func: Callable) -> Callable:
|
28
|
+
"""Decorator for logging Tool class methods."""
|
29
|
+
@wraps(func)
|
30
|
+
async def wrapper(self, **kwargs):
|
31
|
+
logger.info(f"Starting tool: {self.name}")
|
32
|
+
try:
|
33
|
+
result = await func(self, **kwargs)
|
34
|
+
logger.info(f"Finished tool: {self.name}")
|
35
|
+
return result
|
36
|
+
except Exception as e:
|
37
|
+
logger.error(f"Tool {self.name} failed: {e}")
|
38
|
+
raise
|
39
|
+
return wrapper
|
40
|
+
|
41
|
+
|
42
|
+
def validate_xml(xml_string: str) -> bool:
|
43
|
+
"""Validate XML string."""
|
44
|
+
try:
|
45
|
+
etree.fromstring(xml_string)
|
46
|
+
return True
|
47
|
+
except etree.XMLSyntaxError as e:
|
48
|
+
logger.error(f"XML validation failed: {e}")
|
49
|
+
return False
|
50
|
+
|
51
|
+
|
52
|
+
def validate_code(code: str) -> bool:
|
53
|
+
"""Check if code has an async main() function."""
|
54
|
+
try:
|
55
|
+
tree = ast.parse(code)
|
56
|
+
return any(isinstance(node, ast.AsyncFunctionDef) and node.name == "main"
|
57
|
+
for node in ast.walk(tree))
|
58
|
+
except SyntaxError:
|
59
|
+
return False
|
60
|
+
|
61
|
+
|
62
|
+
def format_xml_element(tag: str, value: Any, **attribs) -> etree.Element:
|
63
|
+
"""Create an XML element with optional CDATA and attributes."""
|
64
|
+
elem = etree.Element(tag, **attribs)
|
65
|
+
elem.text = etree.CDATA(str(value)) if value is not None else None
|
66
|
+
return elem
|
67
|
+
|
68
|
+
|
69
|
+
class XMLResultHandler:
|
70
|
+
"""Utility class for handling XML formatting and parsing."""
|
71
|
+
@staticmethod
|
72
|
+
def format_execution_result(result) -> str:
|
73
|
+
"""Format execution result as XML."""
|
74
|
+
root = etree.Element("ExecutionResult")
|
75
|
+
root.append(format_xml_element("Status", "Success" if not result.error else "Error"))
|
76
|
+
root.append(format_xml_element("Value", result.result or result.error))
|
77
|
+
root.append(format_xml_element("ExecutionTime", f"{result.execution_time:.2f} seconds"))
|
78
|
+
|
79
|
+
completed = result.result and result.result.startswith("Task completed:")
|
80
|
+
root.append(format_xml_element("Completed", str(completed).lower()))
|
81
|
+
|
82
|
+
if completed:
|
83
|
+
final_answer = result.result[len("Task completed:"):].strip()
|
84
|
+
root.append(format_xml_element("FinalAnswer", final_answer))
|
85
|
+
|
86
|
+
if result.local_variables:
|
87
|
+
vars_elem = etree.SubElement(root, "Variables")
|
88
|
+
for k, v in result.local_variables.items():
|
89
|
+
if not callable(v) and not k.startswith("__"):
|
90
|
+
vars_elem.append(format_xml_element("Variable", str(v)[:5000] +
|
91
|
+
("... (truncated)" if len(str(v)) > 5000 else ""),
|
92
|
+
name=k))
|
93
|
+
return etree.tostring(root, pretty_print=True, encoding="unicode")
|
94
|
+
|
95
|
+
@staticmethod
|
96
|
+
def format_result_summary(result_xml: str) -> str:
|
97
|
+
"""Format XML result into a readable summary."""
|
98
|
+
try:
|
99
|
+
root = etree.fromstring(result_xml)
|
100
|
+
lines = [
|
101
|
+
f"- Status: {root.findtext('Status', 'N/A')}",
|
102
|
+
f"- Value: {root.findtext('Value', 'N/A')}",
|
103
|
+
f"- Execution Time: {root.findtext('ExecutionTime', 'N/A')}",
|
104
|
+
f"- Completed: {root.findtext('Completed', 'N/A').capitalize()}"
|
105
|
+
]
|
106
|
+
if final_answer := root.findtext("FinalAnswer"):
|
107
|
+
lines.append(f"- Final Answer: {final_answer}")
|
108
|
+
|
109
|
+
if (vars_elem := root.find("Variables")) is not None:
|
110
|
+
lines.append("- Variables:")
|
111
|
+
lines.extend(f" - {var.get('name', 'unknown')}: {var.text.strip() or 'N/A'}"
|
112
|
+
for var in vars_elem.findall("Variable"))
|
113
|
+
return "\n".join(lines)
|
114
|
+
except etree.XMLSyntaxError:
|
115
|
+
logger.error(f"Failed to parse XML: {result_xml}")
|
116
|
+
return result_xml
|
117
|
+
|
118
|
+
@staticmethod
|
119
|
+
def parse_response(response: str) -> Tuple[str, str]:
|
120
|
+
"""Parse XML response to extract thought and code."""
|
121
|
+
try:
|
122
|
+
root = etree.fromstring(response)
|
123
|
+
thought = root.findtext("Thought") or ""
|
124
|
+
code = root.findtext("Code") or ""
|
125
|
+
return thought, code
|
126
|
+
except etree.XMLSyntaxError as e:
|
127
|
+
raise ValueError(f"Failed to parse XML: {e}")
|
128
|
+
|
129
|
+
@staticmethod
|
130
|
+
def extract_result_value(result: str) -> str:
|
131
|
+
"""Extract the value from the result XML."""
|
132
|
+
try:
|
133
|
+
return etree.fromstring(result).findtext("Value") or ""
|
134
|
+
except etree.XMLSyntaxError:
|
135
|
+
return ""
|
quantalogic/coding_agent.py
CHANGED
@@ -15,7 +15,7 @@ from quantalogic.tools import (
|
|
15
15
|
ReadHTMLTool,
|
16
16
|
ReplaceInFileTool,
|
17
17
|
RipgrepTool,
|
18
|
-
|
18
|
+
SearchDefinitionNamesTool,
|
19
19
|
TaskCompleteTool,
|
20
20
|
WriteFileTool,
|
21
21
|
)
|
@@ -71,7 +71,7 @@ def create_coding_agent(
|
|
71
71
|
# Code navigation and search tools
|
72
72
|
ListDirectoryTool(), # Lists directory contents
|
73
73
|
RipgrepTool(), # Searches code with regex
|
74
|
-
|
74
|
+
SearchDefinitionNamesTool(), # Finds code definitions
|
75
75
|
# Specialized language model tools
|
76
76
|
ReadFileTool(),
|
77
77
|
ExecuteBashCommandTool(),
|
@@ -10,11 +10,15 @@ from quantalogic.console_print_token import console_print_token
|
|
10
10
|
from quantalogic.event_emitter import EventEmitter
|
11
11
|
from quantalogic.tools.tool import Tool
|
12
12
|
|
13
|
-
# Configure loguru to output
|
13
|
+
# Configure loguru to output only INFO and above
|
14
14
|
logger.remove() # Remove default handler
|
15
|
-
logger.add(
|
16
|
-
|
15
|
+
logger.add(
|
16
|
+
sink=lambda msg: print(msg, end=""),
|
17
|
+
level="INFO",
|
18
|
+
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>"
|
19
|
+
)
|
17
20
|
|
21
|
+
# Helper function to import tool classes
|
18
22
|
def _import_tool(module_path: str, class_name: str) -> Type[Tool]:
|
19
23
|
"""
|
20
24
|
Import a tool class from a module path using standard Python imports.
|
@@ -78,6 +82,7 @@ TOOL_IMPORTS = {
|
|
78
82
|
# File Tools
|
79
83
|
"download_http_file": lambda: _import_tool("quantalogic.tools.utilities", "PrepareDownloadTool"),
|
80
84
|
"write_file": lambda: _import_tool("quantalogic.tools.write_file_tool", "WriteFileTool"),
|
85
|
+
"file_tracker": lambda: _import_tool("quantalogic.tools.file_tracker_tool", "FileTrackerTool"),
|
81
86
|
"edit_whole_content": lambda: _import_tool("quantalogic.tools", "EditWholeContentTool"),
|
82
87
|
"read_file_block": lambda: _import_tool("quantalogic.tools", "ReadFileBlockTool"),
|
83
88
|
"read_file": lambda: _import_tool("quantalogic.tools", "ReadFileTool"),
|
@@ -128,14 +133,15 @@ TOOL_IMPORTS = {
|
|
128
133
|
# Product Hunt Tools
|
129
134
|
"product_hunt_tool": lambda: _import_tool("quantalogic.tools.product_hunt", "ProductHuntTool"),
|
130
135
|
|
131
|
-
# RAG Tools
|
132
|
-
"
|
136
|
+
# RAG Tools
|
137
|
+
"rag_tool_hf": lambda: _import_tool("quantalogic.tools.rag_tool", "RagToolHf"),
|
133
138
|
|
134
139
|
# Utility Tools
|
135
140
|
"task_complete": lambda: _import_tool("quantalogic.tools.task_complete_tool", "TaskCompleteTool"),
|
136
141
|
"input_question": lambda: _import_tool("quantalogic.tools.utilities", "InputQuestionTool"),
|
137
142
|
"markitdown": lambda: _import_tool("quantalogic.tools.utilities", "MarkitdownTool"),
|
138
|
-
"read_html": lambda: _import_tool("quantalogic.tools.
|
143
|
+
"read_html": lambda: _import_tool("quantalogic.tools.read_html_tool", "ReadHTMLTool"),
|
144
|
+
"oriented_llm_tool": lambda: _import_tool("quantalogic.tools.utilities", "OrientedLLMTool"),
|
139
145
|
"presentation_llm": lambda: _import_tool("quantalogic.tools.presentation_tools", "PresentationLLMTool"),
|
140
146
|
"sequence": lambda: _import_tool("quantalogic.tools.utilities", "SequenceTool"),
|
141
147
|
"csv_processor": lambda: _import_tool("quantalogic.tools.utilities", "CSVProcessorTool"),
|
@@ -152,7 +158,8 @@ def create_custom_agent(
|
|
152
158
|
max_tokens_working_memory: Optional[int] = None,
|
153
159
|
specific_expertise: str = "",
|
154
160
|
tools: Optional[list[dict[str, Any]]] = None,
|
155
|
-
memory: Optional[AgentMemory] = None
|
161
|
+
memory: Optional[AgentMemory] = None,
|
162
|
+
agent_mode: str = "react"
|
156
163
|
) -> Agent:
|
157
164
|
"""Create an agent with lazy-loaded tools and graceful error handling.
|
158
165
|
|
@@ -169,6 +176,8 @@ def create_custom_agent(
|
|
169
176
|
Returns:
|
170
177
|
Agent: Configured agent instance
|
171
178
|
"""
|
179
|
+
logger.info("Creating custom agent with model: {}".format(model_name))
|
180
|
+
logger.info("tools: {}".format(tools))
|
172
181
|
# Create storage directory for RAG
|
173
182
|
storage_dir = os.path.join(os.path.dirname(__file__), "storage", "rag")
|
174
183
|
os.makedirs(storage_dir, exist_ok=True)
|
@@ -188,8 +197,9 @@ def create_custom_agent(
|
|
188
197
|
tool_configs = {
|
189
198
|
# LLM Tools with shared parameters
|
190
199
|
"llm": lambda params: create_tool_instance(TOOL_IMPORTS["llm"](), **get_llm_params(params)),
|
200
|
+
"oriented_llm_tool": lambda params: create_tool_instance(TOOL_IMPORTS["oriented_llm_tool"](), **get_llm_params(params)),
|
191
201
|
"llm_vision": lambda params: create_tool_instance(TOOL_IMPORTS["llm_vision"](),
|
192
|
-
model_name=params.get("vision_model_name") or
|
202
|
+
model_name=params.get("vision_model_name") or "gpt-4-vision",
|
193
203
|
on_token=console_print_token if not no_stream else None,
|
194
204
|
event_emitter=event_emitter
|
195
205
|
) if vision_model_name else None,
|
@@ -203,6 +213,7 @@ def create_custom_agent(
|
|
203
213
|
"download_http_file": lambda _: create_tool_instance(TOOL_IMPORTS["download_http_file"]()),
|
204
214
|
"duck_duck_go_search": lambda _: create_tool_instance(TOOL_IMPORTS["duck_duck_go_search"]()),
|
205
215
|
"write_file": lambda _: create_tool_instance(TOOL_IMPORTS["write_file"]()),
|
216
|
+
"file_tracker": lambda _: create_tool_instance(TOOL_IMPORTS["file_tracker"]()),
|
206
217
|
"task_complete": lambda _: create_tool_instance(TOOL_IMPORTS["task_complete"]()),
|
207
218
|
"edit_whole_content": lambda _: create_tool_instance(TOOL_IMPORTS["edit_whole_content"]()),
|
208
219
|
"execute_bash_command": lambda _: create_tool_instance(TOOL_IMPORTS["execute_bash_command"]()),
|
@@ -296,11 +307,12 @@ def create_custom_agent(
|
|
296
307
|
"nasa_apod_tool": lambda _: create_tool_instance(TOOL_IMPORTS["nasa_apod_tool"]()),
|
297
308
|
"product_hunt_tool": lambda _: create_tool_instance(TOOL_IMPORTS["product_hunt_tool"]()),
|
298
309
|
|
299
|
-
# RAG tool
|
300
|
-
"
|
301
|
-
|
302
|
-
|
303
|
-
|
310
|
+
# Multilingual RAG tool
|
311
|
+
"rag_tool_hf": lambda params: create_tool_instance(TOOL_IMPORTS["rag_tool_hf"](),
|
312
|
+
persist_dir=params.get("persist_dir", "./storage/multilingual_rag"),
|
313
|
+
use_ocr_for_pdfs=params.get("use_ocr_for_pdfs", False),
|
314
|
+
ocr_model=params.get("ocr_model", "openai/gpt-4o-mini"),
|
315
|
+
embed_model=params.get("embed_model", "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"),
|
304
316
|
document_paths=params.get("document_paths", [])
|
305
317
|
),
|
306
318
|
|
@@ -357,26 +369,6 @@ def create_custom_agent(
|
|
357
369
|
else:
|
358
370
|
logger.warning(f"Unknown tool type: {tool_type} - Skipping")
|
359
371
|
|
360
|
-
# Add download tool if any write tool is present
|
361
|
-
if has_write_tool:
|
362
|
-
try:
|
363
|
-
# Get the tool class first
|
364
|
-
download_tool_class = TOOL_IMPORTS["download_file_tool"]()
|
365
|
-
if download_tool_class:
|
366
|
-
# Create an instance with the name 'download'
|
367
|
-
download_tool = create_tool_instance(download_tool_class, name="download")
|
368
|
-
if download_tool:
|
369
|
-
agent_tools.append(download_tool)
|
370
|
-
logger.info("Added download tool automatically due to write tool presence")
|
371
|
-
else:
|
372
|
-
logger.warning("Failed to instantiate download tool")
|
373
|
-
else:
|
374
|
-
logger.warning("Download tool class not found")
|
375
|
-
except ImportError as e:
|
376
|
-
logger.warning(f"Failed to load download tool: Required library missing - {str(e)}")
|
377
|
-
except Exception as e:
|
378
|
-
logger.error(f"Failed to add download tool: {str(e)}")
|
379
|
-
|
380
372
|
|
381
373
|
# Create and return the agent
|
382
374
|
try:
|
@@ -388,52 +380,8 @@ def create_custom_agent(
|
|
388
380
|
max_tokens_working_memory=max_tokens_working_memory,
|
389
381
|
specific_expertise=specific_expertise,
|
390
382
|
memory=memory if memory else AgentMemory(),
|
383
|
+
agent_mode=agent_mode
|
391
384
|
)
|
392
385
|
except Exception as e:
|
393
386
|
logger.error(f"Failed to create agent: {str(e)}")
|
394
387
|
raise
|
395
|
-
|
396
|
-
if __name__ == "__main__":
|
397
|
-
# Example usage
|
398
|
-
tools_config = [
|
399
|
-
{"type": "duck_duck_go_search", "parameters": {}},
|
400
|
-
]
|
401
|
-
|
402
|
-
agent = create_custom_agent(
|
403
|
-
model_name="openrouter/openai/gpt-4o-mini",
|
404
|
-
specific_expertise="General purpose assistant",
|
405
|
-
tools=tools_config
|
406
|
-
)
|
407
|
-
print(f"Created agent with {len(agent.tools.tool_names())} tools")
|
408
|
-
|
409
|
-
# Display all tool names
|
410
|
-
print("Agent Tools:")
|
411
|
-
for tool_name in agent.tools.tool_names():
|
412
|
-
print(f"- {tool_name}")
|
413
|
-
|
414
|
-
# Set up event monitoring to track agent's lifecycle
|
415
|
-
# The event system provides:
|
416
|
-
# 1. Real-time observability into the agent's operations
|
417
|
-
# 2. Debugging and performance monitoring
|
418
|
-
# 3. Support for future analytics and optimization efforts
|
419
|
-
agent.event_emitter.on(
|
420
|
-
event=[
|
421
|
-
"task_complete",
|
422
|
-
"task_think_start",
|
423
|
-
"task_think_end",
|
424
|
-
"tool_execution_start",
|
425
|
-
"tool_execution_end",
|
426
|
-
"error_max_iterations_reached",
|
427
|
-
"memory_full",
|
428
|
-
"memory_compacted",
|
429
|
-
"memory_summary",
|
430
|
-
],
|
431
|
-
listener=console_print_events,
|
432
|
-
)
|
433
|
-
|
434
|
-
# Enable token streaming for detailed output
|
435
|
-
agent.event_emitter.on(event=["stream_chunk"], listener=console_print_token)
|
436
|
-
|
437
|
-
# Solve task with streaming enabled
|
438
|
-
result = agent.solve_task("Who is the Prime Minister of France in 2025 ?", max_iterations=10, streaming=True)
|
439
|
-
print(result)
|
@@ -22,13 +22,17 @@ Tools must be called using the following XML format, with NO additional text:
|
|
22
22
|
|
23
23
|
#### Examples of Correct Tool Usage
|
24
24
|
|
25
|
-
**Example 1 -
|
25
|
+
**Example 1 - Duck Duck Go search tool:**
|
26
26
|
```xml
|
27
27
|
<action>
|
28
|
-
<
|
29
|
-
<query>
|
30
|
-
<max_results>
|
31
|
-
</
|
28
|
+
<duckduckgosearch>
|
29
|
+
<query>machine learning</query>
|
30
|
+
<max_results>20</max_results>
|
31
|
+
<search_type>images</search_type>
|
32
|
+
<region>us-en</region>
|
33
|
+
<safesearch>moderate</safesearch>
|
34
|
+
<timelimit>d</timelimit>
|
35
|
+
</duckduckgosearch>
|
32
36
|
</action>
|
33
37
|
```
|
34
38
|
|
@@ -50,5 +54,4 @@ Tools must be called using the following XML format, with NO additional text:
|
|
50
54
|
**Tools Available**: None
|
51
55
|
{% endif %}
|
52
56
|
|
53
|
-
Don't invent tools that are not listed.
|
54
|
-
|
57
|
+
Don't invent tools that are not listed.
|
@@ -0,0 +1,190 @@
|
|
1
|
+
<agent_identity>
|
2
|
+
You are QuantaLogic, an expert ReAct AI Agent implementing the OODA (Observe-Orient-Decide-Act) loop for powerful, efficient problem-solving.
|
3
|
+
|
4
|
+
- Version: {{ version }}
|
5
|
+
- Expertise: {{ expertise }}
|
6
|
+
- Primary focus: Efficient task completion, robust planning, and adaptive execution
|
7
|
+
</agent_identity>
|
8
|
+
|
9
|
+
<language_settings>
|
10
|
+
- Default working language: English
|
11
|
+
- Use the language specified by the user in messages as the working language when explicitly provided
|
12
|
+
- All thinking and responses must be in the working language
|
13
|
+
- Natural language arguments in tool calls must be in the working language
|
14
|
+
- Avoid using pure lists and bullet points format in any language
|
15
|
+
</language_settings>
|
16
|
+
|
17
|
+
<agent_loop>
|
18
|
+
You are operating in an agent loop, iteratively completing tasks through the following structured steps:
|
19
|
+
|
20
|
+
1. **Initial Thinking Phase**:
|
21
|
+
- Conduct a comprehensive analysis upon receiving a new task
|
22
|
+
- Break down the task into logical steps and create an execution plan
|
23
|
+
- Save the plan in `plan.md` for reference throughout task execution
|
24
|
+
- Include contingencies, fallback actions, and adaptive methods in the plan
|
25
|
+
|
26
|
+
2. **Observe**:
|
27
|
+
- Gather essential data and contextual information when needed
|
28
|
+
- Reference the initial plan and identify any missing details
|
29
|
+
- Only perform additional observation steps if current data doesn't suffice
|
30
|
+
|
31
|
+
3. **Orient**:
|
32
|
+
- Refer to the existing plan and analyze the context briefly
|
33
|
+
- Avoid rethinking unless task objectives or external conditions change significantly
|
34
|
+
|
35
|
+
4. **Decide**:
|
36
|
+
- Select the most appropriate action based on the current step in the plan
|
37
|
+
- Focus decisions on task objectives while minimizing unnecessary interventions
|
38
|
+
|
39
|
+
5. **Act**:
|
40
|
+
- Execute the decided action efficiently using tools
|
41
|
+
- Always update progress markers in the plan after completing a step
|
42
|
+
|
43
|
+
6. **Reflect**:
|
44
|
+
- Evaluate action results against the plan
|
45
|
+
- Adjust the plan only if a significant deviation or new information arises
|
46
|
+
|
47
|
+
7. **Iterate**:
|
48
|
+
- Loop through Observe, Orient, Decide, and Act phases
|
49
|
+
- Ensure one tool call per iteration, avoiding multiple simultaneous operations
|
50
|
+
|
51
|
+
8. **Completion**:
|
52
|
+
- Submit results to the user via messages, attaching all relevant deliverables
|
53
|
+
- Enter standby mode when tasks are fully completed, waiting for new instructions
|
54
|
+
</agent_loop>
|
55
|
+
|
56
|
+
<cognitive_framework>
|
57
|
+
Implement the OODA loop for problem-solving:
|
58
|
+
1. 🔍 **OBSERVE**: Collect essential data if needed
|
59
|
+
2. 🧭 **ORIENT**: Analyze context briefly, referring to the task plan
|
60
|
+
3. 🎯 **DECIDE**: Choose the most effective action from the plan
|
61
|
+
4. ⚡ **ACT**: Perform precise operations aligned with the task plan
|
62
|
+
5. 🔄 **REFLECT**: Evaluate results and adjust the plan only if necessary
|
63
|
+
6. ✅ **ADAPT**: Minimize thinking during execution unless conditions demand reevaluation
|
64
|
+
</cognitive_framework>
|
65
|
+
|
66
|
+
<planner_module>
|
67
|
+
- Create an initial detailed execution plan (task decomposition, contingencies, metrics) upon receiving a task
|
68
|
+
- Provide plans as numbered pseudocode, detailing execution steps
|
69
|
+
- Include current step number, status, and rationales in planning updates
|
70
|
+
- Save the plan as `plan.md`, updating only when the task objective or conditions change significantly
|
71
|
+
- Ensure completion of all planned steps, reaching the task's final objective without unnecessary interruptions
|
72
|
+
</planner_module>
|
73
|
+
|
74
|
+
<knowledge_module>
|
75
|
+
- Use the knowledge and memory module to access best practices, task-relevant knowledge, and references
|
76
|
+
- Apply relevant knowledge during initial planning and action execution, continuously updating based on outcomes
|
77
|
+
- Avoid redundant queries; leverage stored knowledge to enhance efficiency
|
78
|
+
</knowledge_module>
|
79
|
+
|
80
|
+
<response_schema>
|
81
|
+
Mandatory three-block format:
|
82
|
+
|
83
|
+
1. 🧠 **Analysis Block** (only when new thinking is needed):
|
84
|
+
<thinking>
|
85
|
+
<!-- Concise cognitive processing using draft, emojis, and symbols -->
|
86
|
+
<context_analysis when="no_history">
|
87
|
+
• 📋 Task Decomposition: Key steps and dependencies
|
88
|
+
• 🎯 Success Metrics: Quantifiable outcomes
|
89
|
+
• 🛠️ Resources: Tools, data, variables
|
90
|
+
• ⚠️ Risks: Potential failures, mitigation strategies
|
91
|
+
</context_analysis>
|
92
|
+
|
93
|
+
<execution_analysis>
|
94
|
+
• 🔄 Last Operation: Result, impact
|
95
|
+
• 📊 Progress: Completed%, remaining%
|
96
|
+
• 💾 Variables: $var: brief content
|
97
|
+
• 📈 Metrics: Speed, quality, resource use
|
98
|
+
</execution_analysis>
|
99
|
+
|
100
|
+
<decision_matrix>
|
101
|
+
• 🎯 Next Action: Tool + rationale
|
102
|
+
• 📥 Parameters: Values + $var$
|
103
|
+
• 🔄 Fallback: Alternative approach
|
104
|
+
• ✅ Exit Criteria: Completion conditions
|
105
|
+
</decision_matrix>
|
106
|
+
</thinking>
|
107
|
+
|
108
|
+
2. 📊 **Plan Status Block** (default; includes updates only as needed):
|
109
|
+
<plan_status>
|
110
|
+
• 📈 Progress: Step X of Y completed
|
111
|
+
• 🔄 Plan Updates: Modifications to the original plan
|
112
|
+
• 🎯 Next Step: Upcoming action
|
113
|
+
</plan_status>
|
114
|
+
|
115
|
+
3. ⚡ **Action Block**:
|
116
|
+
<action>
|
117
|
+
<tool_name>
|
118
|
+
<param1>value1</param1>
|
119
|
+
<param2>value2</param2>
|
120
|
+
</tool_name>
|
121
|
+
</action>
|
122
|
+
</response_schema>
|
123
|
+
|
124
|
+
<execution_guidelines>
|
125
|
+
1. Prioritize achieving task objectives through data-driven decisions
|
126
|
+
2. Create a robust initial task plan to minimize unnecessary iterations
|
127
|
+
3. Optimize execution using feedback loops and adapt only as needed
|
128
|
+
4. Validate each action's impact and maximize efficiency
|
129
|
+
5. Focus on delivering complete, usable, high-quality results
|
130
|
+
</execution_guidelines>
|
131
|
+
|
132
|
+
<todo_rules>
|
133
|
+
- Create and maintain `todo.md` as a checklist based on the task planning
|
134
|
+
- Update progress markers in `todo.md` after completing each step
|
135
|
+
- Rebuild `todo.md` when the task objective or plan changes significantly
|
136
|
+
- Use it to track and ensure progress, verifying its completion at task end
|
137
|
+
</todo_rules>
|
138
|
+
|
139
|
+
<info_rules>
|
140
|
+
- Prioritize information sources: authoritative data > web search > internal knowledge
|
141
|
+
- Use dedicated tools for information gathering, avoiding redundant searches
|
142
|
+
- Access multiple sources for cross-validation and deeper insights
|
143
|
+
- Conduct searches systematically, processing entities or attributes step by step
|
144
|
+
</info_rules>
|
145
|
+
|
146
|
+
<file_rules>
|
147
|
+
- Save intermediate results and organize information systematically in separate files
|
148
|
+
- Use append mode for merging text files; ensure content continuity and format consistency
|
149
|
+
- Maintain strict version control and follow writing rules for all saved content
|
150
|
+
</file_rules>
|
151
|
+
|
152
|
+
<writing_rules>
|
153
|
+
- Write in engaging prose using varied sentence structures, avoiding lists unless explicitly requested
|
154
|
+
- Provide detailed, comprehensive writing based on user requirements
|
155
|
+
- Cite references actively, including URLs and source documentation
|
156
|
+
- For lengthy documents, save sections individually before appending into a final compilation
|
157
|
+
</writing_rules>
|
158
|
+
|
159
|
+
<message_rules>
|
160
|
+
- Communicate with users via messages, avoiding direct text responses
|
161
|
+
- Notify users immediately of task updates, ensuring clarity in deliverables
|
162
|
+
- Provide all relevant files as attachments, ensuring accessibility for users
|
163
|
+
- Use messaging tools strategically to minimize interruptions
|
164
|
+
</message_rules>
|
165
|
+
|
166
|
+
<error_handling>
|
167
|
+
- Proactively resolve tool-related issues using error messages and alternative methods
|
168
|
+
- Report failure reasons to users if multiple approaches fail
|
169
|
+
- Ensure reliability and adapt quickly to blockers
|
170
|
+
</error_handling>
|
171
|
+
|
172
|
+
<tool_use_rules>
|
173
|
+
- Respond only via tool use (function calling), avoiding plain text responses
|
174
|
+
- Verify tool availability and functionality explicitly; avoid fabricating non-existent tools
|
175
|
+
- Ensure all tool calls align with the task plan and goals
|
176
|
+
</tool_use_rules>
|
177
|
+
|
178
|
+
Operational Parameters:
|
179
|
+
- 🛠️ Tools: {{ tools }}
|
180
|
+
- 🌐 Environment: {{ environment }}
|
181
|
+
|
182
|
+
Input Protocol:
|
183
|
+
Task Format: <task>task_description</task>
|
184
|
+
|
185
|
+
Completion Format:
|
186
|
+
<action>
|
187
|
+
<task_complete>
|
188
|
+
<r>$final_output$</r>
|
189
|
+
</task_complete>
|
190
|
+
</action>
|