import os import json import asyncio import httpx import discord from discord.ext import commands with open("prompt.txt", "r", encoding="utf-8") as f: SYSTEM_PROMPT = f.read() OPENWEBUI_URL = os.environ["OPENWEBUI_URL"] OPENWEBUI_API_KEY = os.environ["OPENWEBUI_API_KEY"] MY_CHANNEL_ID = int(os.environ["DISCORD_CHANNEL_ID"]) OPENWEBUI_MODEL = os.environ.get("OPENWEBUI_MODEL", "gpt-4o") AGENT_CHANNELS = { "varys": int(os.environ.get("DISCORD_CHANNEL_VARYS", 0)), "samwell": int(os.environ.get("DISCORD_CHANNEL_SAMWELL", 0)), "bronn": int(os.environ.get("DISCORD_CHANNEL_BRONN", 0)), "bran": int(os.environ.get("DISCORD_CHANNEL_BRAN", 0)), "davos": int(os.environ.get("DISCORD_CHANNEL_DAVOS", 0)), "arya": int(os.environ.get("DISCORD_CHANNEL_ARYA", 0)), "daenerys": int(os.environ.get("DISCORD_CHANNEL_DAENERYS", 0)), "jon": int(os.environ.get("DISCORD_CHANNEL_JON", 0)), } intents = discord.Intents.default() intents.message_content = True intents.guilds = True bot = commands.Bot(command_prefix="!", intents=intents) async def call_llm(messages: list[dict]) -> str: async with httpx.AsyncClient(timeout=120) as client: response = await client.post( f"{OPENWEBUI_URL}/api/chat/completions", headers={"Authorization": f"Bearer {OPENWEBUI_API_KEY}"}, json={"model": OPENWEBUI_MODEL, "messages": messages}, ) response.raise_for_status() return response.json()["choices"][0]["message"]["content"] @bot.event async def on_ready(): print(f"[TYRION] Conectado como {bot.user}") @bot.event async def on_message(message: discord.Message): if message.author.bot: return if message.channel.id != MY_CHANNEL_ID: return routing_prompt = f""" El usuario dijo: "{message.content}" Analiza la solicitud y determina qué agente debe manejarla. Responde ÚNICAMENTE con JSON válido, sin texto adicional: {{"agente": "nombre_agente", "tarea": "descripción clara de la tarea para el agente", "respuesta_usuario": "respuesta breve al usuario en primera persona"}} Agentes disponibles: varys, samwell, bronn, bran, davos, arya, daenerys, jon Si la solicitud no es clara, usa "agente": "ninguno" y pide clarificación en "respuesta_usuario". """ async with message.channel.typing(): try: llm_response = await call_llm([ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": routing_prompt}, ]) decision = json.loads(llm_response) agente = decision.get("agente", "ninguno") tarea = decision.get("tarea", "") respuesta = decision.get("respuesta_usuario", f"Analizando solicitud...") await message.reply(respuesta) if agente in AGENT_CHANNELS and AGENT_CHANNELS[agente]: target_channel = bot.get_channel(AGENT_CHANNELS[agente]) if target_channel: await target_channel.send( f"**[Delegado por Tyrion]**\n{tarea}\n\n" f"*Contexto original: {message.jump_url}*" ) except json.JSONDecodeError: await message.reply(llm_response) except Exception as e: await message.reply(f"Error al procesar: {e}") await bot.process_commands(message) bot.run(os.environ["DISCORD_TOKEN"])