#!/usr/bin/env python3
"""
Simple client test functions for individual testing.
Usage:
uv run python tests/tests.py small
uv run python tests/tests.py medium
uv run python tests/tests.py large
"""
import os
import sys
import json
from datetime import datetime
from typing import Dict, Any
# Add parent directory to Python path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from client import PerplexityClient
from config import TOOL_CONFIGS
def save_results_to_file(test_type: str, query: str, raw_response: Dict[str, Any], formatted_response: Dict[str, Any]):
"""Save raw and formatted responses to files."""
# Create test_logs directory if it doesn't exist
results_dir = "test_logs"
os.makedirs(results_dir, exist_ok=True)
# Generate timestamp for unique filenames
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# Create filename
filename = f"{test_type}_test_{timestamp}.txt"
filepath = os.path.join(results_dir, filename)
# Write results to file
with open(filepath, 'w', encoding='utf-8') as f:
f.write(f"PERPLEXITY {test_type.upper()} TOOL TEST RESULTS\n")
f.write("=" * 60 + "\n")
f.write(f"Timestamp: {datetime.now().isoformat()}\n")
f.write(f"Test Type: {test_type}\n")
f.write(f"Query: {query}\n")
f.write("=" * 60 + "\n\n")
f.write("RAW API RESPONSE:\n")
f.write("-" * 30 + "\n")
f.write(json.dumps(raw_response, indent=2, ensure_ascii=False))
f.write("\n\n")
f.write("FORMATTED RESPONSE:\n")
f.write("-" * 30 + "\n")
f.write(json.dumps(formatted_response, indent=2, ensure_ascii=False))
f.write("\n\n")
f.write("ANALYSIS:\n")
f.write("-" * 30 + "\n")
if "error" not in formatted_response:
f.write(f"Content length: {len(formatted_response.get('content', ''))} characters\n")
f.write(f"Citations count: {len(formatted_response.get('citations', []))}\n")
# Extract model and usage info from raw response for analysis
if "model" in raw_response:
f.write(f"Model used: {raw_response['model']}\n")
if "usage" in raw_response and raw_response["usage"]:
usage = raw_response["usage"]
f.write(f"Total tokens: {usage.get('total_tokens', 'unknown')}\n")
if "reasoning_tokens" in usage:
f.write(f"Reasoning tokens: {usage['reasoning_tokens']}\n")
else:
f.write(f"ERROR: {formatted_response['error']}\n")
f.write(f"Message: {formatted_response.get('message', 'No message')}\n")
print(f"📁 Results saved to: {filepath}")
return filepath
def test_small_tool():
"""Test perplexity_small configuration (sonar-pro)."""
print("🔍 Testing Small Tool (sonar-pro)")
print("="*50)
try:
client = PerplexityClient()
config = TOOL_CONFIGS["small"]
query = "What is Python programming language?"
messages = [{"role": "user", "content": query}]
print(f"Model: {config['model']}")
print(f"Query: {query}")
print("Making API request...")
raw_response = client.chat_completion(messages=messages, **config)
formatted_response = client.format_response(raw_response)
# Save to file
save_results_to_file("small", query, raw_response, formatted_response)
# Check for errors
if "error" in formatted_response:
print(f"❌ Error: {formatted_response['error']}")
print(f"Message: {formatted_response.get('message', 'No message')}")
return False
# Print results
print(f"✅ Success!")
print(f"Content length: {len(formatted_response['content'])} characters")
print(f"Citations: {len(formatted_response['citations'])}")
# Extract model and usage info from raw response for console output
if "model" in raw_response:
print(f"Model used: {raw_response['model']}")
if "usage" in raw_response and raw_response["usage"]:
usage = raw_response["usage"]
print(f"Total tokens: {usage.get('total_tokens', 'unknown')}")
print(f"\nContent preview:")
print("-" * 30)
preview = formatted_response['content'][:300] + "..." if len(formatted_response['content']) > 300 else formatted_response['content']
print(preview)
return True
except Exception as e:
print(f"❌ Test failed: {str(e)}")
import traceback
traceback.print_exc()
return False
def test_medium_tool():
"""Test perplexity_medium configuration (sonar-reasoning-pro)."""
print("🔍 Testing Medium Tool (sonar-reasoning-pro)")
print("="*50)
try:
client = PerplexityClient()
config = TOOL_CONFIGS["medium"]
query = "Explain the differences between REST and GraphQL APIs"
messages = [{"role": "user", "content": query}]
print(f"Model: {config['model']}")
print(f"Reasoning effort: {config.get('reasoning_effort', 'default')}")
print(f"Search context: {config.get('web_search_options', {}).get('search_context_size', 'default')}")
print(f"Query: {query}")
print("Making API request...")
raw_response = client.chat_completion(messages=messages, **config)
formatted_response = client.format_response(raw_response)
# Save to file
save_results_to_file("medium", query, raw_response, formatted_response)
# Check for errors
if "error" in formatted_response:
print(f"❌ Error: {formatted_response['error']}")
print(f"Message: {formatted_response.get('message', 'No message')}")
return False
# Print results
print(f"✅ Success!")
print(f"Content length: {len(formatted_response['content'])} characters")
print(f"Citations: {len(formatted_response['citations'])}")
# Extract model and usage info from raw response for console output
if "model" in raw_response:
print(f"Model used: {raw_response['model']}")
if "usage" in raw_response and raw_response["usage"]:
usage = raw_response["usage"]
print(f"Total tokens: {usage.get('total_tokens', 'unknown')}")
if "reasoning_tokens" in usage:
print(f"Reasoning tokens: {usage['reasoning_tokens']}")
print(f"\nContent preview:")
print("-" * 30)
preview = formatted_response['content'][:300] + "..." if len(formatted_response['content']) > 300 else formatted_response['content']
print(preview)
return True
except Exception as e:
print(f"❌ Test failed: {str(e)}")
import traceback
traceback.print_exc()
return False
def test_large_tool():
"""Test perplexity_large configuration (sonar-deep-research)."""
print("🔍 Testing Large Tool (sonar-deep-research)")
print("="*50)
print("⚠️ WARNING: This may take 10-30 minutes due to deep research model")
try:
client = PerplexityClient()
config = TOOL_CONFIGS["large"]
query = "What are the latest developments in quantum computing hardware architectures?"
messages = [{"role": "user", "content": query}]
print(f"Model: {config['model']}")
print(f"Reasoning effort: {config.get('reasoning_effort', 'default')}")
print(f"Search context: {config.get('web_search_options', {}).get('search_context_size', 'default')}")
print(f"Query: {query}")
print("⏳ Making API request... (this may take a while)")
raw_response = client.chat_completion(messages=messages, **config)
formatted_response = client.format_response(raw_response)
# Save to file
save_results_to_file("large", query, raw_response, formatted_response)
# Check for errors
if "error" in formatted_response:
print(f"❌ Error: {formatted_response['error']}")
print(f"Message: {formatted_response.get('message', 'No message')}")
return False
# Print results
print(f"✅ Success!")
print(f"Content length: {len(formatted_response['content'])} characters")
print(f"Citations: {len(formatted_response['citations'])}")
# Extract model and usage info from raw response for console output
if "model" in raw_response:
print(f"Model used: {raw_response['model']}")
if "usage" in raw_response and raw_response["usage"]:
usage = raw_response["usage"]
print(f"Total tokens: {usage.get('total_tokens', 'unknown')}")
if "reasoning_tokens" in usage:
print(f"Reasoning tokens: {usage['reasoning_tokens']}")
print(f"\nContent preview:")
print("-" * 30)
preview = formatted_response['content'][:300] + "..." if len(formatted_response['content']) > 300 else formatted_response['content']
print(preview)
return True
except Exception as e:
print(f"❌ Test failed: {str(e)}")
import traceback
traceback.print_exc()
return False
def main():
"""Main function to run individual tests."""
# Check environment first
try:
from config import get_api_key
api_key = get_api_key()
print(f"🔑 API Key found: {api_key[:10]}...{api_key[-4:]}\n")
except Exception as e:
print(f"❌ Environment setup error: {str(e)}")
print("Please make sure PERPLEXITY_API_KEY is set in your .env file")
return False
# Check command line argument
if len(sys.argv) != 2:
print("Usage: python tests.py [small|medium|large]")
return False
test_type = sys.argv[1].lower()
if test_type == "small":
success = test_small_tool()
elif test_type == "medium":
success = test_medium_tool()
elif test_type == "large":
success = test_large_tool()
else:
print("Invalid test type. Use: small, medium, or large")
return False
print(f"\n{'✅ Test completed successfully!' if success else '❌ Test failed!'}")
return success
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)