quantalogic 0.35.0__py3-none-any.whl → 0.50.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/__init__.py +0 -4
- quantalogic/agent.py +603 -363
- quantalogic/agent_config.py +233 -46
- quantalogic/agent_factory.py +34 -22
- quantalogic/coding_agent.py +16 -14
- quantalogic/config.py +2 -1
- quantalogic/console_print_events.py +4 -8
- quantalogic/console_print_token.py +2 -2
- quantalogic/docs_cli.py +15 -10
- quantalogic/event_emitter.py +258 -83
- quantalogic/flow/__init__.py +23 -0
- quantalogic/flow/flow.py +595 -0
- quantalogic/flow/flow_extractor.py +672 -0
- quantalogic/flow/flow_generator.py +89 -0
- quantalogic/flow/flow_manager.py +407 -0
- quantalogic/flow/flow_manager_schema.py +169 -0
- quantalogic/flow/flow_yaml.md +419 -0
- quantalogic/generative_model.py +109 -77
- quantalogic/get_model_info.py +5 -5
- quantalogic/interactive_text_editor.py +100 -73
- quantalogic/main.py +17 -21
- quantalogic/model_info_list.py +3 -3
- quantalogic/model_info_litellm.py +14 -14
- quantalogic/prompts.py +2 -1
- quantalogic/{llm.py → quantlitellm.py} +29 -39
- quantalogic/search_agent.py +4 -4
- quantalogic/server/models.py +4 -1
- quantalogic/task_file_reader.py +5 -5
- quantalogic/task_runner.py +20 -20
- quantalogic/tool_manager.py +10 -21
- quantalogic/tools/__init__.py +98 -68
- quantalogic/tools/composio/composio.py +416 -0
- quantalogic/tools/{generate_database_report_tool.py → database/generate_database_report_tool.py} +4 -9
- quantalogic/tools/database/sql_query_tool_advanced.py +261 -0
- quantalogic/tools/document_tools/markdown_to_docx_tool.py +620 -0
- quantalogic/tools/document_tools/markdown_to_epub_tool.py +438 -0
- quantalogic/tools/document_tools/markdown_to_html_tool.py +362 -0
- quantalogic/tools/document_tools/markdown_to_ipynb_tool.py +319 -0
- quantalogic/tools/document_tools/markdown_to_latex_tool.py +420 -0
- quantalogic/tools/document_tools/markdown_to_pdf_tool.py +623 -0
- quantalogic/tools/document_tools/markdown_to_pptx_tool.py +319 -0
- quantalogic/tools/duckduckgo_search_tool.py +2 -4
- quantalogic/tools/finance/alpha_vantage_tool.py +440 -0
- quantalogic/tools/finance/ccxt_tool.py +373 -0
- quantalogic/tools/finance/finance_llm_tool.py +387 -0
- quantalogic/tools/finance/google_finance.py +192 -0
- quantalogic/tools/finance/market_intelligence_tool.py +520 -0
- quantalogic/tools/finance/technical_analysis_tool.py +491 -0
- quantalogic/tools/finance/tradingview_tool.py +336 -0
- quantalogic/tools/finance/yahoo_finance.py +236 -0
- quantalogic/tools/git/bitbucket_clone_repo_tool.py +181 -0
- quantalogic/tools/git/bitbucket_operations_tool.py +326 -0
- quantalogic/tools/git/clone_repo_tool.py +189 -0
- quantalogic/tools/git/git_operations_tool.py +532 -0
- quantalogic/tools/google_packages/google_news_tool.py +480 -0
- quantalogic/tools/grep_app_tool.py +123 -186
- quantalogic/tools/{dalle_e.py → image_generation/dalle_e.py} +37 -27
- quantalogic/tools/jinja_tool.py +6 -10
- quantalogic/tools/language_handlers/__init__.py +22 -9
- quantalogic/tools/list_directory_tool.py +131 -42
- quantalogic/tools/llm_tool.py +45 -15
- quantalogic/tools/llm_vision_tool.py +59 -7
- quantalogic/tools/markitdown_tool.py +17 -5
- quantalogic/tools/nasa_packages/models.py +47 -0
- quantalogic/tools/nasa_packages/nasa_apod_tool.py +232 -0
- quantalogic/tools/nasa_packages/nasa_neows_tool.py +147 -0
- quantalogic/tools/nasa_packages/services.py +82 -0
- quantalogic/tools/presentation_tools/presentation_llm_tool.py +396 -0
- quantalogic/tools/product_hunt/product_hunt_tool.py +258 -0
- quantalogic/tools/product_hunt/services.py +63 -0
- quantalogic/tools/rag_tool/__init__.py +48 -0
- quantalogic/tools/rag_tool/document_metadata.py +15 -0
- quantalogic/tools/rag_tool/query_response.py +20 -0
- quantalogic/tools/rag_tool/rag_tool.py +566 -0
- quantalogic/tools/rag_tool/rag_tool_beta.py +264 -0
- quantalogic/tools/read_html_tool.py +24 -38
- quantalogic/tools/replace_in_file_tool.py +10 -10
- quantalogic/tools/safe_python_interpreter_tool.py +10 -24
- quantalogic/tools/search_definition_names.py +2 -2
- quantalogic/tools/sequence_tool.py +14 -23
- quantalogic/tools/sql_query_tool.py +17 -19
- quantalogic/tools/tool.py +39 -15
- quantalogic/tools/unified_diff_tool.py +1 -1
- quantalogic/tools/utilities/csv_processor_tool.py +234 -0
- quantalogic/tools/utilities/download_file_tool.py +179 -0
- quantalogic/tools/utilities/mermaid_validator_tool.py +661 -0
- quantalogic/tools/utils/__init__.py +1 -4
- quantalogic/tools/utils/create_sample_database.py +24 -38
- quantalogic/tools/utils/generate_database_report.py +74 -82
- quantalogic/tools/wikipedia_search_tool.py +17 -21
- quantalogic/utils/ask_user_validation.py +1 -1
- quantalogic/utils/async_utils.py +35 -0
- quantalogic/utils/check_version.py +3 -5
- quantalogic/utils/get_all_models.py +2 -1
- quantalogic/utils/git_ls.py +21 -7
- quantalogic/utils/lm_studio_model_info.py +9 -7
- quantalogic/utils/python_interpreter.py +113 -43
- quantalogic/utils/xml_utility.py +178 -0
- quantalogic/version_check.py +1 -1
- quantalogic/welcome_message.py +7 -7
- quantalogic/xml_parser.py +0 -1
- {quantalogic-0.35.0.dist-info → quantalogic-0.50.0.dist-info}/METADATA +40 -1
- quantalogic-0.50.0.dist-info/RECORD +148 -0
- quantalogic-0.35.0.dist-info/RECORD +0 -102
- {quantalogic-0.35.0.dist-info → quantalogic-0.50.0.dist-info}/LICENSE +0 -0
- {quantalogic-0.35.0.dist-info → quantalogic-0.50.0.dist-info}/WHEEL +0 -0
- {quantalogic-0.35.0.dist-info → quantalogic-0.50.0.dist-info}/entry_points.txt +0 -0
quantalogic/agent_config.py
CHANGED
@@ -3,24 +3,51 @@
|
|
3
3
|
# Standard library imports
|
4
4
|
|
5
5
|
# Local application imports
|
6
|
+
import logging
|
7
|
+
import os
|
8
|
+
from typing import Any
|
9
|
+
|
6
10
|
from dotenv import load_dotenv
|
7
11
|
|
8
12
|
from quantalogic.agent import Agent
|
9
13
|
from quantalogic.console_print_token import console_print_token
|
14
|
+
from quantalogic.event_emitter import EventEmitter
|
15
|
+
from quantalogic.memory import AgentMemory
|
10
16
|
from quantalogic.tools import (
|
11
17
|
AgentTool,
|
18
|
+
BitbucketCloneTool,
|
19
|
+
BitbucketOperationsTool,
|
20
|
+
CloneRepoTool,
|
21
|
+
ComposioTool,
|
22
|
+
CSVProcessorTool,
|
12
23
|
DownloadHttpFileTool,
|
13
24
|
DuckDuckGoSearchTool,
|
14
25
|
EditWholeContentTool,
|
15
26
|
ExecuteBashCommandTool,
|
27
|
+
GitOperationsTool,
|
28
|
+
GoogleNewsTool,
|
16
29
|
InputQuestionTool,
|
17
30
|
ListDirectoryTool,
|
18
31
|
LLMImageGenerationTool,
|
19
32
|
LLMTool,
|
20
33
|
LLMVisionTool,
|
34
|
+
MarkdownToDocxTool,
|
35
|
+
MarkdownToEpubTool,
|
36
|
+
MarkdownToHtmlTool,
|
37
|
+
MarkdownToIpynbTool,
|
38
|
+
MarkdownToLatexTool,
|
39
|
+
MarkdownToPdfTool,
|
40
|
+
MarkdownToPptxTool,
|
21
41
|
MarkitdownTool,
|
42
|
+
MermaidValidatorTool,
|
43
|
+
NasaApodTool,
|
44
|
+
NasaNeoWsTool,
|
22
45
|
NodeJsTool,
|
46
|
+
PrepareDownloadTool,
|
47
|
+
PresentationLLMTool,
|
48
|
+
ProductHuntTool,
|
23
49
|
PythonTool,
|
50
|
+
RagTool,
|
24
51
|
ReadFileBlockTool,
|
25
52
|
ReadFileTool,
|
26
53
|
ReadHTMLTool,
|
@@ -28,6 +55,9 @@ from quantalogic.tools import (
|
|
28
55
|
RipgrepTool,
|
29
56
|
SafePythonInterpreterTool,
|
30
57
|
SearchDefinitionNames,
|
58
|
+
SequenceTool,
|
59
|
+
SQLQueryTool,
|
60
|
+
SQLQueryToolAdvanced,
|
31
61
|
TaskCompleteTool,
|
32
62
|
WikipediaSearchTool,
|
33
63
|
WriteFileTool,
|
@@ -37,21 +67,24 @@ load_dotenv()
|
|
37
67
|
|
38
68
|
MODEL_NAME = "deepseek/deepseek-chat"
|
39
69
|
|
70
|
+
logger = logging.getLogger(__name__)
|
40
71
|
|
41
72
|
_current_model_name: str = ""
|
42
73
|
|
74
|
+
|
43
75
|
def get_current_model() -> str:
|
44
76
|
"""Retrieve the currently active model name."""
|
45
77
|
if not _current_model_name:
|
46
78
|
raise ValueError("No model initialized")
|
47
79
|
return _current_model_name
|
48
80
|
|
81
|
+
|
49
82
|
def create_agent(
|
50
|
-
model_name: str,
|
51
|
-
vision_model_name: str | None,
|
52
|
-
no_stream: bool = False,
|
83
|
+
model_name: str,
|
84
|
+
vision_model_name: str | None,
|
85
|
+
no_stream: bool = False,
|
53
86
|
compact_every_n_iteration: int | None = None,
|
54
|
-
max_tokens_working_memory: int | None = None
|
87
|
+
max_tokens_working_memory: int | None = None,
|
55
88
|
) -> Agent:
|
56
89
|
global _current_model_name
|
57
90
|
_current_model_name = model_name
|
@@ -81,18 +114,18 @@ def create_agent(
|
|
81
114
|
SearchDefinitionNames(),
|
82
115
|
MarkitdownTool(),
|
83
116
|
LLMTool(model_name=model_name, on_token=console_print_token if not no_stream else None),
|
84
|
-
DownloadHttpFileTool(),
|
117
|
+
DownloadHttpFileTool(),
|
85
118
|
LLMImageGenerationTool(
|
86
|
-
|
87
|
-
|
88
|
-
on_token=console_print_token if not no_stream else None
|
89
|
-
),
|
119
|
+
provider="dall-e", model_name="openai/dall-e-3", on_token=console_print_token if not no_stream else None
|
120
|
+
),
|
90
121
|
ReadHTMLTool(),
|
91
122
|
# SafePythonInterpreterTool(allowed_modules=["math", "numpy"])
|
92
123
|
]
|
93
124
|
|
94
125
|
if vision_model_name:
|
95
|
-
tools.append(
|
126
|
+
tools.append(
|
127
|
+
LLMVisionTool(model_name=vision_model_name, on_token=console_print_token if not no_stream else None)
|
128
|
+
)
|
96
129
|
|
97
130
|
return Agent(
|
98
131
|
model_name=model_name,
|
@@ -103,11 +136,11 @@ def create_agent(
|
|
103
136
|
|
104
137
|
|
105
138
|
def create_interpreter_agent(
|
106
|
-
model_name: str,
|
107
|
-
vision_model_name: str | None,
|
108
|
-
no_stream: bool = False,
|
139
|
+
model_name: str,
|
140
|
+
vision_model_name: str | None,
|
141
|
+
no_stream: bool = False,
|
109
142
|
compact_every_n_iteration: int | None = None,
|
110
|
-
max_tokens_working_memory: int | None = None
|
143
|
+
max_tokens_working_memory: int | None = None,
|
111
144
|
) -> Agent:
|
112
145
|
"""Create an interpreter agent with the specified model and tools.
|
113
146
|
|
@@ -141,7 +174,7 @@ def create_interpreter_agent(
|
|
141
174
|
ReadHTMLTool(),
|
142
175
|
]
|
143
176
|
return Agent(
|
144
|
-
model_name=model_name,
|
177
|
+
model_name=model_name,
|
145
178
|
tools=tools,
|
146
179
|
compact_every_n_iterations=compact_every_n_iteration,
|
147
180
|
max_tokens_working_memory=max_tokens_working_memory,
|
@@ -149,11 +182,11 @@ def create_interpreter_agent(
|
|
149
182
|
|
150
183
|
|
151
184
|
def create_full_agent(
|
152
|
-
model_name: str,
|
153
|
-
vision_model_name: str | None,
|
154
|
-
no_stream: bool = False,
|
185
|
+
model_name: str,
|
186
|
+
vision_model_name: str | None,
|
187
|
+
no_stream: bool = False,
|
155
188
|
compact_every_n_iteration: int | None = None,
|
156
|
-
max_tokens_working_memory: int | None = None
|
189
|
+
max_tokens_working_memory: int | None = None,
|
157
190
|
) -> Agent:
|
158
191
|
"""Create an agent with the specified model and many tools.
|
159
192
|
|
@@ -188,11 +221,13 @@ def create_full_agent(
|
|
188
221
|
WikipediaSearchTool(),
|
189
222
|
DuckDuckGoSearchTool(),
|
190
223
|
ReadHTMLTool(),
|
191
|
-
|
224
|
+
# SafePythonInterpreterTool(allowed_modules=["math", "numpy"])
|
192
225
|
]
|
193
226
|
|
194
227
|
if vision_model_name:
|
195
|
-
tools.append(
|
228
|
+
tools.append(
|
229
|
+
LLMVisionTool(model_name=vision_model_name, on_token=console_print_token if not no_stream else None)
|
230
|
+
)
|
196
231
|
|
197
232
|
return Agent(
|
198
233
|
model_name=model_name,
|
@@ -203,11 +238,11 @@ def create_full_agent(
|
|
203
238
|
|
204
239
|
|
205
240
|
def create_basic_agent(
|
206
|
-
model_name: str,
|
207
|
-
vision_model_name: str | None = None,
|
208
|
-
no_stream: bool = False,
|
241
|
+
model_name: str,
|
242
|
+
vision_model_name: str | None = None,
|
243
|
+
no_stream: bool = False,
|
209
244
|
compact_every_n_iteration: int | None = None,
|
210
|
-
max_tokens_working_memory: int | None = None
|
245
|
+
max_tokens_working_memory: int | None = None,
|
211
246
|
) -> Agent:
|
212
247
|
"""Create an agent with the specified model and tools.
|
213
248
|
|
@@ -224,7 +259,6 @@ def create_basic_agent(
|
|
224
259
|
# Rebuild AgentTool to resolve forward references
|
225
260
|
AgentTool.model_rebuild()
|
226
261
|
|
227
|
-
|
228
262
|
tools = [
|
229
263
|
TaskCompleteTool(),
|
230
264
|
ListDirectoryTool(),
|
@@ -239,11 +273,13 @@ def create_basic_agent(
|
|
239
273
|
ExecuteBashCommandTool(),
|
240
274
|
LLMTool(model_name=model_name, on_token=console_print_token if not no_stream else None),
|
241
275
|
ReadHTMLTool(),
|
242
|
-
|
276
|
+
# SafePythonInterpreterTool(allowed_modules=["math", "numpy"])
|
243
277
|
]
|
244
278
|
|
245
279
|
if vision_model_name:
|
246
|
-
tools.append(
|
280
|
+
tools.append(
|
281
|
+
LLMVisionTool(model_name=vision_model_name, on_token=console_print_token if not no_stream else None)
|
282
|
+
)
|
247
283
|
|
248
284
|
return Agent(
|
249
285
|
model_name=model_name,
|
@@ -252,12 +288,16 @@ def create_basic_agent(
|
|
252
288
|
max_tokens_working_memory=max_tokens_working_memory,
|
253
289
|
)
|
254
290
|
|
255
|
-
|
291
|
+
|
292
|
+
def create_custom_agent(
|
256
293
|
model_name: str,
|
257
294
|
vision_model_name: str | None = None,
|
258
295
|
no_stream: bool = False,
|
259
296
|
compact_every_n_iteration: int | None = None,
|
260
|
-
max_tokens_working_memory: int | None = None
|
297
|
+
max_tokens_working_memory: int | None = None,
|
298
|
+
specific_expertise: str = "",
|
299
|
+
tools: list[Any] | None = None,
|
300
|
+
memory: AgentMemory | None = None
|
261
301
|
) -> Agent:
|
262
302
|
"""Create an agent with the specified model and tools.
|
263
303
|
|
@@ -267,32 +307,179 @@ def create_minimal_agent(
|
|
267
307
|
no_stream (bool, optional): If True, the agent will not stream results.
|
268
308
|
compact_every_n_iteration (int | None, optional): Frequency of memory compaction.
|
269
309
|
max_tokens_working_memory (int | None, optional): Maximum tokens for working memory.
|
310
|
+
specific_expertise (str, optional): Specific expertise of the agent.
|
311
|
+
tools (list[Any], optional): List of tool configurations to add to the agent.
|
312
|
+
Each tool config should have:
|
313
|
+
- type: str - The type of tool
|
314
|
+
- parameters: dict - The parameters required for the tool
|
315
|
+
memory (AgentMemory, optional): Memory object to use for the agent.
|
270
316
|
|
271
317
|
Returns:
|
272
318
|
Agent: An agent with the specified model and tools
|
273
319
|
"""
|
320
|
+
storage_dir = os.path.join(os.path.dirname(__file__), "storage", "rag")
|
321
|
+
os.makedirs(storage_dir, exist_ok=True)
|
322
|
+
|
274
323
|
# Rebuild AgentTool to resolve forward references
|
275
324
|
AgentTool.model_rebuild()
|
276
325
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
326
|
+
# Create event emitter
|
327
|
+
event_emitter = EventEmitter()
|
328
|
+
|
329
|
+
# Define tool mapping with their parameter requirements
|
330
|
+
tool_mapping = {
|
331
|
+
"llm": lambda params: LLMTool(
|
332
|
+
model_name=params.get("model_name", model_name),
|
333
|
+
on_token=console_print_token if not no_stream else None,
|
334
|
+
event_emitter=event_emitter
|
335
|
+
),
|
336
|
+
"llm_vision": lambda params: LLMVisionTool(
|
337
|
+
model_name=params.get("vision_model_name") or vision_model_name,
|
338
|
+
on_token=console_print_token if not no_stream else None,
|
339
|
+
event_emitter=event_emitter
|
340
|
+
),
|
341
|
+
"llm_image_generation": lambda params: LLMImageGenerationTool(
|
342
|
+
# provider=params.get("provider", "dall-e"),
|
343
|
+
provider="dall-e",
|
344
|
+
# model_name=params.get("model_name", "openai/dall-e-3"),
|
345
|
+
model_name="openai/dall-e-3",
|
346
|
+
on_token=console_print_token if not no_stream else None,
|
347
|
+
# event_emitter=event_emitter
|
348
|
+
),
|
349
|
+
"download_http_file": lambda params: DownloadHttpFileTool(),
|
350
|
+
"duck_duck_go_search": lambda params: DuckDuckGoSearchTool(),
|
351
|
+
"edit_whole_content": lambda params: EditWholeContentTool(),
|
352
|
+
"execute_bash_command": lambda params: ExecuteBashCommandTool(),
|
353
|
+
"input_question": lambda params: InputQuestionTool(),
|
354
|
+
"list_directory": lambda params: ListDirectoryTool(),
|
355
|
+
"markitdown": lambda params: MarkitdownTool(),
|
356
|
+
"nodejs": lambda params: NodeJsTool(),
|
357
|
+
"python": lambda params: PythonTool(),
|
358
|
+
"read_file_block": lambda params: ReadFileBlockTool(),
|
359
|
+
"read_file": lambda params: ReadFileTool(),
|
360
|
+
"read_html": lambda params: ReadHTMLTool(),
|
361
|
+
"replace_in_file": lambda params: ReplaceInFileTool(),
|
362
|
+
"ripgrep": lambda params: RipgrepTool(),
|
363
|
+
"safe_python_interpreter": lambda params: SafePythonInterpreterTool(),
|
364
|
+
"search_definition_names": lambda params: SearchDefinitionNames(),
|
365
|
+
"wikipedia_search": lambda params: WikipediaSearchTool(),
|
366
|
+
"write_file": lambda params: WriteFileTool(),
|
367
|
+
"google_news": lambda params: GoogleNewsTool(
|
368
|
+
# model_name=params.get("model_name", model_name),
|
369
|
+
# on_token=console_print_token if not no_stream else None,
|
370
|
+
# event_emitter=event_emitter
|
371
|
+
),
|
372
|
+
"presentation_llm": lambda params: PresentationLLMTool(
|
373
|
+
model_name=params.get("model_name", model_name),
|
374
|
+
additional_info=params.get("additional_info", ""),
|
375
|
+
on_token=console_print_token if not no_stream else None,
|
376
|
+
event_emitter=event_emitter
|
377
|
+
),
|
378
|
+
"sequence": lambda params: SequenceTool(
|
379
|
+
model_name=params.get("model_name", model_name),
|
380
|
+
on_token=console_print_token if not no_stream else None,
|
381
|
+
# event_emitter=event_emitter
|
382
|
+
),
|
383
|
+
"sql_query": lambda params: SQLQueryTool(
|
384
|
+
connection_string=params.get("connection_string", ""),
|
385
|
+
model_name=params.get("model_name", model_name),
|
386
|
+
on_token=console_print_token if not no_stream else None,
|
387
|
+
# event_emitter=event_emitter
|
388
|
+
),
|
389
|
+
"sql_query_advanced": lambda params: SQLQueryToolAdvanced(
|
390
|
+
connection_string=params.get("connection_string", ""),
|
391
|
+
model_name=params.get("model_name", model_name),
|
392
|
+
on_token=console_print_token if not no_stream else None,
|
393
|
+
# event_emitter=event_emitter
|
394
|
+
),
|
395
|
+
"clone_repo_tool": lambda params: CloneRepoTool(auth_token=params.get("auth_token", "")),
|
396
|
+
"bitbucket_clone_repo_tool": lambda params: BitbucketCloneTool(access_token=params.get("access_token", "")),
|
397
|
+
"bitbucket_operations_tool": lambda params: BitbucketOperationsTool(access_token=params.get("access_token", "")),
|
398
|
+
"git_operations_tool": lambda params: GitOperationsTool(auth_token=params.get("auth_token", "")),
|
399
|
+
"markdown_to_pdf": lambda params: MarkdownToPdfTool(),
|
400
|
+
"markdown_to_pptx": lambda params: MarkdownToPptxTool(),
|
401
|
+
"markdown_to_html": lambda params: MarkdownToHtmlTool(),
|
402
|
+
"markdown_to_epub": lambda params: MarkdownToEpubTool(),
|
403
|
+
"markdown_to_ipynb": lambda params: MarkdownToIpynbTool(),
|
404
|
+
"markdown_to_latex": lambda params: MarkdownToLatexTool(),
|
405
|
+
"markdown_to_docx": lambda params: MarkdownToDocxTool(),
|
406
|
+
"csv_processor": lambda params: CSVProcessorTool(),
|
407
|
+
"mermaid_validator_tool": lambda params: MermaidValidatorTool(),
|
408
|
+
"download_file_tool": lambda params: PrepareDownloadTool(),
|
409
|
+
"email_tool": lambda params: ComposioTool(
|
410
|
+
action="GMAIL_SEND_EMAIL",
|
411
|
+
name="email_tool",
|
412
|
+
description="Send emails via Gmail",
|
413
|
+
need_validation=False
|
414
|
+
),
|
415
|
+
"callendar_tool": lambda params: ComposioTool(
|
416
|
+
action="GOOGLECALENDAR_CREATE_EVENT",
|
417
|
+
name="callendar_tool",
|
418
|
+
description="Create events in Google Calendar",
|
419
|
+
need_validation=False
|
420
|
+
),
|
421
|
+
"weather_tool": lambda params: ComposioTool(
|
422
|
+
action="WEATHERMAP_WEATHER",
|
423
|
+
name="weather_tool",
|
424
|
+
description="Get weather information for a location"
|
425
|
+
),
|
426
|
+
"nasa_neows_tool": lambda params: NasaNeoWsTool(),
|
427
|
+
"nasa_apod_tool": lambda params: NasaApodTool(),
|
428
|
+
"product_hunt_tool": lambda params : ProductHuntTool(),
|
429
|
+
"rag_tool": lambda params: RagTool(
|
430
|
+
vector_store=params.get("vector_store", "chroma"),
|
431
|
+
embedding_model=params.get("embedding_model", "openai"),
|
432
|
+
persist_dir=storage_dir,
|
433
|
+
document_paths=params.get("document_paths", [])
|
434
|
+
)
|
435
|
+
}
|
436
|
+
|
437
|
+
# Define write tools that should trigger automatic download tool addition
|
438
|
+
write_tools = {"write_file", "edit_whole_content", "replace_in_file"}
|
439
|
+
|
440
|
+
agent_tools = []
|
441
|
+
has_write_tool = any(
|
442
|
+
tool_config.get("type") in write_tools
|
443
|
+
for tool_config in (tools or [])
|
444
|
+
)
|
292
445
|
|
446
|
+
# Add tools only if they are provided
|
447
|
+
if tools:
|
448
|
+
for tool_config in tools:
|
449
|
+
tool_type = tool_config.get("type")
|
450
|
+
logger.debug(f"Processing tool type: {tool_type}")
|
451
|
+
|
452
|
+
if tool_type in tool_mapping:
|
453
|
+
try:
|
454
|
+
# Get tool parameters or empty dict if not provided
|
455
|
+
tool_params = tool_config.get("parameters", {})
|
456
|
+
|
457
|
+
# Create tool instance with parameters
|
458
|
+
tool = tool_mapping[tool_type](tool_params)
|
459
|
+
logger.debug(f"Created tool instance: {tool}")
|
460
|
+
|
461
|
+
if tool: # Some tools (like llm_vision) might return None
|
462
|
+
agent_tools.append(tool)
|
463
|
+
logger.info(f"Added tool: {tool_type}")
|
464
|
+
except Exception as e:
|
465
|
+
logger.error(f"Failed to create tool {tool_type}: {str(e)}")
|
466
|
+
|
467
|
+
# If any write tool was added, also add the download tool
|
468
|
+
if has_write_tool:
|
469
|
+
try:
|
470
|
+
agent_tools.append(PrepareDownloadTool())
|
471
|
+
logger.info("Added download tool automatically")
|
472
|
+
except Exception as e:
|
473
|
+
logger.error(f"Failed to add download tool: {str(e)}")
|
474
|
+
|
475
|
+
agent_tools.append(TaskCompleteTool())
|
476
|
+
|
293
477
|
return Agent(
|
294
478
|
model_name=model_name,
|
295
|
-
tools=
|
479
|
+
tools=agent_tools,
|
480
|
+
event_emitter=event_emitter,
|
296
481
|
compact_every_n_iterations=compact_every_n_iteration,
|
297
482
|
max_tokens_working_memory=max_tokens_working_memory,
|
483
|
+
specific_expertise=specific_expertise,
|
484
|
+
memory=memory,
|
298
485
|
)
|
quantalogic/agent_factory.py
CHANGED
@@ -1,21 +1,22 @@
|
|
1
|
-
from typing import Dict, Optional
|
1
|
+
from typing import Any, Dict, List, Optional
|
2
2
|
|
3
3
|
from loguru import logger
|
4
4
|
|
5
5
|
from quantalogic.agent import Agent
|
6
6
|
from quantalogic.agent_config import (
|
7
7
|
create_basic_agent,
|
8
|
+
create_custom_agent,
|
8
9
|
create_full_agent,
|
9
10
|
create_interpreter_agent,
|
10
|
-
create_minimal_agent,
|
11
11
|
)
|
12
12
|
from quantalogic.coding_agent import create_coding_agent
|
13
|
+
from quantalogic.memory import AgentMemory
|
13
14
|
from quantalogic.search_agent import create_search_agent # noqa: E402
|
14
15
|
|
15
16
|
|
16
17
|
class AgentRegistry:
|
17
18
|
"""Registry for managing agent instances by name."""
|
18
|
-
|
19
|
+
|
19
20
|
_instance = None
|
20
21
|
_agents: Dict[str, Agent] = {}
|
21
22
|
|
@@ -27,7 +28,7 @@ class AgentRegistry:
|
|
27
28
|
@classmethod
|
28
29
|
def register_agent(cls, name: str, agent: Agent) -> None:
|
29
30
|
"""Register an agent instance with a name.
|
30
|
-
|
31
|
+
|
31
32
|
Args:
|
32
33
|
name: Unique name for the agent
|
33
34
|
agent: Agent instance to register
|
@@ -39,13 +40,13 @@ class AgentRegistry:
|
|
39
40
|
@classmethod
|
40
41
|
def get_agent(cls, name: str) -> Agent:
|
41
42
|
"""Retrieve a registered agent by name.
|
42
|
-
|
43
|
+
|
43
44
|
Args:
|
44
45
|
name: Name of the agent to retrieve
|
45
|
-
|
46
|
+
|
46
47
|
Returns:
|
47
48
|
Registered Agent instance
|
48
|
-
|
49
|
+
|
49
50
|
Raises:
|
50
51
|
KeyError: If no agent with that name exists
|
51
52
|
"""
|
@@ -54,12 +55,13 @@ class AgentRegistry:
|
|
54
55
|
@classmethod
|
55
56
|
def list_agents(cls) -> Dict[str, str]:
|
56
57
|
"""List all registered agents.
|
57
|
-
|
58
|
+
|
58
59
|
Returns:
|
59
60
|
Dictionary mapping agent names to their types
|
60
61
|
"""
|
61
62
|
return {name: type(agent).__name__ for name, agent in cls._agents.items()}
|
62
63
|
|
64
|
+
|
63
65
|
"""Agent factory module for creating different types of agents."""
|
64
66
|
|
65
67
|
|
@@ -70,10 +72,14 @@ def create_agent_for_mode(
|
|
70
72
|
thinking_model_name: Optional[str],
|
71
73
|
no_stream: bool = False,
|
72
74
|
compact_every_n_iteration: Optional[int] = None,
|
73
|
-
max_tokens_working_memory: Optional[int] = None
|
75
|
+
max_tokens_working_memory: Optional[int] = None,
|
76
|
+
tools: Optional[List[Any]] = None,
|
77
|
+
event_emitter: Any = None,
|
78
|
+
specific_expertise: str = "",
|
79
|
+
memory: AgentMemory | None = None
|
74
80
|
) -> Agent:
|
75
81
|
"""Create an agent based on the specified mode.
|
76
|
-
|
82
|
+
|
77
83
|
Args:
|
78
84
|
mode: The mode of operation for the agent
|
79
85
|
model_name: The name of the language model to use
|
@@ -82,10 +88,14 @@ def create_agent_for_mode(
|
|
82
88
|
no_stream: Whether to disable streaming mode
|
83
89
|
compact_every_n_iteration: Optional number of iterations before compacting memory
|
84
90
|
max_tokens_working_memory: Optional maximum tokens for working memory
|
91
|
+
tools: Optional list of tools to include in the agent
|
92
|
+
event_emitter: Optional event emitter to use in the agent
|
93
|
+
specific_expertise: Optional specific expertise for the agent
|
94
|
+
memory: Optional AgentMemory instance to use in the agent
|
85
95
|
|
86
96
|
Returns:
|
87
97
|
Agent: The created agent instance
|
88
|
-
|
98
|
+
|
89
99
|
Raises:
|
90
100
|
ValueError: If an unknown agent mode is specified
|
91
101
|
"""
|
@@ -104,18 +114,17 @@ def create_agent_for_mode(
|
|
104
114
|
basic=False,
|
105
115
|
no_stream=no_stream,
|
106
116
|
compact_every_n_iteration=compact_every_n_iteration,
|
107
|
-
max_tokens_working_memory=max_tokens_working_memory
|
117
|
+
max_tokens_working_memory=max_tokens_working_memory,
|
108
118
|
)
|
109
119
|
return agent
|
110
120
|
if mode == "code-basic":
|
111
121
|
agent = create_coding_agent(
|
112
122
|
model_name,
|
113
123
|
vision_model_name,
|
114
|
-
|
115
124
|
basic=True,
|
116
125
|
no_stream=no_stream,
|
117
126
|
compact_every_n_iteration=compact_every_n_iteration,
|
118
|
-
max_tokens_working_memory=max_tokens_working_memory
|
127
|
+
max_tokens_working_memory=max_tokens_working_memory,
|
119
128
|
)
|
120
129
|
return agent
|
121
130
|
elif mode == "basic":
|
@@ -124,7 +133,7 @@ def create_agent_for_mode(
|
|
124
133
|
vision_model_name,
|
125
134
|
no_stream=no_stream,
|
126
135
|
compact_every_n_iteration=compact_every_n_iteration,
|
127
|
-
max_tokens_working_memory=max_tokens_working_memory
|
136
|
+
max_tokens_working_memory=max_tokens_working_memory,
|
128
137
|
)
|
129
138
|
return agent
|
130
139
|
elif mode == "full":
|
@@ -133,7 +142,7 @@ def create_agent_for_mode(
|
|
133
142
|
vision_model_name,
|
134
143
|
no_stream=no_stream,
|
135
144
|
compact_every_n_iteration=compact_every_n_iteration,
|
136
|
-
max_tokens_working_memory=max_tokens_working_memory
|
145
|
+
max_tokens_working_memory=max_tokens_working_memory,
|
137
146
|
)
|
138
147
|
return agent
|
139
148
|
elif mode == "interpreter":
|
@@ -142,7 +151,7 @@ def create_agent_for_mode(
|
|
142
151
|
vision_model_name,
|
143
152
|
no_stream=no_stream,
|
144
153
|
compact_every_n_iteration=compact_every_n_iteration,
|
145
|
-
max_tokens_working_memory=max_tokens_working_memory
|
154
|
+
max_tokens_working_memory=max_tokens_working_memory,
|
146
155
|
)
|
147
156
|
return agent
|
148
157
|
elif mode == "search":
|
@@ -150,7 +159,7 @@ def create_agent_for_mode(
|
|
150
159
|
model_name,
|
151
160
|
no_stream=no_stream,
|
152
161
|
compact_every_n_iteration=compact_every_n_iteration,
|
153
|
-
max_tokens_working_memory=max_tokens_working_memory
|
162
|
+
max_tokens_working_memory=max_tokens_working_memory,
|
154
163
|
)
|
155
164
|
return agent
|
156
165
|
if mode == "search-full":
|
@@ -159,16 +168,19 @@ def create_agent_for_mode(
|
|
159
168
|
mode_full=True,
|
160
169
|
no_stream=no_stream,
|
161
170
|
compact_every_n_iteration=compact_every_n_iteration,
|
162
|
-
max_tokens_working_memory=max_tokens_working_memory
|
171
|
+
max_tokens_working_memory=max_tokens_working_memory,
|
163
172
|
)
|
164
173
|
return agent
|
165
|
-
if mode == "
|
166
|
-
agent =
|
174
|
+
if mode == "custom":
|
175
|
+
agent = create_custom_agent(
|
167
176
|
model_name,
|
168
177
|
vision_model_name,
|
169
178
|
no_stream=no_stream,
|
170
179
|
compact_every_n_iteration=compact_every_n_iteration,
|
171
|
-
max_tokens_working_memory=max_tokens_working_memory
|
180
|
+
max_tokens_working_memory=max_tokens_working_memory,
|
181
|
+
specific_expertise=specific_expertise,
|
182
|
+
tools=tools,
|
183
|
+
memory=memory
|
172
184
|
)
|
173
185
|
return agent
|
174
186
|
else:
|
quantalogic/coding_agent.py
CHANGED
@@ -15,9 +15,7 @@ from quantalogic.tools import (
|
|
15
15
|
ReadHTMLTool,
|
16
16
|
ReplaceInFileTool,
|
17
17
|
RipgrepTool,
|
18
|
-
SafePythonInterpreterTool,
|
19
18
|
SearchDefinitionNames,
|
20
|
-
SequenceTool,
|
21
19
|
TaskCompleteTool,
|
22
20
|
WriteFileTool,
|
23
21
|
)
|
@@ -26,13 +24,13 @@ from quantalogic.utils.get_quantalogic_rules_content import get_quantalogic_rule
|
|
26
24
|
|
27
25
|
|
28
26
|
def create_coding_agent(
|
29
|
-
model_name: str,
|
30
|
-
vision_model_name: str | None = None,
|
27
|
+
model_name: str,
|
28
|
+
vision_model_name: str | None = None,
|
31
29
|
thinking_model_name: str | None = None,
|
32
|
-
basic: bool = False,
|
33
|
-
no_stream: bool = False,
|
30
|
+
basic: bool = False,
|
31
|
+
no_stream: bool = False,
|
34
32
|
compact_every_n_iteration: int | None = None,
|
35
|
-
max_tokens_working_memory: int | None = None
|
33
|
+
max_tokens_working_memory: int | None = None,
|
36
34
|
) -> Agent:
|
37
35
|
"""Creates and configures a coding agent with a comprehensive set of tools.
|
38
36
|
|
@@ -84,14 +82,20 @@ def create_coding_agent(
|
|
84
82
|
GrepAppTool(),
|
85
83
|
# SafePythonInterpreterTool(allowed_modules=["math", "numpy","decimal"])
|
86
84
|
]
|
87
|
-
|
88
|
-
|
89
|
-
if vision_model_name:
|
90
|
-
tools.append(LLMVisionTool(model_name=vision_model_name, on_token=console_print_token if not no_stream else None))
|
91
85
|
|
86
|
+
if vision_model_name:
|
87
|
+
tools.append(
|
88
|
+
LLMVisionTool(model_name=vision_model_name, on_token=console_print_token if not no_stream else None)
|
89
|
+
)
|
92
90
|
|
93
91
|
if thinking_model_name:
|
94
|
-
tools.append(
|
92
|
+
tools.append(
|
93
|
+
LLMTool(
|
94
|
+
model_name=thinking_model_name,
|
95
|
+
name="smartest_code_expert",
|
96
|
+
on_token=console_print_token if not no_stream else None,
|
97
|
+
)
|
98
|
+
)
|
95
99
|
|
96
100
|
if not basic:
|
97
101
|
tools.append(
|
@@ -121,8 +125,6 @@ def create_coding_agent(
|
|
121
125
|
on_token=console_print_token if not no_stream else None,
|
122
126
|
)
|
123
127
|
)
|
124
|
-
|
125
|
-
|
126
128
|
|
127
129
|
return Agent(
|
128
130
|
model_name=model_name,
|
quantalogic/config.py
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
2
|
from typing import Optional
|
3
3
|
|
4
|
+
|
4
5
|
@dataclass
|
5
6
|
class QLConfig:
|
6
7
|
"""Central configuration for QuantaLogic agent parameters."""
|
8
|
+
|
7
9
|
model_name: str
|
8
10
|
verbose: bool
|
9
11
|
mode: str
|
@@ -14,4 +16,3 @@ class QLConfig:
|
|
14
16
|
max_tokens_working_memory: Optional[int]
|
15
17
|
no_stream: bool
|
16
18
|
thinking_model_name: str
|
17
|
-
|