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(""" """, unsafe_allow_html=True) # Title st.markdown("

CSR Initiative Portal

", 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("
", 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("
", unsafe_allow_html=True) with col2: st.markdown("
", 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("
", 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(""" ---
CSR Initiative Portal powered by Azure OpenAI - © 2025
""", unsafe_allow_html=True)