quantalogic 0.31.0__py3-none-any.whl → 0.32.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 +3 -3
- quantalogic/agent.py +6 -0
- quantalogic/get_model_info.py +70 -29
- quantalogic/llm.py +41 -9
- quantalogic/model_info.py +12 -0
- quantalogic/model_info_list.py +57 -0
- quantalogic/model_info_litellm.py +70 -0
- quantalogic/task_runner.py +11 -0
- quantalogic/tools/execute_bash_command_tool.py +13 -11
- quantalogic/utils/__init__.py +2 -0
- quantalogic/utils/get_all_models.py +1 -1
- quantalogic/utils/lm_studio_model_info.py +48 -0
- quantalogic/xml_parser.py +1 -0
- {quantalogic-0.31.0.dist-info → quantalogic-0.32.0.dist-info}/METADATA +35 -2
- {quantalogic-0.31.0.dist-info → quantalogic-0.32.0.dist-info}/RECORD +18 -14
- {quantalogic-0.31.0.dist-info → quantalogic-0.32.0.dist-info}/LICENSE +0 -0
- {quantalogic-0.31.0.dist-info → quantalogic-0.32.0.dist-info}/WHEEL +0 -0
- {quantalogic-0.31.0.dist-info → quantalogic-0.32.0.dist-info}/entry_points.txt +0 -0
quantalogic/__init__.py
CHANGED
@@ -11,12 +11,12 @@ warnings.filterwarnings(
|
|
11
11
|
)
|
12
12
|
|
13
13
|
# Import public API
|
14
|
-
from .llm import generate_completion, generate_image, count_tokens # noqa: E402
|
15
14
|
from .agent import Agent # noqa: E402
|
16
|
-
from .event_emitter import EventEmitter # noqa: E402
|
17
|
-
from .memory import AgentMemory, VariableMemory # noqa: E402
|
18
15
|
from .console_print_events import console_print_events # noqa: E402
|
19
16
|
from .console_print_token import console_print_token # noqa: E402
|
17
|
+
from .event_emitter import EventEmitter # noqa: E402
|
18
|
+
from .llm import count_tokens, generate_completion, generate_image # noqa: E402
|
19
|
+
from .memory import AgentMemory, VariableMemory # noqa: E402
|
20
20
|
|
21
21
|
__all__ = [
|
22
22
|
"Agent",
|
quantalogic/agent.py
CHANGED
@@ -412,6 +412,9 @@ class Agent(BaseModel):
|
|
412
412
|
|
413
413
|
def _parse_tool_usage(self, content: str) -> dict:
|
414
414
|
"""Extract tool usage from the response content."""
|
415
|
+
if not content or not isinstance(content, str):
|
416
|
+
return {}
|
417
|
+
|
415
418
|
xml_parser = ToleranceXMLParser()
|
416
419
|
tool_names = self.tools.tool_names()
|
417
420
|
return xml_parser.extract_elements(text=content, element_names=tool_names)
|
@@ -502,6 +505,7 @@ class Agent(BaseModel):
|
|
502
505
|
|
503
506
|
# Format the response message
|
504
507
|
formatted_response = (
|
508
|
+
f"Your next step: you Must now plan the next tool call to complete the based on this new observation\n"
|
505
509
|
f"\n--- Observations for iteration {iteration} / max {self.max_iterations} ---\n"
|
506
510
|
f"\n--- Tool execution result in ${variable_name}$ ---\n"
|
507
511
|
f"<{variable_name}>\n{response_display}\n</{variable_name}>\n\n"
|
@@ -747,6 +751,8 @@ class Agent(BaseModel):
|
|
747
751
|
str: Generated task summary
|
748
752
|
"""
|
749
753
|
try:
|
754
|
+
if len(content) < 200:
|
755
|
+
return content
|
750
756
|
prompt = (
|
751
757
|
"Create an ultra-concise task summary that captures ONLY: \n"
|
752
758
|
"1. Primary objective/purpose\n"
|
quantalogic/get_model_info.py
CHANGED
@@ -1,42 +1,83 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
import loguru
|
2
|
+
|
3
|
+
from quantalogic.model_info_list import model_info
|
4
|
+
from quantalogic.model_info_litellm import litellm_get_model_max_input_tokens, litellm_get_model_max_output_tokens
|
5
|
+
from quantalogic.utils.lm_studio_model_info import ModelInfo, get_model_list
|
6
|
+
|
7
|
+
DEFAULT_MAX_OUTPUT_TOKENS = 4 * 1024 # Reasonable default for most models
|
8
|
+
DEFAULT_MAX_INPUT_TOKENS = 32 * 1024 # Reasonable default for most models
|
9
|
+
|
10
|
+
|
11
|
+
def validate_model_name(model_name: str) -> None:
|
12
|
+
if not isinstance(model_name, str) or not model_name.strip():
|
13
|
+
raise ValueError(f"Invalid model name: {model_name}")
|
10
14
|
|
11
15
|
|
12
16
|
def print_model_info():
|
13
|
-
for
|
14
|
-
print(f"\n{
|
15
|
-
print(f" Max Input Tokens: {info
|
16
|
-
print(f" Max Output Tokens: {info
|
17
|
+
for info in model_info.values():
|
18
|
+
print(f"\n{info.model_name}:")
|
19
|
+
print(f" Max Input Tokens: {info.max_input_tokens:,}")
|
20
|
+
print(f" Max Output Tokens: {info.max_output_tokens:,}")
|
17
21
|
|
18
22
|
|
19
|
-
|
20
|
-
|
23
|
+
def get_max_output_tokens(model_name: str) -> int:
|
24
|
+
"""Get max output tokens with safe fallback"""
|
25
|
+
validate_model_name(model_name)
|
26
|
+
|
27
|
+
if model_name.startswith('lm_studio/'):
|
28
|
+
try:
|
29
|
+
models = get_model_list()
|
30
|
+
for model in models.data:
|
31
|
+
if model.id == model_name[len('lm_studio/'):]:
|
32
|
+
return model.max_context_length
|
33
|
+
except Exception:
|
34
|
+
loguru.logger.warning(f"Could not fetch LM Studio model info for {model_name}, using default")
|
21
35
|
|
36
|
+
if model_name in model_info:
|
37
|
+
return model_info[model_name].max_output_tokens
|
22
38
|
|
23
|
-
|
24
|
-
|
25
|
-
|
39
|
+
try:
|
40
|
+
return litellm_get_model_max_output_tokens(model_name)
|
41
|
+
except Exception as e:
|
42
|
+
loguru.logger.warning(f"Model {model_name} not found in LiteLLM registry, using default")
|
43
|
+
return DEFAULT_MAX_OUTPUT_TOKENS
|
26
44
|
|
27
45
|
|
28
|
-
def get_max_input_tokens(model_name: str) -> int
|
29
|
-
"""Get
|
30
|
-
|
46
|
+
def get_max_input_tokens(model_name: str) -> int:
|
47
|
+
"""Get max input tokens with safe fallback"""
|
48
|
+
validate_model_name(model_name)
|
31
49
|
|
50
|
+
if model_name.startswith('lm_studio/'):
|
51
|
+
try:
|
52
|
+
models = get_model_list()
|
53
|
+
for model in models.data:
|
54
|
+
if model.id == model_name[len('lm_studio/'):]:
|
55
|
+
return model.max_context_length
|
56
|
+
except Exception:
|
57
|
+
loguru.logger.warning(f"Could not fetch LM Studio model info for {model_name}, using default")
|
32
58
|
|
33
|
-
|
34
|
-
|
35
|
-
model_data = model_info.get(model_name, {})
|
36
|
-
max_input = model_data.get("max_input_tokens")
|
37
|
-
max_output = model_data.get("max_output_tokens")
|
59
|
+
if model_name in model_info:
|
60
|
+
return model_info[model_name].max_input_tokens
|
38
61
|
|
39
|
-
|
40
|
-
return
|
62
|
+
try:
|
63
|
+
return litellm_get_model_max_input_tokens(model_name)
|
64
|
+
except Exception:
|
65
|
+
loguru.logger.warning(f"Model {model_name} not found in LiteLLM registry, using default")
|
66
|
+
return DEFAULT_MAX_INPUT_TOKENS
|
41
67
|
|
42
|
-
|
68
|
+
|
69
|
+
def get_max_tokens(model_name: str) -> int:
|
70
|
+
"""Get total maximum tokens (input + output)"""
|
71
|
+
validate_model_name(model_name)
|
72
|
+
|
73
|
+
# Get input and output tokens separately
|
74
|
+
input_tokens = get_max_input_tokens(model_name)
|
75
|
+
output_tokens = get_max_output_tokens(model_name)
|
76
|
+
|
77
|
+
return input_tokens + output_tokens
|
78
|
+
|
79
|
+
|
80
|
+
if __name__ == "__main__":
|
81
|
+
print_model_info()
|
82
|
+
print(get_max_input_tokens("gpt-4o-mini"))
|
83
|
+
print(get_max_output_tokens("openrouter/openai/gpt-4o-mini"))
|
quantalogic/llm.py
CHANGED
@@ -30,18 +30,50 @@ def get_model_info(model_name: str) -> dict | None:
|
|
30
30
|
return model_info.get(model_name, None)
|
31
31
|
|
32
32
|
|
33
|
+
class ModelProviderConfig:
|
34
|
+
def __init__(self, prefix: str, provider: str, base_url: str, env_var: str):
|
35
|
+
self.prefix = prefix
|
36
|
+
self.provider = provider
|
37
|
+
self.base_url = base_url
|
38
|
+
self.env_var = env_var
|
39
|
+
|
40
|
+
def configure(self, model: str, kwargs: Dict[str, Any]) -> None:
|
41
|
+
kwargs["model"] = model.replace(self.prefix, "")
|
42
|
+
kwargs["custom_llm_provider"] = self.provider
|
43
|
+
kwargs["base_url"] = self.base_url
|
44
|
+
api_key = os.getenv(self.env_var)
|
45
|
+
if not api_key:
|
46
|
+
raise ValueError(f"{self.env_var} is not set in the environment variables.")
|
47
|
+
kwargs["api_key"] = api_key
|
48
|
+
|
49
|
+
|
50
|
+
# Default provider configurations
|
51
|
+
PROVIDERS = {
|
52
|
+
"dashscope": ModelProviderConfig(
|
53
|
+
prefix="dashscope/",
|
54
|
+
provider="openai",
|
55
|
+
base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
|
56
|
+
env_var="DASHSCOPE_API_KEY"
|
57
|
+
),
|
58
|
+
"nvidia": ModelProviderConfig(
|
59
|
+
prefix="nvidia/",
|
60
|
+
provider="openai",
|
61
|
+
base_url="https://integrate.api.nvidia.com/v1",
|
62
|
+
env_var="NVIDIA_API_KEY"
|
63
|
+
)
|
64
|
+
}
|
65
|
+
|
66
|
+
|
33
67
|
def generate_completion(**kwargs: Dict[str, Any]) -> Any:
|
34
68
|
"""Wraps litellm completion with proper type hints."""
|
35
69
|
model = kwargs.get("model", "")
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
raise ValueError("DASHSCOPE_API_KEY is not set in the environment variables.")
|
44
|
-
kwargs["api_key"] = api_key
|
70
|
+
|
71
|
+
# Find matching provider
|
72
|
+
for provider_name, provider_config in PROVIDERS.items():
|
73
|
+
if model.startswith(provider_config.prefix):
|
74
|
+
provider_config.configure(model, kwargs)
|
75
|
+
break
|
76
|
+
|
45
77
|
return completion(**kwargs)
|
46
78
|
|
47
79
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
from pydantic import BaseModel
|
2
|
+
|
3
|
+
|
4
|
+
class ModelInfo(BaseModel):
|
5
|
+
model_name: str
|
6
|
+
max_input_tokens: int
|
7
|
+
max_output_tokens: int
|
8
|
+
max_cot_tokens: int | None = None
|
9
|
+
|
10
|
+
|
11
|
+
class ModelNotFoundError(Exception):
|
12
|
+
"""Raised when a model is not found in local registry"""
|
@@ -0,0 +1,57 @@
|
|
1
|
+
from quantalogic.model_info import ModelInfo
|
2
|
+
|
3
|
+
model_info = {
|
4
|
+
"dashscope/qwen-max": ModelInfo(
|
5
|
+
model_name="dashscope/qwen-max",
|
6
|
+
max_output_tokens=8 * 1024,
|
7
|
+
max_input_tokens=32 * 1024,
|
8
|
+
),
|
9
|
+
"dashscope/qwen-plus": ModelInfo(
|
10
|
+
model_name="dashscope/qwen-plus",
|
11
|
+
max_output_tokens=8 * 1024,
|
12
|
+
max_input_tokens=131072,
|
13
|
+
),
|
14
|
+
"dashscope/qwen-turbo": ModelInfo(
|
15
|
+
model_name="dashscope/qwen-turbo",
|
16
|
+
max_output_tokens=8 * 1024,
|
17
|
+
max_input_tokens=1000000,
|
18
|
+
),
|
19
|
+
"deepseek-reasoner": ModelInfo(
|
20
|
+
model_name="deepseek-reasoner",
|
21
|
+
max_output_tokens=8 * 1024,
|
22
|
+
max_input_tokens=1024 * 128,
|
23
|
+
),
|
24
|
+
"openrouter/deepseek/deepseek-r1": ModelInfo(
|
25
|
+
model_name="openrouter/deepseek/deepseek-r1",
|
26
|
+
max_output_tokens=8 * 1024,
|
27
|
+
max_input_tokens=1024 * 128,
|
28
|
+
),
|
29
|
+
"openrouter/mistralai/mistral-large-2411": ModelInfo(
|
30
|
+
model_name="openrouter/mistralai/mistral-large-2411",
|
31
|
+
max_output_tokens=128 * 1024,
|
32
|
+
max_input_tokens=1024 * 128,
|
33
|
+
),
|
34
|
+
"mistralai/mistral-large-2411": ModelInfo(
|
35
|
+
model_name="mistralai/mistral-large-2411",
|
36
|
+
max_output_tokens=128 * 1024,
|
37
|
+
max_input_tokens=1024 * 128,
|
38
|
+
),
|
39
|
+
"deepseek/deepseek-chat": ModelInfo(
|
40
|
+
model_name="deepseek/deepseek-chat",
|
41
|
+
max_output_tokens=8 * 1024,
|
42
|
+
max_input_tokens=1024 * 64,
|
43
|
+
),
|
44
|
+
"deepseek/deepseek-reasoner": ModelInfo(
|
45
|
+
model_name="deepseek/deepseek-reasoner",
|
46
|
+
max_output_tokens=8 * 1024,
|
47
|
+
max_input_tokens=1024 * 64,
|
48
|
+
max_cot_tokens=1024 * 32,
|
49
|
+
),
|
50
|
+
"nvidia/deepseek-ai/deepseek-r1": ModelInfo(
|
51
|
+
model_name="nvidia/deepseek-ai/deepseek-r1",
|
52
|
+
max_output_tokens=8 * 1024,
|
53
|
+
max_input_tokens=1024 * 64,
|
54
|
+
),
|
55
|
+
|
56
|
+
|
57
|
+
}
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import functools
|
2
|
+
|
3
|
+
import litellm
|
4
|
+
|
5
|
+
|
6
|
+
@functools.lru_cache(maxsize=32)
|
7
|
+
def litellm_get_model_info(model_name: str) -> dict | None:
|
8
|
+
"""Get model information with prefix fallback logic using only litellm.
|
9
|
+
|
10
|
+
Args:
|
11
|
+
model_name: The model identifier to get information for
|
12
|
+
|
13
|
+
Returns:
|
14
|
+
Dictionary containing model information
|
15
|
+
|
16
|
+
Raises:
|
17
|
+
ValueError: If model info cannot be found after prefix fallbacks
|
18
|
+
"""
|
19
|
+
tried_models = [model_name]
|
20
|
+
|
21
|
+
while True:
|
22
|
+
try:
|
23
|
+
# Attempt to get model info through litellm
|
24
|
+
info = litellm.get_model_info(model_name)
|
25
|
+
if info:
|
26
|
+
return info
|
27
|
+
except Exception:
|
28
|
+
pass
|
29
|
+
|
30
|
+
# Try removing one prefix level
|
31
|
+
parts = model_name.split("/")
|
32
|
+
if len(parts) <= 1:
|
33
|
+
break
|
34
|
+
|
35
|
+
model_name = "/".join(parts[1:])
|
36
|
+
tried_models.append(model_name)
|
37
|
+
|
38
|
+
return None
|
39
|
+
|
40
|
+
|
41
|
+
def litellm_get_model_max_input_tokens(model_name: str) -> int | None:
|
42
|
+
"""Get maximum input tokens for a model using litellm.
|
43
|
+
|
44
|
+
Args:
|
45
|
+
model_name: The model identifier
|
46
|
+
|
47
|
+
Returns:
|
48
|
+
Maximum input tokens or None if not found
|
49
|
+
"""
|
50
|
+
try:
|
51
|
+
info = litellm_get_model_info(model_name)
|
52
|
+
return info.get("max_input_tokens", 8192)
|
53
|
+
except Exception as e:
|
54
|
+
return 8192 # Default for many modern models
|
55
|
+
|
56
|
+
|
57
|
+
def litellm_get_model_max_output_tokens(model_name: str) -> int | None:
|
58
|
+
"""Get maximum output tokens for a model using litellm.
|
59
|
+
|
60
|
+
Args:
|
61
|
+
model_name: The model identifier
|
62
|
+
|
63
|
+
Returns:
|
64
|
+
Maximum output tokens or None if not found
|
65
|
+
"""
|
66
|
+
try:
|
67
|
+
info = litellm_get_model_info(model_name)
|
68
|
+
return info.get("max_output_tokens", 4096)
|
69
|
+
except Exception as e:
|
70
|
+
return 4096 # Conservative default
|
quantalogic/task_runner.py
CHANGED
@@ -233,6 +233,12 @@ def task_runner(
|
|
233
233
|
"memory_summary",
|
234
234
|
]
|
235
235
|
|
236
|
+
#def ask_continue(event: str, data: any) -> None:
|
237
|
+
# ## Ask for ctrl+return
|
238
|
+
# if event == "task_think_end":
|
239
|
+
# ## Wait return on the keyboard
|
240
|
+
# input("Press [Enter] to continue...")
|
241
|
+
|
236
242
|
# Add spinner control to event handlers
|
237
243
|
def handle_task_think_start(*args, **kwargs):
|
238
244
|
start_spinner(console)
|
@@ -246,6 +252,11 @@ def task_runner(
|
|
246
252
|
if data is not None:
|
247
253
|
console.print(data, end="", markup=False)
|
248
254
|
|
255
|
+
#agent.event_emitter.on(
|
256
|
+
# event="task_think_end",
|
257
|
+
# listener=ask_continue,
|
258
|
+
#)
|
259
|
+
|
249
260
|
agent.event_emitter.on(
|
250
261
|
event=events,
|
251
262
|
listener=console_print_events,
|
@@ -11,7 +11,7 @@ from loguru import logger
|
|
11
11
|
|
12
12
|
# Platform-specific imports
|
13
13
|
try:
|
14
|
-
if sys.platform !=
|
14
|
+
if sys.platform != "win32":
|
15
15
|
import pty
|
16
16
|
except ImportError as e:
|
17
17
|
logger.warning(f"Could not import platform-specific module: {e}")
|
@@ -40,6 +40,7 @@ class ExecuteBashCommandTool(Tool):
|
|
40
40
|
description="The working directory where the command will be executed. Defaults to the current directory.",
|
41
41
|
required=False,
|
42
42
|
example="/path/to/directory",
|
43
|
+
default=os.getcwd(),
|
43
44
|
),
|
44
45
|
ToolArgument(
|
45
46
|
name="timeout",
|
@@ -47,6 +48,7 @@ class ExecuteBashCommandTool(Tool):
|
|
47
48
|
description="Maximum time in seconds to wait for the command to complete. Defaults to 60 seconds.",
|
48
49
|
required=False,
|
49
50
|
example="60",
|
51
|
+
default="60",
|
50
52
|
),
|
51
53
|
]
|
52
54
|
|
@@ -69,16 +71,16 @@ class ExecuteBashCommandTool(Tool):
|
|
69
71
|
cwd=cwd,
|
70
72
|
env=env_vars,
|
71
73
|
text=True,
|
72
|
-
encoding=
|
74
|
+
encoding="utf-8",
|
73
75
|
)
|
74
76
|
|
75
77
|
try:
|
76
78
|
stdout, stderr = process.communicate(timeout=timeout_seconds)
|
77
79
|
return_code = process.returncode
|
78
|
-
|
80
|
+
|
79
81
|
if return_code != 0 and stderr:
|
80
82
|
logger.warning(f"Command failed with error: {stderr}")
|
81
|
-
|
83
|
+
|
82
84
|
formatted_result = (
|
83
85
|
"<command_output>"
|
84
86
|
f" <stdout>{stdout.strip()}</stdout>"
|
@@ -86,11 +88,11 @@ class ExecuteBashCommandTool(Tool):
|
|
86
88
|
f"</command_output>"
|
87
89
|
)
|
88
90
|
return formatted_result
|
89
|
-
|
91
|
+
|
90
92
|
except subprocess.TimeoutExpired:
|
91
93
|
process.kill()
|
92
94
|
return f"Command timed out after {timeout_seconds} seconds."
|
93
|
-
|
95
|
+
|
94
96
|
except Exception as e:
|
95
97
|
return f"Unexpected error executing command: {str(e)}"
|
96
98
|
|
@@ -127,7 +129,7 @@ class ExecuteBashCommandTool(Tool):
|
|
127
129
|
if proc.poll() is not None:
|
128
130
|
break # Process completed but select timed out
|
129
131
|
raise subprocess.TimeoutExpired(command, timeout_seconds)
|
130
|
-
|
132
|
+
|
131
133
|
for fd in rlist:
|
132
134
|
if fd == master:
|
133
135
|
data = os.read(master, 1024).decode()
|
@@ -140,7 +142,7 @@ class ExecuteBashCommandTool(Tool):
|
|
140
142
|
elif fd == sys.stdin:
|
141
143
|
user_input = os.read(sys.stdin.fileno(), 1024)
|
142
144
|
os.write(master, user_input)
|
143
|
-
|
145
|
+
|
144
146
|
if break_loop or proc.poll() is not None:
|
145
147
|
while True:
|
146
148
|
data = os.read(master, 1024).decode()
|
@@ -160,7 +162,7 @@ class ExecuteBashCommandTool(Tool):
|
|
160
162
|
os.close(master)
|
161
163
|
proc.wait()
|
162
164
|
|
163
|
-
stdout_content =
|
165
|
+
stdout_content = "".join(stdout_buffer)
|
164
166
|
return_code = proc.returncode
|
165
167
|
formatted_result = (
|
166
168
|
"<command_output>"
|
@@ -186,7 +188,7 @@ class ExecuteBashCommandTool(Tool):
|
|
186
188
|
if env:
|
187
189
|
env_vars.update(env)
|
188
190
|
|
189
|
-
if sys.platform ==
|
191
|
+
if sys.platform == "win32":
|
190
192
|
return self._execute_windows(command, cwd, timeout_seconds, env_vars)
|
191
193
|
else:
|
192
194
|
if not pty:
|
@@ -197,4 +199,4 @@ class ExecuteBashCommandTool(Tool):
|
|
197
199
|
|
198
200
|
if __name__ == "__main__":
|
199
201
|
tool = ExecuteBashCommandTool()
|
200
|
-
print(tool.to_markdown())
|
202
|
+
print(tool.to_markdown())
|
quantalogic/utils/__init__.py
CHANGED
@@ -5,6 +5,7 @@ from .git_ls import git_ls
|
|
5
5
|
from .get_environment import get_environment
|
6
6
|
from .get_coding_environment import get_coding_environment
|
7
7
|
from .get_quantalogic_rules_content import get_quantalogic_rules_file_content
|
8
|
+
from .lm_studio_model_info import get_model_list
|
8
9
|
|
9
10
|
__all__ = [
|
10
11
|
"download_http_file",
|
@@ -14,4 +15,5 @@ __all__ = [
|
|
14
15
|
"get_environment",
|
15
16
|
"get_coding_environment",
|
16
17
|
"get_quantalogic_rules_file_content",
|
18
|
+
"get_model_list",
|
17
19
|
]
|
@@ -0,0 +1,48 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
from typing import List, Literal, Optional
|
3
|
+
|
4
|
+
from pydantic import BaseModel, Field
|
5
|
+
|
6
|
+
|
7
|
+
class ModelType(str, Enum):
|
8
|
+
LLM = "llm"
|
9
|
+
EMBEDDINGS = "embeddings"
|
10
|
+
VLM = "vlm"
|
11
|
+
|
12
|
+
class CompatibilityType(str, Enum):
|
13
|
+
MLX = "mlx"
|
14
|
+
GGUF = "gguf"
|
15
|
+
|
16
|
+
class ModelState(str, Enum):
|
17
|
+
LOADED = "loaded"
|
18
|
+
NOT_LOADED = "not-loaded"
|
19
|
+
|
20
|
+
class ModelInfo(BaseModel):
|
21
|
+
id: str = Field(..., description="Unique model identifier in LM Studio's namespace")
|
22
|
+
object: Literal["model"] = Field("model", description="Always 'model' for model objects")
|
23
|
+
type: ModelType = Field(..., description="Type of AI model")
|
24
|
+
publisher: str = Field(..., description="Organization or user who published the model")
|
25
|
+
arch: str = Field(..., description="Base architecture family")
|
26
|
+
compatibility_type: CompatibilityType = Field(..., alias="compatibility_type")
|
27
|
+
quantization: Optional[str] = Field(None, description="Quantization method if applicable")
|
28
|
+
state: ModelState = Field(..., description="Current loading state in LM Studio")
|
29
|
+
max_context_length: int = Field(..., alias="max_context_length", ge=0)
|
30
|
+
loaded_context_length: Optional[int] = Field(
|
31
|
+
None,
|
32
|
+
alias="loaded_context_length",
|
33
|
+
description="Currently allocated context length (only when loaded)",
|
34
|
+
ge=0
|
35
|
+
)
|
36
|
+
|
37
|
+
class ModelListResponse(BaseModel):
|
38
|
+
data: List[ModelInfo] = Field(..., description="List of available models")
|
39
|
+
object: Literal["list"] = Field("list", description="Always 'list' for list responses")
|
40
|
+
|
41
|
+
def get_model_list() -> ModelListResponse:
|
42
|
+
"""Fetch and validate model information from LM Studio's API"""
|
43
|
+
import requests
|
44
|
+
|
45
|
+
response = requests.get("http://localhost:1234/api/v0/models")
|
46
|
+
response.raise_for_status()
|
47
|
+
|
48
|
+
return ModelListResponse(**response.json())
|
quantalogic/xml_parser.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: quantalogic
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.32.0
|
4
4
|
Summary: QuantaLogic ReAct Agents
|
5
5
|
Author: Raphaël MANSUY
|
6
6
|
Author-email: raphael.mansuy@gmail.com
|
@@ -116,7 +116,7 @@ We created [QuantaLogic](https://www.quantalogic.app) because we saw a significa
|
|
116
116
|
|
117
117
|
## Usage
|
118
118
|
|
119
|
-
**Usage:** `quantalogic [OPTIONS] COMMAND [ARGS]...`
|
119
|
+
**Usage:** `quantalogic [OPTIONS] COMMAND i[ARGS]...`
|
120
120
|
**Environment Variables:** Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, and `DEEPSEEK_API_KEY` for API integration.
|
121
121
|
|
122
122
|
**Options:**
|
@@ -131,6 +131,7 @@ We created [QuantaLogic](https://www.quantalogic.app) because we saw a significa
|
|
131
131
|
- `--help`: Show help message
|
132
132
|
|
133
133
|
**Commands:**
|
134
|
+
|
134
135
|
- `task`: Execute a task with the QuantaLogic AI Assistant
|
135
136
|
- `--file PATH`: Path to task file
|
136
137
|
- `--model-name TEXT`: Specify model
|
@@ -143,6 +144,25 @@ We created [QuantaLogic](https://www.quantalogic.app) because we saw a significa
|
|
143
144
|
- `--compact-every-n-iteration`: Memory optimization
|
144
145
|
- `--no-stream`: Disable streaming
|
145
146
|
|
147
|
+
|
148
|
+
- `list-models`: List available models with optional filtering.
|
149
|
+
- `--search TEXT`: Filter models by name or description.
|
150
|
+
- `--help`: Show help message.
|
151
|
+
|
152
|
+
Example:
|
153
|
+
```bash
|
154
|
+
quantalogic list-models --search qwen
|
155
|
+
```
|
156
|
+
|
157
|
+
Output:
|
158
|
+
```
|
159
|
+
Model Name Description
|
160
|
+
------------------- -------------------------------------------------------
|
161
|
+
dashscope/qwen-max Alibaba's Qwen-Max model optimized for maximum performance
|
162
|
+
dashscope/qwen-plus Alibaba's Qwen-Plus model offering balanced performance
|
163
|
+
```
|
164
|
+
|
165
|
+
|
146
166
|
## Release Notes
|
147
167
|
|
148
168
|
See our [Release Notes](RELEASE_NOTES.MD) for detailed version history and changes.
|
@@ -164,12 +184,25 @@ See our [Release Notes](RELEASE_NOTES.MD) for detailed version history and chang
|
|
164
184
|
| openrouter/openai/gpt-4o | OPENROUTER_API_KEY | OpenAI's GPT-4o model accessible through OpenRouter platform. |
|
165
185
|
| openrouter/mistralai/mistral-large-2411 | OPENROUTER_API_KEY | Mistral's large model optimized for complex reasoning tasks, available through OpenRouter with enhanced multilingual capabilities. |
|
166
186
|
| mistral/mistral-large-2407 | MISTRAL_API_KEY | Mistral's high-performance model designed for enterprise-grade applications, offering advanced reasoning and multilingual support. |
|
187
|
+
| nvidia/deepseek-ai/deepseek-r1 | NVIDIA_API_KEY | NVIDIA's DeepSeek R1 model optimized for high-performance AI tasks and advanced reasoning capabilities. |
|
188
|
+
| lm_studio/mistral-small-24b-instruct-2501 | LM_STUDIO_API_KEY | LM Studio's Mistral Small model optimized for local inference with advanced reasoning capabilities. |
|
167
189
|
| dashscope/qwen-max | DASHSCOPE_API_KEY | Alibaba's Qwen-Max model optimized for maximum performance and extensive reasoning capabilities. |
|
168
190
|
| dashscope/qwen-plus | DASHSCOPE_API_KEY | Alibaba's Qwen-Plus model offering balanced performance and cost-efficiency for a variety of tasks. |
|
169
191
|
| dashscope/qwen-turbo | DASHSCOPE_API_KEY | Alibaba's Qwen-Turbo model designed for fast and efficient responses, ideal for high-throughput scenarios. |
|
170
192
|
|
171
193
|
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/).
|
172
194
|
|
195
|
+
### LM Studio Local Setup
|
196
|
+
|
197
|
+
To use LM Studio with the Mistral model locally, set the following environment variables:
|
198
|
+
|
199
|
+
```bash
|
200
|
+
export LM_STUDIO_API_BASE="http://localhost:1234/v1"
|
201
|
+
export LM_STUDIO_API_KEY="your-api-key-here"
|
202
|
+
```
|
203
|
+
|
204
|
+
Replace `http://localhost:1234/v1` with your LM Studio server URL and `your-api-key-here` with your actual API key.
|
205
|
+
|
173
206
|
|
174
207
|
## 📦 Installation
|
175
208
|
|
@@ -1,5 +1,5 @@
|
|
1
|
-
quantalogic/__init__.py,sha256=
|
2
|
-
quantalogic/agent.py,sha256=
|
1
|
+
quantalogic/__init__.py,sha256=Su8CnOEdqKu4zTytjiP9P5olg-oIDuUA3fMWM1WUdRY,925
|
2
|
+
quantalogic/agent.py,sha256=VqxM_VizDpwH3SLAnoSFMjH4a1ijBVOHaI6rXahHP7M,33289
|
3
3
|
quantalogic/agent_config.py,sha256=SIRVSF0kkrYfvtyHiMCJhnm_nYqJCD2p1pN-reMIy24,7868
|
4
4
|
quantalogic/agent_factory.py,sha256=HWKwN_DN57EPmME-hoCD2uJE0DqsPCzGU_V7nq54XzI,5284
|
5
5
|
quantalogic/coding_agent.py,sha256=Z7ik6LUvLKDnaW9Ax1iZGC7p1WMnlYEUIlE5lkBP414,4975
|
@@ -9,11 +9,14 @@ quantalogic/console_print_token.py,sha256=qSU-3kmoZk4T5-1ybrEBi8tIXDPcz7eyWKhGh3
|
|
9
9
|
quantalogic/docs_cli.py,sha256=3giVbUpespB9ZdTSJ955A3BhcOaBl5Lwsn1AVy9XAeY,1663
|
10
10
|
quantalogic/event_emitter.py,sha256=jqot2g4JRXc88K6PW837Oqxbf7shZfO-xdPaUWmzupk,7901
|
11
11
|
quantalogic/generative_model.py,sha256=ut_BFy4BqDxNqUXVbM8e_C_CzwNuJkvGWRsbpbKaees,13423
|
12
|
-
quantalogic/get_model_info.py,sha256=
|
12
|
+
quantalogic/get_model_info.py,sha256=_9Nb9JQ09HZzT-_gZUSvl4Er7uCXs5ys36sIBa-8DXA,3005
|
13
13
|
quantalogic/interactive_text_editor.py,sha256=1vW4poJl7SItRGEeGQgtCFcmRDXmfCM8PE-uBtDBJuE,16658
|
14
|
-
quantalogic/llm.py,sha256=
|
14
|
+
quantalogic/llm.py,sha256=Nk2Dn1lJh1-323Fs7ADfR9ov_eAoJOEEnzyGswZSbJI,5460
|
15
15
|
quantalogic/main.py,sha256=__-4pX2pgoSFvt-aLdp6Qlrq55_SrwP_l8u2uTaQbjg,9262
|
16
16
|
quantalogic/memory.py,sha256=zbtRuM05jaS2lJll-92dt5JfYVLERnF_m_9xqp2x-k0,6304
|
17
|
+
quantalogic/model_info.py,sha256=j7QqvjEFQDGpDOgQs8uTkVyI3a50Oa_nrsQjyxizTLc,272
|
18
|
+
quantalogic/model_info_list.py,sha256=bJu2ohQFgZOwmcqydfh5oi5R1G8ZY7jtQlERsR1Z47s,1816
|
19
|
+
quantalogic/model_info_litellm.py,sha256=m1Yt4SIiOBRWLx7S8f8k4fcTiKJZKtOvcPN_QvQ_Oxk,1880
|
17
20
|
quantalogic/model_names.py,sha256=UZlz25zG9B2dpfwdw_e1Gw5qFsKQ7iME9FJh9Ts4u6s,938
|
18
21
|
quantalogic/prompts.py,sha256=M-7rCaQoylnwxedhvy7VmQdgBG6TT1vmcf8_UzPTyY0,4035
|
19
22
|
quantalogic/search_agent.py,sha256=EA_FAPP0dVuUbJ_lAGKfYq1FIJ6oLYzGMgKLMvBL4ZQ,2472
|
@@ -26,7 +29,7 @@ quantalogic/server/static/js/event_visualizer.js,sha256=eFkkWyNZw3zOZlF18kxbfsWq
|
|
26
29
|
quantalogic/server/static/js/quantalogic.js,sha256=x7TrlZGR1Y0WLK2DWl1xY847BhEWMPnL0Ua7KtOldUc,22311
|
27
30
|
quantalogic/server/templates/index.html,sha256=nDnXJoQEm1vXbhXtgaYk0G5VXj0wwzE6KrqEDhHFpj4,7773
|
28
31
|
quantalogic/task_file_reader.py,sha256=AMIJoeVY9Hhu0dBJ-C5EyaOFsXLkhn2oBhVs-WTnnLk,1460
|
29
|
-
quantalogic/task_runner.py,sha256=
|
32
|
+
quantalogic/task_runner.py,sha256=6kL7o0br2YU8FNKyq-rKJo1oGKZKl73vtATpHusPIWQ,10038
|
30
33
|
quantalogic/tool_manager.py,sha256=Uh-ufrJPufHqDUrFwKlXw3MOsVGc_4lQxuc6cRvZ7wU,7186
|
31
34
|
quantalogic/tools/__init__.py,sha256=pTirT5UBynuTkAzFYebu7ttGAMP3_A0idFvDp6lGZJQ,2146
|
32
35
|
quantalogic/tools/agent_tool.py,sha256=MXCXxWHRch7VK4UWhtRP1jeI8Np9Ne2CUGo8vm1oZiM,3064
|
@@ -35,7 +38,7 @@ quantalogic/tools/download_http_file_tool.py,sha256=wTfanbXjIRi5-qrbluuLvNmDNhvm
|
|
35
38
|
quantalogic/tools/duckduckgo_search_tool.py,sha256=xVaEb_SUK5NL3lwMQXj1rGQYYvNT-td-qaB9QCes27Q,7014
|
36
39
|
quantalogic/tools/edit_whole_content_tool.py,sha256=nXmpAvojvqvAcqNMy1kUKZ1ocboky_ZcnCR4SNCSPgw,2360
|
37
40
|
quantalogic/tools/elixir_tool.py,sha256=fzPPtAW-Koy9KB0r5k2zV1f1U0WphL-LXPPOBkeNkug,7652
|
38
|
-
quantalogic/tools/execute_bash_command_tool.py,sha256=
|
41
|
+
quantalogic/tools/execute_bash_command_tool.py,sha256=YK_cMuODJDOYheZKGmlpZTxJdVbimFLCUlND2_zmyMg,6869
|
39
42
|
quantalogic/tools/generate_database_report_tool.py,sha256=QbZjtmegGEOEZAIa-CSeBo5O9dYBZTk_PWrumyFUg1Q,1890
|
40
43
|
quantalogic/tools/grep_app_tool.py,sha256=BDxygwx7WCbqbiP2jmSRnIsoIUVYG5A4SKzId524ys4,19957
|
41
44
|
quantalogic/tools/input_question_tool.py,sha256=UoTlNhdmdr-eyiVtVCG2qJe_R4bU_ag-DzstSdmYkvM,1848
|
@@ -72,24 +75,25 @@ quantalogic/tools/utils/create_sample_database.py,sha256=Aus9xRLGfQfsYnxsAkJ5CW-
|
|
72
75
|
quantalogic/tools/utils/generate_database_report.py,sha256=0D-5fWOfpAh1jEcld5OTQP5x6XkJE5jpNY6FyHv1L2s,10345
|
73
76
|
quantalogic/tools/wikipedia_search_tool.py,sha256=bdZ_0dYTxpEfU04tBFsatnLM5P9Z3kAZgKQEjsopJLA,5405
|
74
77
|
quantalogic/tools/write_file_tool.py,sha256=_mx9_Zjg2oMAAVzlcHEKjZVZUxQVgbRfcoMKgWnoZcg,3764
|
75
|
-
quantalogic/utils/__init__.py,sha256=
|
78
|
+
quantalogic/utils/__init__.py,sha256=E442CJQuTohKzgI0Wrd4NZEpKascFjz6F4Vy8Y1c_0Y,634
|
76
79
|
quantalogic/utils/ask_user_validation.py,sha256=F0jkbFJVXAImcSSP7op6dov5i80hRvZGRvBHbfcZrxg,340
|
77
80
|
quantalogic/utils/check_version.py,sha256=grxTfJE85GMue1OAk8z8_q8tjEJxQ8RO6fN3fJ_qedg,1136
|
78
81
|
quantalogic/utils/download_http_file.py,sha256=FTN3brq9WvCFvuBX-lYAhjsdYTzQT4m9m2vqlcyjkNk,3472
|
79
|
-
quantalogic/utils/get_all_models.py,sha256=
|
82
|
+
quantalogic/utils/get_all_models.py,sha256=Ol4e60MwZiJhu8HZ2i_RpIumLmFYYrncB1X9q1KEQh0,544
|
80
83
|
quantalogic/utils/get_coding_environment.py,sha256=oMK5ZanOqX_SFaJxUZQGlsAAaiLUgJufCJYDrHnHPuQ,584
|
81
84
|
quantalogic/utils/get_environment.py,sha256=7wWruSHYTUlnQWW27qU3WFYZnncqqqdofsxAsUU7lhw,875
|
82
85
|
quantalogic/utils/get_quantalogic_rules_content.py,sha256=fnEFTyClXzpI0MLaM-gB9R6l4CJlu2NnaYiR09ciJC8,673
|
83
86
|
quantalogic/utils/git_ls.py,sha256=_k6QIQtc0aM1bsG340jBp4VrdevbcH8Pg2CV4r9oHok,5264
|
87
|
+
quantalogic/utils/lm_studio_model_info.py,sha256=1eDvZ-I9W8AZbCch1l5rdiSpUxL7qMnfZItdFZkmAWs,1819
|
84
88
|
quantalogic/utils/read_file.py,sha256=tSRVHk8dIP4nNLL89v5kRki4hOTjVyjbmuEb2zwvwCY,2077
|
85
89
|
quantalogic/utils/read_http_text_content.py,sha256=n3IayT5KcqctIVVF2gOQQAMf3Ow6eenlVgfXTpLcQbw,4410
|
86
90
|
quantalogic/version.py,sha256=ea_cRutaQk5_lwlLbUUvPFuOT7Of7-gAsDl7wdveS-g,107
|
87
91
|
quantalogic/version_check.py,sha256=cttR1lR3OienGLl7NrK1Te1fhDkqSjCci7HC1vFUTSY,1627
|
88
92
|
quantalogic/welcome_message.py,sha256=IXMhem8h7srzNUwvw8G_lmEkHU8PFfote021E_BXmVk,3039
|
89
|
-
quantalogic/xml_parser.py,sha256=
|
93
|
+
quantalogic/xml_parser.py,sha256=8yDxvKzAEnefNwUAR-wjerMDOj5T5cxak4WPIA83SBw,11516
|
90
94
|
quantalogic/xml_tool_parser.py,sha256=Vz4LEgDbelJynD1siLOVkJ3gLlfHsUk65_gCwbYJyGc,3784
|
91
|
-
quantalogic-0.
|
92
|
-
quantalogic-0.
|
93
|
-
quantalogic-0.
|
94
|
-
quantalogic-0.
|
95
|
-
quantalogic-0.
|
95
|
+
quantalogic-0.32.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
96
|
+
quantalogic-0.32.0.dist-info/METADATA,sha256=w5kJUS98ou0kVeY9fy-WImrW-W9wWZFOXmIQx4xK-_M,23461
|
97
|
+
quantalogic-0.32.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
98
|
+
quantalogic-0.32.0.dist-info/entry_points.txt,sha256=h74O_Q3qBRCrDR99qvwB4BpBGzASPUIjCfxHq6Qnups,183
|
99
|
+
quantalogic-0.32.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|