praisonaiagents 0.0.133__tar.gz → 0.0.135__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.
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/PKG-INFO +1 -2
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/llm/llm.py +78 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/llm/model_capabilities.py +24 -1
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/llm/openai_client.py +10 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents.egg-info/PKG-INFO +1 -2
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents.egg-info/SOURCES.txt +1 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents.egg-info/requires.txt +0 -1
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/pyproject.toml +1 -2
- praisonaiagents-0.0.135/tests/test_ollama_sequential_fix.py +129 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/README.md +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/agent/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/agent/agent.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/agent/handoff.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/agent/image_agent.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/agent/router_agent.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/agents/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/agents/agents.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/agents/autoagents.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/approval.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/guardrails/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/guardrails/guardrail_result.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/guardrails/llm_guardrail.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/knowledge/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/knowledge/chunking.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/knowledge/knowledge.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/llm/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/llm/model_router.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/main.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/mcp/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/mcp/mcp.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/mcp/mcp_http_stream.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/mcp/mcp_sse.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/memory/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/memory/memory.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/process/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/process/process.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/session.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/task/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/task/task.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/telemetry/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/telemetry/integration.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/telemetry/telemetry.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/README.md +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/__init__.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/arxiv_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/calculator_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/csv_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/duckdb_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/duckduckgo_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/excel_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/file_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/json_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/newspaper_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/pandas_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/python_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/searxng_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/shell_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/spider_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/test.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/train/data/generatecot.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/wikipedia_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/xml_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/yaml_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/yfinance_tools.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents.egg-info/dependency_links.txt +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents.egg-info/top_level.txt +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/setup.cfg +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test-graph-memory.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_fix_comprehensive.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_handoff_compatibility.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_http_stream_basic.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_llm_self_reflection_direct.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_ollama_async_fix.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_ollama_fix.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_posthog_fixed.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_self_reflection_comprehensive.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_self_reflection_fix_simple.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_self_reflection_fix_verification.py +0 -0
- {praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_validation_feedback.py +0 -0
@@ -1,13 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: praisonaiagents
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.135
|
4
4
|
Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
|
5
5
|
Author: Mervin Praison
|
6
6
|
Requires-Python: >=3.10
|
7
7
|
Requires-Dist: pydantic
|
8
8
|
Requires-Dist: rich
|
9
9
|
Requires-Dist: openai
|
10
|
-
Requires-Dist: mcp>=1.6.0
|
11
10
|
Requires-Dist: posthog>=3.0.0
|
12
11
|
Requires-Dist: aiohttp>=3.8.0
|
13
12
|
Provides-Extra: mcp
|
@@ -2,6 +2,7 @@ import logging
|
|
2
2
|
import os
|
3
3
|
import warnings
|
4
4
|
import re
|
5
|
+
import inspect
|
5
6
|
from typing import Any, Dict, List, Optional, Union, Literal, Callable
|
6
7
|
from pydantic import BaseModel
|
7
8
|
import time
|
@@ -379,6 +380,65 @@ class LLM:
|
|
379
380
|
|
380
381
|
return function_name, arguments, tool_call_id
|
381
382
|
|
383
|
+
def _validate_and_filter_ollama_arguments(self, function_name: str, arguments: Dict[str, Any], available_tools: List) -> Dict[str, Any]:
|
384
|
+
"""
|
385
|
+
Validate and filter tool call arguments for Ollama provider.
|
386
|
+
|
387
|
+
Ollama sometimes generates tool calls with mixed parameters where arguments
|
388
|
+
from different functions are combined. This method validates arguments against
|
389
|
+
the actual function signature and removes invalid parameters.
|
390
|
+
|
391
|
+
Args:
|
392
|
+
function_name: Name of the function to call
|
393
|
+
arguments: Arguments provided in the tool call
|
394
|
+
available_tools: List of available tool functions
|
395
|
+
|
396
|
+
Returns:
|
397
|
+
Filtered arguments dictionary with only valid parameters
|
398
|
+
"""
|
399
|
+
if not available_tools:
|
400
|
+
logging.debug(f"[OLLAMA_FIX] No available tools provided for validation")
|
401
|
+
return arguments
|
402
|
+
|
403
|
+
# Find the target function
|
404
|
+
target_function = None
|
405
|
+
for tool in available_tools:
|
406
|
+
tool_name = getattr(tool, '__name__', str(tool))
|
407
|
+
if tool_name == function_name:
|
408
|
+
target_function = tool
|
409
|
+
break
|
410
|
+
|
411
|
+
if not target_function:
|
412
|
+
logging.debug(f"[OLLAMA_FIX] Function {function_name} not found in available tools")
|
413
|
+
return arguments
|
414
|
+
|
415
|
+
try:
|
416
|
+
# Get function signature
|
417
|
+
sig = inspect.signature(target_function)
|
418
|
+
valid_params = set(sig.parameters.keys())
|
419
|
+
|
420
|
+
# Filter arguments to only include valid parameters
|
421
|
+
filtered_args = {}
|
422
|
+
invalid_params = []
|
423
|
+
|
424
|
+
for param_name, param_value in arguments.items():
|
425
|
+
if param_name in valid_params:
|
426
|
+
filtered_args[param_name] = param_value
|
427
|
+
else:
|
428
|
+
invalid_params.append(param_name)
|
429
|
+
|
430
|
+
if invalid_params:
|
431
|
+
logging.debug(f"[OLLAMA_FIX] Function {function_name} received invalid parameters: {invalid_params}")
|
432
|
+
logging.debug(f"[OLLAMA_FIX] Valid parameters for {function_name}: {list(valid_params)}")
|
433
|
+
logging.debug(f"[OLLAMA_FIX] Original arguments: {arguments}")
|
434
|
+
logging.debug(f"[OLLAMA_FIX] Filtered arguments: {filtered_args}")
|
435
|
+
|
436
|
+
return filtered_args
|
437
|
+
|
438
|
+
except Exception as e:
|
439
|
+
logging.debug(f"[OLLAMA_FIX] Error validating arguments for {function_name}: {e}")
|
440
|
+
return arguments
|
441
|
+
|
382
442
|
def _needs_system_message_skip(self) -> bool:
|
383
443
|
"""Check if this model requires skipping system messages"""
|
384
444
|
if not self.model:
|
@@ -542,6 +602,7 @@ class LLM:
|
|
542
602
|
- Lists of pre-formatted tools
|
543
603
|
- Callable functions
|
544
604
|
- String function names
|
605
|
+
- Gemini internal tools ({"googleSearch": {}}, {"urlContext": {}}, {"codeExecution": {}})
|
545
606
|
|
546
607
|
Args:
|
547
608
|
tools: List of tools in various formats
|
@@ -588,6 +649,15 @@ class LLM:
|
|
588
649
|
tool_def = self._generate_tool_definition(tool)
|
589
650
|
if tool_def:
|
590
651
|
formatted_tools.append(tool_def)
|
652
|
+
# Handle Gemini internal tools (e.g., {"googleSearch": {}}, {"urlContext": {}}, {"codeExecution": {}})
|
653
|
+
elif isinstance(tool, dict) and len(tool) == 1:
|
654
|
+
tool_name = next(iter(tool.keys()))
|
655
|
+
gemini_internal_tools = {'googleSearch', 'urlContext', 'codeExecution'}
|
656
|
+
if tool_name in gemini_internal_tools:
|
657
|
+
logging.debug(f"Using Gemini internal tool: {tool_name}")
|
658
|
+
formatted_tools.append(tool)
|
659
|
+
else:
|
660
|
+
logging.debug(f"Skipping unknown tool: {tool_name}")
|
591
661
|
else:
|
592
662
|
logging.debug(f"Skipping tool of unsupported type: {type(tool)}")
|
593
663
|
|
@@ -952,6 +1022,10 @@ class LLM:
|
|
952
1022
|
is_ollama = self._is_ollama_provider()
|
953
1023
|
function_name, arguments, tool_call_id = self._extract_tool_call_info(tool_call, is_ollama)
|
954
1024
|
|
1025
|
+
# Validate and filter arguments for Ollama provider
|
1026
|
+
if is_ollama and tools:
|
1027
|
+
arguments = self._validate_and_filter_ollama_arguments(function_name, arguments, tools)
|
1028
|
+
|
955
1029
|
logging.debug(f"[TOOL_EXEC_DEBUG] About to execute tool {function_name} with args: {arguments}")
|
956
1030
|
tool_result = execute_tool_fn(function_name, arguments)
|
957
1031
|
logging.debug(f"[TOOL_EXEC_DEBUG] Tool execution result: {tool_result}")
|
@@ -1603,6 +1677,10 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
|
1603
1677
|
is_ollama = self._is_ollama_provider()
|
1604
1678
|
function_name, arguments, tool_call_id = self._extract_tool_call_info(tool_call, is_ollama)
|
1605
1679
|
|
1680
|
+
# Validate and filter arguments for Ollama provider
|
1681
|
+
if is_ollama and tools:
|
1682
|
+
arguments = self._validate_and_filter_ollama_arguments(function_name, arguments, tools)
|
1683
|
+
|
1606
1684
|
tool_result = await execute_tool_fn(function_name, arguments)
|
1607
1685
|
tool_results.append(tool_result) # Store the result
|
1608
1686
|
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/llm/model_capabilities.py
RENAMED
@@ -104,4 +104,27 @@ def supports_streaming_with_tools(model_name: str) -> bool:
|
|
104
104
|
"""
|
105
105
|
# For now, use the same logic as structured outputs
|
106
106
|
# In the future, this could be a separate list if needed
|
107
|
-
return supports_structured_outputs(model_name)
|
107
|
+
return supports_structured_outputs(model_name)
|
108
|
+
|
109
|
+
|
110
|
+
# Supported Gemini internal tools
|
111
|
+
GEMINI_INTERNAL_TOOLS = {'googleSearch', 'urlContext', 'codeExecution'}
|
112
|
+
|
113
|
+
|
114
|
+
def is_gemini_internal_tool(tool) -> bool:
|
115
|
+
"""
|
116
|
+
Check if a tool is a Gemini internal tool and should be included in formatted tools.
|
117
|
+
|
118
|
+
Gemini internal tools are single-key dictionaries with specific tool names.
|
119
|
+
Examples: {"googleSearch": {}}, {"urlContext": {}}, {"codeExecution": {}}
|
120
|
+
|
121
|
+
Args:
|
122
|
+
tool: The tool to check
|
123
|
+
|
124
|
+
Returns:
|
125
|
+
bool: True if the tool is a recognized Gemini internal tool, False otherwise
|
126
|
+
"""
|
127
|
+
if isinstance(tool, dict) and len(tool) == 1:
|
128
|
+
tool_name = next(iter(tool.keys()))
|
129
|
+
return tool_name in GEMINI_INTERNAL_TOOLS
|
130
|
+
return False
|
@@ -360,6 +360,7 @@ class OpenAIClient:
|
|
360
360
|
- Callable functions
|
361
361
|
- String function names
|
362
362
|
- MCP tools
|
363
|
+
- Gemini internal tools ({"googleSearch": {}}, {"urlContext": {}}, {"codeExecution": {}})
|
363
364
|
|
364
365
|
Args:
|
365
366
|
tools: List of tools in various formats
|
@@ -404,6 +405,15 @@ class OpenAIClient:
|
|
404
405
|
tool_def = self._generate_tool_definition_from_name(tool)
|
405
406
|
if tool_def:
|
406
407
|
formatted_tools.append(tool_def)
|
408
|
+
# Handle Gemini internal tools (e.g., {"googleSearch": {}}, {"urlContext": {}}, {"codeExecution": {}})
|
409
|
+
elif isinstance(tool, dict) and len(tool) == 1:
|
410
|
+
tool_name = next(iter(tool.keys()))
|
411
|
+
gemini_internal_tools = {'googleSearch', 'urlContext', 'codeExecution'}
|
412
|
+
if tool_name in gemini_internal_tools:
|
413
|
+
logging.debug(f"Using Gemini internal tool: {tool_name}")
|
414
|
+
formatted_tools.append(tool)
|
415
|
+
else:
|
416
|
+
logging.debug(f"Skipping unknown tool: {tool_name}")
|
407
417
|
else:
|
408
418
|
logging.debug(f"Skipping tool of unsupported type: {type(tool)}")
|
409
419
|
|
@@ -1,13 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: praisonaiagents
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.135
|
4
4
|
Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
|
5
5
|
Author: Mervin Praison
|
6
6
|
Requires-Python: >=3.10
|
7
7
|
Requires-Dist: pydantic
|
8
8
|
Requires-Dist: rich
|
9
9
|
Requires-Dist: openai
|
10
|
-
Requires-Dist: mcp>=1.6.0
|
11
10
|
Requires-Dist: posthog>=3.0.0
|
12
11
|
Requires-Dist: aiohttp>=3.8.0
|
13
12
|
Provides-Extra: mcp
|
@@ -72,6 +72,7 @@ tests/test_http_stream_basic.py
|
|
72
72
|
tests/test_llm_self_reflection_direct.py
|
73
73
|
tests/test_ollama_async_fix.py
|
74
74
|
tests/test_ollama_fix.py
|
75
|
+
tests/test_ollama_sequential_fix.py
|
75
76
|
tests/test_posthog_fixed.py
|
76
77
|
tests/test_self_reflection_comprehensive.py
|
77
78
|
tests/test_self_reflection_fix_simple.py
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "praisonaiagents"
|
7
|
-
version = "0.0.
|
7
|
+
version = "0.0.135"
|
8
8
|
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
9
9
|
requires-python = ">=3.10"
|
10
10
|
authors = [
|
@@ -14,7 +14,6 @@ dependencies = [
|
|
14
14
|
"pydantic",
|
15
15
|
"rich",
|
16
16
|
"openai",
|
17
|
-
"mcp>=1.6.0",
|
18
17
|
"posthog>=3.0.0",
|
19
18
|
"aiohttp>=3.8.0"
|
20
19
|
]
|
@@ -0,0 +1,129 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Test script to verify Ollama sequential tool calling argument mixing fix.
|
4
|
+
|
5
|
+
This test validates that the parameter validation and filtering fix correctly handles
|
6
|
+
the case where Ollama generates tool calls with mixed parameters from different functions.
|
7
|
+
"""
|
8
|
+
|
9
|
+
import logging
|
10
|
+
from praisonaiagents.llm.llm import LLM
|
11
|
+
|
12
|
+
# Enable debug logging
|
13
|
+
logging.basicConfig(level=logging.DEBUG)
|
14
|
+
|
15
|
+
# Test functions matching the issue description
|
16
|
+
def get_stock_price(company_name: str) -> str:
|
17
|
+
"""
|
18
|
+
Get the stock price of a company
|
19
|
+
|
20
|
+
Args:
|
21
|
+
company_name (str): The name of the company
|
22
|
+
|
23
|
+
Returns:
|
24
|
+
str: The stock price of the company
|
25
|
+
"""
|
26
|
+
return f"The stock price of {company_name} is 100"
|
27
|
+
|
28
|
+
def multiply(a: int, b: int) -> int:
|
29
|
+
"""
|
30
|
+
Multiply two numbers
|
31
|
+
"""
|
32
|
+
return a * b
|
33
|
+
|
34
|
+
def test_ollama_argument_validation():
|
35
|
+
"""
|
36
|
+
Test the Ollama argument validation and filtering functionality.
|
37
|
+
"""
|
38
|
+
print("Testing Ollama argument validation and filtering...")
|
39
|
+
|
40
|
+
llm = LLM(model="ollama/llama3.2")
|
41
|
+
tools = [get_stock_price, multiply]
|
42
|
+
|
43
|
+
# Test case 1: Valid arguments (should pass through unchanged)
|
44
|
+
print("\n1. Testing valid arguments:")
|
45
|
+
valid_args = {"a": 100, "b": 2}
|
46
|
+
filtered_args = llm._validate_and_filter_ollama_arguments("multiply", valid_args, tools)
|
47
|
+
print(f"Original: {valid_args}")
|
48
|
+
print(f"Filtered: {filtered_args}")
|
49
|
+
assert filtered_args == valid_args, "Valid arguments should pass through unchanged"
|
50
|
+
print("✅ Valid arguments test passed")
|
51
|
+
|
52
|
+
# Test case 2: Mixed arguments (the actual issue from #918)
|
53
|
+
print("\n2. Testing mixed arguments (the main issue):")
|
54
|
+
mixed_args = {"a": "get_stock_price", "company_name": "Google", "b": "2"}
|
55
|
+
filtered_args = llm._validate_and_filter_ollama_arguments("multiply", mixed_args, tools)
|
56
|
+
expected_filtered = {"a": "get_stock_price", "b": "2"} # Should remove 'company_name'
|
57
|
+
print(f"Original: {mixed_args}")
|
58
|
+
print(f"Filtered: {filtered_args}")
|
59
|
+
print(f"Expected: {expected_filtered}")
|
60
|
+
assert filtered_args == expected_filtered, f"Expected {expected_filtered}, got {filtered_args}"
|
61
|
+
print("✅ Mixed arguments filtering test passed")
|
62
|
+
|
63
|
+
# Test case 3: All invalid arguments
|
64
|
+
print("\n3. Testing all invalid arguments:")
|
65
|
+
invalid_args = {"invalid_param1": "value1", "invalid_param2": "value2"}
|
66
|
+
filtered_args = llm._validate_and_filter_ollama_arguments("multiply", invalid_args, tools)
|
67
|
+
expected_empty = {}
|
68
|
+
print(f"Original: {invalid_args}")
|
69
|
+
print(f"Filtered: {filtered_args}")
|
70
|
+
assert filtered_args == expected_empty, "All invalid arguments should be filtered out"
|
71
|
+
print("✅ Invalid arguments filtering test passed")
|
72
|
+
|
73
|
+
# Test case 4: Function not found in tools
|
74
|
+
print("\n4. Testing function not found:")
|
75
|
+
some_args = {"param": "value"}
|
76
|
+
filtered_args = llm._validate_and_filter_ollama_arguments("nonexistent_function", some_args, tools)
|
77
|
+
print(f"Original: {some_args}")
|
78
|
+
print(f"Filtered: {filtered_args}")
|
79
|
+
assert filtered_args == some_args, "Arguments should pass through if function not found"
|
80
|
+
print("✅ Function not found test passed")
|
81
|
+
|
82
|
+
# Test case 5: Empty tools list
|
83
|
+
print("\n5. Testing empty tools list:")
|
84
|
+
some_args = {"param": "value"}
|
85
|
+
filtered_args = llm._validate_and_filter_ollama_arguments("multiply", some_args, [])
|
86
|
+
print(f"Original: {some_args}")
|
87
|
+
print(f"Filtered: {filtered_args}")
|
88
|
+
assert filtered_args == some_args, "Arguments should pass through if no tools provided"
|
89
|
+
print("✅ Empty tools test passed")
|
90
|
+
|
91
|
+
print("\n🎉 All Ollama argument validation tests passed!")
|
92
|
+
return True
|
93
|
+
|
94
|
+
def test_provider_detection():
|
95
|
+
"""
|
96
|
+
Test the Ollama provider detection functionality.
|
97
|
+
"""
|
98
|
+
print("\nTesting Ollama provider detection...")
|
99
|
+
|
100
|
+
# Test Ollama provider detection
|
101
|
+
ollama_llm = LLM(model="ollama/llama3.2")
|
102
|
+
assert ollama_llm._is_ollama_provider(), "Should detect ollama/ prefix"
|
103
|
+
print("✅ Ollama prefix detection works")
|
104
|
+
|
105
|
+
# Test non-Ollama provider
|
106
|
+
openai_llm = LLM(model="gpt-4o-mini")
|
107
|
+
assert not openai_llm._is_ollama_provider(), "Should not detect OpenAI as Ollama"
|
108
|
+
print("✅ Non-Ollama provider detection works")
|
109
|
+
|
110
|
+
print("✅ Provider detection tests passed!")
|
111
|
+
return True
|
112
|
+
|
113
|
+
if __name__ == "__main__":
|
114
|
+
print("Running Ollama sequential tool calling fix tests...")
|
115
|
+
print("=" * 60)
|
116
|
+
|
117
|
+
# Run tests
|
118
|
+
try:
|
119
|
+
test_provider_detection()
|
120
|
+
test_ollama_argument_validation()
|
121
|
+
|
122
|
+
print("\n" + "=" * 60)
|
123
|
+
print("🎉 ALL TESTS PASSED!")
|
124
|
+
print("The Ollama sequential tool calling argument mixing issue has been fixed!")
|
125
|
+
|
126
|
+
except Exception as e:
|
127
|
+
print(f"\n❌ TEST FAILED: {e}")
|
128
|
+
import traceback
|
129
|
+
traceback.print_exc()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/guardrails/guardrail_result.py
RENAMED
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/guardrails/llm_guardrail.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/telemetry/integration.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/calculator_tools.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/duckduckgo_tools.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/newspaper_tools.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/train/data/generatecot.py
RENAMED
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents/tools/wikipedia_tools.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/praisonaiagents.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_llm_self_reflection_direct.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_self_reflection_comprehensive.py
RENAMED
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_self_reflection_fix_simple.py
RENAMED
File without changes
|
{praisonaiagents-0.0.133 → praisonaiagents-0.0.135}/tests/test_self_reflection_fix_verification.py
RENAMED
File without changes
|
File without changes
|