Đỗ Hải Nam
feat(backend): core multi-agent orchestration and API
ba5110e
"""
Wolfram Alpha tool for algebraic calculations.
"""
import os
import httpx
from typing import Optional
from backend.utils.rate_limit import wolfram_limiter, query_cache
WOLFRAM_BASE_URL = "https://api.wolframalpha.com/v2/query"
async def query_wolfram_alpha(
query: str,
max_retries: int = 3
) -> tuple[bool, str]:
"""
Query Wolfram Alpha for algebraic calculations.
Includes rate limiting (2000/month) and caching.
Returns:
tuple[bool, str]: (success, result_or_error_message)
"""
# Check cache first to save API calls
cached = query_cache.get(query, context="wolfram")
if cached:
return True, f"(Cached) {cached}"
# Check monthly rate limit
can_proceed, limit_msg, remaining = wolfram_limiter.can_make_request()
if not can_proceed:
return False, limit_msg
app_id = os.getenv("WOLFRAM_ALPHA_APP_ID")
if not app_id:
return False, "Wolfram Alpha APP_ID not configured"
params = {
"appid": app_id,
"input": query,
"format": "plaintext",
"output": "json",
}
for attempt in range(max_retries):
try:
async with httpx.AsyncClient(timeout=30.0, follow_redirects=True) as client:
response = await client.get(WOLFRAM_BASE_URL, params=params)
response.raise_for_status()
# Record usage only on successful API call
wolfram_limiter.record_usage()
data = response.json()
if data.get("queryresult", {}).get("success"):
pods = data["queryresult"].get("pods", [])
results = []
for pod in pods:
title = pod.get("title", "")
subpods = pod.get("subpods", [])
for subpod in subpods:
plaintext = subpod.get("plaintext", "")
if plaintext:
results.append(f"**{title}**: {plaintext}")
if results:
result_text = "\n\n".join(results)
# Cache successful result
query_cache.set(query, result_text, context="wolfram")
# Add warning if running low on quota
if remaining <= 100:
result_text += f"\n\n⚠️ {limit_msg}"
return True, result_text
else:
return False, "No results found from Wolfram Alpha"
else:
# Don't retry if query was understood but no answer
return False, "Wolfram Alpha could not interpret the query"
except httpx.TimeoutException:
if attempt == max_retries - 1:
return False, "Wolfram Alpha request timed out after 3 attempts"
continue
except httpx.HTTPStatusError as e:
if attempt == max_retries - 1:
return False, f"Wolfram Alpha HTTP error: {e.response.status_code}"
continue
except Exception as e:
if attempt == max_retries - 1:
return False, f"Wolfram Alpha error: {str(e)}"
continue
return False, "Wolfram Alpha failed after maximum retries"
def get_wolfram_status() -> dict:
"""Get Wolfram API usage status."""
return wolfram_limiter.get_status()