This commit is contained in:
@@ -13,26 +13,40 @@ intents.messages = True
|
|||||||
intents.message_content = True
|
intents.message_content = True
|
||||||
client = discord.Client(intents=intents)
|
client = discord.Client(intents=intents)
|
||||||
|
|
||||||
|
|
||||||
@client.event
|
@client.event
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
print(f"Logged in as {client.user.name} running {model}.", flush=True)
|
print(f"Logged in as {client.user.name} running {model}.", flush=True)
|
||||||
|
|
||||||
|
|
||||||
@client.event
|
@client.event
|
||||||
async def on_message(message):
|
async def on_message(message):
|
||||||
if message.author == client.user:
|
if message.author == client.user:
|
||||||
return
|
return
|
||||||
if message.content.lower().startswith("hey money") or isinstance(message.channel, discord.DMChannel):
|
if message.content.lower().startswith("hey money") or isinstance(
|
||||||
question = message.content[9:] if message.content.lower().startswith("hey money") else message.content
|
message.channel, discord.DMChannel
|
||||||
|
):
|
||||||
|
question = (
|
||||||
|
message.content[9:]
|
||||||
|
if message.content.lower().startswith("hey money")
|
||||||
|
else message.content
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
response = openai.ChatCompletion.create(
|
response = openai.ChatCompletion.create(
|
||||||
model=model,
|
model=model,
|
||||||
messages=[
|
messages=[
|
||||||
{"role": "system", "content": "Pretend you are eccentric conspiracy theorist Planetside 2 gamer named Dr. Moneypants."},
|
{
|
||||||
{"role": "user", "content": f"{question} please keep it short with religious undertones"}
|
"role": "system",
|
||||||
],
|
"content": "Pretend you are eccentric conspiracy theorist Planetside 2 gamer named Dr. Moneypants.",
|
||||||
max_tokens=400
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": f"{question} please keep it short with religious undertones",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
max_tokens=400,
|
||||||
)
|
)
|
||||||
answer = response['choices'][0]['message']['content']
|
answer = response["choices"][0]["message"]["content"]
|
||||||
answer = answer.replace("an AI language model", "a man of God")
|
answer = answer.replace("an AI language model", "a man of God")
|
||||||
answer = answer.replace("language model AI", "man of God")
|
answer = answer.replace("language model AI", "man of God")
|
||||||
await message.channel.send(answer)
|
await message.channel.send(answer)
|
||||||
@@ -40,14 +54,16 @@ async def on_message(message):
|
|||||||
e = str(e)
|
e = str(e)
|
||||||
await message.channel.send(f"`MoneyBot Error: {e}`")
|
await message.channel.send(f"`MoneyBot Error: {e}`")
|
||||||
|
|
||||||
|
|
||||||
async def moneybot_connect():
|
async def moneybot_connect():
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
await client.start(moneykey)
|
await client.start(moneykey)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
e = str(e)
|
e = str(e)
|
||||||
logger.error(f"Moneybot couldn't connect! {e}")
|
logger.error(f"Moneybot couldn't connect! {e}")
|
||||||
await asyncio.sleep(60)
|
await asyncio.sleep(60)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(moneybot_connect())
|
asyncio.run(moneybot_connect())
|
||||||
|
|||||||
15
garfmain.py
15
garfmain.py
@@ -42,18 +42,19 @@ weather = WeatherAPI()
|
|||||||
|
|
||||||
|
|
||||||
URL_PATTERNS = [
|
URL_PATTERNS = [
|
||||||
r'https?://(?:www\.)?youtube\.com/watch\?[^\s]*',
|
r"https?://(?:www\.)?youtube\.com/watch\?[^\s]*",
|
||||||
r'https?://youtu\.be/[^\s]*',
|
r"https?://youtu\.be/[^\s]*",
|
||||||
r'https?://(?:open\.)?spotify\.com/[^\s]*',
|
r"https?://(?:open\.)?spotify\.com/[^\s]*",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def clean_url(url):
|
def clean_url(url):
|
||||||
try:
|
try:
|
||||||
parsed = urlparse(url)
|
parsed = urlparse(url)
|
||||||
|
|
||||||
if 'youtube.com' in parsed.hostname:
|
if "youtube.com" in parsed.hostname:
|
||||||
params = parse_qs(parsed.query)
|
params = parse_qs(parsed.query)
|
||||||
video_id = params.get('v', [None])[0]
|
video_id = params.get("v", [None])[0]
|
||||||
if not video_id:
|
if not video_id:
|
||||||
return None
|
return None
|
||||||
# timestamp = params.get('t', [None])[0]
|
# timestamp = params.get('t', [None])[0]
|
||||||
@@ -61,10 +62,10 @@ def clean_url(url):
|
|||||||
# return f"https://www.youtube.com/watch?v={video_id}&t={timestamp}"
|
# return f"https://www.youtube.com/watch?v={video_id}&t={timestamp}"
|
||||||
return f"https://www.youtube.com/watch?v={video_id}"
|
return f"https://www.youtube.com/watch?v={video_id}"
|
||||||
|
|
||||||
if 'youtu.be' in parsed.hostname:
|
if "youtu.be" in parsed.hostname:
|
||||||
return f"https://youtu.be{parsed.path}"
|
return f"https://youtu.be{parsed.path}"
|
||||||
|
|
||||||
if 'spotify.com' in parsed.hostname:
|
if "spotify.com" in parsed.hostname:
|
||||||
return f"https://open.spotify.com{parsed.path}"
|
return f"https://open.spotify.com{parsed.path}"
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -134,4 +134,3 @@ async def aod_message(garfbot, message):
|
|||||||
|
|
||||||
# if count >= 3 or (len(words) >= 2 and count / len(words) >= 0.75):
|
# if count >= 3 or (len(words) >= 2 and count / len(words) >= 0.75):
|
||||||
# await message.channel.send("Boy, you said it!")
|
# await message.channel.send("Boy, you said it!")
|
||||||
|
|
||||||
|
|||||||
171
garfpy/garfai.py
171
garfpy/garfai.py
@@ -13,13 +13,31 @@ from garfpy import logger
|
|||||||
|
|
||||||
INVOKEAI_BASE = config.INVOKEAI_URL
|
INVOKEAI_BASE = config.INVOKEAI_URL
|
||||||
|
|
||||||
_MODEL_KEY = "0eb50094-5c9b-431b-ba01-87e145edb849"
|
_MODEL_KEY = "0eb50094-5c9b-431b-ba01-87e145edb849"
|
||||||
_VAE_KEY = "dde3627c-8a45-4088-93d1-66c44acbb337"
|
_VAE_KEY = "dde3627c-8a45-4088-93d1-66c44acbb337"
|
||||||
_ENCODER_KEY = "7ba22542-4687-4946-a52e-c92f925f4b75"
|
_ENCODER_KEY = "7ba22542-4687-4946-a52e-c92f925f4b75"
|
||||||
|
|
||||||
_MODEL_REF = {"key": _MODEL_KEY, "hash": "blake3:c3ee838d71d99497db01fae6f304eafd9e734e935f3b783e968d50febb56be2c", "name": "FLUX.2 Klein 4B (GGUF Q4)", "base": "flux2", "type": "main"}
|
_MODEL_REF = {
|
||||||
_VAE_REF = {"key": _VAE_KEY, "hash": "blake3:531855de70db993d0f6181f82cde27d15411d58b7ffa3b2fdce2b9434c0173c2", "name": "FLUX.2 VAE", "base": "flux2", "type": "vae"}
|
"key": _MODEL_KEY,
|
||||||
_ENCODER_REF = {"key": _ENCODER_KEY, "hash": "blake3:af5840e6770dc99f678e69867949c8b9264835915eb82a990e940fa6e4fa6c81", "name": "FLUX.2 Klein Qwen3 4B Encoder", "base": "any", "type": "qwen3_encoder"}
|
"hash": "blake3:c3ee838d71d99497db01fae6f304eafd9e734e935f3b783e968d50febb56be2c",
|
||||||
|
"name": "FLUX.2 Klein 4B (GGUF Q4)",
|
||||||
|
"base": "flux2",
|
||||||
|
"type": "main",
|
||||||
|
}
|
||||||
|
_VAE_REF = {
|
||||||
|
"key": _VAE_KEY,
|
||||||
|
"hash": "blake3:531855de70db993d0f6181f82cde27d15411d58b7ffa3b2fdce2b9434c0173c2",
|
||||||
|
"name": "FLUX.2 VAE",
|
||||||
|
"base": "flux2",
|
||||||
|
"type": "vae",
|
||||||
|
}
|
||||||
|
_ENCODER_REF = {
|
||||||
|
"key": _ENCODER_KEY,
|
||||||
|
"hash": "blake3:af5840e6770dc99f678e69867949c8b9264835915eb82a990e940fa6e4fa6c81",
|
||||||
|
"name": "FLUX.2 Klein Qwen3 4B Encoder",
|
||||||
|
"base": "any",
|
||||||
|
"type": "qwen3_encoder",
|
||||||
|
}
|
||||||
|
|
||||||
_POLL_INTERVAL = 2
|
_POLL_INTERVAL = 2
|
||||||
_POLL_ATTEMPTS = 60
|
_POLL_ATTEMPTS = 60
|
||||||
@@ -31,49 +49,103 @@ def _node_id(prefix: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _build_graph(prompt: str) -> dict:
|
def _build_graph(prompt: str) -> dict:
|
||||||
seed = int(time.time() * 1000) % (2 ** 31)
|
seed = int(time.time() * 1000) % (2**31)
|
||||||
|
|
||||||
p = _node_id("positive_prompt")
|
p = _node_id("positive_prompt")
|
||||||
ml = _node_id("flux2_klein_model_loader")
|
ml = _node_id("flux2_klein_model_loader")
|
||||||
te = _node_id("flux2_klein_text_encoder")
|
te = _node_id("flux2_klein_text_encoder")
|
||||||
dn = _node_id("flux2_denoise")
|
dn = _node_id("flux2_denoise")
|
||||||
out = _node_id("canvas_output")
|
out = _node_id("canvas_output")
|
||||||
|
|
||||||
nodes = {
|
nodes = {
|
||||||
p: {"id": p, "is_intermediate": True, "use_cache": True, "value": prompt, "type": "string"},
|
p: {
|
||||||
ml: {"id": ml, "is_intermediate": True, "use_cache": True, "type": "flux2_klein_model_loader",
|
"id": p,
|
||||||
"model": _MODEL_REF, "vae_model": _VAE_REF, "qwen3_encoder_model": _ENCODER_REF},
|
"is_intermediate": True,
|
||||||
te: {"id": te, "is_intermediate": True, "use_cache": True, "type": "flux2_klein_text_encoder"},
|
"use_cache": True,
|
||||||
dn: {"id": dn, "is_intermediate": True, "use_cache": True, "type": "flux2_denoise", "seed": seed},
|
"value": prompt,
|
||||||
out: {"id": out, "is_intermediate": False, "use_cache": False, "type": "flux2_vae_decode"},
|
"type": "string",
|
||||||
|
},
|
||||||
|
ml: {
|
||||||
|
"id": ml,
|
||||||
|
"is_intermediate": True,
|
||||||
|
"use_cache": True,
|
||||||
|
"type": "flux2_klein_model_loader",
|
||||||
|
"model": _MODEL_REF,
|
||||||
|
"vae_model": _VAE_REF,
|
||||||
|
"qwen3_encoder_model": _ENCODER_REF,
|
||||||
|
},
|
||||||
|
te: {
|
||||||
|
"id": te,
|
||||||
|
"is_intermediate": True,
|
||||||
|
"use_cache": True,
|
||||||
|
"type": "flux2_klein_text_encoder",
|
||||||
|
},
|
||||||
|
dn: {
|
||||||
|
"id": dn,
|
||||||
|
"is_intermediate": True,
|
||||||
|
"use_cache": True,
|
||||||
|
"type": "flux2_denoise",
|
||||||
|
"seed": seed,
|
||||||
|
},
|
||||||
|
out: {
|
||||||
|
"id": out,
|
||||||
|
"is_intermediate": False,
|
||||||
|
"use_cache": False,
|
||||||
|
"type": "flux2_vae_decode",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
edges = [
|
edges = [
|
||||||
{"source": {"node_id": ml, "field": "qwen3_encoder"}, "destination": {"node_id": te, "field": "qwen3_encoder"}},
|
{
|
||||||
{"source": {"node_id": ml, "field": "max_seq_len"}, "destination": {"node_id": te, "field": "max_seq_len"}},
|
"source": {"node_id": ml, "field": "qwen3_encoder"},
|
||||||
{"source": {"node_id": p, "field": "value"}, "destination": {"node_id": te, "field": "prompt"}},
|
"destination": {"node_id": te, "field": "qwen3_encoder"},
|
||||||
{"source": {"node_id": ml, "field": "transformer"}, "destination": {"node_id": dn, "field": "transformer"}},
|
},
|
||||||
{"source": {"node_id": ml, "field": "vae"}, "destination": {"node_id": dn, "field": "vae"}},
|
{
|
||||||
{"source": {"node_id": te, "field": "conditioning"}, "destination": {"node_id": dn, "field": "positive_text_conditioning"}},
|
"source": {"node_id": ml, "field": "max_seq_len"},
|
||||||
{"source": {"node_id": ml, "field": "vae"}, "destination": {"node_id": out, "field": "vae"}},
|
"destination": {"node_id": te, "field": "max_seq_len"},
|
||||||
{"source": {"node_id": dn, "field": "latents"}, "destination": {"node_id": out, "field": "latents"}},
|
},
|
||||||
|
{
|
||||||
|
"source": {"node_id": p, "field": "value"},
|
||||||
|
"destination": {"node_id": te, "field": "prompt"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": {"node_id": ml, "field": "transformer"},
|
||||||
|
"destination": {"node_id": dn, "field": "transformer"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": {"node_id": ml, "field": "vae"},
|
||||||
|
"destination": {"node_id": dn, "field": "vae"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": {"node_id": te, "field": "conditioning"},
|
||||||
|
"destination": {"node_id": dn, "field": "positive_text_conditioning"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": {"node_id": ml, "field": "vae"},
|
||||||
|
"destination": {"node_id": out, "field": "vae"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": {"node_id": dn, "field": "latents"},
|
||||||
|
"destination": {"node_id": out, "field": "latents"},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
return {"nodes": nodes, "edges": edges}
|
return {"nodes": nodes, "edges": edges}
|
||||||
|
|
||||||
|
|
||||||
async def _poll_batch(session: aiohttp.ClientSession, base: str, batch_id: str) -> bool:
|
async def _poll_batch(session: aiohttp.ClientSession, base: str, batch_id: str) -> bool:
|
||||||
"""Poll batch status until completed, failed, or timed out. Returns True on success."""
|
|
||||||
for _ in range(_POLL_ATTEMPTS):
|
for _ in range(_POLL_ATTEMPTS):
|
||||||
await asyncio.sleep(_POLL_INTERVAL)
|
await asyncio.sleep(_POLL_INTERVAL)
|
||||||
try:
|
try:
|
||||||
async with session.get(f"{base}/api/v1/queue/default/b/{batch_id}/status") as resp:
|
async with session.get(
|
||||||
|
f"{base}/api/v1/queue/default/b/{batch_id}/status"
|
||||||
|
) as resp:
|
||||||
if not resp.ok:
|
if not resp.ok:
|
||||||
continue
|
continue
|
||||||
s = await resp.json(content_type=None)
|
s = await resp.json(content_type=None)
|
||||||
total = s.get("total", 0)
|
total = s.get("total", 0)
|
||||||
completed = s.get("completed", 0)
|
completed = s.get("completed", 0)
|
||||||
failed = s.get("failed", 0)
|
failed = s.get("failed", 0)
|
||||||
if total > 0 and failed >= total:
|
if total > 0 and failed >= total:
|
||||||
logger.error(f"Batch {batch_id} failed")
|
logger.error(f"Batch {batch_id} failed")
|
||||||
return False
|
return False
|
||||||
@@ -84,7 +156,9 @@ async def _poll_batch(session: aiohttp.ClientSession, base: str, batch_id: str)
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def _get_image_name(session: aiohttp.ClientSession, base: str, batch_id: str) -> str | None:
|
async def _get_image_name(
|
||||||
|
session: aiohttp.ClientSession, base: str, batch_id: str
|
||||||
|
) -> str | None:
|
||||||
try:
|
try:
|
||||||
async with session.get(f"{base}/api/v1/queue/default/i/{batch_id}") as resp:
|
async with session.get(f"{base}/api/v1/queue/default/i/{batch_id}") as resp:
|
||||||
if resp.ok:
|
if resp.ok:
|
||||||
@@ -110,8 +184,9 @@ async def _get_image_name(session: aiohttp.ClientSession, base: str, batch_id: s
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def _fetch_image_bytes(session: aiohttp.ClientSession, base: str, name: str) -> bytes | None:
|
async def _fetch_image_bytes(
|
||||||
"""Try the full image endpoint, then fall back to thumbnail."""
|
session: aiohttp.ClientSession, base: str, name: str
|
||||||
|
) -> bytes | None:
|
||||||
urls = [
|
urls = [
|
||||||
f"{base}/api/v1/images/i/{name}/full",
|
f"{base}/api/v1/images/i/{name}/full",
|
||||||
f"{base}/api/v1/images/i/{name}/thumbnail",
|
f"{base}/api/v1/images/i/{name}/thumbnail",
|
||||||
@@ -119,9 +194,11 @@ async def _fetch_image_bytes(session: aiohttp.ClientSession, base: str, name: st
|
|||||||
for url in urls:
|
for url in urls:
|
||||||
try:
|
try:
|
||||||
async with session.get(url) as resp:
|
async with session.get(url) as resp:
|
||||||
ct = resp.headers.get("Content-Type", "")
|
ct = resp.headers.get("Content-Type", "")
|
||||||
data = await resp.read()
|
data = await resp.read()
|
||||||
logger.info(f"Image fetch {url}: status={resp.status} content-type={ct} size={len(data)}")
|
logger.info(
|
||||||
|
f"Image fetch {url}: status={resp.status} content-type={ct} size={len(data)}"
|
||||||
|
)
|
||||||
if "html" not in ct and len(data) >= _MIN_IMAGE_BYTES:
|
if "html" not in ct and len(data) >= _MIN_IMAGE_BYTES:
|
||||||
return data
|
return data
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -131,10 +208,10 @@ async def _fetch_image_bytes(session: aiohttp.ClientSession, base: str, name: st
|
|||||||
|
|
||||||
class GarfAI:
|
class GarfAI:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.baseurl = config.BASE_URL
|
self.baseurl = config.BASE_URL
|
||||||
self.sysprompt = config.SYSTEM_PROMPT
|
self.sysprompt = config.SYSTEM_PROMPT
|
||||||
self.txtmodel = config.TXT_MODEL
|
self.txtmodel = config.TXT_MODEL
|
||||||
self.imgmodel = config.IMG_MODEL
|
self.imgmodel = config.IMG_MODEL
|
||||||
|
|
||||||
self._oai = AsyncOpenAI(
|
self._oai = AsyncOpenAI(
|
||||||
api_key=config.OPENAI_TOKEN,
|
api_key=config.OPENAI_TOKEN,
|
||||||
@@ -145,7 +222,9 @@ class GarfAI:
|
|||||||
async def garfpic(self, ctx, prompt):
|
async def garfpic(self, ctx, prompt):
|
||||||
await self.image_request_queue.put({"ctx": ctx, "prompt": prompt})
|
await self.image_request_queue.put({"ctx": ctx, "prompt": prompt})
|
||||||
|
|
||||||
async def generate_image(self, session: aiohttp.ClientSession, prompt: str) -> bytes | str:
|
async def generate_image(
|
||||||
|
self, session: aiohttp.ClientSession, prompt: str
|
||||||
|
) -> bytes | str:
|
||||||
base = INVOKEAI_BASE
|
base = INVOKEAI_BASE
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -157,7 +236,7 @@ class GarfAI:
|
|||||||
text = await resp.text()
|
text = await resp.text()
|
||||||
logger.error(f"InvokeAI enqueue failed {resp.status}: {text}")
|
logger.error(f"InvokeAI enqueue failed {resp.status}: {text}")
|
||||||
return "`GarfBot Error: InvokeAI rejected the request`"
|
return "`GarfBot Error: InvokeAI rejected the request`"
|
||||||
data = await resp.json(content_type=None)
|
data = await resp.json(content_type=None)
|
||||||
batch_id = data["batch"]["batch_id"]
|
batch_id = data["batch"]["batch_id"]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"InvokeAI enqueue error: {e}")
|
logger.error(f"InvokeAI enqueue error: {e}")
|
||||||
@@ -182,19 +261,21 @@ class GarfAI:
|
|||||||
return "`GarfBot Error: Odie`"
|
return "`GarfBot Error: Odie`"
|
||||||
|
|
||||||
async def process_image_requests(self):
|
async def process_image_requests(self):
|
||||||
async with aiohttp.ClientSession(headers={"Accept": "application/json"}) as session:
|
async with aiohttp.ClientSession(
|
||||||
|
headers={"Accept": "application/json"}
|
||||||
|
) as session:
|
||||||
while True:
|
while True:
|
||||||
request = await self.image_request_queue.get()
|
request = await self.image_request_queue.get()
|
||||||
ctx = request["ctx"]
|
ctx = request["ctx"]
|
||||||
prompt = request["prompt"]
|
prompt = request["prompt"]
|
||||||
|
|
||||||
result = await self.generate_image(session, prompt)
|
result = await self.generate_image(session, prompt)
|
||||||
|
|
||||||
if isinstance(result, bytes):
|
if isinstance(result, bytes):
|
||||||
logger.info("Sending image...")
|
logger.info("Sending image...")
|
||||||
image = io.BytesIO(result)
|
image = io.BytesIO(result)
|
||||||
timestamp = ctx.message.created_at.strftime("%Y%m%d%H%M%S")
|
timestamp = ctx.message.created_at.strftime("%Y%m%d%H%M%S")
|
||||||
filename = f"{timestamp}_generated_image.png"
|
filename = f"{timestamp}_generated_image.png"
|
||||||
try:
|
try:
|
||||||
await ctx.reply(file=discord.File(fp=image, filename=filename))
|
await ctx.reply(file=discord.File(fp=image, filename=filename))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -211,7 +292,7 @@ class GarfAI:
|
|||||||
model=self.txtmodel,
|
model=self.txtmodel,
|
||||||
messages=[
|
messages=[
|
||||||
{"role": "system", "content": self.sysprompt},
|
{"role": "system", "content": self.sysprompt},
|
||||||
{"role": "user", "content": question},
|
{"role": "user", "content": question},
|
||||||
],
|
],
|
||||||
max_tokens=400,
|
max_tokens=400,
|
||||||
temperature=1.2,
|
temperature=1.2,
|
||||||
@@ -231,7 +312,9 @@ class GarfAI:
|
|||||||
async def wikisum(self, query: str) -> str:
|
async def wikisum(self, query: str) -> str:
|
||||||
try:
|
try:
|
||||||
summary = wikipedia.summary(query)
|
summary = wikipedia.summary(query)
|
||||||
return await self.generate_chat(f"Please summarize in your own words: {summary}")
|
return await self.generate_chat(
|
||||||
|
f"Please summarize in your own words: {summary}"
|
||||||
|
)
|
||||||
except wikipedia.exceptions.DisambiguationError as e:
|
except wikipedia.exceptions.DisambiguationError as e:
|
||||||
options = ", ".join(e.options[:3])
|
options = ", ".join(e.options[:3])
|
||||||
return f"`GarfBot Error: Ambiguous query — did you mean: {options}?`"
|
return f"`GarfBot Error: Ambiguous query — did you mean: {options}?`"
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ async def generate_qr(text):
|
|||||||
|
|
||||||
qr = qrcode.QRCode(
|
qr = qrcode.QRCode(
|
||||||
version=version,
|
version=version,
|
||||||
error_correction=qrcode.constants.ERROR_CORRECT_L, # type: ignore
|
error_correction=qrcode.constants.ERROR_CORRECT_L, # type: ignore
|
||||||
box_size=box_size,
|
box_size=box_size,
|
||||||
border=4,
|
border=4,
|
||||||
)
|
)
|
||||||
@@ -58,7 +58,7 @@ async def generate_qr(text):
|
|||||||
qr_image = qr.make_image(fill_color="black", back_color="white")
|
qr_image = qr.make_image(fill_color="black", back_color="white")
|
||||||
|
|
||||||
img_buffer = BytesIO()
|
img_buffer = BytesIO()
|
||||||
qr_image.save(img_buffer, format="PNG") # type: ignore
|
qr_image.save(img_buffer, format="PNG") # type: ignore
|
||||||
img_buffer.seek(0)
|
img_buffer.seek(0)
|
||||||
|
|
||||||
return img_buffer
|
return img_buffer
|
||||||
|
|||||||
@@ -46,10 +46,12 @@ client = commands.Bot(
|
|||||||
intents=intents,
|
intents=intents,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@client.event
|
@client.event
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
print(f"Logged in as {client.user.name} running {txtmodel}.", flush=True)
|
print(f"Logged in as {client.user.name} running {txtmodel}.", flush=True)
|
||||||
|
|
||||||
|
|
||||||
@client.command(name="chat")
|
@client.command(name="chat")
|
||||||
async def jonchat(ctx, *, prompt):
|
async def jonchat(ctx, *, prompt):
|
||||||
if "is this true" in prompt.lower():
|
if "is this true" in prompt.lower():
|
||||||
@@ -62,6 +64,7 @@ async def jonchat(ctx, *, prompt):
|
|||||||
)
|
)
|
||||||
await ctx.reply(answer)
|
await ctx.reply(answer)
|
||||||
|
|
||||||
|
|
||||||
@client.event
|
@client.event
|
||||||
async def on_message(message):
|
async def on_message(message):
|
||||||
if message.author == client.user:
|
if message.author == client.user:
|
||||||
@@ -69,9 +72,7 @@ async def on_message(message):
|
|||||||
|
|
||||||
content = message.content.strip()
|
content = message.content.strip()
|
||||||
lower = content.lower()
|
lower = content.lower()
|
||||||
if lower.startswith("hey jon") or isinstance(
|
if lower.startswith("hey jon") or isinstance(message.channel, discord.DMChannel):
|
||||||
message.channel, discord.DMChannel
|
|
||||||
):
|
|
||||||
ctx = await client.get_context(message)
|
ctx = await client.get_context(message)
|
||||||
await jonchat(ctx, prompt=content)
|
await jonchat(ctx, prompt=content)
|
||||||
|
|
||||||
@@ -81,13 +82,14 @@ oai = AsyncOpenAI(
|
|||||||
base_url=config.BASE_URL,
|
base_url=config.BASE_URL,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def generate_chat(question: str) -> str:
|
async def generate_chat(question: str) -> str:
|
||||||
try:
|
try:
|
||||||
response = await oai.chat.completions.create(
|
response = await oai.chat.completions.create(
|
||||||
model=txtmodel,
|
model=txtmodel,
|
||||||
messages=[
|
messages=[
|
||||||
{"role": "system", "content": sysprompt},
|
{"role": "system", "content": sysprompt},
|
||||||
{"role": "user", "content": question},
|
{"role": "user", "content": question},
|
||||||
],
|
],
|
||||||
max_tokens=400,
|
max_tokens=400,
|
||||||
temperature=1.2,
|
temperature=1.2,
|
||||||
@@ -105,15 +107,15 @@ async def generate_chat(question: str) -> str:
|
|||||||
return "`JonBot Error: Liz`"
|
return "`JonBot Error: Liz`"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def jonbot_connect():
|
async def jonbot_connect():
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
await client.start(jonkey)
|
await client.start(jonkey)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
e = str(e)
|
e = str(e)
|
||||||
logger.error(f"Jonbot couldn't connect! {e}")
|
logger.error(f"Jonbot couldn't connect! {e}")
|
||||||
await asyncio.sleep(60)
|
await asyncio.sleep(60)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(jonbot_connect())
|
asyncio.run(jonbot_connect())
|
||||||
|
|||||||
Reference in New Issue
Block a user