GeminiFan207 commited on
Commit
3aad904
·
verified ·
1 Parent(s): 140f4e4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -320
app.py CHANGED
@@ -1,337 +1,69 @@
1
  import gradio as gr
2
  import requests
3
- import json
4
  import os
5
- import base64
6
- from PIL import Image
7
- import soundfile as sf
8
- import mimetypes
9
- import logging
10
- from io import BytesIO
11
- import tempfile
12
 
13
- # Set up logging
14
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
15
- logger = logging.getLogger(__name__)
16
 
17
- # Hugging Face API configuration
18
- HF_API_URL = os.getenv("HF_API_URL") # URL of your Hugging Face model endpoint
19
- HF_API_TOKEN = os.getenv("HF_API_TOKEN") # Hugging Face API token
 
 
 
20
 
21
- # Default parameter values
22
- default_max_tokens = 4096
23
- default_temperature = 0.7
24
- default_top_p = 0.9
25
- default_presence_penalty = 0.0
26
- default_frequency_penalty = 0.0
27
-
28
- # Initialize MIME types
29
- mimetypes.init()
30
-
31
- def call_hf_endpoint(payload, api_url, api_token, params=None):
32
- """Call Hugging Face Inference API with the given payload."""
33
- # Set parameters from the UI inputs or use defaults
34
- if params is None:
35
- params = {
36
- "max_tokens": default_max_tokens,
37
- "temperature": default_temperature,
38
- "top_p": default_top_p,
39
- "presence_penalty": default_presence_penalty,
40
- "frequency_penalty": default_frequency_penalty
41
- }
42
-
43
- # Add parameters to the payload
44
- if "parameters" not in payload:
45
- payload["parameters"] = params
46
-
47
- # Set up headers
48
- headers = {
49
- "Authorization": f"Bearer {api_token}",
50
- "Content-Type": "application/json"
51
- }
52
-
53
- try:
54
- logger.info(f"Sending request to {api_url}")
55
- logger.info(f"Using parameters: {params}")
56
- response = requests.post(api_url, headers=headers, json=payload)
57
- response.raise_for_status()
58
- result = response.json()
59
- logger.info("Received response successfully")
60
- return result
61
- except requests.exceptions.HTTPError as error:
62
- logger.error(f"Request failed with status code: {error.response.status_code}")
63
- logger.error(f"Error message: {error.response.text}")
64
- return {"error": error.response.text}
65
-
66
- def improved_fetch_audio_from_url(url):
67
- """Fetch audio data from URL and convert to base64."""
68
- try:
69
- logger.info(f"Fetching audio from URL: {url}")
70
- response = requests.get(url, timeout=30)
71
- response.raise_for_status()
72
-
73
- # Determine MIME type based on URL
74
- file_extension = os.path.splitext(url)[1].lower()
75
- mime_type = None
76
-
77
- if file_extension == '.wav':
78
- mime_type = "audio/wav"
79
- elif file_extension == '.mp3':
80
- mime_type = "audio/mpeg"
81
- elif file_extension == '.flac':
82
- mime_type = "audio/flac"
83
- elif file_extension in ['.m4a', '.aac']:
84
- mime_type = "audio/aac"
85
- elif file_extension == '.ogg':
86
- mime_type = "audio/ogg"
87
- else:
88
- # Try to detect the MIME type from headers
89
- content_type = response.headers.get('Content-Type', '')
90
- if content_type.startswith('audio/'):
91
- mime_type = content_type
92
- else:
93
- mime_type = "audio/wav" # Default to WAV
94
-
95
- logger.info(f"Detected MIME type: {mime_type}")
96
-
97
- # Convert to base64
98
- base64_audio = base64.b64encode(response.content).decode('utf-8')
99
- logger.info(f"Successfully encoded audio to base64, length: {len(base64_audio)}")
100
-
101
- return mime_type, base64_audio
102
- except Exception as e:
103
- logger.error(f"Error fetching audio from URL: {e}", exc_info=True)
104
- return None, None
105
-
106
- def fetch_image_from_url(url):
107
- """Fetch image data from URL and convert to base64."""
108
- try:
109
- logger.info(f"Fetching image from URL: {url}")
110
- response = requests.get(url)
111
- response.raise_for_status()
112
-
113
- # Determine MIME type based on URL
114
- file_extension = os.path.splitext(url)[1].lower()
115
- if file_extension in ['.jpg', '.jpeg']:
116
- mime_type = "image/jpeg"
117
- elif file_extension == '.png':
118
- mime_type = "image/png"
119
- elif file_extension == '.gif':
120
- mime_type = "image/gif"
121
- elif file_extension in ['.bmp', '.tiff', '.webp']:
122
- mime_type = f"image/{file_extension[1:]}"
123
- else:
124
- mime_type = "image/jpeg" # Default to JPEG
125
-
126
- # Convert to base64
127
- base64_image = base64.b64encode(response.content).decode('utf-8')
128
-
129
- logger.info(f"Successfully fetched and encoded image, mime type: {mime_type}")
130
- return mime_type, base64_image
131
- except Exception as e:
132
- logger.error(f"Error fetching image from URL: {e}")
133
- return None, None
134
-
135
- def encode_base64_from_file(file_path):
136
- """Encode file content to base64 string and determine MIME type."""
137
- file_extension = os.path.splitext(file_path)[1].lower()
138
-
139
- # Map file extensions to MIME types
140
- if file_extension in ['.jpg', '.jpeg']:
141
- mime_type = "image/jpeg"
142
- elif file_extension == '.png':
143
- mime_type = "image/png"
144
- elif file_extension == '.gif':
145
- mime_type = "image/gif"
146
- elif file_extension in ['.bmp', '.tiff', '.webp']:
147
- mime_type = f"image/{file_extension[1:]}"
148
- elif file_extension == '.flac':
149
- mime_type = "audio/flac"
150
- elif file_extension == '.wav':
151
- mime_type = "audio/wav"
152
- elif file_extension == '.mp3':
153
- mime_type = "audio/mpeg"
154
- elif file_extension in ['.m4a', '.aac']:
155
- mime_type = "audio/aac"
156
- elif file_extension == '.ogg':
157
- mime_type = "audio/ogg"
158
  else:
