Skip to content

Commit 0bd7138

Browse files
author
Zvi Fried
committed
final fixes, ci + workflow
1 parent 654f078 commit 0bd7138

27 files changed

+401
-139
lines changed

examples/rate_limit_demo.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
"""
88

99
import asyncio
10-
import os
1110
from unittest.mock import patch
1211

1312
import litellm
@@ -20,7 +19,7 @@ async def demo_rate_limit_handling():
2019
"""Demonstrate rate limit handling with exponential backoff."""
2120
print("🚀 Rate Limit Handling Demo")
2221
print("=" * 50)
23-
22+
2423
# Create a test LLM configuration
2524
config = LLMConfig(
2625
api_key="demo-key",
@@ -29,69 +28,69 @@ async def demo_rate_limit_handling():
2928
max_tokens=1000,
3029
temperature=0.1,
3130
)
32-
31+
3332
client = LLMClient(config)
34-
33+
3534
print("📝 Test 1: Successful retry after rate limit errors")
3635
print("-" * 50)
37-
36+
3837
# Mock response for successful case
3938
from unittest.mock import MagicMock
4039
mock_response = MagicMock()
4140
mock_response.choices = [MagicMock()]
4241
mock_response.choices[0].message.content = "Success after retries!"
43-
42+
4443
# Simulate rate limit errors followed by success
4544
with patch.object(client, "_litellm") as mock_litellm:
4645
mock_litellm.completion.side_effect = [
4746
litellm.RateLimitError("Rate limit exceeded", "openai", "gpt-4"),
4847
litellm.RateLimitError("Rate limit exceeded", "openai", "gpt-4"),
4948
mock_response, # Success on third attempt
5049
]
51-
50+
5251
messages = [{"role": "user", "content": "Hello, world!"}]
53-
52+
5453
try:
5554
result = await client.generate_text(messages)
5655
print(f"✅ Success: {result}")
5756
print(f"📊 Total attempts: {mock_litellm.completion.call_count}")
5857
except Exception as e:
5958
print(f"❌ Failed: {e}")
60-
59+
6160
print("\n📝 Test 2: Rate limit exhaustion (all retries fail)")
6261
print("-" * 50)
63-
62+
6463
# Simulate persistent rate limit errors
6564
with patch.object(client, "_litellm") as mock_litellm:
6665
mock_litellm.completion.side_effect = litellm.RateLimitError(
6766
"Rate limit exceeded", "openai", "gpt-4"
6867
)
69-
68+
7069
messages = [{"role": "user", "content": "This will fail"}]
71-
70+
7271
try:
7372
result = await client.generate_text(messages)
7473
print(f"✅ Unexpected success: {result}")
7574
except Exception as e:
7675
print(f"❌ Expected failure after retries: {e}")
7776
print(f"📊 Total attempts: {mock_litellm.completion.call_count}")
78-
77+
7978
print("\n📝 Test 3: Non-rate-limit error (no retries)")
8079
print("-" * 50)
81-
80+
8281
# Simulate a different type of error
8382
with patch.object(client, "_litellm") as mock_litellm:
8483
mock_litellm.completion.side_effect = ValueError("Invalid input")
85-
84+
8685
messages = [{"role": "user", "content": "This will fail immediately"}]
87-
86+
8887
try:
8988
result = await client.generate_text(messages)
9089
print(f"✅ Unexpected success: {result}")
9190
except Exception as e:
9291
print(f"❌ Expected immediate failure: {e}")
9392
print(f"📊 Total attempts: {mock_litellm.completion.call_count}")
94-
93+
9594
print("\n🎯 Rate Limit Configuration")
9695
print("-" * 50)
9796
print("• Max retries: 5 attempts")
@@ -100,7 +99,7 @@ async def demo_rate_limit_handling():
10099
print("• Exponential base: 2.0")
101100
print("• Jitter: Enabled (±20%)")
102101
print("\nDelay pattern: ~2s, ~4s, ~8s, ~16s, ~32s")
103-
102+
104103
print("\n✨ Demo completed!")
105104

106105

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ addopts = [
143143
"--strict-config",
144144
"--verbose",
145145
]
146+
# No filterwarnings - we want to catch any remaining Pydantic issues
147+
# filterwarnings = []
146148
markers = [
147149
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
148150
"integration: marks tests as integration tests",

scripts/test_dynamic_urls.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
URLValidationResult,
1313
)
1414
from src.mcp_as_a_judge.models.task_metadata import TaskMetadata
15-
from src.mcp_as_a_judge.research_requirements_analyzer import (
16-
ResearchRequirementsAnalyzer,
17-
)
1815

1916

2017
def test_models():
@@ -72,12 +69,9 @@ async def test_analyzer_mock():
7269
"""Test the ResearchRequirementsAnalyzer with a mock scenario."""
7370
print("\n🧪 Testing ResearchRequirementsAnalyzer...")
7471

75-
analyzer = ResearchRequirementsAnalyzer()
76-
7772
# Test scenario
7873
task_title = "Implement JWT Authentication System"
7974
task_description = "Build secure user authentication with JWT tokens, password hashing, and session management"
80-
user_requirements = "Users should be able to register, login, logout securely with proper token validation"
8175

8276
print(f"📋 Task: {task_title}")
8377
print(f"📋 Description: {task_description}")

src/mcp_as_a_judge/elicitation/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@
66
fallback prompts, etc.).
77
"""
88

