arad1367 commited on
Commit
563ecd1
·
verified ·
1 Parent(s): 41de520

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -230
app.py CHANGED
@@ -1,25 +1,19 @@
1
- # Create updated app.py file with fixes
2
  import gradio as gr
3
- import os
4
  import json
5
- import base64
6
- from datetime import datetime
7
  from openai import OpenAI
8
- from tempfile import NamedTemporaryFile
9
 
10
  # Global variables
11
- api_key = None
12
  client = None
13
- chat_history = []
14
- current_response_id = None
15
- current_image = None
16
 
17
- def validate_api_key(key):
18
- """Validate OpenAI API key by making a simple request"""
19
  try:
20
- temp_client = OpenAI(api_key=key)
21
- # Make a minimal request to check if the key works
22
- response = temp_client.responses.create(
23
  model="gpt-4o-mini",
24
  input="Hello"
25
  )
@@ -27,255 +21,153 @@ def validate_api_key(key):
27
  except Exception as e:
28
  return False, f"Invalid API key: {str(e)}"
29
 
30
- def set_api_key(key):
31
- """Set the OpenAI API key and initialize client"""
32
- global api_key, client
33
- is_valid, message = validate_api_key(key)
 
34
  if is_valid:
35
- api_key = key
36
  client = OpenAI(api_key=api_key)
37
  return gr.update(visible=False), gr.update(visible=True), message
38
  else:
39
  return gr.update(visible=True), gr.update(visible=False), message
40
 
41
- def encode_image(image_path):
42
- """Encode image to base64"""
43
- with open(image_path, 'rb') as image_file:
44
- return base64.b64encode(image_file.read()).decode("utf-8")
45
-
46
- def chat(message, chat_history):
47
- """Process chat messages with optional image"""
48
- global client, current_response_id, current_image
49
 
50
  if not client:
51
- return chat_history + [{"role": "assistant", "content": "Please set your OpenAI API key first."}]
52
 
53
  try:
54
  # Add user message to history
55
- chat_history.append({"role": "user", "content": message})
56
-
57
- if current_image is not None:
58
- # Save the uploaded image to a temporary file
59
- temp_file = NamedTemporaryFile(delete=False, suffix=".png")
60
- image_path = temp_file.name
61
- current_image.save(image_path)
62
-
63
- # Encode the image
64
- base64_image = encode_image(image_path)
65
-
66
- # Create input with text and image
67
- input_messages = [
68
- {
69
- "role": "user",
70
- "content": [
71
- {
72
- "type": "input_text",
73
- "text": message
74
- },
75
- {
76
- "type": "input_image",
77
- "image_url": f"data:image/png;base64,{base64_image}"
78
- }
79
- ]
80
- }
81
- ]
82
-
83
- response = client.responses.create(
84
- model="gpt-4o-mini",
85
- input=input_messages,
86
- previous_response_id=current_response_id
87
- )
88
-
89
- # Clean up the temporary file
90
- os.unlink(image_path)
91
- # Reset the image
92
- current_image = None
93
- else:
94
- # Text-only message
95
- response = client.responses.create(
96
- model="gpt-4o-mini",
97
- input=message,
98
- previous_response_id=current_response_id
99
- )
100
 
101
- current_response_id = response.id
 
 
 
 
 
102
 
103
  # Add assistant response to history
104
- chat_history.append({"role": "assistant", "content": response.output_text})
105
 
106
- return chat_history
107
  except Exception as e:
108
  error_message = f"Error: {str(e)}"
109
- chat_history.append({"role": "assistant", "content": error_message})
110
- return chat_history
111
 
112
  def export_chat():
113
- """Export chat history to JSON file"""
114
- global chat_history
115
 
116
- if not chat_history:
117
- return "No chat history to export."
118
 
119
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
120
  filename = f"chat_export_{timestamp}.json"
121
 
122
  with open(filename, "w") as f:
123
- json.dump(chat_history, f, indent=2)
124
 