159
- mime_type = "application/octet-stream"
160
-
161
- # Read and encode file content
162
- with open(file_path, "rb") as file:
163
- encoded_string = base64.b64encode(file.read()).decode('utf-8')
164
-
165
- return encoded_string, mime_type
166
-
167
- def process_message(history, message, conversation_state):
168
- """Process user message and update both history and internal state."""
169
- # Extract text and files
170
- text_content = message["text"] if message["text"] else ""
171
-
172
- image_files = []
173
- audio_files = []
174
-
175
- # Create content array for internal state
176
- content_items = []
177
-
178
- # Add text if available
179
- if text_content:
180
- content_items.append({"type": "text", "text": text_content})
181
-
182
- # Process and immediately convert files to base64
183
- if message["files"] and len(message["files"]) > 0:
184
- for file_path in message["files"]:
185
- file_extension = os.path.splitext(file_path)[1].lower()
186
- file_name = os.path.basename(file_path)
187
-
188
- # Convert the file to base64 immediately
189
- base64_content, mime_type = encode_base64_from_file(file_path)
190
-
191
- # Add to content items for the API
192
- if mime_type.startswith("image/"):
193
- content_items.append({
194
- "type": "image_url",
195
- "image_url": {
196
- "url": f"data:{mime_type};base64,{base64_content}"
197
- }
198
- })
199
- image_files.append(file_path)
200
- elif mime_type.startswith("audio/"):
201
- content_items.append({
202
- "type": "audio_url",
203
- "audio_url": {
204
- "url": f"data:{mime_type};base64,{base64_content}"
205
- }
206
- })
207
- audio_files.append(file_path)
208
-
209
- # Only proceed if we have content
210
- if content_items:
211
- # Add to Gradio chatbot history (for display)
212
- history.append({"role": "user", "content": text_content})
213
-
214
- # Add file messages if present
215
- for file_path in image_files + audio_files:
216
- history.append({"role": "user", "content": {"path": file_path}})
217
-
218
- logger.info(f"Updated history with user message. Current conversation has {len(image_files)} images and {len(audio_files)} audio files")
219
-
220
- # Add to internal conversation state (with base64 data)
221
- conversation_state.append({
222
- "role": "user",
223
- "content": content_items
224
- })
225
-
226
- return history, gr.MultimodalTextbox(value=None, interactive=False), conversation_state
227
 
