jeanbaptdzd's picture
Reorganize tests and clean up documentation
6d3bf74
#!/usr/bin/env python3
"""
Test script to verify tool calls functionality in the OpenAI-compatible API.
This script tests:
1. Tool calls are accepted in requests
2. Tools are formatted correctly in prompts
3. Tool calls are parsed from responses
4. Tool calls are returned in the correct format
"""
import json
import requests
import sys
from typing import Dict, Any, List
# Configuration
BASE_URL = "https://jeanbaptdzd-open-finance-llm-8b.hf.space" # Hugging Face Space
API_KEY = "not-needed" # No authentication required
def test_tool_calls_basic():
"""Test basic tool calls functionality."""
print("=" * 60)
print("Test 1: Basic Tool Calls")
print("=" * 60)
# Define a simple calculator tool
tools = [
{
"type": "function",
"function": {
"name": "calculer_valeur_future",
"description": "Calcule la valeur future d'un investissement avec intérêts composés",
"parameters": {
"type": "object",
"properties": {
"capital_initial": {
"type": "number",
"description": "Le montant initial investi"
},
"taux_annuel": {
"type": "number",
"description": "Le taux d'intérêt annuel (en décimal, ex: 0.05 pour 5%)"
},
"annees": {
"type": "number",
"description": "Le nombre d'années"
}
},
"required": ["capital_initial", "taux_annuel", "annees"]
}
}
}
]
# Make request with tools
payload = {
"model": "DragonLLM/Qwen-Open-Finance-R-8B",
"messages": [
{
"role": "user",
"content": "Calcule la valeur future de 10000 euros investis à 5% par an pendant 10 ans."
}
],
"tools": tools,
"tool_choice": "auto",
"temperature": 0.7,
"max_tokens": 500
}
print(f"\n📤 Request:")
print(json.dumps(payload, indent=2, ensure_ascii=False))
try:
response = requests.post(
f"{BASE_URL}/v1/chat/completions",
json=payload,
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=120
)
print(f"\n📥 Response Status: {response.status_code}")
if response.status_code != 200:
print(f"❌ Error: {response.text}")
return False
data = response.json()
print(f"\n📥 Response:")
print(json.dumps(data, indent=2, ensure_ascii=False))
# Check if tool_calls are present
choice = data.get("choices", [{}])[0]
message = choice.get("message", {})
tool_calls = message.get("tool_calls")
if tool_calls:
print(f"\n✅ Tool calls found: {len(tool_calls)}")
for i, tool_call in enumerate(tool_calls, 1):
print(f"\n Tool Call {i}:")
print(f" ID: {tool_call.get('id')}")
print(f" Type: {tool_call.get('type')}")
func = tool_call.get("function", {})
print(f" Function: {func.get('name')}")
print(f" Arguments: {func.get('arguments')}")
return True
else:
print("\n⚠️ No tool calls found in response")
print(f" Content: {message.get('content', '')[:200]}")
return False
except Exception as e:
print(f"\n❌ Error: {e}")
import traceback
traceback.print_exc()
return False
def test_tool_calls_multiple():
"""Test multiple tool calls."""
print("\n" + "=" * 60)
print("Test 2: Multiple Tool Calls")
print("=" * 60)
tools = [
{
"type": "function",
"function": {
"name": "calculer_valeur_future",
"description": "Calcule la valeur future d'un investissement",
"parameters": {
"type": "object",
"properties": {
"capital_initial": {"type": "number"},
"taux_annuel": {"type": "number"},
"annees": {"type": "number"}
},
"required": ["capital_initial", "taux_annuel", "annees"]
}
}
},
{
"type": "function",
"function": {
"name": "calculer_paiement_mensuel",
"description": "Calcule le paiement mensuel d'un prêt",
"parameters": {
"type": "object",
"properties": {
"montant": {"type": "number"},
"taux_annuel": {"type": "number"},
"duree_annees": {"type": "number"}
},
"required": ["montant", "taux_annuel", "duree_annees"]
}
}
}
]
payload = {
"model": "DragonLLM/Qwen-Open-Finance-R-8B",
"messages": [
{
"role": "user",
"content": "Calcule la valeur future de 5000 euros à 4% sur 5 ans, puis le paiement mensuel d'un prêt de 200000 euros à 3% sur 20 ans."
}
],
"tools": tools,
"tool_choice": "auto",
"temperature": 0.7,
"max_tokens": 800
}
print(f"\n📤 Request with {len(tools)} tools")
try:
response = requests.post(
f"{BASE_URL}/v1/chat/completions",
json=payload,
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=120
)
if response.status_code != 200:
print(f"❌ Error: {response.text}")
return False
data = response.json()
choice = data.get("choices", [{}])[0]
message = choice.get("message", {})
tool_calls = message.get("tool_calls")
if tool_calls:
print(f"\n✅ Found {len(tool_calls)} tool calls")
return True
else:
print("\n⚠️ No tool calls found")
return False
except Exception as e:
print(f"\n❌ Error: {e}")
return False
def test_tool_calls_format():
"""Test that tool calls are in the correct format."""
print("\n" + "=" * 60)
print("Test 3: Tool Calls Format Validation")
print("=" * 60)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather information",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["location"]
}
}
}
]
payload = {
"model": "DragonLLM/Qwen-Open-Finance-R-8B",
"messages": [
{
"role": "user",
"content": "Quel est le temps à Paris?"
}
],
"tools": tools,
"tool_choice": "auto",
"max_tokens": 300
}
try:
response = requests.post(
f"{BASE_URL}/v1/chat/completions",
json=payload,
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=120
)
if response.status_code != 200:
print(f"❌ Error: {response.text}")
return False
data = response.json()
choice = data.get("choices", [{}])[0]
message = choice.get("message", {})
tool_calls = message.get("tool_calls")
if tool_calls:
# Validate format
for tool_call in tool_calls:
required_fields = ["id", "type", "function"]
for field in required_fields:
if field not in tool_call:
print(f"❌ Missing required field: {field}")
return False
func = tool_call.get("function", {})
if "name" not in func or "arguments" not in func:
print(f"❌ Missing function fields: {func}")
return False
# Try to parse arguments as JSON
try:
args = json.loads(func["arguments"])
print(f"✅ Tool call format valid: {tool_call['function']['name']}")
except json.JSONDecodeError:
print(f"⚠️ Arguments not valid JSON: {func['arguments']}")
return True
else:
print("⚠️ No tool calls to validate")
return False
except Exception as e:
print(f"❌ Error: {e}")
return False
def main():
"""Run all tests."""
print("\n" + "=" * 60)
print("Tool Calls Test Suite")
print("=" * 60)
print(f"\nTesting API at: {BASE_URL}")
print(f"Make sure the server is running!\n")
# Check if server is up
try:
health = requests.get(f"{BASE_URL}/health", timeout=5)
if health.status_code == 200:
print("✅ Server is running")
else:
print(f"⚠️ Server health check returned: {health.status_code}")
except Exception as e:
print(f"❌ Cannot connect to server: {e}")
print(" Make sure the server is running at", BASE_URL)
sys.exit(1)
results = []
# Run tests
results.append(("Basic Tool Calls", test_tool_calls_basic()))
results.append(("Multiple Tool Calls", test_tool_calls_multiple()))
results.append(("Format Validation", test_tool_calls_format()))
# Summary
print("\n" + "=" * 60)
print("Test Summary")
print("=" * 60)
passed = sum(1 for _, result in results if result)
total = len(results)
for name, result in results:
status = "✅ PASS" if result else "❌ FAIL"
print(f"{status}: {name}")
print(f"\nTotal: {passed}/{total} tests passed")
if passed == total:
print("\n🎉 All tests passed!")
return 0
else:
print(f"\n⚠️ {total - passed} test(s) failed")
return 1
if __name__ == "__main__":
sys.exit(main())