|
import streamlit as st |
|
import os |
|
import re |
|
from datetime import datetime |
|
import json |
|
from openai import AzureOpenAI |
|
from dotenv import load_dotenv |
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
|
|
if 'AZURE_OPENAI_API_KEY' in os.environ: |
|
api_key = os.environ['AZURE_OPENAI_API_KEY'] |
|
endpoint = os.environ['AZURE_OPENAI_ENDPOINT'] |
|
else: |
|
|
|
from dotenv import load_dotenv |
|
load_dotenv() |
|
api_key = os.getenv("AZURE_OPENAI_API_KEY") |
|
endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") |
|
|
|
|
|
client = AzureOpenAI( |
|
api_key=api_key, |
|
api_version="2024-02-15-preview", |
|
azure_endpoint=endpoint |
|
) |
|
|
|
|
|
st.set_page_config( |
|
page_title="CSR Initiative Portal", |
|
page_icon="🌱", |
|
layout="wide" |
|
) |
|
|
|
|
|
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) |
|
|
|
|
|
st.markdown("<h1 class='title'>CSR Initiative Portal</h1>", unsafe_allow_html=True) |
|
|
|
|
|
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. |
|
""" |
|
|
|
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 |
|
|
|
|
|
text = text.strip() |
|
|
|
|
|
if text.startswith('```json'): |
|
text = text[7:] |
|
elif text.startswith('```'): |
|
text = text[3:] |
|
|
|
|
|
if text.endswith('```'): |
|
text = text[:-3] |
|
|
|
|
|
if not text.startswith('{'): |
|
try: |
|
start_idx = text.index('{') |
|
text = text[start_idx:] |
|
except ValueError: |
|
return None |
|
|
|
|
|
if not text.endswith('}'): |
|
try: |
|
end_idx = text.rindex('}') |
|
text = text[:end_idx+1] |
|
except ValueError: |
|
return None |
|
|
|
|
|
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: |
|
|
|
response = client.chat.completions.create( |
|
model="gpt-4o-mini", |
|
messages=[ |
|
{"role": "system", "content": system_prompt}, |
|
{"role": "user", "content": description} |
|
], |
|
temperature=0.3, |
|
max_tokens=1000, |
|
response_format={"type": "json_object"} |
|
) |
|
|
|
|
|
result = response.choices[0].message.content |
|
|
|
|
|
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 |
|
|
|
|
|
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] |
|
|
|
|
|
col1, col2 = st.columns([1, 1]) |
|
|
|
with col1: |
|
st.markdown("<div class='form-section'>", unsafe_allow_html=True) |
|
st.subheader("Create with AI") |
|
|
|
|
|
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." |
|
) |
|
|
|
|
|
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: |
|
|
|
st.write("Debug - Generated JSON:", result) |
|
|
|
|
|
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", "") |
|
|
|
|
|
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)}") |
|
|
|
|
|
predicted_beneficiary = result.get("Beneficiary group", "") |
|
if predicted_beneficiary in beneficiary_groups: |
|
st.session_state.beneficiary_group = predicted_beneficiary |
|
|
|
|
|
st.success("Initiative details generated successfully!") |
|
st.rerun() |
|
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") |
|
|
|
|
|
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) |
|
|
|
|
|
col1, col2, col3 = st.columns([1, 2, 1]) |
|
with col2: |
|
if st.button("Submit Initiative", key="submit_button"): |
|
|
|
st.success("✅ Initiative created successfully!") |
|
|
|
|
|
|
|
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) |