Skip to content

Commit

Permalink
Merge pull request #2 from SaM-92/dev_b
Browse files Browse the repository at this point in the history
Resolve Midnight Data Gaps & Integrate ElevenLabs Audio Generation
  • Loading branch information
SaM-92 authored Feb 23, 2024
2 parents b73b2e1 + 851a13e commit 320a317
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 49 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ __pycache__/
# for workflow

docker_and_azure.txt
eirgrid_api.ipynb
21 changes: 18 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
ConversationHandler,
CallbackContext,
)
from elevenlabs import generate
from subs.energy_api import *
from subs.openai_script import *
from dotenv import load_dotenv
Expand All @@ -20,6 +21,8 @@
load_dotenv()
Telegram_energy_api = os.environ.get("Telegram_energy_api")
CHANNEL_ID_FOR_FEEDBACK = os.environ.get("CHANNEL_ID_FOR_FEEDBACK")
ELEVEN_API_KEY = os.environ.get("ELEVEN_API_KEY")

# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -123,16 +126,28 @@ async def energy_api_func(update: Update, context: CallbackContext):
summary_text, df_with_trend = find_optimized_relative_periods(df_)
today_date = df_with_trend.index[0].strftime("%d/%m/%Y")
eu_summary_text = optimize_categorize_periods(df_with_trend)
quantile_summary_text, _ = find_optimized_relative_periods(
quantile_summary_text, df_with_trend_ = find_optimized_relative_periods(
df_with_trend
) # Generate this based on your DataFrame

prompt = create_combined_gpt_prompt(
today_date, eu_summary_text, quantile_summary_text
)

# get generated prompt
gpt_recom = opt_gpt_summarise(prompt)
# slice the energy saving actions part
energy_saving_actions = get_energy_actions(gpt_recom)
audio_msg = generate_voice(energy_saving_actions)
await context.bot.send_voice(
update.effective_chat.id,
audio_msg,
caption="Here's your energy-saving tips 🎙️",
)
await update.message.reply_text(gpt_recom)
await send_co2_intensity_plot(update, context, df_with_trend)
if len(df_with_trend) > 1:
await send_co2_intensity_plot(update, context, df_with_trend)
del audio_msg

else:
await update.message.reply_text(
Expand Down Expand Up @@ -172,7 +187,7 @@ async def energy_status(update: Update, context: ContextTypes.DEFAULT_TYPE):

# send the list of options and ask the user to select one
await update.message.reply_text(
"I'm here to help you with energy insights. Which category would you like more information about?",
"I'm here to help you with energy insights. Which category would you like more information about?💡🌍🔍",
reply_markup=reply_markup,
)
# Set the conversation state to SELECT_COLUMN
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ matplotlib==3.7.0
requests==2.31.0
openai==1.11.1
python-dotenv==1.0.1
seaborn==0.13.2
seaborn==0.13.2
elevenlabs==0.2.27
132 changes: 87 additions & 45 deletions subs/openai_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import numpy as np
import pandas as pd
from dotenv import load_dotenv
from elevenlabs import generate

# Load environment variables from .env file
load_dotenv()
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
ELEVEN_API_KEY = os.environ.get("ELEVEN_API_KEY")


def optimize_categorize_periods(df):
Expand Down Expand Up @@ -55,52 +57,60 @@ def optimize_categorize_periods(df):


def find_optimized_relative_periods(df):
# Normalize CO2 values to a 0-1 scale
df["normalized"] = (df["Value"] - df["Value"].min()) / (
df["Value"].max() - df["Value"].min()
)

# Define thresholds for relative categorization
low_threshold = df["normalized"].quantile(0.33)
high_threshold = df["normalized"].quantile(0.66)

# Categorize each timestamp
df["category"] = pd.cut(
df["normalized"],
bins=[-np.inf, low_threshold, high_threshold, np.inf],
labels=["Low", "Medium", "High"],
)

# Find consecutive periods with the same category
df["group"] = (df["category"] != df["category"].shift()).cumsum()

# Prepare summary text
# summary_text = "Considering absolute CO2 emission values, determined by data trends, distinct periods are identified as:\n\n"
summary_text = ""

# Initialize a dictionary to store concatenated periods for each category
period_summary = {"Low": [], "Medium": [], "High": []}
if len(df) > 1:
# Normalize CO2 values to a 0-1 scale
df["normalized"] = (df["Value"] - df["Value"].min()) / (
df["Value"].max() - df["Value"].min()
)

# Define emojis for each category
emoji_dict = {"Low": "🟢", "Medium": "🟡", "High": "🔴"}
# Define thresholds for relative categorization
low_threshold = df["normalized"].quantile(0.33)
high_threshold = df["normalized"].quantile(0.66)

# Group by category and group to concatenate periods
for (category, group), data in df.groupby(["category", "group"]):
start_time = data.index.min().strftime("%H:%M")
end_time = data.index.max().strftime("%H:%M")
# For periods that start and end at the same time, just show one time
period_str = (
f"{start_time} to {end_time}" if start_time != end_time else start_time
# Categorize each timestamp
df["category"] = pd.cut(
df["normalized"],
bins=[-np.inf, low_threshold, high_threshold, np.inf],
labels=["Low", "Medium", "High"],
)
period_summary[category].append(period_str)

# Format the summary text for each category
for category in ["Low", "Medium", "High"]:
if period_summary[category]:
periods = ", ".join(period_summary[category])
summary_text += f"- {emoji_dict[category]} {category} Emission: {periods}\n"
else:
summary_text += f"- {emoji_dict[category]} {category} Emission: No specific periods identified.\n"
# Find consecutive periods with the same category
df["group"] = (df["category"] != df["category"].shift()).cumsum()

# Prepare summary text
# summary_text = "Considering absolute CO2 emission values, determined by data trends, distinct periods are identified as:\n\n"
summary_text = ""

# Initialize a dictionary to store concatenated periods for each category
period_summary = {"Low": [], "Medium": [], "High": []}

# Define emojis for each category
emoji_dict = {"Low": "🟢", "Medium": "🟡", "High": "🔴"}

# Group by category and group to concatenate periods
for (category, group), data in df.groupby(["category", "group"]):
start_time = data.index.min().strftime("%H:%M")
end_time = data.index.max().strftime("%H:%M")
# For periods that start and end at the same time, just show one time
period_str = (
f"{start_time} to {end_time}" if start_time != end_time else start_time
)
period_summary[category].append(period_str)

# Format the summary text for each category
for category in ["Low", "Medium", "High"]:
if period_summary[category]:
periods = ", ".join(period_summary[category])
summary_text += (
f"- {emoji_dict[category]} {category} Emission: {periods}\n"
)
else:
summary_text += f"- {emoji_dict[category]} {category} Emission: No specific periods identified.\n"
else:
summary_text = (
"Sorry, we do not have enough data to process data trend analysis."
)

return summary_text, df

Expand All @@ -120,9 +130,9 @@ def create_combined_gpt_prompt(date, eu_summary_text, quantile_summary_text):
"- 🔍 Data Trend Schedule: ONLY report it\n"
f"- 💡 Energy-Saving Actions: Give an example of energy-saving actions for each category of CO2 emission trend, "
f"considering the current season ({date}). Examples should cover:\n"
" - Low Emission Periods: [Your Example Here]\n"
" - Medium Emission Periods: [Your Example Here]\n"
" - High Emission Periods: [Your Example Here]\n"
" -🟢 Low Emission Periods: [Your Example Here]\n"
" -🟡 Medium Emission Periods: [Your Example Here]\n"
" -🔴High Emission Periods: [Your Example Here]\n"
)

prompt_text = (
Expand All @@ -131,7 +141,7 @@ def create_combined_gpt_prompt(date, eu_summary_text, quantile_summary_text):
"advice, utilizing specific data trends.\n\n"
f"{prompt_data}"
"💡 In periods of low emissions, feel free to use energy-intensive appliances without much concern for reduction.\n\n"
f"👉 Please use the following format for your response: \n\n {structure_example}\n"
f"👉 Please use the following format for your response and avoid using * in your response: \n\n {structure_example}\n"
)

return prompt_text
Expand Down Expand Up @@ -166,3 +176,35 @@ def opt_gpt_summarise(prompt):
return generated_text
except Exception as e:
return str(e)


def get_energy_actions(text):
start_keyword = "- 💡 Energy-Saving Actions:"
end_keywords = [
"📋",
"- 🇪🇺",
"- 🔍",
"- 💡",
] # Add possible start of next sections if format varies
end_keyword = next(
(kw for kw in end_keywords if kw in text[text.find(start_keyword) :]),
None,
)

# Find start and end positions
start_pos = text.find(start_keyword)
end_pos = text.find(end_keyword, start_pos + 1) if end_keyword else len(text)

# Extract the section
energy_saving_actions = text[start_pos:end_pos].strip()
return energy_saving_actions


def generate_voice(text):
return generate(
text=text,
voice="Callum",
model="eleven_multilingual_v1",
output_format="mp3_44100_128",
api_key=ELEVEN_API_KEY,
)

0 comments on commit 320a317

Please sign in to comment.