jzou19950715 commited on
Commit
e9d4249
Β·
verified Β·
1 Parent(s): 7eeac78

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -52
app.py CHANGED
@@ -4,6 +4,7 @@ import requests
4
  import json
5
  from typing import List, Dict, Optional, Tuple
6
  import random
 
7
 
8
  class GifChatBot:
9
  def __init__(self):
@@ -11,6 +12,7 @@ class GifChatBot:
11
  self.giphy_key = None
12
  self.chat_history = []
13
  self.is_initialized = False
 
14
 
15
  def setup_keys(self, openai_key: str, giphy_key: str) -> str:
16
  """Initialize API clients with user's keys"""
@@ -25,16 +27,16 @@ class GifChatBot:
25
  except Exception as error:
26
  self.is_initialized = False
27
  return f"❌ Error setting up: {str(error)}"
28
-
29
  def _test_giphy_key(self):
30
  """Test if GIPHY key is valid"""
31
- response = requests.get(
32
  "https://api.giphy.com/v1/gifs/trending",
33
  params={"api_key": self.giphy_key, "limit": 1}
34
  )
35
  if response.status_code != 200:
36
  raise Exception("Invalid GIPHY API key")
37
-
38
  def _test_openai_key(self):
39
  """Test if OpenAI key is valid"""
40
  try:
@@ -46,78 +48,111 @@ class GifChatBot:
46
  except Exception:
47
  raise Exception("Invalid OpenAI API key")
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  def get_gif(self, search_query: str) -> Optional[str]:
50
- """Search GIPHY with natural, contextual queries"""
51
  try:
52
- # Keep the search query simple and contextual
53
  params = {
54
  'api_key': self.giphy_key,
55
  'q': search_query,
56
- 'limit': 15,
57
  'rating': 'pg-13',
58
  'bundle': 'messaging_non_clips'
59
  }
60
 
61
- response = requests.get(
62
  "https://api.giphy.com/v1/gifs/search",
63
- params=params
 
64
  )
65
 
66
  if response.status_code == 200:
67
  data = response.json()
68
  if data["data"]:
69
- # Filter for good quality GIFs
70
- good_gifs = [
71
- gif for gif in data["data"]
72
- if self._is_good_quality_gif(gif)
73
- ]
 
 
 
 
 
 
 
74
 
75
- if good_gifs:
76
- return random.choice(good_gifs)["images"]["original"]["url"]
77
-
78
- # Fallback to trending if no good matches
79
- return self._get_trending_gif()
80
 
81
  except Exception as error:
82
  print(f"GIPHY error: {error}")
83
  return None
84
 
85
- def _is_good_quality_gif(self, gif: Dict) -> bool:
86
- """Check if a GIF meets quality criteria"""
87
- try:
88
- # Avoid very long GIFs
89
- if int(gif.get("images", {}).get("original", {}).get("frames", 50)) > 50:
90
- return False
91
-
92
- # Check if size is reasonable (under 2MB)
93
- if int(gif.get("images", {}).get("original", {}).get("size", 0)) > 2000000:
94
- return False
95
-
96
- return True
97
- except:
98
- return True
99
-
100
  def _get_trending_gif(self) -> Optional[str]:
101
- """Get a trending GIF as fallback"""
102
  try:
103
- response = requests.get(
104
  "https://api.giphy.com/v1/gifs/trending",
105
  params={
106
  'api_key': self.giphy_key,
107
  'limit': 25,
108
  'rating': 'pg-13',
109
  'bundle': 'messaging_non_clips'
110
- }
 
111
  )
112
 
113
  if response.status_code == 200:
114
  data = response.json()
115
  if data["data"]:
116
- return random.choice(data["data"])["images"]["original"]["url"]
 
 
 
 
 
 
 
 
117
  except Exception as error:
118
  print(f"Error getting trending GIF: {error}")
119
  return None
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  def reset_chat(self) -> Tuple[str, List[List[str]]]:
122
  """Reset the chat history"""
123
  self.chat_history = []
@@ -132,24 +167,22 @@ class GifChatBot:
132
  return message, history, ""
133
 
134
  try:
