import os import httpx import asyncio from typing import Optional from soul import JARVIS_SOUL PROVIDERS = [ { "name": "Groq", "url": "https://api.groq.com/openai/v1/chat/completions", "key_env": "GROQ_API_KEY", "model": "llama-3.3-70b-versatile", "headers": lambda key: {"Authorization": f"Bearer {key}", "Content-Type": "application/json"} }, { "name": "Gemini", "url": "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions", "key_env": "GEMINI_API_KEY", "model": "gemini-2.0-flash", "headers": lambda key: {"Authorization": f"Bearer {key}", "Content-Type": "application/json"} }, { "name": "OpenRouter", "url": "https://openrouter.ai/api/v1/chat/completions", "key_env": "OPENROUTER_API_KEY", "model": "tngtech/deepseek-r1t-chimera:free", "headers": lambda key: {"Authorization": f"Bearer {key}", "Content-Type": "application/json"} }, { "name": "OpenRouter-Mistral", "url": "https://openrouter.ai/api/v1/chat/completions", "key_env": "OPENROUTER_API_KEY", "model": "mistralai/mistral-7b-instruct:free", "headers": lambda key: {"Authorization": f"Bearer {key}", "Content-Type": "application/json"} }, { "name": "Mistral", "url": "https://api.mistral.ai/v1/chat/completions", "key_env": "MISTRAL_API_KEY", "model": "mistral-small-latest", "headers": lambda key: {"Authorization": f"Bearer {key}", "Content-Type": "application/json"} }, { "name": "Together", "url": "https://api.together.xyz/v1/chat/completions", "key_env": "TOGETHER_API_KEY", "model": "meta-llama/Llama-3-70b-chat-hf", "headers": lambda key: {"Authorization": f"Bearer {key}", "Content-Type": "application/json"} }, { "name": "Cerebras", "url": "https://api.cerebras.ai/v1/chat/completions", "key_env": "CEREBRAS_API_KEY", "model": "llama3.1-70b", "headers": lambda key: {"Authorization": f"Bearer {key}", "Content-Type": "application/json"} }, { "name": "HuggingFace", "url": "https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.3/v1/chat/completions", "key_env": "HF_API_KEY", "model": "mistralai/Mistral-7B-Instruct-v0.3", "headers": lambda key: {"Authorization": f"Bearer {key}", "Content-Type": "application/json"} }, { "name": "Novita", "url": "https://api.novita.ai/v3/openai/chat/completions", "key_env": "NOVITA_API_KEY", "model": "meta-llama/llama-3.1-70b-instruct", "headers": lambda key: {"Authorization": f"Bearer {key}", "Content-Type": "application/json"} }, ] class JarvisAIEngine: def __init__(self): self.providers = PROVIDERS self.active_provider = None self.stats = {p["name"]: {"success": 0, "fail": 0} for p in PROVIDERS} async def think(self, user_message: str, context: str = "", history: list = None) -> dict: messages = [{"role": "system", "content": JARVIS_SOUL}] if context: messages.append({"role": "system", "content": f"Context: {context}"}) if history: messages.extend(history[-10:]) messages.append({"role": "user", "content": user_message}) for provider in self.providers: api_key = os.environ.get(provider["key_env"]) if not api_key: continue try: payload = { "model": provider["model"], "messages": messages, "max_tokens": 2048, "temperature": 0.7 } headers = provider["headers"](api_key) async with httpx.AsyncClient(timeout=30) as client: response = await client.post(provider["url"], headers=headers, json=payload) if response.status_code == 200: data = response.json() result = data["choices"][0]["message"]["content"] if result: self.stats[provider["name"]]["success"] += 1 self.active_provider = provider["name"] return {"success": True, "response": result, "provider": provider["name"]} self.stats[provider["name"]]["fail"] += 1 except Exception: self.stats[provider["name"]]["fail"] += 1 continue return { "success": False, "response": "⚠️ Semua provider AI tidak tersedia. Cek API keys di Settings.", "provider": "none" } def get_available_providers(self) -> list: return [p["name"] for p in self.providers if os.environ.get(p["key_env"])] def get_stats(self) -> dict: return { "active_provider": self.active_provider, "available": self.get_available_providers(), "stats": self.stats } engine = JarvisAIEngine()