Updated plugins. AI plugin updated

This commit is contained in:
Hash Borgir 2024-03-03 16:34:39 -07:00
parent 387606426c
commit 551c5ddc02
7 changed files with 1520 additions and 30 deletions

1226
plugins/ai.json Normal file

File diff suppressed because it is too large Load Diff

109
plugins/ai.py Normal file
View File

@ -0,0 +1,109 @@
"""
This plugin provides commands to interact with different AI models.
"""
import logging
import requests
import json
import simplematrixbotlib as botlib
import re
import markdown2
async def handle_command(room, message, bot, prefix, config):
"""
Function to handle AI commands.
Args:
room (Room): The Matrix room where the command was invoked.
message (RoomMessage): The message object containing the command.
bot (Bot): The bot object.
prefix (str): The command prefix.
Returns:
None
"""
match = botlib.MessageMatch(room, message, bot, prefix)
if match.is_not_from_this_bot() and match.prefix():
logging.info(f"Received command: {match.command()}")
command = match.command()
conf = load_config()
if command in conf:
await handle_ai_command(room, bot, command, match.args(), conf)
#else:
#await bot.api.send_text_message(room.room_id, f"Unknown command: {command}")
#logging.info("Sent unknown command message to the room")
async def handle_ai_command(room, bot, command, args, config):
"""
Function to handle AI commands.
Args:
room (Room): The Matrix room where the command was invoked.
bot (Bot): The bot object.
command (str): The name of the AI model command.
args (list): List of arguments provided with the command.
config: Configuration parameters.
Returns:
None
"""
if len(args) < 1:
await bot.api.send_text_message(room.room_id, f"Usage: !{command} [prompt]")
logging.info("Sent usage message to the room")
return
prompt = ' '.join(args)
# Prepare data for the API request
url = "http://127.0.0.1:5000/v1/completions"
headers = {
"Content-Type": "application/json"
}
data = {
"prompt": f"<s>[INST]{config[command]['prompt']}{prompt}[/INST]",
"max_tokens": 1024,
"temperature": config[command]["temperature"],
"top_p": config[command]["top_p"],
"top_k": config[command]["top_k"],
"repetition_penalty": config[command]["repetition_penalty"],
"seed": -1,
"stream": False
}
# Make HTTP request to the API endpoint
try:
response = requests.post(url, headers=headers, json=data, verify=False)
response.raise_for_status() # Raise HTTPError for bad responses
payload = response.json()
new_text = payload['choices'][0]['text']
new_text = markdown_to_html(new_text)
if new_text.count('<p>') > 1 or new_text.count('<li>') > 1: # Check if new_text has more than one paragraph
new_text = f"<details><summary><strong>{config[command]['summary']}</strong></summary>{new_text}</details>"
await bot.api.send_markdown_message(room.room_id, new_text)
else:
await bot.api.send_markdown_message(room.room_id, new_text)
logging.info("Sent generated text to the room")
except requests.exceptions.RequestException as e:
logging.error(f"HTTP request failed for '{prompt}': {e}")
await bot.api.send_text_message(room.room_id, f"Error generating text: {e}")
def markdown_to_html(markdown_text):
html_content = markdown2.markdown(markdown_text)
return html_content
def load_config():
"""
Load configuration from ai.json file.
Returns:
dict: Configuration parameters.
"""
with open("plugins/ai.json", "r") as f:
config = json.load(f)
return config
CONFIG = load_config()

View File

