arad1367's picture
Update app.py
9f92924 verified
raw
history blame
10.1 kB
# 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"""<iframe
src="{app_url}"
width="100%"
height="500px"
style="border: 1px solid #ddd; border-radius: 8px;"
allow="microphone"
></iframe>"""
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("""
<a href="https://www.linkedin.com/in/pejman-ebrahimi-4a60151a7/" target="_blank">
<img src="https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white" alt="LinkedIn">
</a>
<a href="https://huggingface.co/arad1367" target="_blank">
<img src="https://img.shields.io/badge/πŸ€—_Hugging_Face-FFD21E?style=for-the-badge" alt="HuggingFace">
</a>
<a href="https://arad1367.github.io/pejman-ebrahimi/" target="_blank">
<img src="https://img.shields.io/badge/Website-008080?style=for-the-badge&logo=About.me&logoColor=white" alt="Website">
</a>
<a href="https://www.uni.li/pejman.ebrahimi?set_language=en" target="_blank">
<img src="https://img.shields.io/badge/University-00205B?style=for-the-badge&logo=academia&logoColor=white" alt="University">
</a>
""")
# 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()