File size: 22,826 Bytes
ef9649a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
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()