@ -1,9 +1,7 @@
"""
This plugin provides a command to display the list of available commands and their descriptions.
Plugin for providing a command to display the list of available commands and their descriptions.
"""
# plugins/help.py
import logging
import simplematrixbotlib as botlib
@ -14,6 +12,9 @@ async def handle_command(room, message, bot, prefix, config):
Args:
room (Room): The Matrix room where the command was invoked.
message (RoomMessage): The message object containing the command.
bot (MatrixBot): The Matrix bot instance.
prefix (str): The command prefix.
config (dict): The bot's configuration.
Returns:
None
@ -52,12 +53,16 @@ async def handle_command(room, message, bot, prefix, config):
<p>Decreases the karma points for the specified user by 1. Decreases the karma points for the specified user by 1 in the database and sends the updated points as a message to the chat room.</p>
</details>
<details><summary>📄 <strong>!funguy [prompt]</strong></summary>
<p>An AI large language model designed to serve as a chatbot within a vibrant and diverse community chat room hosted on the Matrix platform. (Currently loaded model: <strong>TheBloke_Mistral-7B-Instruct-v0.2-GPTQ</strong>)</p>
<details><summary>📸 <strong>!sd [prompt]</strong></summary>
<p>Generates images using self-hosted Stable Diffusion. See available options using just '!sd'.</p>
</details>
<details><summary>🎝 <strong>!music [prompt]</strong></summary>
<p>Your music expert! Try it out.</p>
<details><summary>💡 <strong>!enable</strong></summary>
<p>Enables a disabled command. Use '!enable plugin room' to enable a specific command.</p>
</details>
<details><summary>🚫 <strong>!disable</strong></summary>
<p>Disables a command. Use '!disable plugin room' to disable a specific command.</p>
</details>
<details><summary>🌟 <strong>Funguy Bot Credits</strong> 🌟</summary>
@ -66,6 +71,10 @@ async def handle_command(room, message, bot, prefix, config):
</details>
</p>
</details>
<details><summary>📸 <strong>Funguy Bot AI Commands</strong> 🌟</summary>
!tech, !music, !eth, !seo, !term, !eng, !intv, !js, !xls, !pron, !spk, !trv, !plag, !char, !adv, !story, !foot, !comic, !motiv, !music, !debate, !write, !script, !author, !crit, !rel, !poem, !rap, !speak, !phil, !math, !tutor, !design, !sec, !recruit, !coach, !etymo, !com, !magic, !counsel, !behavior, !fit, !mh, !realest, !log, !dental, !web, !health, !acc, !chef, !auto, !art, !fin, !invest, !tea, !interior, !florist, !selfhelp, !gnome, !aph, !adv, !advgame, !esc, !title, !stats, !prompt, !teach, !db, !diet, !psych, !domain, !tech, !review, !devrel, !acad, !arch, !insane, !manip, !logic, !review, !diy, !influencer, !philos, !socrat, !edu, !meditate, !writer, !smm, !eloc, !viz, !nav, !hypno, !hist, !astro, !critic, !comp, !journo, !curation, !pscoach, !makeup, !childcare, !writing, !art, !py, !syn, !shop, !dining, !telemed, !cook, !law, !fashion, !ml, !trans, !design, !it, !chess, !prompt, !dev, !math, !regex, !time, !dream, !coach, !r, !comm, !trans, !php, !emergency, !worksheet, !test, !game, !security, !create, !browse, !dev, !search, !startup, !guide, !langdet, !sales, !msg, !ceo, !diag, !coach, !therapy, !legal, !gen, !mgmt, !drunk, !hist, !rec, !write, !techtrans, !ai, !game, !proof, !spirit, !spirit, !chem, !friend, !py, !chat, !wiki, !kanji, !note, !litcrit, !enhance, !travel, !data, !gaming
</details>
"""
await bot.api.send_markdown_message(room.room_id, commands_message)

View File

@ -1,35 +1,64 @@
"""
This plugin provides a command for the admin to load a plugin
Plugin for providing a command for the admin to load a plugin.
"""
# plugins/load_plugin.py
import os
import logging
import importlib
import simplematrixbotlib as botlib
# Dictionary to store loaded plugins
PLUGINS = {}
async def load_plugin(plugin_name):
"""
Asynchronously loads a plugin.
Args:
plugin_name (str): The name of the plugin to load.
Returns:
bool: True if the plugin is loaded successfully, False otherwise.
"""
try:
# Import the plugin module
module = importlib.import_module(f"plugins.{plugin_name}")
# Add the plugin module to the PLUGINS dictionary
PLUGINS[plugin_name] = module
logging.info(f"Loaded plugin: {plugin_name}")
return True
except Exception as e:
# Log an error if the plugin fails to load
logging.error(f"Error loading plugin {plugin_name}: {e}")
return False
async def handle_command(room, message, bot, prefix, config):
"""
Asynchronously handles the command to load a plugin.
Args:
room (Room): The Matrix room where the command was invoked.
message (RoomMessage): The message object containing the command.
bot (MatrixBot): The Matrix bot instance.
prefix (str): The command prefix.
config (dict): The bot's configuration.
Returns:
None
"""
match = botlib.MessageMatch(room, message, bot, prefix)
if match.is_not_from_this_bot() and match.prefix() and match.command("load"):
# Check if the sender is the admin
if str(message.sender) == config.admin_user:
args = match.args()
if len(args) != 1:
# Send usage message if the command format is incorrect
await bot.api.send_text_message(room.room_id, "Usage: !load <plugin>")
else:
plugin_name = args[0]
# Check if the plugin is not already loaded
if plugin_name not in PLUGINS:
# Load the plugin
success = await load_plugin(plugin_name)
if success:
await bot.api.send_text_message(room.room_id, f"Plugin '{plugin_name}' loaded successfully")
@ -38,4 +67,5 @@ async def handle_command(room, message, bot, prefix, config):
else:
await bot.api.send_text_message(room.room_id, f"Plugin '{plugin_name}' is already loaded")
else:
# Send unauthorized message if the sender is not the admin
await bot.api.send_text_message(room.room_id, "You are not authorized to load plugins.")

View File

@ -1,7 +1,7 @@
"""
This plugin provides a command to generate images using self hosted Stable Diffusion and send to the room
Plugin for generating images using self-hosted Stable Diffusion and sending them to a Matrix chat room.
"""
# plugins/stable-diffusion.py
import requests
import base64
from asyncio import Queue
@ -11,17 +11,45 @@ import markdown2
from slugify import slugify
def slugify_prompt(prompt):
# Generate a slug from the prompt
"""
Generates a URL-friendly slug from the given prompt.
Args:
prompt (str): The prompt to slugify.
Returns:
str: A URL-friendly slug version of the prompt.
"""
return slugify(prompt)
# Queue to store pending commands
command_queue = Queue()
def markdown_to_html(markdown_text):
"""
Converts Markdown text to HTML.
Args:
markdown_text (str): The Markdown text to convert.
Returns:
str: The HTML version of the input Markdown text.
"""
html_content = markdown2.markdown(markdown_text)
return html_content
async def process_command(room, message, bot, prefix, config):
"""
Asynchronously processes the commands received in the Matrix room.
Args:
room (Room): The Matrix room where the command was received.
message (Message): The message object containing the command.
bot (MatrixBot): The Matrix bot instance.
prefix (str): The command prefix.
config (dict): The bot's configuration.
"""
match = botlib.MessageMatch(room, message, bot, prefix)
if match.prefix() and match.command("sd"):
if command_queue.empty():
@ -30,10 +58,21 @@ async def process_command(room, message, bot, prefix, config):
await command_queue.put((room, message, bot, prefix, config))
async def handle_command(room, message, bot, prefix, config):
"""
Asynchronously handles the 'sd' command, which generates images using Stable Diffusion.
Args:
room (Room): The Matrix room where the command was received.
message (Message): The message object containing the command.
bot (MatrixBot): The Matrix bot instance.
prefix (str): The command prefix.
config (dict): The bot's configuration.
"""
match = botlib.MessageMatch(room, message, bot, prefix)
if match.prefix() and match.command("sd"):
try:
parser = argparse.ArgumentParser(description='Generate images using self hosted Stable Diffusion')
# Parse command-line arguments
parser = argparse.ArgumentParser(description='Generate images using self-hosted Stable Diffusion')
parser.add_argument('--steps', type=int, default=4, help='Number of steps, default=16')
parser.add_argument('--cfg', type=int, default=1.25, help='CFG scale, default=7')
parser.add_argument('--h', type=int, default=512, help='Height of the image, default=512')
@ -61,32 +100,46 @@ async def handle_command(room, message, bot, prefix, config):
}
url = "http://127.0.0.1:7860/sdapi/v1/txt2img"
# Send request to the Stable Diffusion API
response = requests.post(url=url, json=payload)
r = response.json()
# Slugify the prompt
prompt_slug = prompt[:120]
prompt_slug = slugify(prompt[:120])
# Construct filename
filename = f"{prompt_slug}_{args.steps}_{args.h}x{args.w}_{sampler_name}_{args.cfg}.jpg"
with open(f"/tmp/{filename}", 'wb') as f:
f.write(base64.b64decode(r['images'][0]))
await bot.api.send_image_message(room_id=room.room_id, image_filepath=f"/tmp/{filename}") # Corrected argument name
# Send the generated image to the Matrix room
await bot.api.send_image_message(room_id=room.room_id, image_filepath=f"/tmp/{filename}")
# Format and send information about the generated image
neg = neg.replace(" ", "")
info_msg = f"""<details><summary>🍄⤵Image Info:⤵︎</summary><strong>Prompt:</strong> {prompt_slug}<br><strong>Steps:</strong> {args.steps}<br><strong>Dimensions:</strong> {args.h}x{args.w}<br><strong>Sampler:</strong> {sampler_name}<br><strong>CFG Scale:</strong> {args.cfg}<br><strong>Negative Prompt: {neg}</strong></details>"""
await bot.api.send_markdown_message(room.room_id, info_msg)
except argparse.ArgumentError as e:
# Handle argument errors
await bot.api.send_text_message(room.room_id, f"Error: {e}")
await bot.api.send_markdown_message(room.room_id, "<details><summary>Stable Diffusion Help</summary>" + print_help() + "</details>")
except Exception as e:
# Handle general errors
await bot.api.send_text_message(room.room_id, f"Error processing the command: {str(e)}")
finally:
# Process next command from the queue, if any
if not command_queue.empty():
next_command = await command_queue.get()
await handle_command(*next_command)
def print_help():
"""
Generates help text for the 'sd' command.
Returns:
str: Help text for the 'sd' command.
"""
return """
<p>Generate images using self-hosted Stable Diffusion</p>
@ -95,6 +148,8 @@ def print_help():
<li>prompt - Prompt for the image</li>
</ul>
<p>Default Negative Prompts: ((((ugly)))), (((duplicate))), ((morbid)), ((mutilated)), out of frame, extra fingers, mutated hands, ((poorly drawn hands)), ((poorly drawn face)), (((mutation))), (((deformed))), ((ugly)), blurry, ((bad anatomy)), (((bad proportions))), ((extra limbs)), cloned face, (((disfigured))), out of frame, ugly, extra limbs, (bad anatomy), gross proportions, (malformed limbs), ((missing arms)), ((missing legs)), (((extra arms))), (((extra legs))), mutated hands, (fused fingers), (too many fingers), (((long neck)))</p>
<p>Optional arguments:</p>
<ul>
<li>--steps STEPS - Number of steps, default=16</li>