125
- return f"Chat exported to {filename}"
126
 
127
- def clear_chat():
128
- """Clear chat history and reset response ID"""
129
- global chat_history, current_response_id, current_image
130
- chat_history = []
131
- current_response_id = None
132
- current_image = None
133
- return []
134
 
135
- def generate_iframe_code(request: gr.Request):
136
- """Generate iframe code for embedding the app"""
137
- app_url = request.headers.get('host', 'localhost')
138
- if not app_url.startswith('http'):
139
- app_url = f"https://{app_url}"
140
-
141
- iframe_code = f"""<iframe
142
- src="{app_url}"
143
- width="100%"
144
- height="500px"
145
- style="border: 1px solid #ddd; border-radius: 8px;"
146
- allow="microphone"
147
- ></iframe>"""
148
 
149
- return iframe_code
150
-
151
- def save_image(img):
152
- """Save uploaded image to global variable"""
153
- global current_image
154
- current_image = img
155
- return "[Image attached]"
156
-
157
- def create_ui():
158
- """Create the Gradio UI"""
159
- with gr.Blocks(theme=gr.themes.Soft(), css="""
160
- .container { max-width: 900px; margin: auto; }
161
- .title { text-align: center; margin-bottom: 10px; }
162
- .subtitle { text-align: center; margin-bottom: 20px; color: #666; }
163
- .social-links { display: flex; justify-content: center; gap: 10px; margin-bottom: 20px; }
164
- .footer { text-align: center; margin-top: 20px; padding: 10px; border-top: 1px solid #eee; }
165
- .tab-content { padding: 20px; }
166
- """) as demo:
167
- with gr.Column(elem_classes="container"):
168
- gr.Markdown("# Responses API Chatbot", elem_classes="title")
169
- gr.Markdown("### Created by Pejman Ebrahimi", elem_classes="subtitle")
170
-
171
- with gr.Row(elem_classes="social-links"):
172
- gr.HTML("""
173
- <a href="https://www.linkedin.com/in/pejman-ebrahimi-4a60151a7/" target="_blank">
174
- <img src="https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white" alt="LinkedIn">
175
- </a>
176
- <a href="https://huggingface.co/arad1367" target="_blank">
177
- <img src="https://img.shields.io/badge/🤗_Hugging_Face-FFD21E?style=for-the-badge" alt="HuggingFace">
178
- </a>
179
- <a href="https://arad1367.github.io/pejman-ebrahimi/" target="_blank">
180
- <img src="https://img.shields.io/badge/Website-008080?style=for-the-badge&logo=About.me&logoColor=white" alt="Website">
181
- </a>
182
- <a href="https://www.uni.li/pejman.ebrahimi?set_language=en" target="_blank">
183
- <img src="https://img.shields.io/badge/University-00205B?style=for-the-badge&logo=academia&logoColor=white" alt="University">
184
- </a>
185
- """)
186
-
187
- # API Key Input Section
188
- with gr.Group(visible=True) as api_key_group:
189
- with gr.Row():
190
- api_key_input = gr.Textbox(
191
- label="Enter your OpenAI API Key",
192
- placeholder="sk-...",
193
- type="password",
194
- scale=4
195
- )
196
- api_key_button = gr.Button("Set API Key", scale=1)
197
- api_key_message = gr.Markdown("")
198
-
199
- # Main Chat Interface (hidden until API key is set)
200
- with gr.Group(visible=False) as chat_interface:
201
- with gr.Tabs() as tabs:
202
- with gr.TabItem("Chat", elem_classes="tab-content"):
203
- chatbot = gr.Chatbot(height=400, type="messages")
204
-
205
- with gr.Row():
206
- with gr.Column(scale=4):
207
- msg = gr.Textbox(
208
- placeholder="Type your message here...",
209
- show_label=False,
210
- container=False
211
- )
212
- with gr.Column(scale=1):
213
- image_btn = gr.UploadButton("📎", file_types=["image"])
214
-
215
- with gr.Row():
216
- clear_btn = gr.Button("Clear Chat")
217
- export_btn = gr.Button("Export Chat")
218
- theme_btn = gr.Button("Toggle Theme")
219
-
220
- export_message = gr.Markdown("")
221
-
222
- with gr.TabItem("Embed", elem_classes="tab-content"):
223
- gr.Markdown("### Embed this chatbot on your website")
224
- iframe_code = gr.Code(language="html")
225
- generate_iframe_btn = gr.Button("Generate Embed Code")
226
-
227
- gr.Markdown("© 2025 Pejman Ebrahimi - All Rights Reserved", elem_classes="footer")
228
-
229
- # Set up event handlers
230
- api_key_button.click(
231
- set_api_key,
232
- inputs=[api_key_input],
233
- outputs=[api_key_group, chat_interface, api_key_message]
234
- )
235
-
236
- # Handle image uploads
237
- image_btn.upload(
238
- save_image,
239
- inputs=[image_btn],
240
- outputs=[msg]
241
- )
242
-
243
- # Handle chat submission
244
- msg.submit(
245
- chat,
246
- inputs=[msg, chatbot],
247
- outputs=[chatbot]
248
- ).then(
249
- lambda: gr.update(value=""),
250
- None,
251
- [msg]
252
- )
253
-
254
- clear_btn.click(
255
- clear_chat,
256
- outputs=[chatbot]
257
  )
 
 
 
 
 
 
 