228
- def bot_response(history, conversation_state):
229
- """Generate bot response based on conversation state."""
230
- if not conversation_state:
231
- return history, conversation_state
232
 
233
- # Create the payload
234
  payload = {
235
- "inputs": conversation_state
 
236
  }
 
237
 
238
- # Log the payload for debugging (without base64 data)
239
- debug_payload = json.loads(json.dumps(payload))
240
- for item in debug_payload["inputs"]:
241
- if "content" in item and isinstance(item["content"], list):
242
- for content_item in item["content"]:
243
- if "image_url" in content_item:
244
- parts = content_item["image_url"]["url"].split(",")
245
- if len(parts) > 1:
246
- content_item["image_url"]["url"] = parts[0] + ",[BASE64_DATA_REMOVED]"
247
- if "audio_url" in content_item:
248
- parts = content_item["audio_url"]["url"].split(",")
249
- if len(parts) > 1:
250
- content_item["audio_url"]["url"] = parts[0] + ",[BASE64_DATA_REMOVED]"
251
-
252
- logger.info(f"Sending payload: {json.dumps(debug_payload, indent=2)}")
253
-
254
- # Call Hugging Face Inference API
255
- response = call_hf_endpoint(payload, HF_API_URL, HF_API_TOKEN)
256
-
257
- # Extract text response from the Hugging Face API response
258
- try:
259
- if isinstance(response, dict):
260
- if "generated_text" in response:
261
- result = response["generated_text"]
262
- elif "error" in response:
263
- result = f"Error: {response['error']}"
264
- else:
265
- result = f"Received response: {json.dumps(response)}"
266
- else:
267
- result = str(response)
268
- except Exception as e:
269
- result = f"Error processing response: {str(e)}"
270
-
271
- # Add bot response to history
272
- history.append({"role": "assistant", "content": result})
273
-
274
- # Add to conversation state
275
- conversation_state.append({
276
- "role": "assistant",
277
- "content": [{"type": "text", "text": result}]
278
- })
279
 
280
- return history, conversation_state
281
 
282
- def enable_input():
283
- """Re-enable the input box after bot responds."""
284
- return gr.MultimodalTextbox(interactive=True)
 
 
 
 
 
285
 
286
- def update_debug(conversation_state):
287
- """Update debug output with the last payload that would be sent."""
288
- if not conversation_state:
289
- return {}
290
-
291
- # Create a payload from the conversation
292
- payload = {
293
- "inputs": conversation_state
294
- }
295
-
296
- # Remove base64 data to avoid cluttering the UI
297
- sanitized_payload = json.loads(json.dumps(payload))
298
- for item in sanitized_payload["inputs"]:
299
- if "content" in item and isinstance(item["content"], list):
300
- for content_item in item["content"]:
301
- if "image_url" in content_item:
302
- parts = content_item["image_url"]["url"].split(",")
303
- if len(parts) > 1:
304
- content_item["image_url"]["url"] = parts[0] + ",[BASE64_DATA_REMOVED]"
305
- if "audio_url" in content_item:
306
- parts = content_item["audio_url"]["url"].split(",")
307
- if len(parts) > 1:
308
- content_item["audio_url"]["url"] = parts[0] + ",[BASE64_DATA_REMOVED]"
309
-
310
- return sanitized_payload
311
-
312
- # Gradio interface setup
313
- with gr.Blocks() as demo:
314
- gr.Markdown("# Chatbot with Hugging Face Models")
315
-
316
- with gr.Tab("Chat"):
317
- # Chat history display
318
- chat_history = gr.Chatbot(label="Chat")
319
-
320
- with gr.Row():
321
- with gr.Column():
322
- prompt_input = gr.MultimodalTextbox(label="Enter your prompt", placeholder="Type your message here...", lines=2)
323
- generate_button = gr.Button("Send")
324
-
325
- # Chat interaction
326
- generate_button.click(
327
- process_message,
328
- inputs=[chat_history, prompt_input],
329
- outputs=[chat_history, prompt_input]
330
- )
331
-
332
- # Debug output
333
- debug_output = gr.JSON(label="Debug Output")
334
- demo.load(update_debug, inputs=[chat_history], outputs=debug_output, every=1)
335
 