View File

@ -1,21 +1,39 @@
"""
This plugin provides a command to fetch YouTube video information from links.
Plugin for providing a command to fetch YouTube video information from links.
"""
# plugins/youtube.py
# Importing necessary libraries
import re
import logging
import asyncio
from pytubefix import YouTube
import simplematrixbotlib as botlib
import asyncio
def seconds_to_minutes_seconds(seconds):
"""
Converts seconds to a string representation of minutes and seconds.
Args:
seconds (int): The number of seconds.
Returns:
str: A string representation of minutes and seconds in the format MM:SS.
"""
minutes = seconds // 60
seconds %= 60
return f"{minutes:02d}:{seconds:02d}"
async def fetch_youtube_info(youtube_url):
"""
Asynchronously fetches information about a YouTube video.
Args:
youtube_url (str): The URL of the YouTube video.
Returns:
str: A message containing information about the YouTube video.
None if an error occurs during fetching.
"""
try:
video = YouTube(youtube_url)
title = video.title
@ -31,8 +49,21 @@ async def fetch_youtube_info(youtube_url):
return None
async def handle_command(room, message, bot, prefix, config):
"""
Asynchronously handles the command to fetch YouTube video information.
Args:
room (Room): The Matrix room where the command was invoked.
message (RoomMessage): The message object containing the command.
bot (MatrixBot): The Matrix bot instance.
prefix (str): The command prefix.
config (dict): The bot's configuration.
Returns:
None
"""
match = botlib.MessageMatch(room, message, bot, prefix)
if match.is_not_from_this_bot() and re.search(r'youtube\.com/watch\?v=', message.body): # and room.room_id != '!uFhErnfpYhhlauJsNK:matrix.org':
if match.is_not_from_this_bot() and re.search(r'youtube\.com/watch\?v=', message.body):
logging.info("YouTube link detected")
video_id_match = re.search(r'youtube\.com/watch\?v=([^\s]+)', message.body)
if video_id_match:
@ -52,5 +83,3 @@ async def handle_command(room, message, bot, prefix, config):
await asyncio.sleep(1) # wait for 1 second before retrying
else:
logging.error("Failed to fetch YouTube video information after retries")

