Spaces:
Runtime error
Runtime error
| import os | |
| import streamlit as st | |
| import streamlit.components.v1 as components | |
| from dotenv import load_dotenv | |
| import base64 | |
| from openai import OpenAI | |
| from repo_library.prompts import combine_prompts, get_available_prompts | |
| # Load environment variables | |
| load_dotenv() | |
| def refine_with_openai(prompt: str, api_key: str) -> str: | |
| """ | |
| Use OpenAI to refine and improve the combined prompt. | |
| """ | |
| if not api_key: | |
| return prompt | |
| try: | |
| client = OpenAI(api_key=api_key) | |
| response = client.chat.completions.create( | |
| model="gpt-4", | |
| messages=[ | |
| { | |
| "role": "system", | |
| "content": "You are an expert at crafting system prompts. Your task is to take the provided prompt components and combine them into a natural, cohesive system prompt that maintains the essence of each component while ensuring they flow together seamlessly." | |
| }, | |
| { | |
| "role": "user", | |
| "content": f"Please refine this system prompt while maintaining its core elements:\n\n{prompt}" | |
| } | |
| ] | |
| ) | |
| return response.choices[0].message.content | |
| except Exception as e: | |
| st.error(f"Error refining prompt with OpenAI: {str(e)}") | |
| return prompt | |
| def get_download_link(text, filename="system_prompt.txt"): | |
| """Generate a download link for text content.""" | |
| b64 = base64.b64encode(text.encode()).decode() | |
| return f'<a href="data:text/plain;base64,{b64}" download="{filename}" style="text-decoration: none;">📥 Download System Prompt</a>' | |
| def reset_all_fields(): | |
| """Reset all session state variables.""" | |
| for key in st.session_state.keys(): | |
| del st.session_state[key] | |
| def display_prompt_preview(prompt: str): | |
| """Display a preview of the prompt with proper formatting.""" | |
| st.code(prompt, language="markdown") | |
| def main(): | |
| # Initialize session state | |
| if 'active_tab' not in st.session_state: | |
| st.session_state.active_tab = 0 | |
| st.set_page_config( | |
| page_title="System Prompt Factory", | |
| page_icon="🎯", | |
| layout="wide", | |
| initial_sidebar_state="expanded", | |
| menu_items={ | |
| 'Get Help': 'https://github.com/All-Hands-AI/OpenHands', | |
| 'About': 'System Prompt Factory - Enhanced by OpenHands' | |
| } | |
| ) | |
| # Set sidebar width and ensure it's always expanded | |
| st.markdown(""" | |
| <style> | |
| section[data-testid="stSidebar"] { | |
| width: 350px !important; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Custom CSS for better styling | |
| st.markdown(""" | |
| <style> | |
| .main { | |
| padding: 2rem; | |
| } | |
| .stButton button { | |
| border-radius: 20px; | |
| } | |
| .stExpander { | |
| border: none !important; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
| margin-bottom: 1rem; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Header with improved design | |
| st.markdown(""" | |
| <div style='text-align: center; padding: 2rem 0; background: linear-gradient(135deg, #f6f8fa, #e9ecef); border-radius: 15px; margin-bottom: 2rem;'> | |
| <h1 style='color: #1a1a1a; margin-bottom: 1rem;'>🎯 System Prompt Factory</h1> | |
| <p style='color: #666; font-size: 1.2em; max-width: 600px; margin: 0 auto;'> | |
| Create perfectly tailored AI system prompts | |
| </p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Add welcome message | |
| st.markdown(""" | |
| <div style='text-align: center; margin: 2rem 0;'> | |
| <p style='color: #666; font-size: 1.1em; margin-bottom: 2rem;'> | |
| Follow the steps in the sidebar to create your perfect AI assistant. | |
| Each step builds upon the last to create a comprehensive system prompt. | |
| </p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Get available prompts | |
| available_prompts = get_available_prompts() | |
| # OpenAI API Key input in sidebar | |
| with st.sidebar: | |
| st.subheader("OpenAI Integration") | |
| api_key = st.text_input( | |
| "OpenAI API Key (optional)", | |
| type="password", | |
| help="Enter your OpenAI API key to enable AI-powered prompt refinement" | |
| ) | |
| st.subheader("Prompt Settings") | |
| target_length = st.selectbox( | |
| "Target Word Length", | |
| options=[0, 100, 200, 300, 400, 500], | |
| help="Set a target word length for the prompt. Select 0 for no limit.", | |
| format_func=lambda x: "No Limit" if x == 0 else f"{x} words" | |
| ) | |
| st.divider() | |
| st.markdown(""" | |
| ### About | |
| This tool helps you create custom system prompts by combining different components: | |
| - Model Personality | |
| - User Location/Culture | |
| - User Type/Background | |
| - Worldview/Perspective | |
| Each component adds a unique aspect to the final prompt. | |
| """) | |
| # Style tabs | |
| st.markdown(""" | |
| <style> | |
| .stTabs [data-baseweb="tab-list"] { | |
| gap: 8px; | |
| } | |
| .stTabs [data-baseweb="tab"] { | |
| padding: 8px 16px; | |
| border-radius: 4px; | |
| } | |
| .stTabs [data-baseweb="tab-list"] button[aria-selected="true"] { | |
| background: rgba(25, 118, 210, 0.1); | |
| border-bottom: none; | |
| color: rgb(25, 118, 210); | |
| font-weight: 600; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Create sections using tabs with active tab from session state | |
| tab_titles = ["🤖 Configure AI Assistant", "👤 Set User Preferences", "📝 Choose Output Format"] | |
| tabs = st.tabs(tab_titles) | |
| # Ensure the correct tab is shown based on sidebar selection | |
| current_tab = st.session_state.active_tab | |
| with tabs[0]: | |
| st.markdown(""" | |
| <div style='background: linear-gradient(135deg, #e3f2fd, #bbdefb); padding: 1.5rem; border-radius: 10px; margin-bottom: 1.5rem;'> | |
| <h2 style='color: #1565c0; margin: 0; font-size: 1.5em;'>AI Identity & Behavior</h2> | |
| <p style='color: #1565c0; margin-top: 0.5rem; margin-bottom: 0;'>Configure how your AI assistant should present itself and interact</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Create three sections with cards | |
| st.markdown(""" | |
| <div style='display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;'> | |
| <div style='background: white; padding: 1.5rem; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);'> | |
| <h3 style='color: #1565c0; font-size: 1.2em; margin-bottom: 1rem;'>🎭 Core Identity</h3> | |
| </div> | |
| <div style='background: white; padding: 1.5rem; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);'> | |
| <h3 style='color: #1565c0; font-size: 1.2em; margin-bottom: 1rem;'>💬 Communication Style</h3> | |
| </div> | |
| <div style='background: white; padding: 1.5rem; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);'> | |
| <h3 style='color: #1565c0; font-size: 1.2em; margin-bottom: 1rem;'>🎨 Personality & Expression</h3> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Core Identity Section | |
| with st.container(): | |
| st.markdown("##### Core Identity Settings") | |
| identity_type = st.selectbox( | |
| "AI Identity Type", | |
| options=available_prompts["model_identity"], | |
| help="Choose how your AI assistant should present itself", | |
| format_func=lambda x: { | |
| "neutral": "🤖 Standard AI Assistant", | |
| "bot": "⚡ Proud AI Bot", | |
| "alien": "👽 Extraterrestrial Intelligence", | |
| "sloth": "🦥 Laid-back Sloth" | |
| }.get(x, "🤖 " + x.replace("_", " ").title()) | |
| ) | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| ai_name = st.text_input( | |
| "AI Name", | |
| help="Give your AI assistant a unique name", | |
| placeholder="e.g., Atlas, Nova, Sage" | |
| ) | |
| with col2: | |
| personality = st.selectbox( | |
| "Base Personality", | |
| options=available_prompts["model_personalities"], | |
| help="Select the core personality trait", | |
| format_func=lambda x: "😊 " + x.replace("_", " ").title() | |
| ) | |
| backstory = st.text_area( | |
| "Backstory (optional)", | |
| help="Add a brief backstory to give your AI more character", | |
| placeholder="e.g., Created in a secret lab beneath Mount Everest...", | |
| max_chars=200, | |
| height=100 | |
| ) | |
| st.divider() | |
| # Communication Style Section | |
| st.markdown("##### Communication Preferences") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| formality = st.select_slider( | |
| "Formality Level", | |
| options=available_prompts["model_formality"], | |
| help="Adjust how formal or casual the AI should be", | |
| format_func=lambda x: x.replace("_", " ").title() | |
| ) | |
| expertise = st.select_slider( | |
| "Expertise Level", | |
| options=available_prompts["model_expertise"], | |
| help="Set the depth of knowledge and explanation", | |
| format_func=lambda x: x.replace("_", " ").title() | |
| ) | |
| with col2: | |
| response_style = st.selectbox( | |
| "Response Style", | |
| options=available_prompts["model_response_style"], | |
| help="How should the AI structure its responses?", | |
| format_func=lambda x: x.replace("_", " ").title() | |
| ) | |
| language_style = st.selectbox( | |
| "Language Style", | |
| options=available_prompts["model_language_style"], | |
| help="Choose the linguistic style", | |
| format_func=lambda x: { | |
| "neutral": "🔤 Modern English", | |
| "shakespearean": "📜 Shakespearean", | |
| "middle_ages": "⚔️ Medieval", | |
| "rhyming": "🎵 Rhyming" | |
| }.get(x, "🔤 " + x.replace("_", " ").title()) | |
| ) | |
| with tabs[1]: | |
| st.markdown(""" | |
| <div style='background: linear-gradient(135deg, #e8f5e9, #c8e6c9); padding: 1.5rem; border-radius: 10px; margin-bottom: 1.5rem;'> | |
| <h2 style='color: #2e7d32; margin: 0; font-size: 1.5em;'>User Preferences</h2> | |
| <p style='color: #2e7d32; margin-top: 0.5rem; margin-bottom: 0;'>Customize how the AI understands and interacts with you</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Create three card sections | |
| st.markdown(""" | |
| <div style='display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;'> | |
| <div style='background: white; padding: 1.5rem; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);'> | |
| <h3 style='color: #2e7d32; font-size: 1.2em; margin-bottom: 1rem;'>👤 Personal Profile</h3> | |
| </div> | |
| <div style='background: white; padding: 1.5rem; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);'> | |
| <h3 style='color: #2e7d32; font-size: 1.2em; margin-bottom: 1rem;'>🌍 Context & Background</h3> | |
| </div> | |
| <div style='background: white; padding: 1.5rem; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);'> | |
| <h3 style='color: #2e7d32; font-size: 1.2em; margin-bottom: 1rem;'>🎯 Learning Preferences</h3> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Personal Profile Section | |
| st.markdown("##### Personal Information") | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| user_name = st.text_input( | |
| "Name (optional)", | |
| help="Your preferred name for personalized interactions", | |
| placeholder="e.g., John Doe" | |
| ) | |
| with col2: | |
| age_group = st.selectbox( | |
| "Age Group", | |
| options=["", "Under 18", "18-25", "26-35", "36-50", "51+"], | |
| help="Help the AI adjust its communication style", | |
| format_func=lambda x: "🔹 " + (x if x else "Not specified") | |
| ) | |
| with col3: | |
| occupation = st.text_input( | |
| "Occupation", | |
| help="Helps the AI provide relevant examples", | |
| placeholder="e.g., Software Engineer" | |
| ) | |
| st.divider() | |
| # Context & Background Section | |
| st.markdown("##### Cultural & Perspective Settings") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| location = st.selectbox( | |
| "Cultural Context", | |
| options=available_prompts["user_geolocation"], | |
| help="Adapt responses to your cultural background", | |
| format_func=lambda x: "🌍 " + x.replace("_", " ").title() | |
| ) | |
| worldview = st.selectbox( | |
| "Worldview", | |
| options=available_prompts["user_worldview"], | |
| help="Choose a philosophical perspective", | |
| format_func=lambda x: "🔮 " + x.replace("_", " ").title() | |
| ) | |
| with col2: | |
| political_leaning = st.selectbox( | |
| "Political Perspective", | |
| options=available_prompts["user_political_leaning"], | |
| help="Select your preferred political framing", | |
| format_func=lambda x: "⚖️ " + x.replace("_", " ").title() | |
| ) | |
| user_type = st.selectbox( | |
| "Interaction Style", | |
| options=available_prompts["user_personality"], | |
| help="How would you like the AI to interact with you?", | |
| format_func=lambda x: "🤝 " + x.replace("_", " ").title() | |
| ) | |
| st.divider() | |
| # Learning Preferences Section | |
| st.markdown("##### Learning & Communication Style") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| learning_style = st.select_slider( | |
| "Learning Approach", | |
| options=available_prompts["user_learning_style"], | |
| help="How do you prefer to learn new information?", | |
| format_func=lambda x: x.replace("_", " ").title() | |
| ) | |
| with col2: | |
| communication_pace = st.select_slider( | |
| "Communication Pace", | |
| options=available_prompts["user_communication_pace"], | |
| help="How detailed should the responses be?", | |
| format_func=lambda x: x.replace("_", " ").title() | |
| ) | |
| with tabs[2]: | |
| st.markdown(""" | |
| <div style='background: linear-gradient(135deg, #fff3e0, #ffe0b2); padding: 1.5rem; border-radius: 10px; margin-bottom: 1.5rem;'> | |
| <h2 style='color: #e65100; margin: 0; font-size: 1.5em;'>Output Format</h2> | |
| <p style='color: #e65100; margin-top: 0.5rem; margin-bottom: 0;'>Customize how the AI should structure and present information</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Create two card sections | |
| st.markdown(""" | |
| <div style='display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;'> | |
| <div style='background: white; padding: 1.5rem; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);'> | |
| <h3 style='color: #e65100; font-size: 1.2em; margin-bottom: 1rem;'>📄 Documentation Style</h3> | |
| </div> | |
| <div style='background: white; padding: 1.5rem; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);'> | |
| <h3 style='color: #e65100; font-size: 1.2em; margin-bottom: 1rem;'>🔢 Data Format</h3> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Documentation Format Section | |
| st.markdown("##### Documentation Preferences") | |
| doc_style = st.select_slider( | |
| "Documentation Structure", | |
| options=available_prompts["user_output_preference"], | |
| help="How should information be organized and presented?", | |
| format_func=lambda x: x.replace("_", " ").title() | |
| ) | |
| st.divider() | |
| # Data Structure Section | |
| st.markdown("##### Data Formatting") | |
| data_format = st.select_slider( | |
| "Data Structure", | |
| options=["neutral", "data_format"], | |
| help="Choose how structured data should be presented", | |
| format_func=lambda x: { | |
| "neutral": "Standard Text Format", | |
| "data_format": "Strict Data Format (CSV, JSON, etc.)" | |
| }.get(x, x.replace("_", " ").title()) | |
| ) | |
| # Final section with generate button and results | |
| st.markdown(""" | |
| <div style='background: linear-gradient(135deg, #f8f9fa, #e9ecef); padding: 2rem; border-radius: 15px; margin: 2rem 0; text-align: center;'> | |
| <h2 style='color: #1a1a1a; margin-bottom: 1rem; font-size: 1.5em;'>🎯 Ready to Create Your System Prompt?</h2> | |
| <p style='color: #666; margin-bottom: 1.5rem; font-size: 1.1em;'>Review your settings and generate your customized prompt</p> | |
| <div style='display: flex; justify-content: center; gap: 1rem; max-width: 600px; margin: 0 auto;'> | |
| """, unsafe_allow_html=True) | |
| # Create a row for the action buttons | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| if st.button("✨ Generate System Prompt", type="primary", use_container_width=True): | |
| generate_prompt = True | |
| with col2: | |
| if st.button("↺ Reset All", type="secondary", use_container_width=True, on_click=reset_all_fields): | |
| st.rerun() | |
| st.markdown("</div></div>", unsafe_allow_html=True) | |
| if 'generate_prompt' in locals(): | |
| # Combine selected components | |
| combined_prompt = combine_prompts( | |
| personality=personality, | |
| geolocation=location, | |
| user_type=user_type, | |
| worldview=worldview, | |
| response_style=response_style, | |
| expertise=expertise, | |
| learning_style=learning_style, | |
| communication_pace=communication_pace, | |
| political_leaning=political_leaning, | |
| formality=formality, | |
| language_style=language_style, | |
| identity_type=identity_type, | |
| ai_name=ai_name, | |
| backstory=backstory, | |
| output_preference=doc_style, | |
| data_format=data_format, | |
| user_name=user_name, | |
| age_group=age_group, | |
| occupation=occupation, | |
| target_length=target_length if target_length > 0 else None | |
| ) | |
| # Results section with improved design | |
| st.markdown(""" | |
| <div style='background: white; padding: 2rem; border-radius: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); margin: 2rem 0;'> | |
| <h3 style='color: #1a1a1a; margin-bottom: 1.5rem; font-size: 1.3em;'>🎨 Generated System Prompt</h3> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Create tabs for different views with custom styling | |
| tab_style = """ | |
| <style> | |
| .stTabs [data-baseweb="tab-list"] { | |
| gap: 16px; | |
| } | |
| .stTabs [data-baseweb="tab"] { | |
| padding: 8px 16px; | |
| border-radius: 4px; | |
| } | |
| </style> | |
| """ | |
| st.markdown(tab_style, unsafe_allow_html=True) | |
| raw_tab, refined_tab = st.tabs(["📝 Base Prompt", "✨ AI-Enhanced Version"]) | |
| with raw_tab: | |
| st.markdown("##### Generated from your selections") | |
| display_prompt_preview(combined_prompt) | |
| col1, col2 = st.columns([1, 2]) | |
| with col1: | |
| if st.button("📋 Copy Prompt", type="secondary", use_container_width=True): | |
| st.toast("✅ Prompt copied to clipboard!") | |
| with col2: | |
| st.markdown(get_download_link(combined_prompt), unsafe_allow_html=True) | |
| with refined_tab: | |
| if api_key: | |
| st.markdown("##### Enhanced by AI for natural flow") | |
| with st.spinner("✨ Enhancing your prompt with AI..."): | |
| refined_prompt = refine_with_openai(combined_prompt, api_key) | |
| display_prompt_preview(refined_prompt) | |
| col1, col2 = st.columns([1, 2]) | |
| with col1: | |
| if st.button("📋 Copy Enhanced", type="secondary", use_container_width=True): | |
| st.toast("✅ Enhanced prompt copied to clipboard!") | |
| with col2: | |
| st.markdown(get_download_link(refined_prompt, "enhanced_system_prompt.txt"), unsafe_allow_html=True) | |
| else: | |
| st.info("💡 Enter your OpenAI API key in the sidebar to enable AI enhancement of your prompt.") | |
| # Add footer with improved design | |
| st.markdown(""" | |
| <div style='background: linear-gradient(135deg, #f8f9fa, #e9ecef); | |
| margin-top: 4rem; | |
| padding: 2rem; | |
| border-radius: 15px; | |
| text-align: center;'> | |
| <p style='color: #666; font-size: 1.1em; margin-bottom: 0.5rem;'> | |
| System Prompt Factory | |
| </p> | |
| <p style='color: #666; font-size: 0.9em; margin: 0;'> | |
| Created by <a href="https://danielrosehill.com" target="_blank" style="color: #1565c0; text-decoration: none;">Daniel Rosehill</a> | |
| in collaboration with Claude 3.5 Sonnet | |
| </p> | |
| <p style='color: #666; font-size: 0.9em; margin-top: 0.5rem;'> | |
| Enhanced by <a href="https://github.com/All-Hands-AI/OpenHands" target="_blank" style="color: #1565c0; text-decoration: none;">OpenHands</a> | |
| </p> | |
| <p style='color: #999; font-size: 0.8em; margin-top: 1rem;'> | |
| Build version 1.0 • | |
| <a href="https://github.com/danielrosehill/System-Prompt-Factory" target="_blank" style="color: #666; text-decoration: none;">Original Repo</a> • | |
| <a href="https://github.com/All-Hands-AI/OpenHands" target="_blank" style="color: #666; text-decoration: none;">OpenHands</a> | |
| </p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| if __name__ == "__main__": | |
| main() |