Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import time | |
| import os | |
| from utils.run_agent import execute_agent | |
| from config.configs import AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT, AZURE_DEPLOYMENT | |
| from config.generation_config import get_generation_prompt, get_hashtag_suggestions, DEFAULT_SETTINGS | |
| from utils.credential_manager import CredentialManager, format_endpoint_url, mask_api_key | |
| st.set_page_config( | |
| page_title="LinkedIn Post Generator", | |
| page_icon="π", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| st.markdown(""" | |
| <style> | |
| .main-header { | |
| background: linear-gradient(90deg, #0077B5, #00A0DC); | |
| padding: 2rem; | |
| border-radius: 10px; | |
| color: white; | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| } | |
| .sidebar-header { | |
| background: linear-gradient(135deg, #f8f9fa, #e9ecef); | |
| padding: 1rem; | |
| border-radius: 8px; | |
| margin-bottom: 1rem; | |
| } | |
| .config-section { | |
| background: #f8f9fa; | |
| padding: 1rem; | |
| border-radius: 8px; | |
| margin-bottom: 1rem; | |
| border-left: 4px solid #0077B5; | |
| } | |
| .output-container { | |
| background: #f8f9fa; | |
| padding: 1.5rem; | |
| border-radius: 10px; | |
| border: 1px solid #dee2e6; | |
| margin-top: 1rem; | |
| } | |
| .loading-spinner { | |
| text-align: center; | |
| padding: 2rem; | |
| } | |
| .success-message { | |
| background: #d4edda; | |
| color: #155724; | |
| padding: 1rem; | |
| border-radius: 8px; | |
| border: 1px solid #c3e6cb; | |
| margin: 1rem 0; | |
| } | |
| .error-message { | |
| background: #f8d7da; | |
| color: #721c24; | |
| padding: 1rem; | |
| border-radius: 8px; | |
| border: 1px solid #f5c6cb; | |
| margin: 1rem 0; | |
| } | |
| .credentials-section { | |
| background: #fff3cd; | |
| padding: 1rem; | |
| border-radius: 8px; | |
| border: 1px solid #ffeaa7; | |
| margin-bottom: 1rem; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Initialize session state for credentials | |
| if 'azure_api_key' not in st.session_state: | |
| st.session_state.azure_api_key = "" | |
| if 'azure_endpoint' not in st.session_state: | |
| st.session_state.azure_endpoint = "" | |
| if 'azure_deployment' not in st.session_state: | |
| st.session_state.azure_deployment = "" | |
| if 'azure_api_version' not in st.session_state: | |
| st.session_state.azure_api_version = "2024-02-01" | |
| with st.sidebar: | |
| st.title("βοΈ Configuration") | |
| st.subheader("π Azure OpenAI Credentials") | |
| st.info("π‘ Enter your Azure OpenAI credentials below:") | |
| api_key = st.text_input( | |
| "Azure OpenAI API Key", | |
| value=st.session_state.azure_api_key, | |
| type="password", | |
| help="Your Azure OpenAI API key" | |
| ) | |
| endpoint = st.text_input( | |
| "Azure OpenAI Endpoint", | |
| value=st.session_state.azure_endpoint, | |
| placeholder="https://your-resource.openai.azure.com/", | |
| help="Your Azure OpenAI endpoint URL" | |
| ) | |
| deployment = st.text_input( | |
| "Deployment Name", | |
| value=st.session_state.azure_deployment, | |
| placeholder="gpt-35-turbo", | |
| help="Name of your deployed model" | |
| ) | |
| api_version = st.text_input( | |
| "API Version", | |
| value=st.session_state.azure_api_version, | |
| placeholder="2024-02-01", | |
| help="Azure OpenAI API version" | |
| ) | |
| if st.button("πΎ Save Credentials", use_container_width=True): | |
| credentials = { | |
| 'api_key': api_key, | |
| 'endpoint': format_endpoint_url(endpoint) if endpoint else '', | |
| 'deployment': deployment, | |
| 'api_version': api_version | |
| } | |
| is_valid, message = CredentialManager.validate_credentials(credentials) | |
| if is_valid: | |
| CredentialManager.save_credentials_to_session( | |
| credentials['api_key'], | |
| credentials['endpoint'], | |
| credentials['deployment'], | |
| credentials['api_version'] | |
| ) | |
| st.success("β Credentials saved successfully!") | |
| st.rerun() | |
| else: | |
| st.error(f"β {message}") | |
| if st.button("ποΈ Clear Credentials", use_container_width=True): | |
| CredentialManager.clear_session_credentials() | |
| st.success("β Credentials cleared!") | |
| st.rerun() | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| st.subheader("π API Status") | |
| current_credentials = CredentialManager.get_credentials_from_session() | |
| if current_credentials['api_key']: | |
| masked_key = mask_api_key(current_credentials['api_key']) | |
| st.success(f"β API Key: {masked_key}") | |
| else: | |
| st.error("β API Key not found") | |
| if current_credentials['endpoint']: | |
| st.success(f"β Endpoint: {current_credentials['endpoint']}") | |
| else: | |
| st.warning("β οΈ Endpoint not configured") | |
| if current_credentials['deployment']: | |
| st.success(f"β Deployment: {current_credentials['deployment']}") | |
| else: | |
| st.warning("β οΈ Deployment not configured") | |
| if all(current_credentials.values()): | |
| if st.button("π§ͺ Test Connection", use_container_width=True): | |
| with st.spinner("Testing Azure OpenAI connection..."): | |
| try: | |
| CredentialManager.set_environment_variables(current_credentials) | |
| test_output = execute_agent("Test connection") | |
| st.success("β Connection successful! Azure OpenAI is working.") | |
| except Exception as e: | |
| st.error(f"β Connection failed: {str(e)}") | |
| st.subheader("π― Generation Settings") | |
| post_length = st.selectbox( | |
| "Post Length", | |
| ["Short (100-200 words)", "Medium (200-400 words)", "Long (400-600 words)"], | |
| index=1 | |
| ) | |
| tone = st.selectbox( | |
| "Tone", | |
| ["Professional", "Casual", "Enthusiastic", "Educational", "Inspirational"], | |
| index=0 | |
| ) | |
| include_hashtags = st.checkbox("Include Hashtags", value=True) | |
| include_call_to_action = st.checkbox("Include Call to Action", value=True) | |
| st.subheader("βΉοΈ About") | |
| st.write("**LinkedIn Post Generator**") | |
| st.write("Powered by LangGraph and Azure OpenAI") | |
| st.write("Version: 1.0.0") | |
| st.title("π LinkedIn Post Generator") | |
| st.markdown("Transform your ideas into engaging LinkedIn posts using AI") | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| st.subheader("π― What would you like to write about?") | |
| user_input = st.text_area( | |
| "Enter your topic, idea, or subject matter:", | |
| value=st.session_state.get("user_input", ""), | |
| placeholder="e.g., 'The future of artificial intelligence in healthcare' or 'Tips for remote team collaboration'", | |
| height=100, | |
| help="Be specific about your topic to get better results" | |
| ) | |
| if user_input and include_hashtags: | |
| suggested_hashtags = get_hashtag_suggestions(user_input) | |
| st.info(f"π‘ **Suggested hashtags for '{user_input}':**") | |
| hashtag_cols = st.columns(3) | |
| for i, hashtag in enumerate(suggested_hashtags[:3]): | |
| with hashtag_cols[i]: | |
| st.write(f"β’ {hashtag}") | |
| with st.expander("π Additional Context (Optional)"): | |
| context = st.text_area( | |
| "Add any specific details, target audience, or context:", | |
| placeholder="e.g., 'Target audience: Tech professionals, Focus on practical applications'", | |
| height=80 | |
| ) | |
| col1_btn, col2_btn = st.columns([3, 1]) | |
| with col1_btn: | |
| generate_clicked = st.button("π Generate LinkedIn Post", type="primary", use_container_width=True) | |
| with col2_btn: | |
| clear_clicked = st.button("ποΈ Clear", use_container_width=True) | |
| if clear_clicked: | |
| st.session_state.user_input = "" | |
| st.session_state.example_topic = "" | |
| st.rerun() | |
| if generate_clicked: | |
| if user_input: | |
| current_credentials = CredentialManager.get_credentials_from_session() | |
| if not all(current_credentials.values()): | |
| st.error("β Please configure your Azure OpenAI credentials in the sidebar first.") | |
| else: | |
| CredentialManager.set_environment_variables(current_credentials) | |
| with st.spinner("π€ AI is crafting your perfect LinkedIn post..."): | |
| try: | |
| settings = { | |
| "post_length": post_length, | |
| "tone": tone, | |
| "include_hashtags": include_hashtags, | |
| "include_call_to_action": include_call_to_action | |
| } | |
| # Generate formatted prompt using the configuration | |
| full_query = get_generation_prompt(user_input, context, settings) | |
| # Execute the agent | |
| output = execute_agent(full_query) | |
| # Update session state | |
| if 'generated_posts' not in st.session_state: | |
| st.session_state.generated_posts = 0 | |
| st.session_state.generated_posts += 1 | |
| st.success("β Your LinkedIn post has been generated successfully!") | |
| st.subheader("π Generated LinkedIn Post") | |
| st.markdown("---") | |
| st.write(output) | |
| st.markdown("---") | |
| if st.button("π Copy to Clipboard", use_container_width=True): | |
| st.write("π Post copied to clipboard!") | |
| except Exception as e: | |
| st.error(f"β An error occurred: {str(e)}") | |
| else: | |
| st.warning("β οΈ Please enter a topic to generate a post.") | |
| with col2: | |
| st.subheader("π‘ Tips for Better Posts") | |
| tips = [ | |
| "π― Be specific about your topic", | |
| "π₯ Consider your target audience", | |
| "π Include relevant statistics if applicable", | |
| "π¬ Ask engaging questions", | |
| "π Reference current trends or news", | |
| "π Keep paragraphs short and readable", | |
| "π¨ Use emojis sparingly but effectively" | |
| ] | |
| for tip in tips: | |
| st.write(tip) | |
| st.markdown("---") | |
| st.subheader("π Post Analytics") | |
| if 'generated_posts' not in st.session_state: | |
| st.session_state.generated_posts = 0 | |
| st.metric("Posts Generated", st.session_state.generated_posts) | |
| st.subheader("π― Example Topics") | |
| example_topics = [ | |
| "AI in healthcare", | |
| "Remote work productivity", | |
| "Digital transformation", | |
| "Leadership skills", | |
| "Innovation in business" | |
| ] | |
| for topic in example_topics: | |
| if st.button(topic, key=f"example_{topic}"): | |
| st.session_state.example_topic = topic | |
| st.session_state.user_input = topic | |
| st.rerun() | |
| st.markdown("---") | |
| st.markdown( | |
| """ | |
| <div style='text-align: center; color: #666; padding: 1rem;'> | |
| <p>Made with β€οΈ using Streamlit, LangGraph, and Azure OpenAI</p> | |
| <p>For questions or support, please check the documentation</p> | |
| </div> | |
| """, | |
| unsafe_allow_html=True | |
| ) |