135
- # System message emphasizing natural GIF search
136
  system_message = """You are a supportive, empathetic friend who uses GIFs naturally in conversation.
137
- When using GIFs, keep search terms simple and contextual, like humans do:
138
 
139
- Examples of natural GIF searches:
140
- - When someone's hungry: [GIF: hungry]
141
- - When comforting someone: [GIF: comforting hug]
142
- - When celebrating: [GIF: celebration]
143
- - When confused: [GIF: confused]
144
- - When agreeing strongly: [GIF: absolutely yes]
145
 
146
  Keep your responses:
147
- 1. Empathetic and supportive
148
- 2. Context-aware (reference previous messages naturally)
149
- 3. Use GIFs that match the emotional context
150
 
151
- Use 0-1 GIFs per message unless the context really calls for more.
152
- The GIF should enhance your message, not replace it."""
153
 
154
  # Prepare conversation history
155
  messages = [{"role": "system", "content": system_message}]
@@ -192,6 +225,10 @@ class GifChatBot:
192
  error_message = f"Oops! Something went wrong: {str(error)}"
193
  return message, history, error_message
194
 
 
 
 
 
195
  def create_interface():
196
  """Create the Gradio interface"""
197
  bot = GifChatBot()
@@ -262,11 +299,18 @@ def create_interface():
262
 
263
  gr.Markdown("""
264
  ### Tips:
265
- - 🀝 Share how you're feeling - the AI will respond empathetically
266
  - πŸ’­ The conversation is context-aware
267
- - 🎯 GIFs are chosen to match the emotional context
268
  - πŸ”„ Use 'Clear Chat' to start fresh
269
  """)
 
 
 
 
 
 
 
270
 
271
  return interface
272
 
 
4
  import json
5
  from typing import List, Dict, Optional, Tuple
6
  import random
7
+ import time
8
 
9
  class GifChatBot:
10
  def __init__(self):
 
12
  self.giphy_key = None
13
  self.chat_history = []
14
  self.is_initialized = False
15
+ self.session = requests.Session() # Use session for better performance
16
 
17
  def setup_keys(self, openai_key: str, giphy_key: str) -> str:
18
  """Initialize API clients with user's keys"""
 
27
  except Exception as error:
28
  self.is_initialized = False
29
  return f"❌ Error setting up: {str(error)}"
30
+
31
  def _test_giphy_key(self):
32
  """Test if GIPHY key is valid"""
33
+ response = self.session.get(
34
  "https://api.giphy.com/v1/gifs/trending",
35
  params={"api_key": self.giphy_key, "limit": 1}
36
  )
37
  if response.status_code != 200:
38
  raise Exception("Invalid GIPHY API key")
39
+
40
  def _test_openai_key(self):
41
  """Test if OpenAI key is valid"""
42
  try:
 
48
  except Exception:
49
  raise Exception("Invalid OpenAI API key")
50
 
51
+ def verify_gif_url(self, gif_url: str) -> bool:
52
+ """Verify if a GIF URL is accessible"""
53
+ try:
54
+ # Head request is faster than full GET
55
+ response = self.session.head(gif_url, timeout=3)
56
+
57
+ # Check if status is OK and content type is correct
58
+ if response.status_code == 200:
59
+ content_type = response.headers.get('content-type', '').lower()
60
+ return 'gif' in content_type or 'image' in content_type
61
+ return False
62
+ except:
63
+ return False
64
+
65
  def get_gif(self, search_query: str) -> Optional[str]:
66
+ """Search GIPHY with validation for working GIFs"""
67
  try:
 
68
  params = {
69
  'api_key': self.giphy_key,
70
  'q': search_query,
71
+ 'limit': 25, # Get more options
72
  'rating': 'pg-13',
73
  'bundle': 'messaging_non_clips'
74
  }
75
 
76
+ response = self.session.get(
77
  "https://api.giphy.com/v1/gifs/search",
78
+ params=params,
79
+ timeout=5
80
  )
81
 
82
  if response.status_code == 200:
83
  data = response.json()
84
  if data["data"]:
