Skip to content

Commit

Permalink
feat: Creates new AI commands (#49)
Browse files Browse the repository at this point in the history
- Beta function to crete mind maps

- Allows to ask, summarize and explain topics
  • Loading branch information
miguelcsx authored Jun 7, 2024
1 parent 888ffca commit 9668f98
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 39 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,5 @@ cython_debug/

# Other folders
data/db/*.db
data/reports/*
data/reports/*
data/mindmaps/*
62 changes: 38 additions & 24 deletions app/server/commands/ai_command.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,57 @@
# aura/app/server/commands/ai_command.py

from enum import Enum
import os
from datetime import datetime
import discord
from app.utils.cmdline import run_npx_command
from app.server.commands.discord_commands import Commands
from app.sources.llms.google_ai import GoogleAI


class Model(Enum):
GOOGLE_AI = "google_ai"
OPEN_AI = "open_ai"
from app.sources.generative.text_model import TextModel


class AICommand(Commands):

def __init__(self, model: Model = Model.GOOGLE_AI):
super().__init__()
self.model = model

def execute(self, sub_command: str, prompt: str) -> discord.Embed:
ai = self.get_model()

if sub_command == "chat":
return self.chat(ai, prompt)
def execute(self, sub_command: str, *args) -> discord.Embed:
ai = TextModel()

if sub_command == "ask":
return self.ask(ai, *args)
elif sub_command == "explain":
return self.explain(ai, *args)
elif sub_command == "summarize":
return self.summarize(ai, *args)
elif sub_command == "mindmap":
return self.generate_map(ai, *args)
else:
return self.get_help()["brief"]

def chat(self, ai: GoogleAI, prompt: str) -> discord.Embed:
response = ai.generate_text(prompt)
def ask(self, ai: TextModel, prompt: str) -> discord.Embed:
response = ai.ask(prompt)
return self.create_embed(prompt, response, "")

def get_model(self):
if self.model == Model.GOOGLE_AI:
return GoogleAI()
else:
return None
def explain(self, ai: TextModel, topic: str) -> discord.Embed:
response = ai.explain(topic)
return self.create_embed(topic, response, "")

def summarize(self, ai: TextModel, text: str, type: str = "brief") -> discord.Embed:
response = ai.summarize(text, type)
return self.create_embed(text, response, "")

async def generate_map(self, ai: TextModel, text: str, user_id: str) -> None:
user_folder = os.path.join("data", "mindmaps", str(user_id))
# Create the user folder if it does not exist
os.makedirs(user_folder, exist_ok=True)
response = ai.create_mindmap(text)
filename = f"{user_id}_{datetime.utcnow().isoformat()}_mindmap.md"
mindmap_path = os.path.join(user_folder, filename)
with open(mindmap_path, "w", encoding="utf-8") as file:
file.write(response)

# Create the visual mind map
run_npx_command("markmap-cli", "--no-open", "--no-toolbar", "--offline", "-o", mindmap_path, f"{mindmap_path}.html")

def get_help(self):
return {
"brief": "Commands to interact with the AI",
"search": "Generate text from the AI",
"parameters": ["chat", "prompt"]
"parameters": ["ask", "prompt"]
}
36 changes: 34 additions & 2 deletions app/server/commands/command_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,50 @@ def _ai_commands(bot):
description=bot.ai_command.get_help()["brief"]
)

@ai.command(name="chat")
@ai.command(name="ask")
async def ai_chat(
interaction: discord.Interaction, prompt: str
) -> None:
sub_command = "chat"
sub_command = "ask"
await interaction.response.send_message(embed=discord.Embed(title="Generating text from the AI"))
consult = bot.ai_command.execute(sub_command, prompt)
if isinstance(consult, discord.Embed):
await interaction.edit_original_response(embed=consult)
else:
await interaction.response.send_message(consult)

@ai.command(name="explain")
async def ai_explain(
interaction: discord.Interaction, topic: str
) -> None:
sub_command = "explain"
await interaction.response.send_message(embed=discord.Embed(title=f"Explaining {topic}"))
consult = bot.ai_command.execute(sub_command, topic)
if isinstance(consult, discord.Embed):
await interaction.edit_original_response(embed=consult)
else:
await interaction.response.send_message(consult)

@ai.command(name="summarize")
async def ai_summarize(
interaction: discord.Interaction, text: str, type: str
) -> None:
sub_command = "summarize"
await interaction.response.send_message(embed=discord.Embed(title="Summarizing text"))
consult = bot.ai_command.execute(sub_command, text, type)
if isinstance(consult, discord.Embed):
await interaction.edit_original_response(embed=consult)
else:
await interaction.response.send_message(consult)

@ai.command(name="mindmap")
async def ai_mindmap(
interaction: discord.Interaction, text: str
) -> None:
sub_command = "mindmap"
await interaction.response.send_message(embed=discord.Embed(title="Creating mind map"))
await bot.ai_command.execute(sub_command, text, interaction.user.id)

bot.tree.add_command(ai)


Expand Down
File renamed without changes.
29 changes: 29 additions & 0 deletions app/sources/generative/text_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# aura/app/sources/llms/google_ai.py

from langchain_google_genai import ChatGoogleGenerativeAI


class TextModel:

def __init__(self, model_name: str = "gemini-pro"):
self.llm = ChatGoogleGenerativeAI(model=model_name)

def ask(self, question: str) -> str:
prompt = f"Question: {question}\nAnswer: Be concise and clear."
result = self.llm.invoke(prompt)
return result.content

def explain(self, topic: str) -> str:
prompt = f"Explain: {topic}\nAnswer: Provide a step by step detailed explanation."
result = self.llm.invoke(prompt)
return result.content

def summarize(self, text: str, type: str) -> str:
prompt = f"Summarize: {text}\nAnswer: Provide a {type} summary."
result = self.llm.invoke(prompt)
return result.content

def create_mindmap(self, text: str) -> str:
prompt = f"Create a markdown mind map from the following text: {text} to use with markmap"
result = self.llm.invoke(prompt)
return result.content
12 changes: 0 additions & 12 deletions app/sources/llms/google_ai.py

This file was deleted.

Empty file added app/sources/video/__init__.py
Empty file.
Empty file added app/utils/__init__.py
Empty file.
23 changes: 23 additions & 0 deletions app/utils/cmdline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# aura/app/utils/cmdline.py

import subprocess


def run_cli_command(command: str, *args) -> str:
"""
Run a command line command with the given arguments
"""
command_args = [command, *args]
with subprocess.Popen(command_args, stdout=subprocess.PIPE) as process:
output, _ = process.communicate()
return output.decode("utf-8")


def run_npx_command(command: str, *args) -> str:
"""
Run an npx command with the given arguments
"""
command_args = ["npx", command, *args]
with subprocess.Popen(command_args, stdout=subprocess.PIPE) as process:
output, _ = process.communicate()
return output.decode("utf-8")
21 changes: 21 additions & 0 deletions app/utils/parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# aura/app/utils/parser.py

import cairosvg


def convert_html_to_svg(html: str, output_file: str) -> None:
"""
Convert HTML to SVG
"""
with open(html, "r", encoding="uft-8") as file:
html_content = file.read()
cairosvg.svg2svg(html_content, write_to=output_file)


def convert_html_to_png(html: str, output_file: str) -> None:
"""
Convert HTML to PNG
"""
with open(html, "r", encoding="utf-8") as file:
html_content = file.read()
cairosvg.svg2png(html_content, write_to=output_file)
7 changes: 7 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ async-timeout==4.0.3
attrs==23.2.0
beautifulsoup4==4.12.3
cachetools==5.3.3
cairocffi==1.7.0
CairoSVG==2.7.1
certifi==2024.2.2
cffi==1.16.0
charset-normalizer==3.3.2
cssselect2==0.7.0
dataclasses-json==0.6.4
defusedxml==0.7.1
dill==0.3.8
Expand Down Expand Up @@ -62,6 +66,7 @@ protobuf==4.25.3
pyasn1==0.6.0
pyasn1_modules==0.4.0
pycodestyle==2.11.1
pycparser==2.22
pydantic==2.7.1
pydantic_core==2.18.2
pyflakes==3.2.0
Expand All @@ -76,6 +81,7 @@ sniffio==1.3.1
soupsieve==2.5
SQLAlchemy==2.0.29
tenacity==8.2.3
tinycss2==1.3.0
tokenizers==0.19.1
tomli==2.0.1
tomlkit==0.12.4
Expand All @@ -84,5 +90,6 @@ typing-inspect==0.9.0
typing_extensions==4.10.0
uritemplate==4.1.1
urllib3==2.2.1
webencodings==0.5.1
wikipedia==1.4.0
yarl==1.9.4

0 comments on commit 9668f98

Please sign in to comment.