View File

@ -1,13 +1,25 @@
"""
This plugin provides a command to search for YouTube videos in the room
Plugin for providing a command to search for YouTube videos in the room.
"""
# plugins/youtube_search.py
import logging
import simplematrixbotlib as botlib
from youtube_search import YoutubeSearch
async def handle_command(room, message, bot, PREFIX, config):
"""
Asynchronously handles the command to search for YouTube videos in the room.
Args:
room (Room): The Matrix room where the command was invoked.
message (RoomMessage): The message object containing the command.
bot (MatrixBot): The Matrix bot instance.
PREFIX (str): The command prefix.
config (dict): The bot's configuration.
Returns:
None
"""
match = botlib.MessageMatch(room, message, bot, PREFIX)
if match.is_not_from_this_bot() and match.prefix() and match.command("yt"):
args = match.args()
@ -16,7 +28,7 @@ async def handle_command(room, message, bot, PREFIX, config):
else:
search_terms = " ".join(args)
logging.info(f"Performing YouTube search for: {search_terms}")
results = YoutubeSearch(search_terms, max_results=3).to_dict()
results = YoutubeSearch(search_terms, max_results=10).to_dict()
if results:
output = generate_output(results)
await send_collapsible_message(room, bot, output)
@ -24,6 +36,15 @@ async def handle_command(room, message, bot, PREFIX, config):
await bot.api.send_text_message(room.room_id, "No results found.")
def generate_output(results):
"""
Generates HTML output for displaying YouTube search results.
Args:
results (list): A list of dictionaries containing information about YouTube videos.
Returns:
str: HTML formatted output containing YouTube search results.
"""
output = ""
for video in results:
output += f'<a href="https://www.youtube.com/watch?v={video["id"]}">'
@ -37,5 +58,16 @@ def generate_output(results):
async def send_collapsible_message(room, bot, content):
"""
Sends a collapsible message containing YouTube search results to the room.
Args:
room (Room): The Matrix room where the message will be sent.
bot (MatrixBot): The Matrix bot instance.
content (str): HTML content to be included in the collapsible message.
Returns:
None
"""
message = f'<details><summary><strong>🍄Funguy ▶YouTube Search🍄<br>⤵Click Here To See Results⤵</strong></summary>{content}</details>'
await bot.api.send_markdown_message(room.room_id, message)