99 lines
3.4 KiB
Python
99 lines
3.4 KiB
Python
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"])
|