# Create updated app.py file with fixes import gradio as gr import os import json import base64 from datetime import datetime from openai import OpenAI from tempfile import NamedTemporaryFile # Global variables api_key = None client = None chat_history = [] current_response_id = None current_image = None def validate_api_key(key): """Validate OpenAI API key by making a simple request""" try: temp_client = OpenAI(api_key=key) # Make a minimal request to check if the key works response = temp_client.responses.create( model="gpt-4o-mini", input="Hello" ) return True, "API key is valid!" except Exception as e: return False, f"Invalid API key: {str(e)}" def set_api_key(key): """Set the OpenAI API key and initialize client""" global api_key, client is_valid, message = validate_api_key(key) if is_valid: api_key = key client = OpenAI(api_key=api_key) return gr.update(visible=False), gr.update(visible=True), message else: return gr.update(visible=True), gr.update(visible=False), message def encode_image(image_path): """Encode image to base64""" with open(image_path, 'rb') as image_file: return base64.b64encode(image_file.read()).decode("utf-8") def chat(message, chat_history): """Process chat messages with optional image""" global client, current_response_id, current_image if not client: return chat_history + [{"role": "assistant", "content": "Please set your OpenAI API key first."}] try: # Add user message to history chat_history.append({"role": "user", "content": message}) if current_image is not None: # Save the uploaded image to a temporary file temp_file = NamedTemporaryFile(delete=False, suffix=".png") image_path = temp_file.name current_image.save(image_path) # Encode the image base64_image = encode_image(image_path) # Create input with text and image input_messages = [ { "role": "user", "content": [ { "type": "input_text", "text": message }, { "type": "input_image", "image_url": f"data:image/png;base64,{base64_image}" } ] } ] response = client.responses.create( model="gpt-4o-mini", input=input_messages, previous_response_id=current_response_id ) # Clean up the temporary file os.unlink(image_path) # Reset the image current_image = None else: # Text-only message response = client.responses.create( model="gpt-4o-mini", input=message, previous_response_id=current_response_id ) current_response_id = response.id # Add assistant response to history chat_history.append({"role": "assistant", "content": response.output_text}) return chat_history except Exception as e: error_message = f"Error: {str(e)}" chat_history.append({"role": "assistant", "content": error_message}) return chat_history def export_chat(): """Export chat history to JSON file""" global chat_history if not chat_history: return "No chat history to export." timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"chat_export_{timestamp}.json" with open(filename, "w") as f: json.dump(chat_history, f, indent=2) return f"Chat exported to {filename}" def clear_chat(): """Clear chat history and reset response ID""" global chat_history, current_response_id, current_image chat_history = [] current_response_id = None current_image = None return [] def generate_iframe_code(request: gr.Request): """Generate iframe code for embedding the app""" app_url = request.headers.get('host', 'localhost') if not app_url.startswith('http'): app_url = f"https://{app_url}" iframe_code = f"""""" return iframe_code def save_image(img): """Save uploaded image to global variable""" global current_image current_image = img return "[Image attached]" def create_ui(): """Create the Gradio UI""" with gr.Blocks(theme=gr.themes.Soft(), css=""" .container { max-width: 900px; margin: auto; } .title { text-align: center; margin-bottom: 10px; } .subtitle { text-align: center; margin-bottom: 20px; color: #666; } .social-links { display: flex; justify-content: center; gap: 10px; margin-bottom: 20px; } .footer { text-align: center; margin-top: 20px; padding: 10px; border-top: 1px solid #eee; } .tab-content { padding: 20px; } """) as demo: with gr.Column(elem_classes="container"): gr.Markdown("# Responses API Chatbot", elem_classes="title") gr.Markdown("### Created by Pejman Ebrahimi", elem_classes="subtitle") with gr.Row(elem_classes="social-links"): gr.HTML(""" LinkedIn HuggingFace Website University """) # API Key Input Section with gr.Group(visible=True) as api_key_group: with gr.Row(): api_key_input = gr.Textbox( label="Enter your OpenAI API Key", placeholder="sk-...", type="password", scale=4 ) api_key_button = gr.Button("Set API Key", scale=1) api_key_message = gr.Markdown("") # Main Chat Interface (hidden until API key is set) with gr.Group(visible=False) as chat_interface: with gr.Tabs() as tabs: with gr.TabItem("Chat", elem_classes="tab-content"): chatbot = gr.Chatbot(height=400, type="messages") with gr.Row(): with gr.Column(scale=4): msg = gr.Textbox( placeholder="Type your message here...", show_label=False, container=False ) with gr.Column(scale=1): image_btn = gr.UploadButton("📎", file_types=["image"]) with gr.Row(): clear_btn = gr.Button("Clear Chat") export_btn = gr.Button("Export Chat") theme_btn = gr.Button("Toggle Theme") export_message = gr.Markdown("") with gr.TabItem("Embed", elem_classes="tab-content"): gr.Markdown("### Embed this chatbot on your website") iframe_code = gr.Code(language="html") generate_iframe_btn = gr.Button("Generate Embed Code") gr.Markdown("© 2025 Pejman Ebrahimi - All Rights Reserved", elem_classes="footer") # Set up event handlers api_key_button.click( set_api_key, inputs=[api_key_input], outputs=[api_key_group, chat_interface, api_key_message] ) # Handle image uploads image_btn.upload( save_image, inputs=[image_btn], outputs=[msg] ) # Handle chat submission msg.submit( chat, inputs=[msg, chatbot], outputs=[chatbot] ).then( lambda: gr.update(value=""), None, [msg] ) clear_btn.click( clear_chat, outputs=[chatbot] ) export_btn.click( export_chat, outputs=[export_message] ) theme_btn.click( None, None, None, _js="() => {document.body.classList.toggle('dark');}" ) generate_iframe_btn.click( generate_iframe_code, None, iframe_code ) return demo if __name__ == "__main__": demo = create_ui() demo.launch()