Invite_AI / app.py
LiminalVR-AR's picture
Init Project v2
89c010a
import streamlit as st
import pandas as pd
from groq_llms import LLMHandler
#from openrouter_llms import LLMHandler
import tempfile
import os
from dotenv import load_dotenv
load_dotenv()
# Initialize LLMHandler
llm_handler = LLMHandler()
def process_csv(file, user_prompt):
"""Read CSV, generate responses using LLMHandler, and return processed DataFrame."""
df = pd.read_csv(file)
responses = []
for _, row in df.iterrows():
try:
response = llm_handler.generate_response(user_prompt, row.to_dict())
responses.append(response)
except Exception as e:
responses.append(f"Error: {e}")
df["Generated Text"] = responses
return df
def initialize_session_state():
"""Initialize session state variables"""
if 'prompt_creation_method' not in st.session_state:
st.session_state.prompt_creation_method = None
if 'current_step' not in st.session_state:
st.session_state.current_step = 'choose_method'
if 'context' not in st.session_state:
st.session_state.context = ""
if 'questions' not in st.session_state:
st.session_state.questions = []
if 'answers' not in st.session_state:
st.session_state.answers = {}
if 'multiselect_answers' not in st.session_state:
st.session_state.multiselect_answers = {}
if 'custom_options' not in st.session_state:
st.session_state.custom_options = {}
if 'final_prompt' not in st.session_state:
st.session_state.final_prompt = ""
if 'direct_prompt' not in st.session_state:
st.session_state.direct_prompt = ""
def display_progress_tracker():
"""Display current progress and previous responses"""
with st.expander("πŸ“‹ View Progress", expanded=True):
if st.session_state.prompt_creation_method:
st.write(f"**Method chosen:** {st.session_state.prompt_creation_method.title()}")
if st.session_state.context:
st.write("**Initial Context:**")
st.info(st.session_state.context)
if st.button("Edit Context", key="edit_context"):
st.session_state.current_step = 'initial_context'
st.rerun()
if st.session_state.answers:
st.write("**Your Responses:**")
for i, question in enumerate(st.session_state.questions):
if i in st.session_state.multiselect_answers:
answers = ", ".join(st.session_state.multiselect_answers[i])
st.success(f"Q: {question['question']}\nA: {answers}")
elif i in st.session_state.answers:
st.success(f"Q: {question['question']}\nA: {st.session_state.answers[i]}")
if st.button("Edit Responses", key="edit_responses"):
st.session_state.current_step = 'answer_questions'
st.rerun()
if st.session_state.direct_prompt:
st.write("**Your Direct Prompt:**")
st.info(st.session_state.direct_prompt)
if st.button("Edit Prompt", key="edit_direct_prompt"):
st.session_state.current_step = 'direct_prompt'
st.rerun()
if st.session_state.final_prompt:
st.write("**Final Generated Prompt:**")
st.info(st.session_state.final_prompt)
if st.button("Edit Final Prompt", key="edit_final_prompt"):
st.session_state.current_step = 'edit_prompt'
st.rerun()
# Streamlit UI
st.set_page_config(page_title="Invite AI", page_icon="πŸ’¬", layout="wide")
# Header
st.title("Invite AI")
st.markdown(
"""
Welcome to the Invitation Generator! This tool helps you create personalized invitations using the power of AI.
"""
)
# Initialize session state
initialize_session_state()
# Display progress tracker (always visible)
display_progress_tracker()
# Sidebar with instructions
st.sidebar.title("Instructions")
st.sidebar.markdown(
"""
### Template Download
[Click here to download the suggested CSV template](http://surl.li/ptvzzv) πŸ“₯
### Suggested Requirements
- **Unique Identifier for each receiver**
- **Name of the receiver**
- **Designation/Job title of the receiver**
- **Company/Organisation where the receiver works**
- **Areas the receiver is interested in / has expertise in**
- **Categorize receivers into groups**
[Note: The above template is for your reference, you are free to submit your own data.]
"""
)
# Main content area with steps
st.markdown("---") # Separator between progress tracker and current step
if st.session_state.current_step == 'choose_method':
st.subheader("Choose Your Prompt Creation Method")
col1, col2 = st.columns(2)
with col1:
st.markdown("""
### Guided Prompt Builder
- Step-by-step assistance
- AI-generated questions
- Structured approach
""")
if st.button("Use Guided Builder"):
st.session_state.prompt_creation_method = 'guided'
st.session_state.current_step = 'initial_context'
st.rerun()
with col2:
st.markdown("""
### Direct Prompt Entry
- Write your own prompt
- Complete control
- Quick setup
""")
if st.button("Use Direct Entry"):
st.session_state.prompt_creation_method = 'direct'
st.session_state.current_step = 'direct_prompt'
st.rerun()
elif st.session_state.current_step == 'direct_prompt':
st.subheader("Enter Your Prompt")
st.markdown(
"Write your complete prompt for generating invitations. Include all necessary details and requirements.")
direct_prompt = st.text_area(
"Your Prompt:",
value=st.session_state.direct_prompt,
placeholder="Example: Generate a professional invitation for a product launch...",
height=200
)
col1, col2 = st.columns([1, 5])
with col1:
if st.button("← Back"):
st.session_state.current_step = 'choose_method'
st.rerun()
with col2:
if st.button("Continue β†’"):
if direct_prompt:
st.session_state.direct_prompt = direct_prompt
st.session_state.final_prompt = direct_prompt
st.session_state.current_step = 'upload_process'
st.rerun()
else:
st.error("Please enter a prompt before continuing.")
elif st.session_state.prompt_creation_method == 'guided':
if st.session_state.current_step == 'initial_context':
st.subheader("Step 1: Provide Initial Context")
st.markdown("Briefly describe what your invitation is about (e.g., 'Launching a new GPU product')")
context = st.text_area(
"Context:",
value=st.session_state.context,
placeholder="Example: Launching a new GPU product for AI and HPC applications",
height=100
)
col1, col2 = st.columns([1, 5])
with col1:
if st.button("← Back"):
st.session_state.current_step = 'choose_method'
st.rerun()
with col2:
if st.button("Generate Questions β†’"):
if context:
st.session_state.context = context
st.session_state.questions = llm_handler.generate_questions(context)
st.session_state.current_step = 'answer_questions'
st.rerun()
else:
st.error("Please provide context before proceeding.")
# In the answer_questions section of your code, replace the multiselect implementation with this:
elif st.session_state.current_step == 'answer_questions':
st.subheader("Step 2: Answer Questions")
for i, question in enumerate(st.session_state.questions):
if 'choices' in question:
# Get previously selected options
previous_selections = st.session_state.multiselect_answers.get(i, [])
# Initialize base choices
base_choices = question['choices'].copy()
if "Custom" not in base_choices:
base_choices.append("Custom")
# Add any previous custom value to the choices if it exists
custom_values = [x for x in previous_selections if x not in question['choices'] and x != "Custom"]
all_choices = base_choices + custom_values
# Handle word count questions differently
if any(word in question['question'].lower() for word in ['word count', 'words', 'length']):
selected_options = st.multiselect(
question['question'],
options=all_choices,
default=previous_selections,
key=f"multiselect_{i}"
)
if "Custom" in selected_options:
# Pre-fill with previous custom value if exists
default_custom = next((x for x in previous_selections if x not in base_choices), "")
custom_value = st.text_input(
"Enter custom word count:",
value=default_custom,
key=f"custom_{i}"
)
if custom_value:
try:
word_count = int(custom_value)
if word_count > 0:
selected_options = [opt for opt in selected_options if opt != "Custom"]
if str(word_count) not in selected_options:
selected_options.append(str(word_count))
else:
st.error("Please enter a positive number")
except ValueError:
st.error("Please enter a valid number")
else:
# Regular non-numeric multiselect handling
selected_options = st.multiselect(
question['question'],
options=all_choices,
default=previous_selections,
key=f"multiselect_{i}"
)
if "Custom" in selected_options:
# Pre-fill with previous custom value if exists
default_custom = next((x for x in previous_selections if x not in base_choices), "")
custom_value = st.text_input(
"Enter your custom response:",
value=default_custom,
key=f"custom_{i}"
)
if custom_value:
selected_options = [opt for opt in selected_options if opt != "Custom"]
if custom_value not in selected_options:
selected_options.append(custom_value)
# Update session state
st.session_state.multiselect_answers[i] = selected_options
st.session_state.answers[i] = ", ".join(selected_options) if selected_options else ""
else:
# Handle non-choice questions
st.session_state.answers[i] = st.text_input(
question['question'],
value=st.session_state.answers.get(i, ""),
key=f"question_{i}"
)
col1, col2 = st.columns([1, 5])
with col1:
if st.button("← Back"):
st.session_state.current_step = 'initial_context'
st.rerun()
with col2:
if st.button("Generate Prompt β†’"):
if all(st.session_state.answers.values()):
st.session_state.final_prompt = llm_handler.generate_final_prompt(
st.session_state.context,
st.session_state.questions,
st.session_state.answers
)
st.session_state.current_step = 'edit_prompt'
st.rerun()
else:
st.error("Please answer all questions before proceeding.")
elif st.session_state.current_step == 'edit_prompt':
st.subheader("Step 3: Review and Edit Final Prompt")
edited_prompt = st.text_area(
"Edit your prompt if needed:",
value=st.session_state.final_prompt,
height=200
)
col1, col2 = st.columns([1, 5])
with col1:
if st.button("← Back"):
st.session_state.current_step = 'answer_questions'
st.rerun()
with col2:
if st.button("Continue to Upload β†’"):
st.session_state.final_prompt = edited_prompt
st.session_state.current_step = 'upload_process'
st.rerun()
# Common upload and processing section for both paths
if st.session_state.current_step == 'upload_process':
st.subheader("Upload and Process")
uploaded_file = st.file_uploader("πŸ“‚ Upload CSV File", type=["csv"])
col1, col2 = st.columns([1, 5])
with col1:
if st.button("← Back"):
if st.session_state.prompt_creation_method == 'guided':
st.session_state.current_step = 'edit_prompt'
else:
st.session_state.current_step = 'direct_prompt'
st.rerun()
if uploaded_file is not None and st.session_state.final_prompt:
st.write("⏳ Processing your file... Please wait.")
processed_df = process_csv(uploaded_file, st.session_state.final_prompt)
st.write("### Generated Invitations")
st.dataframe(processed_df, use_container_width=True)
with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as temp_file:
processed_df.to_csv(temp_file.name, index=False)
temp_file.close()
st.download_button(
label="πŸ“₯ Download Results CSV",
data=open(temp_file.name, "rb"),
file_name="generated_invitations.csv",
mime="text/csv",
)
os.unlink(temp_file.name)
# Reset button (moved to sidebar)
st.sidebar.markdown("---")
if st.sidebar.button("πŸ”„ Start Over"):
st.session_state.prompt_creation_method = None
st.session_state.current_step = 'choose_method'
st.session_state.context = ""
st.session_state.questions = []
st.session_state.answers = {}
st.session_state.multiselect_answers = {}
st.session_state.custom_options = {}
st.session_state.final_prompt = ""
st.session_state.direct_prompt = ""
st.rerun()
st.markdown("---")
st.markdown("πŸ’‘ **Tip:** Ensure your data aligns with the provided template for accurate results.")