quantalogic 0.30.8__py3-none-any.whl → 0.31.1__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/main.py CHANGED
@@ -8,6 +8,7 @@ from typing import Optional
8
8
  # Third-party imports
9
9
  import click
10
10
  from dotenv import load_dotenv
11
+ from fuzzywuzzy import process
11
12
  from loguru import logger
12
13
 
13
14
  from quantalogic.version import get_version
@@ -26,7 +27,9 @@ from rich.panel import Panel # noqa: E402
26
27
  from quantalogic.agent_config import ( # noqa: E402
27
28
  MODEL_NAME,
28
29
  )
30
+ from quantalogic.config import QLConfig # noqa: E402
29
31
  from quantalogic.task_runner import task_runner # noqa: E402
32
+ from quantalogic.utils.get_all_models import get_all_models # noqa: E402
30
33
 
31
34
  # Platform-specific imports
32
35
  try:
@@ -149,8 +152,7 @@ def cli(
149
152
  ctx.exit()
150
153
 
151
154
  if ctx.invoked_subcommand is None:
152
- ctx.invoke(
153
- task,
155
+ config = QLConfig(
154
156
  model_name=model_name,
155
157
  verbose=verbose,
156
158
  mode=mode,
@@ -159,6 +161,18 @@ def cli(
159
161
  max_iterations=max_iterations,
160
162
  compact_every_n_iteration=compact_every_n_iteration,
161
163
  max_tokens_working_memory=max_tokens_working_memory,
164
+ no_stream=False # Default value for backward compatibility
165
+ )
166
+ ctx.invoke(
167
+ task,
168
+ model_name=config.model_name,
169
+ verbose=config.verbose,
170
+ mode=config.mode,
171
+ log=config.log,
172
+ vision_model_name=config.vision_model_name,
173
+ max_iterations=config.max_iterations,
174
+ compact_every_n_iteration=config.compact_every_n_iteration,
175
+ max_tokens_working_memory=config.max_tokens_working_memory,
162
176
  )
163
177
 
164
178
 
@@ -222,19 +236,23 @@ def task(
222
236
  console = Console()
223
237
 
224
238
  try:
239
+ config = QLConfig(
240
+ model_name=model_name,
241
+ verbose=verbose,
242
+ mode=mode,
243
+ log=log,
244
+ vision_model_name=vision_model_name,
245
+ max_iterations=max_iterations,
246
+ compact_every_n_iteration=compact_every_n_iteration,
247
+ max_tokens_working_memory=max_tokens_working_memory,
248
+ no_stream=no_stream,
249
+ )
250
+
225
251
  task_runner(
226
252
  console,
227
253
  file,
228
- model_name,
229
- verbose,
230
- mode,
231
- log,
232
- vision_model_name,
254
+ config,
233
255
  task,
234
- max_iterations,
235
- compact_every_n_iteration,
236
- max_tokens_working_memory,
237
- no_stream,
238
256
  )
239
257
  except Exception as e:
240
258
  console.print(f"[red]{str(e)}[/red]")
@@ -242,6 +260,37 @@ def task(
242
260
  sys.exit(1)
243
261
 
244
262
 
263
+ @cli.command()
264
+ @click.option("--search", type=str, help="Fuzzy search for models containing the given string.")
265
+ def list_models(search: Optional[str] = None):
266
+ """List supported LiteLLM models with optional fuzzy search.
267
+
268
+ If a search term is provided, it will return models that closely match the term.
269
+ """
270
+ console = Console()
271
+ all_models = get_all_models()
272
+
273
+ if search:
274
+ # Perform fuzzy matching
275
+ matched_models = process.extractBests(search, all_models, limit=None, score_cutoff=70)
276
+ models = [model for model, score in matched_models]
277
+ else:
278
+ models = all_models
279
+
280
+ console.print(Panel(
281
+ f"Total Models: {len(models)} "
282
+ f"({len(all_models)} total)",
283
+ title="Supported LiteLLM Models"
284
+ ))
285
+
286
+ if not models:
287
+ console.print(f"[yellow]No models found matching '[bold]{search}[/bold]'[/yellow]")
288
+ return
289
+
290
+ for model in sorted(models):
291
+ console.print(f"- {model}")
292
+
293
+
245
294
  def main():
246
295
  """Main entry point."""
247
296
  old_settings = setup_terminal()
quantalogic/prompts.py CHANGED
@@ -1,8 +1,9 @@
1
+
1
2
  def system_prompt(tools: str, environment: str, expertise: str = ""):
2
3
  """System prompt for the ReAct chatbot."""
3
4
  return f"""
4
5
  ### Core Identity
5
- You are QuantaLogic, an advanced ReAct AI Agent specialized in systematic problem-solving.
6
+ You are QuantaLogic, an advanced ReAct AI Agent specializing in systematic problem-solving.
6
7
 
7
8
  ### Specific Expertise
8
9
  {expertise}
@@ -14,81 +15,105 @@ Tasks will be presented within XML tags:
14
15
  ### Response Protocol
15
16
  Every response must contain exactly two XML blocks:
16
17
 
17
- 1. Analysis Block:
18
+ 1. **Analysis Block**:
18
19
  ```xml
19
20
  <thinking>
20
- <!-- Must follow this precise format, concise, dense, use abreviations, emojis, unicode characters to make it denser -->
21
- <task_analysis_if_no_history>
22
- Only if no conversation history:
23
- * Rewrite the <task> and its context with your own words in detailed, clear, and specific manner.
24
- * If not previously defined, clarify detailed criteria for task completion.
21
+ <!-- Follow this precise format. Be concise, dense, and use abbreviations, emojis, and Unicode characters to maximize density. -->
22
+ <task_analysis_if_no_history>
23
+ <!-- Only include if no conversation history exists: -->
24
+ * Rewrite the <task> and its context in your own words, ensuring clarity and specificity.
25
+ * Define detailed criteria for task completion if not already provided.
25
26
  * Identify key components, constraints, and potential challenges.
26
- * Decompose into Sub-Tasks: Break the <task> down into smaller, manageable sub-tasks if necessary.
27
- * Each sub-task should have a clear objective, specific deliverables, and be sequenced logically to facilitate step-by-step progress tracking.
27
+ * Break the <task> into smaller, manageable sub-tasks if necessary.
28
+ - Each sub-task should have a clear objective, specific deliverables, and a logical sequence for progress tracking.
28
29
  </task_analysis_if_no_history>
29
30
  <success_criteria_if_no_history>
30
- If no conversation history:
31
+ <!-- Only include if no conversation history exists: -->
31
32
  * Specify measurable outcomes for task completion.
32
33
  * Define explicit quality benchmarks and performance indicators.
33
- * Note any constraints or limitations that may affect the task.
34
+ * Note any constraints or limitations affecting the task.
34
35
  </success_criteria_if_no_history>
35
- <strategic_approach_if_no_history>
36
- If no conversation history:
37
- * Lay out a clear, high-level strategy for solving the task.
36
+ <strategic_approach_if_no_history>
37
+ <!-- Only include if no conversation history exists: -->
38
+ * Outline a high-level strategy for solving the task.
38
39
  * Identify required resources, tools, or information.
39
- * Anticipate possible roadblocks and outline contingency plans.
40
+ * Anticipate potential roadblocks and propose contingency plans.
40
41
  </strategic_approach_if_no_history>
41
42
  <last_observation>
42
- <!-- if there is a conversation history -->
43
+ <!-- Include if conversation history exists: -->
43
44
  <variable>
44
- <name> ... variable name ... </name>
45
- <description> ... concise description ... </description>
45
+ <name>...variable name...</name>
46
+ <description>...concise description...</description>
46
47
  </variable>
47
48
  <result>
48
- ... concise description ...
49
- How this result help to the progress of the task or the problem?
49
+ ...concise description of the result...
50
+ How does this result contribute to task progress?
50
51
  </result>
51
52
  </last_observation>
52
- <progess_analysis>
53
- <!-- if there is a conversation history -->
54
- * Detail each step failed and completed so far, be concise.
55
- * Identify and evaluate any blockers or challenges to the progress of global task.
56
- * Identify repetitions: if repeated steps, take a step back and rethink your approach.
57
- * Provide potential solutions, and if needed, suggest reevaluating the approach and the plan.
58
- </progess_analysis>
53
+ <progress_analysis>
54
+ <!-- Include if conversation history exists: -->
55
+ * Summarize completed and failed steps concisely.
56
+ * Identify and evaluate blockers or challenges.
57
+ * Highlight repetitions and suggest reevaluating the approach if necessary.
58
+ * Propose potential solutions or alternative strategies.
59
+ </progress_analysis>
59
60
  <variables>
60
- <!-- if there is a conversation history -->
61
- * List all variable names and concisely describe their current values.
61
+ <!-- Include if conversation history exists: -->
62
+ * List all variable names and their current values concisely.
62
63
  </variables>
63
64
  <next_steps>
64
65
  * Outline immediate actions required.
65
66
  * Justify tool selection and parameter choices.
66
- * Prefer variable interpolation if possible, to minimize generation of tokens.
67
- * Consider alternatives, take a step back if previous attempts were unsuccessful to review the plan.
67
+ * Use variable interpolation (e.g., `$var1$`) to minimize token generation.
68
+ * Consider alternatives or reevaluate the plan if previous attempts failed.
69
+ * Use the `task_complete` tool to confirm task completion.
68
70
  </next_steps>
69
71
  <taskpad>
70
- <!-- optional -->
71
- <note>Use this to record notes about intermediate steps.</note>
72
+ <!-- Optional: Use for notes about intermediate steps. -->
73
+ <note>...</note>
72
74
  </taskpad>
73
75
  </thinking>
74
76
  ```
75
77
 
76
- 2. Action Block:
78
+ 2. **Action Block**:
77
79
  ```xml
78
80
  <tool_name>
79
- <!-- tool_name is the name of the tool from available tools -->
80
- <parameter1>
81
- <!-- Use variable interpolation to pass context to minimize generation of tokens, example: <content>$var1$<</content> -->
82
- value1
83
- </parameter1>
84
- <parameter2>value2</parameter2>
81
+ <!-- Replace `tool_name` with the name of the tool from the available tools. -->
82
+ <parameter1>
83
+ <!-- Use variable interpolation (e.g., `$var1$`) to pass context and minimize token generation. -->
84
+ value1
85
+ </parameter1>
86
+ <parameter2>value2</parameter2>
85
87
  </tool_name>
86
88
  ```
87
89
 
90
+ ### Examples of Action Blocks
91
+ - **New Task Example**:
92
+ ```xml
93
+ <data_analyzer>
94
+ <file_path>$input_file$</file_path>
95
+ <operation>validate_structure</operation>
96
+ </data_analyzer>
97
+ ```
98
+
99
+ - **Continuing Task Example**:
100
+ ```xml
101
+ <memory_optimizer>
102
+ <process_id>$current_process$</process_id>
103
+ <target_utilization>75%</target_utilization>
104
+ </memory_optimizer>
105
+ ```
106
+
107
+ - **Task Completion Example / When a task is completed**:
108
+ ```xml
109
+ <task_complete>
110
+ <answer>Task completed successfully</answer>
111
+ </task_complete>
112
+ ```
113
+
88
114
  ### Available Tools
89
115
  {tools}
90
116
 
91
117
  ### Environment Details
92
118
  {environment}
93
-
94
119
  """
@@ -9,7 +9,8 @@ from rich.console import Console
9
9
  from rich.panel import Panel
10
10
  from rich.prompt import Confirm
11
11
 
12
- from quantalogic.agent_factory import create_agent_for_mode
12
+ from quantalogic.agent_factory import AgentRegistry, create_agent_for_mode
13
+ from quantalogic.config import QLConfig
13
14
  from quantalogic.console_print_events import console_print_events
14
15
  from quantalogic.interactive_text_editor import get_multiline_input
15
16
  from quantalogic.task_file_reader import get_task_from_file
@@ -144,52 +145,38 @@ def interactive_task_runner(
144
145
  def task_runner(
145
146
  console: Console,
146
147
  file: Optional[str],
147
- model_name: str,
148
- verbose: bool,
149
- mode: str,
150
- log: str,
151
- vision_model_name: str | None,
148
+ config: QLConfig,
152
149
  task: Optional[str],
153
- max_iterations: int,
154
- compact_every_n_iteration: int | None,
155
- max_tokens_working_memory: int | None,
156
- no_stream: bool,
157
150
  ) -> None:
158
151
  """Execute a task with the QuantaLogic AI Assistant.
159
152
 
160
153
  Args:
161
154
  console: Rich console instance for output
162
155
  file: Optional path to task file
163
- model_name: Name of the model to use
164
- verbose: Enable verbose logging
165
- mode: Operation mode
166
- log: Log level
167
- vision_model_name: Optional vision model name
156
+ config: QuantaLogic configuration object
168
157
  task: Optional task string
169
- max_iterations: Maximum number of iterations
170
- compact_every_n_iteration: Optional number of iterations before memory compaction
171
- max_tokens_working_memory: Optional maximum tokens for working memory
172
- no_stream: Disable streaming output
173
158
  """
174
- switch_verbose(verbose, log)
159
+ switch_verbose(config.verbose, config.log)
175
160
 
176
161
  # Create the agent instance with the specified configuration
177
162
  agent = create_agent_for_mode(
178
- mode=mode,
179
- model_name=model_name,
180
- vision_model_name=vision_model_name,
181
- compact_every_n_iteration=compact_every_n_iteration,
182
- max_tokens_working_memory=max_tokens_working_memory
163
+ mode=config.mode,
164
+ model_name=config.model_name,
165
+ vision_model_name=config.vision_model_name,
166
+ compact_every_n_iteration=config.compact_every_n_iteration,
167
+ max_tokens_working_memory=config.max_tokens_working_memory
183
168
  )
184
169
 
170
+ AgentRegistry.register_agent("main_agent", agent)
171
+
185
172
  if file:
186
173
  task_content = get_task_from_file(file)
187
174
  # Execute single task from file
188
175
  logger.debug(f"Solving task with agent: {task_content}")
189
- if max_iterations < 1:
176
+ if config.max_iterations < 1:
190
177
  raise ValueError("max_iterations must be greater than 0")
191
- result = agent.solve_task(task=task_content, max_iterations=max_iterations, streaming=not no_stream)
192
- logger.debug(f"Task solved with result: {result} using {max_iterations} iterations")
178
+ result = agent.solve_task(task=task_content, max_iterations=config.max_iterations, streaming=not config.no_stream)
179
+ logger.debug(f"Task solved with result: {result} using {config.max_iterations} iterations")
193
180
 
194
181
  console.print(
195
182
  Panel.fit(
@@ -204,10 +191,10 @@ def task_runner(
204
191
  task_content = task
205
192
  # Execute single task from command line
206
193
  logger.debug(f"Solving task with agent: {task_content}")
207
- if max_iterations < 1:
194
+ if config.max_iterations < 1:
208
195
  raise ValueError("max_iterations must be greater than 0")
209
- result = agent.solve_task(task=task_content, max_iterations=max_iterations, streaming=not no_stream)
210
- logger.debug(f"Task solved with result: {result} using {max_iterations} iterations")
196
+ result = agent.solve_task(task=task_content, max_iterations=config.max_iterations, streaming=not config.no_stream)
197
+ logger.debug(f"Task solved with result: {result} using {config.max_iterations} iterations")
211
198
 
212
199
  console.print(
213
200
  Panel.fit(
@@ -220,17 +207,17 @@ def task_runner(
220
207
  # Interactive mode
221
208
  display_welcome_message(
222
209
  console=console,
223
- model_name=model_name,
210
+ model_name=config.model_name,
224
211
  version=get_version(),
225
- vision_model_name=vision_model_name,
226
- max_iterations=max_iterations,
227
- compact_every_n_iteration=compact_every_n_iteration,
228
- max_tokens_working_memory=max_tokens_working_memory,
229
- mode=mode,
212
+ vision_model_name=config.vision_model_name,
213
+ max_iterations=config.max_iterations,
214
+ compact_every_n_iteration=config.compact_every_n_iteration,
215
+ max_tokens_working_memory=config.max_tokens_working_memory,
216
+ mode=config.mode,
230
217
  )
231
218
  check_new_version()
232
219
  logger.debug(
233
- f"Created agent for mode: {mode} with model: {model_name}, vision model: {vision_model_name}, no_stream: {no_stream}"
220
+ f"Created agent for mode: {config.mode} with model: {config.model_name}, vision model: {config.vision_model_name}, no_stream: {config.no_stream}"
234
221
  )
235
222
 
236
223
  events = [
@@ -281,4 +268,4 @@ def task_runner(
281
268
 
282
269
  logger.debug("Registered event handlers for agent events with events: {events}")
283
270
 
284
- interactive_task_runner(agent, console, max_iterations, no_stream)
271
+ interactive_task_runner(agent, console, config.max_iterations, config.no_stream)
@@ -91,6 +91,72 @@ class ToolManager(BaseModel):
91
91
  "bool": lambda x: str(x).lower() in ['true', '1', 'yes']
92
92
  }
93
93
 
94
+ for arg_def in tool.arguments:
95
+ arg_name = arg_def.name
96
+ arg_type = arg_def.arg_type
97
+ required = arg_def.required
98
+ default = arg_def.default
99
+
100
+ # Handle missing arguments
101
+ if arg_name not in provided_args:
102
+ if required:
103
+ raise ValueError(f"Missing required argument: {arg_name}")
104
+ if default is None:
105
+ continue # Skip optional args with no default
106
+ provided_args[arg_name] = default
107
+
108
+ value = provided_args[arg_name]
109
+
110
+ # Handle empty string for non-string types by replacing with default if available
111
+ if (
112
+ arg_type != "string"
113
+ and isinstance(value, str)
114
+ and value.strip() == ""
115
+ and default is not None
116
+ ):
117
+ logger.debug(f"Replaced empty string for argument {arg_name} with default value {default}")
118
+ value = default
119
+ provided_args[arg_name] = value # Update to ensure validation uses the default
120
+
121
+ # Type conversion
122
+ if arg_type in type_conversion:
123
+ try:
124
+ converted = type_conversion[arg_type](value)
125
+ except (ValueError, TypeError) as e:
126
+ raise ValueError(
127
+ f"Invalid value '{value}' for {arg_name} ({arg_type}): {str(e)}"
128
+ )
129
+ converted_args[arg_name] = converted
130
+ else:
131
+ converted_args[arg_name] = value # Unknown type, pass through
132
+
133
+ # Validate extra arguments
134
+ extra_args = set(provided_args.keys()) - {a.name for a in tool.arguments}
135
+ if extra_args:
136
+ raise ValueError(f"Unexpected arguments: {', '.join(extra_args)}")
137
+
138
+ return converted_args
139
+ """Validates and converts arguments based on tool definition.
140
+
141
+ Args:
142
+ tool_name: Name of the tool to validate against
143
+ provided_args: Dictionary of arguments to validate
144
+
145
+ Returns:
146
+ Dictionary of converted arguments with proper types
147
+
148
+ Raises:
149
+ ValueError: For missing/invalid arguments or conversion errors
150
+ """
151
+ tool = self.get(tool_name)
152
+ converted_args = {}
153
+ type_conversion = {
154
+ "string": lambda x: str(x),
155
+ "int": lambda x: int(x),
156
+ "float": lambda x: float(x),
157
+ "bool": lambda x: str(x).lower() in ['true', '1', 'yes']
158
+ }
159
+
94
160
  for arg_def in tool.arguments:
95
161
  arg_name = arg_def.name
96
162
  arg_type = arg_def.arg_type
@@ -11,7 +11,7 @@ from loguru import logger
11
11
 
12
12
  # Platform-specific imports
13
13
  try:
14
- if sys.platform != 'win32':
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='utf-8'
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 = ''.join(stdout_buffer)
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 == 'win32':
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())
@@ -35,7 +35,7 @@ class SearchReplaceBlock(BaseModel):
35
35
 
36
36
  search: str = Field(
37
37
  ...,
38
- description="Exact content to search for in the file.",
38
+ description="Exact content to search for in the file. Space and tab characters are VERY important.",
39
39
  example="def old_function():\n pass",
40
40
  )
41
41
  replace: str = Field(
@@ -69,6 +69,7 @@ class SearchDefinitionNames(Tool):
69
69
  description="The page number to retrieve (1-based index).",
70
70
  required=False,
71
71
  example="1",
72
+ default="1"
72
73
  ),
73
74
  ToolArgument(
74
75
  name="page_size",
@@ -76,6 +77,7 @@ class SearchDefinitionNames(Tool):
76
77
  description="The number of results per page (default: 10).",
77
78
  required=False,
78
79
  example="10",
80
+ default="10"
79
81
  ),
80
82
  ]
81
83
 
@@ -30,14 +30,16 @@ class SQLQueryTool(Tool):
30
30
  arg_type="int",
31
31
  description="1-based starting row number for results",
32
32
  required=True,
33
- example="1"
33
+ example="1",
34
+ default="1"
34
35
  ),
35
36
  ToolArgument(
36
37
  name="end_row",
37
38
  arg_type="int",
38
39
  description="1-based ending row number for results",
39
40
  required=True,
40
- example="100"
41
+ example="100",
42
+ default="100"
41
43
  ),
42
44
  ]
43
45
  connection_string: str = Field(
@@ -0,0 +1,20 @@
1
+ import litellm
2
+
3
+
4
+ from quantalogic.get_model_info import model_info
5
+
6
+ def get_all_models() -> list[str]:
7
+ """
8
+ Retrieves a unified list of all model names supported by LiteLLM and Quantalogic.
9
+
10
+ Returns:
11
+ list: A list of strings representing the model names.
12
+ """
13
+ litellm_models = set(litellm.model_list)
14
+ quantalogic_models = set(model_info.keys())
15
+ return list(litellm_models.union(quantalogic_models))
16
+
17
+ # Example usage
18
+ if __name__ == "__main__":
19
+ models = get_all_models()
20
+ print("Supported models:", models)
quantalogic/xml_parser.py CHANGED
@@ -298,5 +298,6 @@ class ToleranceXMLParser:
298
298
 
299
299
  except Exception as e:
300
300
  error_msg = f"Error extracting XML elements: {str(e)}"
301
+ error_msg = error_msg + f"\n{text}\n"
301
302
  logger.error(error_msg)
302
303
  raise ValueError(error_msg)