9-
from mcp_as_a_judge.elicitation.factory import ElicitationProviderFactory, elicitation_provider
9+
from mcp_as_a_judge.elicitation.factory import (
10+
ElicitationProviderFactory,
11+
elicitation_provider,
12+
)
1013
from mcp_as_a_judge.elicitation.fallback_provider import FallbackElicitationProvider
1114
from mcp_as_a_judge.elicitation.interface import ElicitationProvider, ElicitationResult
1215
from mcp_as_a_judge.elicitation.mcp_provider import MCPElicitationProvider
1316

1417
__all__ = [
1518
"ElicitationProvider",
16-
"ElicitationResult",
17-
"MCPElicitationProvider",
18-
"FallbackElicitationProvider",
1919
"ElicitationProviderFactory",
20+
"ElicitationResult",
21+
"FallbackElicitationProvider",
22+
"MCPElicitationProvider",
2023
"elicitation_provider",
2124
]

src/mcp_as_a_judge/elicitation/factory.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ async def elicit_user_input(
6161

6262
def get_available_providers(self, ctx: Context) -> dict[str, dict[str, object]]:
6363
"""Get information about all available providers.
64-
64+
6565
Args:
6666
ctx: MCP context for capability checking
67-
67+
6868
Returns:
6969
Dictionary with provider availability information
7070
"""

src/mcp_as_a_judge/elicitation/fallback_provider.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ async def _elicit(
2525
self, message: str, schema: type[BaseModel], ctx: Context
2626
) -> ElicitationResult:
2727
"""Generate a fallback message for the AI assistant to prompt the user.
28-
28+
2929
Args:
3030
message: Original message to display to the user
3131
schema: Pydantic model schema defining expected fields
3232
ctx: MCP context
33-
33+
3434
Returns:
3535
ElicitationResult with success=False and a formatted message
3636
"""

src/mcp_as_a_judge/elicitation/interface.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def __init__(
2222
message: str | None = None,
2323
):
2424
"""Initialize elicitation result.
25-
25+
2626
Args:
2727
success: Whether the elicitation was successful
2828
data: Data returned from successful elicitation
@@ -44,12 +44,12 @@ async def elicit(
4444
This is the public interface method that can contain common logic
4545
for all providers (logging, validation, etc.) and calls the internal
4646
implementation method.
47-
47+
4848
Args:
4949
message: Message to display to the user
5050
schema: Pydantic model schema defining expected fields
5151
ctx: MCP context
52-
52+
5353
Returns:
5454
ElicitationResult with success status and data/message
5555
"""
@@ -69,12 +69,12 @@ async def _elicit(
6969
self, message: str, schema: type[BaseModel], ctx: Context
7070
) -> ElicitationResult:
7171
"""Internal elicitation implementation - override this in subclasses.
72-
72+
7373
Args:
7474
message: Message to display to the user
7575
schema: Pydantic model schema defining expected fields
7676
ctx: MCP context
77-
77+
7878
Returns:
7979
ElicitationResult with success status and data/message
8080
"""

src/mcp_as_a_judge/elicitation/mcp_provider.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ async def _elicit(
2323
self, message: str, schema: type[BaseModel], ctx: Context
2424
) -> ElicitationResult:
2525
"""Elicit user input using MCP elicitation.
26-
26+
2727
Args:
2828
message: Message to display to the user
2929
schema: Pydantic model schema defining expected fields
3030
ctx: MCP context
31-
31+
3232
Returns:
3333
ElicitationResult with success status and data/message
3434
"""

src/mcp_as_a_judge/llm/llm_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
from mcp_as_a_judge.core.logging_config import get_logger
2121
from mcp_as_a_judge.llm.llm_integration import LLMConfig, LLMVendor
2222

23-
# Set global drop_params to handle model-specific parameter restrictions
24-
# This is especially important for GPT-5 models which don't support temperature at all
23+
2524
litellm.drop_params = True
25+
litellm.suppress_debug_info = True
2626

2727
# Set up logger
2828
logger = get_logger(__name__)

src/mcp_as_a_judge/messaging/interface.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010

1111
from pydantic import BaseModel, Field
1212

13-
from mcp_as_a_judge.core.constants import DEFAULT_TEMPERATURE, DEFAULT_TIMEOUT, MAX_TOKENS
13+
from mcp_as_a_judge.core.constants import (
14+
DEFAULT_TEMPERATURE,
15+
DEFAULT_TIMEOUT,
16+
MAX_TOKENS,
17+
)
1418

1519

1620
class Message(BaseModel):

0 commit comments

Comments
 (0)