336
- # Launch the interface
337
  demo.launch()
 
1
  import gradio as gr
2
  import requests
3
+ from datetime import datetime
4
  import os
 
 
 
 
 
 
 
5
 
6
+ # GitHub image URL as chatbot icon
7
+ BOT_ICON = "https://raw.githubusercontent.com/GeminiFan207/Secialix_Chatbot/main/IMG_0528-removebg-preview.png"
 
8
 
9
+ # Load API token from Hugging Face Spaces secrets
10
+ API_TOKEN = os.getenv("HF_API_TOKEN") # Set this in Spaces Secrets
11
+ if not API_TOKEN:
12
+ raise ValueError("HF_API_TOKEN not set in Spaces Secrets. Please configure it in the Space settings.")
13
+ API_URL = "https://api-inference.huggingface.co/models/ZeppelinCorp/Charm_15"
14
+ headers = {"Authorization": f"Bearer {API_TOKEN}"}
15
 
16
+ def query_huggingface(payload):
17
+ response = requests.post(API_URL, headers=headers, json=payload)
18
+ if response.status_code == 200:
19
+ return response.json()[0]["generated_text"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  else:
21
+ return f"Error: API request failed with status {response.status_code}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ def chatbot_response(user_input):
24
+ timestamp = datetime.now().strftime("%H:%M:%S")
 
 
25
 
26
+ # Query the Charm_15 model via Hugging Face API
27
  payload = {
28
+ "inputs": user_input,
29
+ "parameters": {"max_length": 100, "num_return_sequences": 1}
30
  }
31
+ bot_response = query_huggingface(payload)
32
 
33
+ # Fallback if response is empty or an error
34
+ if not bot_response or "Error" in bot_response:
35
+ bot_response = f"Failed to generate response. Echo: '{user_input}' at {timestamp}"
36
+ else:
37
+ bot_response = f"{bot_response} (Generated at {timestamp})"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
+ return [[user_input, bot_response]]
40
 
41
+ # Custom CSS for circular avatar
42
+ custom_css = """
43
+ .bot-avatar {
44
+ border-radius: 50% !important;
45
+ width: 32px !important;
46
+ height: 32px !important;
47
+ }
48
+ """
49
 
50
+ # Gradio interface
51
+ with gr.Blocks(css=custom_css) as demo:
52
+ chatbot = gr.Chatbot(
53
+ label="Charm_15 Chatbot Playground",
54
+ avatar_images=[None, BOT_ICON], # None for user, GitHub image for bot
55
+ bubble_full_width=False
56
+ )
57
+ msg = gr.Textbox(placeholder="Type your message here...")
58
+ submit_btn = gr.Button("Send")
59
+
60
+ def submit_message(user_input, history=[]):
61
+ new_conversation = chatbot_response(user_input)
62
+ return history + new_conversation, ""
63
+
64
+ # Bind submission events
65
+ msg.submit(submit_message, [msg, chatbot], [chatbot, msg])
66
+ submit_btn.click(submit_message, [msg, chatbot], [chatbot, msg])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
+ # Launch the app (Spaces handles this automatically)
69
  demo.launch()