quantalogic 0.30.6__tar.gz → 0.31.0__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.
- {quantalogic-0.30.6 → quantalogic-0.31.0}/PKG-INFO +6 -1
- {quantalogic-0.30.6 → quantalogic-0.31.0}/README.md +3 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/pyproject.toml +3 -1
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/__init__.py +17 -7
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/agent.py +87 -37
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/agent_config.py +10 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/agent_factory.py +66 -11
- quantalogic-0.31.0/quantalogic/config.py +15 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/generative_model.py +17 -98
- quantalogic-0.31.0/quantalogic/get_model_info.py +42 -0
- quantalogic-0.31.0/quantalogic/interactive_text_editor.py +368 -0
- quantalogic-0.31.0/quantalogic/llm.py +135 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/main.py +60 -11
- quantalogic-0.31.0/quantalogic/prompts.py +119 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/task_runner.py +26 -39
- quantalogic-0.31.0/quantalogic/tool_manager.py +192 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/replace_in_file_tool.py +1 -1
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/search_definition_names.py +2 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/sql_query_tool.py +4 -2
- quantalogic-0.31.0/quantalogic/utils/get_all_models.py +20 -0
- quantalogic-0.30.6/quantalogic/get_model_info.py +0 -16
- quantalogic-0.30.6/quantalogic/interactive_text_editor.py +0 -194
- quantalogic-0.30.6/quantalogic/prompts.py +0 -94
- quantalogic-0.30.6/quantalogic/tool_manager.py +0 -115
- {quantalogic-0.30.6 → quantalogic-0.31.0}/LICENSE +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/coding_agent.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/console_print_events.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/console_print_token.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/docs_cli.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/event_emitter.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/memory.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/model_names.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/search_agent.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/server/__init__.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/server/agent_server.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/server/models.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/server/routes.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/server/state.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/server/static/js/event_visualizer.js +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/server/static/js/quantalogic.js +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/server/templates/index.html +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/task_file_reader.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/__init__.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/agent_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/dalle_e.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/download_http_file_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/duckduckgo_search_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/edit_whole_content_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/elixir_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/execute_bash_command_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/generate_database_report_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/grep_app_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/input_question_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/jinja_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/language_handlers/__init__.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/language_handlers/c_handler.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/language_handlers/cpp_handler.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/language_handlers/go_handler.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/language_handlers/java_handler.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/language_handlers/javascript_handler.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/language_handlers/python_handler.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/language_handlers/rust_handler.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/language_handlers/scala_handler.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/language_handlers/typescript_handler.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/list_directory_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/llm_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/llm_vision_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/markitdown_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/nodejs_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/python_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/read_file_block_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/read_file_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/read_html_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/ripgrep_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/serpapi_search_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/task_complete_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/unified_diff_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/utils/__init__.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/utils/create_sample_database.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/utils/generate_database_report.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/wikipedia_search_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/tools/write_file_tool.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/utils/__init__.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/utils/ask_user_validation.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/utils/check_version.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/utils/download_http_file.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/utils/get_coding_environment.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/utils/get_environment.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/utils/get_quantalogic_rules_content.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/utils/git_ls.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/utils/read_file.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/utils/read_http_text_content.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/version.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/version_check.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/welcome_message.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/xml_parser.py +0 -0
- {quantalogic-0.30.6 → quantalogic-0.31.0}/quantalogic/xml_tool_parser.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: quantalogic
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.31.0
|
4
4
|
Summary: QuantaLogic ReAct Agents
|
5
5
|
Author: Raphaël MANSUY
|
6
6
|
Author-email: raphael.mansuy@gmail.com
|
@@ -14,6 +14,7 @@ Requires-Dist: click (>=8.1.8,<9.0.0)
|
|
14
14
|
Requires-Dist: duckduckgo-search (>=7.2.1,<8.0.0)
|
15
15
|
Requires-Dist: faker (>=33.3.1,<34.0.0)
|
16
16
|
Requires-Dist: fastapi (>=0.115.6,<0.116.0)
|
17
|
+
Requires-Dist: fuzzywuzzy (>=0.18.0,<0.19.0)
|
17
18
|
Requires-Dist: google-auth (>=2.20.0,<3.0.0)
|
18
19
|
Requires-Dist: google-search-results (>=2.4.2,<3.0.0)
|
19
20
|
Requires-Dist: jinja2 (>=3.1.5,<4.0.0)
|
@@ -35,6 +36,7 @@ Requires-Dist: prompt-toolkit (>=3.0.48,<4.0.0)
|
|
35
36
|
Requires-Dist: pydantic (>=2.10.4,<3.0.0)
|
36
37
|
Requires-Dist: pymdown-extensions (>=10.3.1,<11.0.0)
|
37
38
|
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
39
|
+
Requires-Dist: python-levenshtein (>=0.26.1,<0.27.0)
|
38
40
|
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
39
41
|
Requires-Dist: rich (>=13.9.4,<14.0.0)
|
40
42
|
Requires-Dist: serpapi (>=0.1.5,<0.2.0)
|
@@ -162,6 +164,9 @@ See our [Release Notes](RELEASE_NOTES.MD) for detailed version history and chang
|
|
162
164
|
| openrouter/openai/gpt-4o | OPENROUTER_API_KEY | OpenAI's GPT-4o model accessible through OpenRouter platform. |
|
163
165
|
| openrouter/mistralai/mistral-large-2411 | OPENROUTER_API_KEY | Mistral's large model optimized for complex reasoning tasks, available through OpenRouter with enhanced multilingual capabilities. |
|
164
166
|
| mistral/mistral-large-2407 | MISTRAL_API_KEY | Mistral's high-performance model designed for enterprise-grade applications, offering advanced reasoning and multilingual support. |
|
167
|
+
| dashscope/qwen-max | DASHSCOPE_API_KEY | Alibaba's Qwen-Max model optimized for maximum performance and extensive reasoning capabilities. |
|
168
|
+
| dashscope/qwen-plus | DASHSCOPE_API_KEY | Alibaba's Qwen-Plus model offering balanced performance and cost-efficiency for a variety of tasks. |
|
169
|
+
| dashscope/qwen-turbo | DASHSCOPE_API_KEY | Alibaba's Qwen-Turbo model designed for fast and efficient responses, ideal for high-throughput scenarios. |
|
165
170
|
|
166
171
|
To configure the environment API key for Quantalogic using LiteLLM, set the required environment variable for your chosen provider and any optional variables like `OPENAI_API_BASE` or `OPENROUTER_REFERRER`. Use a `.env` file or a secrets manager to securely store these keys, and load them in your code using `python-dotenv`. For advanced configurations, refer to the [LiteLLM documentation](https://docs.litellm.ai/docs/).
|
167
172
|
|
@@ -104,6 +104,9 @@ See our [Release Notes](RELEASE_NOTES.MD) for detailed version history and chang
|
|
104
104
|
| openrouter/openai/gpt-4o | OPENROUTER_API_KEY | OpenAI's GPT-4o model accessible through OpenRouter platform. |
|
105
105
|
| openrouter/mistralai/mistral-large-2411 | OPENROUTER_API_KEY | Mistral's large model optimized for complex reasoning tasks, available through OpenRouter with enhanced multilingual capabilities. |
|
106
106
|
| mistral/mistral-large-2407 | MISTRAL_API_KEY | Mistral's high-performance model designed for enterprise-grade applications, offering advanced reasoning and multilingual support. |
|
107
|
+
| dashscope/qwen-max | DASHSCOPE_API_KEY | Alibaba's Qwen-Max model optimized for maximum performance and extensive reasoning capabilities. |
|
108
|
+
| dashscope/qwen-plus | DASHSCOPE_API_KEY | Alibaba's Qwen-Plus model offering balanced performance and cost-efficiency for a variety of tasks. |
|
109
|
+
| dashscope/qwen-turbo | DASHSCOPE_API_KEY | Alibaba's Qwen-Turbo model designed for fast and efficient responses, ideal for high-throughput scenarios. |
|
107
110
|
|
108
111
|
To configure the environment API key for Quantalogic using LiteLLM, set the required environment variable for your chosen provider and any optional variables like `OPENAI_API_BASE` or `OPENROUTER_REFERRER`. Use a `.env` file or a secrets manager to securely store these keys, and load them in your code using `python-dotenv`. For advanced configurations, refer to the [LiteLLM documentation](https://docs.litellm.ai/docs/).
|
109
112
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "quantalogic"
|
3
|
-
version = "0.
|
3
|
+
version = "0.31.0"
|
4
4
|
description = "QuantaLogic ReAct Agents"
|
5
5
|
authors = ["Raphaël MANSUY <raphael.mansuy@gmail.com>"]
|
6
6
|
readme = "README.md"
|
@@ -54,6 +54,8 @@ sqlalchemy = "^2.0.37"
|
|
54
54
|
python-dotenv = "^1.0.1"
|
55
55
|
networkx = "^3.4.2"
|
56
56
|
faker = "^33.3.1"
|
57
|
+
fuzzywuzzy = "^0.18.0"
|
58
|
+
python-levenshtein = "^0.26.1"
|
57
59
|
|
58
60
|
[tool.poetry.scripts]
|
59
61
|
quantalogic = "quantalogic.main:cli"
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
"""QuantaLogic package initialization."""
|
2
|
+
|
2
3
|
import warnings
|
3
4
|
|
4
5
|
# Suppress specific warnings related to Pydantic's V2 configuration changes
|
@@ -9,13 +10,22 @@ warnings.filterwarnings(
|
|
9
10
|
message=".*config keys have changed in V2:.*|.*'fields' config key is removed in V2.*",
|
10
11
|
)
|
11
12
|
|
12
|
-
|
13
|
+
# Import public API
|
14
|
+
from .llm import generate_completion, generate_image, count_tokens # noqa: E402
|
13
15
|
from .agent import Agent # noqa: E402
|
14
|
-
from .console_print_events import console_print_events # noqa: E402
|
15
|
-
from .console_print_token import console_print_token # noqa: E402
|
16
16
|
from .event_emitter import EventEmitter # noqa: E402
|
17
17
|
from .memory import AgentMemory, VariableMemory # noqa: E402
|
18
|
+
from .console_print_events import console_print_events # noqa: E402
|
19
|
+
from .console_print_token import console_print_token # noqa: E402
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
__all__ = [
|
22
|
+
"Agent",
|
23
|
+
"EventEmitter",
|
24
|
+
"AgentMemory",
|
25
|
+
"VariableMemory",
|
26
|
+
"console_print_events",
|
27
|
+
"console_print_token",
|
28
|
+
"generate_completion",
|
29
|
+
"generate_image",
|
30
|
+
"count_tokens"
|
31
|
+
]
|
@@ -5,7 +5,7 @@ from datetime import datetime
|
|
5
5
|
from typing import Any
|
6
6
|
|
7
7
|
from loguru import logger
|
8
|
-
from pydantic import BaseModel, ConfigDict
|
8
|
+
from pydantic import BaseModel, ConfigDict, PrivateAttr
|
9
9
|
|
10
10
|
from quantalogic.event_emitter import EventEmitter
|
11
11
|
from quantalogic.generative_model import GenerativeModel, ResponseStats, TokenUsage
|
@@ -52,12 +52,16 @@ class ObserveResponseResult(BaseModel):
|
|
52
52
|
class Agent(BaseModel):
|
53
53
|
"""Enhanced QuantaLogic agent implementing ReAct framework."""
|
54
54
|
|
55
|
-
model_config = ConfigDict(
|
55
|
+
model_config = ConfigDict(
|
56
|
+
arbitrary_types_allowed=True,
|
57
|
+
validate_assignment=True,
|
58
|
+
extra="forbid"
|
59
|
+
)
|
56
60
|
|
57
61
|
specific_expertise: str
|
58
62
|
model: GenerativeModel
|
59
|
-
memory: AgentMemory = AgentMemory()
|
60
|
-
variable_store: VariableMemory = VariableMemory()
|
63
|
+
memory: AgentMemory = AgentMemory() # A list User / Assistant Messages
|
64
|
+
variable_store: VariableMemory = VariableMemory() # A dictionary of variables
|
61
65
|
tools: ToolManager = ToolManager()
|
62
66
|
event_emitter: EventEmitter = EventEmitter()
|
63
67
|
config: AgentConfig
|
@@ -71,8 +75,9 @@ class Agent(BaseModel):
|
|
71
75
|
max_output_tokens: int = DEFAULT_MAX_OUTPUT_TOKENS
|
72
76
|
max_iterations: int = 30
|
73
77
|
system_prompt: str = ""
|
74
|
-
compact_every_n_iterations: int | None = None
|
75
|
-
max_tokens_working_memory: int | None = None
|
78
|
+
compact_every_n_iterations: int | None = None
|
79
|
+
max_tokens_working_memory: int | None = None
|
80
|
+
_model_name: str = PrivateAttr(default="")
|
76
81
|
|
77
82
|
def __init__(
|
78
83
|
self,
|
@@ -84,17 +89,18 @@ class Agent(BaseModel):
|
|
84
89
|
task_to_solve: str = "",
|
85
90
|
specific_expertise: str = "General AI assistant with coding and problem-solving capabilities",
|
86
91
|
get_environment: Callable[[], str] = get_environment,
|
87
|
-
compact_every_n_iterations: int | None = None,
|
88
|
-
max_tokens_working_memory: int | None = None,
|
92
|
+
compact_every_n_iterations: int | None = None,
|
93
|
+
max_tokens_working_memory: int | None = None,
|
89
94
|
):
|
90
95
|
"""Initialize the agent with model, memory, tools, and configurations."""
|
91
96
|
try:
|
92
97
|
logger.debug("Initializing agent...")
|
93
|
-
|
98
|
+
|
99
|
+
# Create event emitter
|
94
100
|
event_emitter = EventEmitter()
|
95
101
|
|
96
102
|
# Add TaskCompleteTool to the tools list if not already present
|
97
|
-
if TaskCompleteTool
|
103
|
+
if not any(isinstance(t, TaskCompleteTool) for t in tools):
|
98
104
|
tools.append(TaskCompleteTool())
|
99
105
|
|
100
106
|
tool_manager = ToolManager(tools={tool.name: tool for tool in tools})
|
@@ -114,32 +120,50 @@ class Agent(BaseModel):
|
|
114
120
|
system_prompt=system_prompt_text,
|
115
121
|
)
|
116
122
|
|
117
|
-
|
123
|
+
# Initialize using Pydantic's model_validate
|
118
124
|
super().__init__(
|
125
|
+
specific_expertise=specific_expertise,
|
119
126
|
model=GenerativeModel(model=model_name, event_emitter=event_emitter),
|
120
127
|
memory=memory,
|
121
128
|
variable_store=variable_store,
|
122
129
|
tools=tool_manager,
|
130
|
+
event_emitter=event_emitter,
|
123
131
|
config=config,
|
124
|
-
ask_for_user_validation=ask_for_user_validation,
|
125
132
|
task_to_solve=task_to_solve,
|
126
|
-
|
127
|
-
|
133
|
+
task_to_solve_summary="",
|
134
|
+
ask_for_user_validation=ask_for_user_validation,
|
135
|
+
last_tool_call={},
|
136
|
+
total_tokens=0,
|
137
|
+
current_iteration=0,
|
138
|
+
max_input_tokens=DEFAULT_MAX_INPUT_TOKENS,
|
139
|
+
max_output_tokens=DEFAULT_MAX_OUTPUT_TOKENS,
|
140
|
+
max_iterations=30,
|
141
|
+
system_prompt="",
|
142
|
+
compact_every_n_iterations=compact_every_n_iterations or 30,
|
143
|
+
max_tokens_working_memory=max_tokens_working_memory,
|
128
144
|
)
|
129
145
|
|
130
|
-
|
131
|
-
self.compact_every_n_iterations = compact_every_n_iterations or self.max_iterations
|
132
|
-
logger.debug(f"Memory will be compacted every {self.compact_every_n_iterations} iterations")
|
146
|
+
self._model_name = model_name
|
133
147
|
|
134
|
-
|
135
|
-
self.max_tokens_working_memory = max_tokens_working_memory
|
148
|
+
logger.debug(f"Memory will be compacted every {self.compact_every_n_iterations} iterations")
|
136
149
|
logger.debug(f"Max tokens for working memory set to: {self.max_tokens_working_memory}")
|
137
|
-
|
138
150
|
logger.debug("Agent initialized successfully.")
|
139
151
|
except Exception as e:
|
140
152
|
logger.error(f"Failed to initialize agent: {str(e)}")
|
141
153
|
raise
|
142
154
|
|
155
|
+
@property
|
156
|
+
def model_name(self) -> str:
|
157
|
+
"""Get the current model name."""
|
158
|
+
return self._model_name
|
159
|
+
|
160
|
+
@model_name.setter
|
161
|
+
def model_name(self, value: str) -> None:
|
162
|
+
"""Set the model name."""
|
163
|
+
self._model_name = value
|
164
|
+
# Update the model instance with the new name
|
165
|
+
self.model = GenerativeModel(model=value, event_emitter=self.event_emitter)
|
166
|
+
|
143
167
|
def clear_memory(self):
|
144
168
|
"""Clear the memory and reset the session."""
|
145
169
|
self._reset_session(clear_memory=True)
|
@@ -533,7 +557,10 @@ class Agent(BaseModel):
|
|
533
557
|
question_validation: str = (
|
534
558
|
"Do you permit the execution of this tool?\n"
|
535
559
|
f"Tool: {tool_name}\n"
|
536
|
-
|
560
|
+
"Arguments:\n"
|
561
|
+
"<arguments>\n"
|
562
|
+
+ "\n".join([f" <{key}>{value}</{key}>" for key, value in arguments_with_values.items()])
|
563
|
+
+ "\n</arguments>\n"
|
537
564
|
"Yes or No"
|
538
565
|
)
|
539
566
|
permission_granted = self.ask_for_user_validation(question_validation)
|
@@ -559,20 +586,24 @@ class Agent(BaseModel):
|
|
559
586
|
key: self._interpolate_variables(value) for key, value in arguments_with_values.items()
|
560
587
|
}
|
561
588
|
|
562
|
-
|
563
|
-
try:
|
564
|
-
converted_args = self.tools._convert_kwargs_types(tool_name, **arguments_with_values_interpolated)
|
565
|
-
except ValueError as e:
|
566
|
-
logger.error(f"Type conversion failed: {str(e)}")
|
567
|
-
return "", f"Error: Type conversion failed for tool '{tool_name}': {str(e)}"
|
589
|
+
arguments_with_values_interpolated = arguments_with_values_interpolated
|
568
590
|
|
569
591
|
# test if tool need variables in context
|
570
592
|
if tool.need_variables:
|
571
593
|
# Inject variables into the tool if needed
|
572
|
-
|
594
|
+
arguments_with_values_interpolated["variables"] = self.variable_store
|
573
595
|
if tool.need_caller_context_memory:
|
574
596
|
# Inject caller context into the tool if needed
|
575
|
-
|
597
|
+
arguments_with_values_interpolated["caller_context_memory"] = self.memory.memory
|
598
|
+
|
599
|
+
try:
|
600
|
+
# Convert arguments to proper types
|
601
|
+
converted_args = self.tools.validate_and_convert_arguments(
|
602
|
+
tool_name,
|
603
|
+
arguments_with_values_interpolated
|
604
|
+
)
|
605
|
+
except ValueError as e:
|
606
|
+
return "", f"Argument Error: {str(e)}"
|
576
607
|
|
577
608
|
# Add injectable variables
|
578
609
|
injectable_properties = tool.get_injectable_properties_in_execution()
|
@@ -599,10 +630,14 @@ class Agent(BaseModel):
|
|
599
630
|
return executed_tool, response
|
600
631
|
|
601
632
|
def _interpolate_variables(self, text: str) -> str:
|
602
|
-
"""Interpolate variables using $
|
633
|
+
"""Interpolate variables using $var$ syntax in the given text."""
|
603
634
|
try:
|
635
|
+
import re
|
604
636
|
for var in self.variable_store.keys():
|
605
|
-
|
637
|
+
# Escape the variable name for regex, but use raw value for replacement
|
638
|
+
pattern = rf'\${re.escape(var)}\$'
|
639
|
+
replacement = self.variable_store[var]
|
640
|
+
text = re.sub(pattern, replacement, text)
|
606
641
|
return text
|
607
642
|
except Exception as e:
|
608
643
|
logger.error(f"Error in _interpolate_variables: {str(e)}")
|
@@ -641,6 +676,7 @@ class Agent(BaseModel):
|
|
641
676
|
"1. Select ONE tool per message\n"
|
642
677
|
"2. You will receive the tool's output in the next user response\n"
|
643
678
|
"3. Choose the most appropriate tool for each step\n"
|
679
|
+
"4. Use task_complete tool to confirm task completion\n"
|
644
680
|
)
|
645
681
|
return prompt_use_tools
|
646
682
|
|
@@ -702,23 +738,32 @@ class Agent(BaseModel):
|
|
702
738
|
return summary.response
|
703
739
|
|
704
740
|
def _generate_task_summary(self, content: str) -> str:
|
705
|
-
"""Generate a concise summary
|
741
|
+
"""Generate a concise task-focused summary using the generative model.
|
706
742
|
|
707
743
|
Args:
|
708
744
|
content (str): The content to summarize
|
709
745
|
|
710
746
|
Returns:
|
711
|
-
str: Generated summary
|
747
|
+
str: Generated task summary
|
712
748
|
"""
|
713
749
|
try:
|
714
750
|
prompt = (
|
715
|
-
"
|
716
|
-
|
717
|
-
"
|
751
|
+
"Create an ultra-concise task summary that captures ONLY: \n"
|
752
|
+
"1. Primary objective/purpose\n"
|
753
|
+
"2. Core actions/requirements\n"
|
754
|
+
"3. Desired end-state/outcome\n\n"
|
755
|
+
"Guidelines:\n"
|
756
|
+
"- Use imperative voice\n"
|
757
|
+
"- Exclude background, explanations, and examples\n"
|
758
|
+
"- Compress information using semantic density\n"
|
759
|
+
"- Strict 2-3 sentence maximum (under 50 words)\n"
|
760
|
+
"- Format: 'Concise Task Summary: [Your summary]'\n\n"
|
761
|
+
f"Input Task Description:\n{content}\n\n"
|
762
|
+
"Concise Task Summary:"
|
718
763
|
)
|
719
764
|
result = self.model.generate(prompt=prompt)
|
720
765
|
logger.debug(f"Generated summary: {result.response}")
|
721
|
-
return result.response
|
766
|
+
return result.response.strip() + "\n🚨 The FULL task is in <task> tag in the previous messages.\n"
|
722
767
|
except Exception as e:
|
723
768
|
logger.error(f"Error generating summary: {str(e)}")
|
724
769
|
return f"Summary generation failed: {str(e)}"
|
@@ -743,3 +788,8 @@ class Agent(BaseModel):
|
|
743
788
|
"session_add_message",
|
744
789
|
{"role": "assistant", "content": assistant_content},
|
745
790
|
)
|
791
|
+
|
792
|
+
def update_model(self, new_model_name: str) -> None:
|
793
|
+
"""Update the model name and recreate the model instance."""
|
794
|
+
self.model_name = new_model_name
|
795
|
+
self.model = GenerativeModel(model=new_model_name, event_emitter=self.event_emitter)
|
@@ -37,6 +37,14 @@ load_dotenv()
|
|
37
37
|
MODEL_NAME = "deepseek/deepseek-chat"
|
38
38
|
|
39
39
|
|
40
|
+
_current_model_name: str = ""
|
41
|
+
|
42
|
+
def get_current_model() -> str:
|
43
|
+
"""Retrieve the currently active model name."""
|
44
|
+
if not _current_model_name:
|
45
|
+
raise ValueError("No model initialized")
|
46
|
+
return _current_model_name
|
47
|
+
|
40
48
|
def create_agent(
|
41
49
|
model_name: str,
|
42
50
|
vision_model_name: str | None,
|
@@ -44,6 +52,8 @@ def create_agent(
|
|
44
52
|
compact_every_n_iteration: int | None = None,
|
45
53
|
max_tokens_working_memory: int | None = None
|
46
54
|
) -> Agent:
|
55
|
+
global _current_model_name
|
56
|
+
_current_model_name = model_name
|
47
57
|
"""Create an agent with the specified model and tools.
|
48
58
|
|
49
59
|
Args:
|
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
from typing import Optional
|
1
|
+
from typing import Dict, Optional
|
4
2
|
|
5
3
|
from loguru import logger
|
6
4
|
|
@@ -11,7 +9,57 @@ from quantalogic.agent_config import (
|
|
11
9
|
create_interpreter_agent,
|
12
10
|
)
|
13
11
|
from quantalogic.coding_agent import create_coding_agent
|
14
|
-
from quantalogic.search_agent import create_search_agent
|
12
|
+
from quantalogic.search_agent import create_search_agent # noqa: E402
|
13
|
+
|
14
|
+
|
15
|
+
class AgentRegistry:
|
16
|
+
"""Registry for managing agent instances by name."""
|
17
|
+
|
18
|
+
_instance = None
|
19
|
+
_agents: Dict[str, Agent] = {}
|
20
|
+
|
21
|
+
def __new__(cls):
|
22
|
+
if cls._instance is None:
|
23
|
+
cls._instance = super().__new__(cls)
|
24
|
+
return cls._instance
|
25
|
+
|
26
|
+
@classmethod
|
27
|
+
def register_agent(cls, name: str, agent: Agent) -> None:
|
28
|
+
"""Register an agent instance with a name.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
name: Unique name for the agent
|
32
|
+
agent: Agent instance to register
|
33
|
+
"""
|
34
|
+
if name in cls._agents:
|
35
|
+
raise ValueError(f"Agent with name {name} already exists")
|
36
|
+
cls._agents[name] = agent
|
37
|
+
|
38
|
+
@classmethod
|
39
|
+
def get_agent(cls, name: str) -> Agent:
|
40
|
+
"""Retrieve a registered agent by name.
|
41
|
+
|
42
|
+
Args:
|
43
|
+
name: Name of the agent to retrieve
|
44
|
+
|
45
|
+
Returns:
|
46
|
+
Registered Agent instance
|
47
|
+
|
48
|
+
Raises:
|
49
|
+
KeyError: If no agent with that name exists
|
50
|
+
"""
|
51
|
+
return cls._agents[name]
|
52
|
+
|
53
|
+
@classmethod
|
54
|
+
def list_agents(cls) -> Dict[str, str]:
|
55
|
+
"""List all registered agents.
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
Dictionary mapping agent names to their types
|
59
|
+
"""
|
60
|
+
return {name: type(agent).__name__ for name, agent in cls._agents.items()}
|
61
|
+
|
62
|
+
"""Agent factory module for creating different types of agents."""
|
15
63
|
|
16
64
|
|
17
65
|
def create_agent_for_mode(
|
@@ -46,7 +94,7 @@ def create_agent_for_mode(
|
|
46
94
|
|
47
95
|
if mode == "code":
|
48
96
|
logger.debug("Creating code agent without basic mode")
|
49
|
-
|
97
|
+
agent = create_coding_agent(
|
50
98
|
model_name,
|
51
99
|
vision_model_name,
|
52
100
|
basic=False,
|
@@ -54,8 +102,9 @@ def create_agent_for_mode(
|
|
54
102
|
compact_every_n_iteration=compact_every_n_iteration,
|
55
103
|
max_tokens_working_memory=max_tokens_working_memory
|
56
104
|
)
|
105
|
+
return agent
|
57
106
|
if mode == "code-basic":
|
58
|
-
|
107
|
+
agent = create_coding_agent(
|
59
108
|
model_name,
|
60
109
|
vision_model_name,
|
61
110
|
basic=True,
|
@@ -63,44 +112,50 @@ def create_agent_for_mode(
|
|
63
112
|
compact_every_n_iteration=compact_every_n_iteration,
|
64
113
|
max_tokens_working_memory=max_tokens_working_memory
|
65
114
|
)
|
115
|
+
return agent
|
66
116
|
elif mode == "basic":
|
67
|
-
|
117
|
+
agent = create_basic_agent(
|
68
118
|
model_name,
|
69
119
|
vision_model_name,
|
70
120
|
no_stream=no_stream,
|
71
121
|
compact_every_n_iteration=compact_every_n_iteration,
|
72
122
|
max_tokens_working_memory=max_tokens_working_memory
|
73
123
|
)
|
124
|
+
return agent
|
74
125
|
elif mode == "full":
|
75
|
-
|
126
|
+
agent = create_full_agent(
|
76
127
|
model_name,
|
77
128
|
vision_model_name,
|
78
129
|
no_stream=no_stream,
|
79
130
|
compact_every_n_iteration=compact_every_n_iteration,
|
80
131
|
max_tokens_working_memory=max_tokens_working_memory
|
81
132
|
)
|
133
|
+
return agent
|
82
134
|
elif mode == "interpreter":
|
83
|
-
|
135
|
+
agent = create_interpreter_agent(
|
84
136
|
model_name,
|
85
137
|
vision_model_name,
|
86
138
|
no_stream=no_stream,
|
87
139
|
compact_every_n_iteration=compact_every_n_iteration,
|
88
140
|
max_tokens_working_memory=max_tokens_working_memory
|
89
141
|
)
|
142
|
+
return agent
|
90
143
|
elif mode == "search":
|
91
|
-
|
144
|
+
agent = create_search_agent(
|
92
145
|
model_name,
|
93
146
|
no_stream=no_stream,
|
94
147
|
compact_every_n_iteration=compact_every_n_iteration,
|
95
148
|
max_tokens_working_memory=max_tokens_working_memory
|
96
149
|
)
|
150
|
+
return agent
|
97
151
|
if mode == "search-full":
|
98
|
-
|
152
|
+
agent = create_search_agent(
|
99
153
|
model_name,
|
100
154
|
mode_full=True,
|
101
155
|
no_stream=no_stream,
|
102
156
|
compact_every_n_iteration=compact_every_n_iteration,
|
103
157
|
max_tokens_working_memory=max_tokens_working_memory
|
104
158
|
)
|
159
|
+
return agent
|
105
160
|
else:
|
106
161
|
raise ValueError(f"Unknown agent mode: {mode}")
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
|
3
|
+
|
4
|
+
@dataclass
|
5
|
+
class QLConfig:
|
6
|
+
"""Central configuration for QuantaLogic agent parameters."""
|
7
|
+
model_name: str
|
8
|
+
verbose: bool
|
9
|
+
mode: str
|
10
|
+
log: str
|
11
|
+
vision_model_name: str | None
|
12
|
+
max_iterations: int
|
13
|
+
compact_every_n_iteration: int | None
|
14
|
+
max_tokens_working_memory: int | None
|
15
|
+
no_stream: bool
|