tamilprabaharan's picture
Create app.py
4ca3484 verified
import streamlit as st
import os
import re
from datetime import datetime
import json
from openai import AzureOpenAI
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# For Hugging Face Spaces
if 'AZURE_OPENAI_API_KEY' in os.environ:
api_key = os.environ['AZURE_OPENAI_API_KEY']
endpoint = os.environ['AZURE_OPENAI_ENDPOINT']
else:
# Fall back to dotenv for local development
from dotenv import load_dotenv
load_dotenv()
api_key = os.getenv("AZURE_OPENAI_API_KEY")
endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
# Configure Azure OpenAI client
client = AzureOpenAI(
api_key=api_key,
api_version="2024-02-15-preview",
azure_endpoint=endpoint
)
# Set page configuration
st.set_page_config(
page_title="CSR Initiative Portal",
page_icon="🌱",
layout="wide"
)
# CSS to improve UI
st.markdown("""
<style>
.main {
padding: 2rem;
}
.stButton>button {
width: 100%;
margin-top: 10px;
}
.title {
text-align: center;
margin-bottom: 30px;
}
.form-section {
background-color: #f8f9fa;
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
}
</style>
""", unsafe_allow_html=True)
# Title
st.markdown("<h1 class='title'>CSR Initiative Portal</h1>", unsafe_allow_html=True)
# List of beneficiary groups
beneficiary_groups = [
"Supporting next generation",
"Impact entrepreneurs",
"Environment sustainability",
"Disaster response"
]
def extract_json_from_text(text):
"""
Extracts JSON from text that might contain other content.
"""
# Try to find JSON pattern with regex first
json_pattern = r'({[\s\S]*})'
matches = re.search(json_pattern, text)
if matches:
json_text = matches.group(1)
try:
return json.loads(json_text)
except:
pass
# If regex extraction fails, try cleaning the text directly
text = text.strip()
# If the text starts with markdown code block, remove it
if text.startswith('```json'):
text = text[7:]
elif text.startswith('```'):
text = text[3:]
# If the text ends with markdown code block, remove it
if text.endswith('```'):
text = text[:-3]
# Try to find the start of the JSON object if there's other text before it
if not text.startswith('{'):
try:
start_idx = text.index('{')
text = text[start_idx:]
except ValueError:
return None
# Try to find the end of the JSON object if there's other text after it
if not text.endswith('}'):
try:
end_idx = text.rindex('}')
text = text[:end_idx+1]
except ValueError:
return None
# Try to parse the cleaned text
try:
return json.loads(text)
except json.JSONDecodeError as e:
st.error(f"JSON parsing error: {str(e)}")
return None
def analyze_initiative_with_ai(description):
"""
Use Azure OpenAI to analyze initiative description and extract fields
"""
system_prompt = """
You are an AI assistant for a CSR portal. Analyze the initiative description and extract the following fields accurately:
1. Initiative Name (create a concise, descriptive name)
2. Date (extract start and end dates)
3. Location (extract location)
4. Who will be working with and who will the initiative help? (2-line description)
5. What will the participant be doing? (2-line description)
6. How does the initiative align with focus areas and how will it change lives? (2-line description)
7. Role Name (extract or suggest an appropriate role)
8. Role Description (2-line description)
9. Start date (in format YYYY-MM-DD)
10. End date (in format YYYY-MM-DD)
11. Deadline date (in format YYYY-MM-DD)
12. Beneficiary group (select ONE from: Supporting next generation, Impact entrepreneurs, Environment sustainability, Disaster response)
Format your response as JSON with exact keys corresponding to the field names above.
IMPORTANT: Provide ONLY the JSON object with no additional text before or after.
"""
try:
# Using the new OpenAI API format
response = client.chat.completions.create(
model="gpt-4o-mini", # Adjust to your deployed model name
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": description}
],
temperature=0.3,
max_tokens=1000,
response_format={"type": "json_object"} # Request JSON formatted response
)
# Extract the generated text
result = response.choices[0].message.content
# Parse the JSON with our robust function
parsed_result = extract_json_from_text(result)
if parsed_result:
return parsed_result
else:
st.error("Failed to parse AI response into a valid JSON format.")
return None
except Exception as e:
st.error(f"Error analyzing initiative: {str(e)}")
return None
# Initialize session state for form fields if they don't exist
if 'initiative_name' not in st.session_state:
st.session_state.initiative_name = ""
if 'date' not in st.session_state:
st.session_state.date = ""
if 'location' not in st.session_state:
st.session_state.location = ""
if 'owner' not in st.session_state:
st.session_state.owner = "Prabaharan S"
if 'working_with' not in st.session_state:
st.session_state.working_with = ""
if 'participant_doing' not in st.session_state:
st.session_state.participant_doing = ""
if 'alignment' not in st.session_state:
st.session_state.alignment = ""
if 'role_name' not in st.session_state:
st.session_state.role_name = ""
if 'role_description' not in st.session_state:
st.session_state.role_description = ""
if 'start_date' not in st.session_state:
st.session_state.start_date = None
if 'end_date' not in st.session_state:
st.session_state.end_date = None
if 'deadline_date' not in st.session_state:
st.session_state.deadline_date = None
if 'beneficiary_group' not in st.session_state:
st.session_state.beneficiary_group = beneficiary_groups[0]
# Create two columns for layout
col1, col2 = st.columns([1, 1])
with col1:
st.markdown("<div class='form-section'>", unsafe_allow_html=True)
st.subheader("Create with AI")
# Text area for the initiative description
initiative_description = st.text_area(
"Enter a detailed description of your initiative",
height=300,
placeholder="Describe your initiative in detail. Include information about dates, location, activities, beneficiaries, and goals."
)
# Button to trigger AI analysis
if st.button("Generate with AI", key="generate_button"):
if initiative_description:
with st.spinner("Analyzing your initiative..."):
result = analyze_initiative_with_ai(initiative_description)
if result:
# For debugging: Show raw JSON
st.write("Debug - Generated JSON:", result)
# Update the session state with AI-generated content
st.session_state.initiative_name = result.get("Initiative Name", "")
st.session_state.date = result.get("Date", "")
st.session_state.location = result.get("Location", "")
st.session_state.working_with = result.get("Who will be working with and who will the initiative help?", "")
st.session_state.participant_doing = result.get("What will the participant be doing?", "")
st.session_state.alignment = result.get("How does the initiative align with focus areas and how will it change lives?", "")
st.session_state.role_name = result.get("Role Name", "")
st.session_state.role_description = result.get("Role Description", "")
# Handle dates
try:
start_date_str = result.get("Start date", "")
if start_date_str:
st.session_state.start_date = datetime.strptime(start_date_str, "%Y-%m-%d").date()
except Exception as e:
st.warning(f"Could not parse start date: {start_date_str}. Error: {str(e)}")
try:
end_date_str = result.get("End date", "")
if end_date_str:
st.session_state.end_date = datetime.strptime(end_date_str, "%Y-%m-%d").date()
except Exception as e:
st.warning(f"Could not parse end date: {end_date_str}. Error: {str(e)}")
try:
deadline_date_str = result.get("Deadline date", "")
if deadline_date_str:
st.session_state.deadline_date = datetime.strptime(deadline_date_str, "%Y-%m-%d").date()
except Exception as e:
st.warning(f"Could not parse deadline date: {deadline_date_str}. Error: {str(e)}")
# Handle beneficiary group
predicted_beneficiary = result.get("Beneficiary group", "")
if predicted_beneficiary in beneficiary_groups:
st.session_state.beneficiary_group = predicted_beneficiary
# Display success message
st.success("Initiative details generated successfully!")
st.rerun() # Rerun the app to update the form fields
else:
st.warning("Please enter a description of your initiative first.")
st.markdown("</div>", unsafe_allow_html=True)
with col2:
st.markdown("<div class='form-section'>", unsafe_allow_html=True)
st.subheader("Initiative Details")
# Form for user to input initiative details manually
initiative_name = st.text_input("Initiative Name", value=st.session_state.initiative_name)
date = st.text_input("Date", value=st.session_state.date)
location = st.text_input("Location", value=st.session_state.location)
owner = st.text_input("Owner", value=st.session_state.owner)
working_with = st.text_area("Who will be working with and who will the initiative help?",
value=st.session_state.working_with, height=100)
participant_doing = st.text_area("What will the participant be doing?",
value=st.session_state.participant_doing, height=100)
alignment = st.text_area("How does your initiative align with our focus areas and how will it change lives?",
value=st.session_state.alignment, height=100)
role_name = st.text_input("Role Name", value=st.session_state.role_name)
role_description = st.text_area("Role Description", value=st.session_state.role_description, height=100)
start_date = st.date_input("Start Date", value=st.session_state.start_date)
end_date = st.date_input("End Date", value=st.session_state.end_date)
deadline_date = st.date_input("Deadline Date", value=st.session_state.deadline_date)
beneficiary_group = st.selectbox("Beneficiary Group", options=beneficiary_groups,
index=beneficiary_groups.index(st.session_state.beneficiary_group)
if st.session_state.beneficiary_group in beneficiary_groups else 0)
st.markdown("</div>", unsafe_allow_html=True)
# Submit button
col1, col2, col3 = st.columns([1, 2, 1])
with col2:
if st.button("Submit Initiative", key="submit_button"):
# Here you would add code to save the initiative to your database
st.success("✅ Initiative created successfully!")
# Clear form or redirect
# Add footer
st.markdown("""
---
<div style="text-align: center; color: grey; font-size: 12px;">
CSR Initiative Portal powered by Azure OpenAI - © 2025
</div>
""", unsafe_allow_html=True)