85
+ # Shuffle results for variety
86
+ gifs = list(data["data"])
87
+ random.shuffle(gifs)
88
+
89
+ # Try GIFs until we find a good one
90
+ for gif in gifs:
91
+ if not self._is_good_quality_gif(gif):
92
+ continue
93
+
94
+ gif_url = gif["images"]["original"]["url"]
95
+ if self.verify_gif_url(gif_url):
96
+ return gif_url
97
 
98
+ # If no GIFs passed validation, try trending
99
+ return self._get_trending_gif()
100
+
101
+ return None
 
102
 
103
  except Exception as error:
104
  print(f"GIPHY error: {error}")
105
  return None
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  def _get_trending_gif(self) -> Optional[str]:
108
+ """Get a verified trending GIF as fallback"""
109
  try:
110
+ response = self.session.get(
111
  "https://api.giphy.com/v1/gifs/trending",
112
  params={
113
  'api_key': self.giphy_key,
114
  'limit': 25,
115
  'rating': 'pg-13',
116
  'bundle': 'messaging_non_clips'
117
+ },
118
+ timeout=5
119
  )
120
 
121
  if response.status_code == 200:
122
  data = response.json()
123
  if data["data"]:
124
+ # Try each trending GIF until we find a working one
125
+ gifs = list(data["data"])
126
+ random.shuffle(gifs)
127
+
128
+ for gif in gifs:
129
+ gif_url = gif["images"]["original"]["url"]
130
+ if self.verify_gif_url(gif_url):
131
+ return gif_url
132
+
133
  except Exception as error:
134
  print(f"Error getting trending GIF: {error}")
135
  return None
136
 
137
+ def _is_good_quality_gif(self, gif: Dict) -> bool:
138
+ """Check if a GIF meets quality criteria"""
139
+ try:
140
+ # Skip GIFs that are too long
141
+ if int(gif.get("images", {}).get("original", {}).get("frames", 50)) > 50:
142
+ return False
143
+
144
+ # Skip GIFs that are too large
145
+ if int(gif.get("images", {}).get("original", {}).get("size", 0)) > 2000000: # 2MB
146
+ return False
147
+
148
+ # Skip if no image data
149
+ if not gif.get("images", {}).get("original", {}).get("url"):
150
+ return False
151
+
152
+ return True
153
+ except:
154
+ return False
155
+
156
  def reset_chat(self) -> Tuple[str, List[List[str]]]:
157
  """Reset the chat history"""
158
  self.chat_history = []
 
167
  return message, history, ""
168
 
169
  try:
170
+ # System message emphasizing natural GIF usage
171
  system_message = """You are a supportive, empathetic friend who uses GIFs naturally in conversation.
172
+ When using GIFs, keep search terms simple and contextual:
173
 
174
+ Examples:
175
+ - User feeling hungry -> [GIF: hungry]
176
+ - User feeling sad -> [GIF: comforting hug]
177
+ - User celebrating -> [GIF: celebration]
178
+ - User confused -> [GIF: confused]
 
179
 
180
  Keep your responses:
181
+ 1. Empathetic and natural
182
+ 2. Context-aware
183
+ 3. Use GIFs that match the emotion
184
 
185
+ Use 0-1 GIFs per message unless the moment really calls for more."""
 
186
 
187
  # Prepare conversation history
188
  messages = [{"role": "system", "content": system_message}]
 
225
  error_message = f"Oops! Something went wrong: {str(error)}"
226
  return message, history, error_message
227
 
228
+ def cleanup(self):
229
+ """Cleanup resources"""
230
+ self.session.close()
231
+
232
  def create_interface():
233
  """Create the Gradio interface"""
234
  bot = GifChatBot()
 
299
 
300
  gr.Markdown("""
301
  ### Tips:
302
+ - 🀝 Share how you're feeling - the AI responds empathetically
303
  - πŸ’­ The conversation is context-aware
304
+ - 🎯 GIFs are chosen to match the emotion
305
  - πŸ”„ Use 'Clear Chat' to start fresh
306
  """)
307
+
308
+ # Cleanup on page unload
309
+ interface.load(lambda: None, [], [], _js="""() => {
310
+ window.addEventListener('unload', function() {
311
+ // Cleanup resources
312
+ })
313
+ }""")
314
 
315
  return interface
316