cognee/test_cognee_responses_api_comprehensive.py
2025-05-09 09:25:42 +02:00

353 lines
No EOL
11 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Comprehensive test script for Cognee's OpenAI-compatible Responses API
"""
import os
import json
import asyncio
import httpx
from typing import Dict, Any, Optional, List
import sys
# Configuration
API_BASE_URL = os.getenv("COGNEE_API_URL", "http://localhost:8000")
API_ENDPOINT = "/api/v1/responses/"
AUTH_ENDPOINT = "/api/v1/auth/login"
EMAIL = os.getenv("COGNEE_EMAIL", "default_user@example.com") # Default test user
PASSWORD = os.getenv("COGNEE_PASSWORD", "default_password") # Default test password
# Constants
GREEN = "\033[92m"
RED = "\033[91m"
YELLOW = "\033[93m"
RESET = "\033[0m"
def log_success(message: str) -> None:
"""Print a success message in green"""
print(f"{GREEN}{message}{RESET}")
def log_error(message: str) -> None:
"""Print an error message in red"""
print(f"{RED}{message}{RESET}")
def log_warning(message: str) -> None:
"""Print a warning message in yellow"""
print(f"{YELLOW}⚠️ {message}{RESET}")
def log_info(message: str) -> None:
"""Print an info message"""
print(f" {message}")
async def authenticate() -> Optional[str]:
"""Authenticate with the API and return access token"""
log_info("Authenticating with the API...")
auth_payload = {
"email": EMAIL,
"password": PASSWORD
}
try:
async with httpx.AsyncClient() as client:
response = await client.post(
f"{API_BASE_URL}{AUTH_ENDPOINT}",
json=auth_payload,
headers={"Content-Type": "application/json"}
)
if response.status_code == 200:
auth_data = response.json()
token = auth_data.get("access_token")
if token:
log_success(f"Authentication successful")
return token
else:
log_error("Authentication response did not contain access token")
return None
else:
log_error(f"Authentication failed with status {response.status_code}: {response.text}")
return None
except Exception as e:
log_error(f"Authentication error: {str(e)}")
return None
async def make_api_request(
payload: Dict[str, Any],
token: Optional[str] = None,
expected_status: int = 200
) -> Dict[str, Any]:
"""Make a request to the API and return the response"""
headers = {"Content-Type": "application/json"}
if token:
headers["Authorization"] = f"Bearer {token}"
try:
async with httpx.AsyncClient() as client:
response = await client.post(
f"{API_BASE_URL}{API_ENDPOINT}",
json=payload,
headers=headers,
timeout=60.0 # Increased timeout for cognify operations
)
log_info(f"Response status: {response.status_code}")
if response.status_code == expected_status:
if expected_status == 200:
result = response.json()
return result
else:
return {"status": response.status_code, "text": response.text}
else:
log_error(f"Request failed with status {response.status_code}: {response.text}")
return {"error": response.text, "status_code": response.status_code}
except Exception as e:
log_error(f"Request error: {str(e)}")
return {"error": str(e)}
def validate_response(response: Dict[str, Any]) -> bool:
"""Validate the response structure"""
required_fields = ["id", "created", "model", "object", "status", "tool_calls"]
missing_fields = [field for field in required_fields if field not in response]
if missing_fields:
log_error(f"Response missing required fields: {', '.join(missing_fields)}")
return False
if response["object"] != "response":
log_error(f"Expected 'object' to be 'response', got '{response['object']}'")
return False
if not isinstance(response["tool_calls"], list):
log_error(f"Expected 'tool_calls' to be a list, got {type(response['tool_calls'])}")
return False
for i, tool_call in enumerate(response["tool_calls"]):
if "id" not in tool_call or "function" not in tool_call or "type" not in tool_call:
log_error(f"Tool call {i} missing required fields")
return False
if "name" not in tool_call["function"] or "arguments" not in tool_call["function"]:
log_error(f"Tool call {i} function missing required fields")
return False
return True
async def test_search_function(token: Optional[str] = None) -> bool:
"""Test the search function via the responses API"""
log_info("\n--- Testing search function ---")
# Define request payload
payload = {
"model": "cognee-v1",
"input": "What information do we have about Python's asyncio module?",
"tools": [
{
"type": "function",
"function": {
"name": "search",
"description": "Search for information within the knowledge graph",
"parameters": {
"type": "object",
"properties": {
"search_query": {
"type": "string",
"description": "The query to search for in the knowledge graph"
},
"search_type": {
"type": "string",
"description": "Type of search to perform",
"enum": ["INSIGHTS", "CODE", "GRAPH_COMPLETION", "SEMANTIC", "NATURAL_LANGUAGE"]
}
},
"required": ["search_query"]
}
}
}
],
"tool_choice": "auto"
}
result = await make_api_request(payload, token)
if "error" in result:
return False
if not validate_response(result):
return False
# Check if we got tool calls
if not result["tool_calls"]:
log_warning("No tool calls found in response")
return False
search_tool_calls = [tc for tc in result["tool_calls"]
if tc["function"]["name"] == "search"]
if not search_tool_calls:
log_error("No search tool calls found in response")
return False
log_success("Search function test passed")
return True
async def test_cognify_function(token: Optional[str] = None) -> bool:
"""Test the cognify_text function via the responses API"""
log_info("\n--- Testing cognify_text function ---")
# Define request payload
payload = {
"model": "cognee-v1",
"input": "Please add this information to the knowledge graph: Python's asyncio module provides infrastructure for writing single-threaded concurrent code using coroutines.",
"tools": [
{
"type": "function",
"function": {
"name": "cognify_text",
"description": "Convert text into a knowledge graph",
"parameters": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "Text content to be converted into a knowledge graph"
}
},
"required": ["text"]
}
}
}
],
"tool_choice": "auto"
}
result = await make_api_request(payload, token)
if "error" in result:
return False
if not validate_response(result):
return False
# Check if we got tool calls
if not result["tool_calls"]:
log_warning("No tool calls found in response")
return False
cognify_tool_calls = [tc for tc in result["tool_calls"]
if tc["function"]["name"] == "cognify_text"]
if not cognify_tool_calls:
log_error("No cognify_text tool calls found in response")
return False
# Check if output is successful
for tool_call in cognify_tool_calls:
if "output" in tool_call:
output = tool_call["output"]
if output.get("status") != "success":
log_error(f"Cognify operation failed: {output}")
return False
log_success("Cognify function test passed")
return True
async def test_with_default_tools(token: Optional[str] = None) -> bool:
"""Test using the default tools provided by the API"""
log_info("\n--- Testing with default tools ---")
# Define request payload - omitting tools to use defaults
payload = {
"model": "cognee-v1",
"input": "What can I do with this API?",
"tool_choice": "auto"
}
result = await make_api_request(payload, token)
if "error" in result:
return False
if not validate_response(result):
return False
log_success("Default tools test passed")
return True
async def test_invalid_request(token: Optional[str] = None) -> bool:
"""Test handling of invalid requests"""
log_info("\n--- Testing invalid request handling ---")
# Missing required parameter (model)
payload = {
"input": "What can I do with this API?"
}
result = await make_api_request(payload, token, expected_status=422)
if "status_code" in result and result["status_code"] == 422:
log_success("Invalid request properly rejected")
return True
else:
log_error("Invalid request not properly rejected")
return False
async def main():
"""Run all tests"""
log_info("Starting Cognee Responses API Tests")
# Get authentication token
token = await authenticate()
# Run tests
results = {}
# Basic functionality
results["search_function"] = await test_search_function(token)
results["cognify_function"] = await test_cognify_function(token)
results["default_tools"] = await test_with_default_tools(token)
# Error handling
results["invalid_request"] = await test_invalid_request(token)
# Summary
print("\n" + "="*50)
print("TEST RESULTS SUMMARY")
print("="*50)
passed = sum(1 for result in results.values() if result)
total = len(results)
for test_name, result in results.items():
status = f"{GREEN}PASSED{RESET}" if result else f"{RED}FAILED{RESET}"
print(f"{test_name.replace('_', ' ').title()}: {status}")
print("-"*50)
print(f"Tests passed: {passed}/{total} ({100 * passed / total:.1f}%)")
if passed == total:
log_success("\nAll tests passed! The OpenAI-compatible Responses API is working correctly.")
return 0
else:
log_error("\nSome tests failed. Please check the logs for details.")
return 1
if __name__ == "__main__":
exit_code = asyncio.run(main())
sys.exit(exit_code)