saap-plattform / backend /agents /openrouter_saap_agent.py
Hwandji's picture
feat: initial HuggingFace Space deployment
4343907
raw
history blame
11.3 kB
#!/usr/bin/env python3
"""
SAAP OpenRouter Integration Agent (FREE Fallback)
OpenRouter GLM 4.5 Air (kostenlos) als Fallback für colossus Server
Author: Hanan Wandji Danga
"""
import os
from dotenv import load_dotenv
import requests
import json
import time
import asyncio
import logging
from typing import Dict, List, Optional, Any
# Load environment variables
load_dotenv()
class OpenRouterSAAPAgent:
def __init__(self, agent_name: str, role: str, api_key: Optional[str] = None):
"""
OpenRouter SAAP Agent für GLM 4.5 Air (FREE) als Fallback
Args:
agent_name: Name des Agents
role: Rolle des Agents
api_key: OpenRouter API Key (optional für FREE models)
"""
self.agent_name = agent_name
self.role = role
self.api_key = api_key
self.base_url = "https://openrouter.ai/api/v1"
self.model_name = "deepseek/deepseek-chat" # FREE model
# Fallback models (alle kostenlos)
self.free_models = [
"deepseek/deepseek-chat",
"microsoft/phi-3-medium-4k-instruct:free",
"microsoft/phi-3-mini-128k-instruct:free",
"huggingface/zephyr-7b-beta:free",
"openchat/openchat-7b:free"
]
# Agent Context
self.context = self._initialize_context()
# Logging
logging.basicConfig(level=logging.INFO)
self.logger = logging.getLogger(f"OpenRouterSAAP.{agent_name}")
self.logger.info(f"🌐 {agent_name} ({role}) initialized with OpenRouter FREE")
def _initialize_context(self) -> str:
"""Rollenspezifischer Kontext"""
contexts = {
"Analyst": """Du bist ein SAAP Analyst Agent. Du spezialisierst dich auf:
- Datenanalyse und Requirements Engineering
- Performance-Bewertung von Multi-Agent-Systemen
- Use Case Definition und Dokumentation
- Optimierungspotentiale identifizieren""",
"Fallback": """Du bist ein SAAP Fallback Agent. Du hilfst bei:
- Backup-Processing wenn primäre Agenten nicht verfügbar sind
- Allgemeine Anfragen beantworten
- System-Stabilität durch Redundanz gewährleisten
- Kontinuität der SAAP-Services sicherstellen"""
}
return contexts.get(self.role, contexts["Fallback"])
async def send_request_to_openrouter(self, prompt: str, max_tokens: int = 400) -> Dict[str, Any]:
"""
Sendet Request an OpenRouter API (FREE models)
"""
start_time = time.time()
headers = {
"Content-Type": "application/json",
}
# API Key nur wenn vorhanden (für FREE models optional)
if self.api_key:
headers["Authorization"] = f"Bearer {self.api_key}"
payload = {
"model": self.model_name,
"messages": [
{"role": "system", "content": self.context},
{"role": "user", "content": prompt}
],
"max_tokens": max_tokens,
"temperature": 0.7
}
try:
response = requests.post(
f"{self.base_url}/chat/completions",
headers=headers,
json=payload,
timeout=30
)
response_time = time.time() - start_time
if response.status_code == 200:
data = response.json()
response_text = data['choices'][0]['message']['content']
token_count = data.get('usage', {}).get('total_tokens', 0)
result = {
"success": True,
"response": response_text,
"response_time": round(response_time, 2),
"token_count": token_count,
"model": self.model_name,
"agent_role": self.role,
"provider": "OpenRouter FREE",
"timestamp": time.time()
}
self.logger.info(f"✅ OpenRouter Response: {response_time:.2f}s, FREE model")
return result
else:
# Try fallback models if primary fails
if response.status_code == 429 or response.status_code == 402: # Rate limit or payment
return await self._try_fallback_models(prompt, max_tokens)
error_result = {
"success": False,
"error": f"HTTP {response.status_code}: {response.text}",
"response_time": round(response_time, 2),
"timestamp": time.time()
}
return error_result
except requests.exceptions.RequestException as e:
error_result = {
"success": False,
"error": f"OpenRouter request failed: {str(e)}",
"response_time": round(time.time() - start_time, 2),
"timestamp": time.time()
}
self.logger.error(f"❌ OpenRouter Error: {e}")
return error_result
async def _try_fallback_models(self, prompt: str, max_tokens: int) -> Dict[str, Any]:
"""
Versucht verschiedene FREE models als Fallback
"""
self.logger.info("🔄 Trying fallback models...")
for model in self.free_models[1:]: # Skip first (already tried)
self.logger.info(f"🔄 Trying {model}...")
old_model = self.model_name
self.model_name = model
result = await self.send_request_to_openrouter(prompt, max_tokens)
if result["success"]:
self.logger.info(f"✅ Fallback successful with {model}")
return result
# Restore original model for next attempt
self.model_name = old_model
await asyncio.sleep(1) # Rate limiting
return {
"success": False,
"error": "All fallback models failed",
"timestamp": time.time()
}
async def health_check(self) -> Dict[str, Any]:
"""
Health check für OpenRouter FREE services
"""
try:
test_prompt = "Hello, this is a connection test for SAAP."
result = await self.send_request_to_openrouter(test_prompt, max_tokens=20)
return {
"agent_name": self.agent_name,
"provider": "OpenRouter",
"status": "healthy" if result["success"] else "unhealthy",
"model": self.model_name,
"response_time": result.get("response_time", 0),
"error": result.get("error") if not result["success"] else None,
"timestamp": time.time()
}
except Exception as e:
return {
"agent_name": self.agent_name,
"provider": "OpenRouter",
"status": "error",
"error": str(e),
"timestamp": time.time()
}
# Utility function für SAAP Fallback-System
def create_openrouter_fallback_agent(api_key: Optional[str] = None) -> OpenRouterSAAPAgent:
"""
Erstellt OpenRouter Fallback Agent für SAAP System
"""
return OpenRouterSAAPAgent("fallback_analyst", "Analyst", api_key)
class SAAPHybridSystem:
"""
Hybrid System: colossus (Primary) + OpenRouter (Fallback)
"""
def __init__(self, colossus_api_key: str, openrouter_api_key: Optional[str] = None):
from colossus_saap_agent import ColossusSAAPAgent
self.primary_agent = ColossusSAAPAgent("hybrid_primary", "Coordinator", colossus_api_key)
self.fallback_agent = OpenRouterSAAPAgent("hybrid_fallback", "Fallback", openrouter_api_key)
self.logger = logging.getLogger("SAAPHybrid")
async def process_with_fallback(self, prompt: str, max_tokens: int = 400) -> Dict[str, Any]:
"""
Versucht zuerst colossus, dann OpenRouter als Fallback
"""
self.logger.info("🚀 Processing with hybrid primary/fallback system")
# Try primary (colossus) first
try:
primary_result = await self.primary_agent.send_request_to_colossus(prompt, max_tokens)
if primary_result["success"]:
primary_result["provider"] = "colossus (Primary)"
self.logger.info("✅ Primary (colossus) successful")
return primary_result
else:
self.logger.warning(f"⚠️ Primary failed: {primary_result.get('error')}")
except Exception as e:
self.logger.error(f"❌ Primary system error: {e}")
# Fallback to OpenRouter
self.logger.info("🔄 Switching to OpenRouter fallback...")
fallback_result = await self.fallback_agent.send_request_to_openrouter(prompt, max_tokens)
if fallback_result["success"]:
fallback_result["fallback_used"] = True
fallback_result["provider"] = "OpenRouter (Fallback)"
self.logger.info("✅ Fallback (OpenRouter) successful")
else:
self.logger.error("❌ Both primary and fallback failed")
return fallback_result
if __name__ == "__main__":
# Demo OpenRouter Integration
async def demo_openrouter():
print("🌐 OpenRouter FREE Model Demo")
# Test OpenRouter agent
agent = OpenRouterSAAPAgent("demo_fallback", "Analyst")
# Health check
health = await agent.health_check()
print(f"Health: {health}")
if health["status"] == "healthy":
# Test query
result = await agent.send_request_to_openrouter(
"Erkläre die Vorteile eines Hybrid-AI-Systems mit Primary und Fallback."
)
print(f"Response: {result.get('response', 'No response')}")
print(f"Time: {result.get('response_time')}s")
print(f"Model: {result.get('model')}")
# Demo Hybrid System
async def demo_hybrid():
print("\n🔄 Hybrid System Demo (colossus + OpenRouter)")
COLOSSUS_KEY = os.getenv("COLOSSUS_API_KEY")
if not COLOSSUS_KEY:
print("❌ Error: COLOSSUS_API_KEY not set in environment variables")
print("Please set it in backend/.env file")
return
hybrid = SAAPHybridSystem(COLOSSUS_KEY)
result = await hybrid.process_with_fallback(
"Was sind die Hauptvorteile von Multi-Agent-Systemen?"
)
print(f"Provider: {result.get('provider', 'Unknown')}")
print(f"Response: {result.get('response', 'No response')[:100]}...")
print(f"Fallback used: {result.get('fallback_used', False)}")
# Run demos
async def run_demos():
await demo_openrouter()
await demo_hybrid()
asyncio.run(run_demos())