258
 
259
- export_btn.click(
260
- export_chat,
261
- outputs=[export_message]
262
- )
 
 
 
263
 
264
- theme_btn.click(
265
- None,
266
- None,
267
- None,
268
- _js="() => {document.body.classList.toggle('dark');}"
269
- )
270
 
271
- generate_iframe_btn.click(
272
- generate_iframe_code,
273
- None,
274
- iframe_code
275
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
276
 
277
- return demo
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
 
 
279
  if __name__ == "__main__":
280
- demo = create_ui()
281
- demo.launch()
 
 
 
1
  import gradio as gr
 
2
  import json
3
+ import os
 
4
  from openai import OpenAI
5
+ from datetime import datetime
6
 
7
  # Global variables
 
8
  client = None
9
+ conversation_history = []
 
 
10
 
11
+ def validate_api_key(api_key):
12
+ """Validate OpenAI API key by making a test request"""
13
  try:
14
+ test_client = OpenAI(api_key=api_key)
15
+ # Make a minimal test request
16
+ test_client.responses.create(
17
  model="gpt-4o-mini",
18
  input="Hello"
19
  )
 
21
  except Exception as e:
22
  return False, f"Invalid API key: {str(e)}"
23
 
24
+ def save_api_key(api_key):
25
+ """Save API key and initialize client"""
26
+ global client
27
+ is_valid, message = validate_api_key(api_key)
28
+
29
  if is_valid:
 
30
  client = OpenAI(api_key=api_key)
31
  return gr.update(visible=False), gr.update(visible=True), message
32
  else:
33
  return gr.update(visible=True), gr.update(visible=False), message
34
 
35
+ def chat(message, history, response_id):
36
+ """Process chat message and get response"""
37
+ global client, conversation_history
 
 
 
 
 
38
 
39
  if not client:
40
+ return history + [[message, "Please enter a valid API key first"]], None
41
 
42
  try:
43
  # Add user message to history
44
+ conversation_history.append({"role": "user", "content": message})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
+ # Get response from OpenAI
47
+ response = client.responses.create(
48
+ model="gpt-4o-mini",
49
+ input=message,
50
+ previous_response_id=response_id if response_id else None
51
+ )
52
 
53
  # Add assistant response to history
54
+ conversation_history.append({"role": "assistant", "content": response.output_text})
55
 
56
+ return history + [[message, response.output_text]], response.id
57
  except Exception as e:
58
  error_message = f"Error: {str(e)}"
59
+ return history + [[message, error_message]], None
 
60
 
61
  def export_chat():
62
+ """Export conversation history to JSON file"""
63
+ global conversation_history
64
 
65
+ if not conversation_history:
66
+ return "No conversation to export"
67
 
68
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
69
  filename = f"chat_export_{timestamp}.json"
70
 
71
  with open(filename, "w") as f:
72
+ json.dump(conversation_history, f, indent=2)
73
 
74
+ return f"Conversation exported to {filename}"
75
 
76
+ def clear_chat(history):
77
+ """Clear the chat history"""
78
+ global conversation_history
79
+ conversation_history = []
80
+ return [], None
 
 
81
 
82
+ # Create Gradio interface
83
+ with gr.Blocks(theme=gr.themes.Soft()) as app:
84
+ gr.HTML("""
85
+ <div style="text-align: center; margin-bottom: 1rem">
86
+ <h1 style="margin-bottom: 0.5rem">Chatbot based on responses API by Pejman Ebrahimi</h1>
87
+ <p>Powered by OpenAI's Responses API</p>
88
+ </div>
89
+ """)
 
 
 
 
 
90
 
91
+ # API key input interface
92
+ with gr.Group(visible=True) as api_key_group:
93
+ api_key_input = gr.Textbox(
94
+ label="Enter your OpenAI API Key",
95
+ placeholder="sk-...",
96
+ type="password"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  )
98
+ api_submit_btn = gr.Button("Submit API Key")
99
+ api_message = gr.Textbox(label="Status")
100
+
101
+ # Chat interface
102
+ with gr.Group(visible=False) as chat_group:
103
+ chatbot = gr.Chatbot(height=500)
104
+ response_id = gr.State(None)
105
 
106
+ with gr.Row():
107
+ msg = gr.Textbox(
108
+ label="Message",
109
+ placeholder="Type your message here...",
110
+ show_label=False
111
+ )
112
+ submit_btn = gr.Button("Send")
113
 
114
+ with gr.Row():
115
+ clear_btn = gr.Button("Clear Chat")
116
+ export_btn = gr.Button("Export Chat (JSON)")
 
 
 
117
 
118
+ export_message = gr.Textbox(label="Export Status", visible=True)
119
+
120
+ # Set up event handlers
121
+ api_submit_btn.click(
122
+ save_api_key,
123
+ inputs=[api_key_input],
124
+ outputs=[api_key_group, chat_group, api_message]
125
+ )
126
+
127
+ msg.submit(
128
+ chat,
129
+ inputs=[msg, chatbot, response_id],
130
+ outputs=[chatbot, response_id]
131
+ ).then(
132
+ lambda: "",
133
+ None,
134
+ [msg]
135
+ )
136
 
137
+ submit_btn.click(
138
+ chat,
139
+ inputs=[msg, chatbot, response_id],
140
+ outputs=[chatbot, response_id]
141
+ ).then(
142
+ lambda: "",
143
+ None,
144
+ [msg]
145
+ )
146
+
147
+ clear_btn.click(
148
+ clear_chat,
149
+ inputs=[chatbot],
150
+ outputs=[chatbot, response_id]
151
+ )
152
+
153
+ export_btn.click(
154
+ export_chat,
155
+ outputs=[export_message]
156
+ )
157
+
158
+ # Footer
159
+ gr.HTML("""
160
+ <div style="text-align: center; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid #ddd">
161
+ <p>© 2025 Pejman Ebrahimi | Built with Gradio and OpenAI Responses API</p>
162
+ <p style="font-size: 0.8rem; color: #666">
163
+ This application securely processes your conversations using OpenAI's technology.
164
+ Your API key is used only for authentication and is not stored permanently.
165
+ </p>
166
+ </div>
167
+ """)
168
 
169
+ # Launch the app
170
  if __name__ == "__main__":
171
+ app.launch()
172
+
173
+ print("Gradio app code generated successfully. Run this code to launch your chatbot application.")