Guiyom commited on
Commit
407f9e3
Β·
verified Β·
1 Parent(s): 587e959

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +138 -40
app.py CHANGED
@@ -6,6 +6,9 @@ import os
6
  import logging
7
  from typing import Dict, List
8
  from datetime import datetime
 
 
 
9
 
10
  # Set up logging
11
  logging.basicConfig(
@@ -18,11 +21,51 @@ class RaindropSearchBot:
18
  def __init__(self):
19
  self.openai_api_key = os.getenv('openaikey')
20
  self.raindrop_api_token = os.getenv('raindroptoken')
21
- if not self.openai_api_key or not self.raindrop_api_token:
 
 
 
22
  raise EnvironmentError(
23
- "Missing required environment variables. Please ensure 'openaikey' and 'raindroptoken' are set."
24
  )
 
25
  self.client = OpenAI(api_key=self.openai_api_key)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  def generate_search_query(self, user_request: str) -> str:
28
  """Convert user request to optimized search terms."""
@@ -105,31 +148,53 @@ class RaindropSearchBot:
105
  logger.error(f"Search error: {e}")
106
  return []
107
 
108
- def analyze_results(self, results: List[Dict], user_query: str) -> str:
109
- """Generate an analysis of the search results."""
110
- if not results:
 
111
  return "No relevant results found. Try modifying your search terms."
112
 
113
  # Create context for analysis
114
  context = f"Based on the search query: '{user_query}'\n\n"
115
- context += "Analyze these relevant sources:\n\n"
116
 
117
- for item in results:
118
- context += f"Title: {item.get('title', 'No title')}\n"
119
- if item.get('excerpt'):
120
- context += f"Content: {item['excerpt'][:500]}...\n"
121
- context += f"Created: {item.get('created', 'No date')}\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
  try:
124
  prompt = f"""
125
- Based on these search results, provide a comprehensive analysis of {user_query}.
126
 
127
  Requirements:
128
- 1. Focus only on information directly related to the query
129
- 2. Organize the response by key themes or chronologically
130
  3. Include only factual information from the sources
131
  4. Highlight any significant developments or changes
132
- 5. Note any gaps in information
 
133
 
134
  Context:
135
  {context}
@@ -148,28 +213,53 @@ class RaindropSearchBot:
148
  logger.error(f"Analysis generation error: {e}")
149
  return "Error generating analysis."
150
 
151
- def format_results(self, results: List[Dict], analysis: str) -> str:
152
- """Format the search results with analysis."""
153
- if not results:
154
- return "No results found. Try modifying your search terms."
155
-
156
  output = f"{analysis}\n\n"
157
  output += "-------\n\n"
158
- output += "πŸ” Source Links:\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
- for idx, item in enumerate(results, 1):
161
- # Only include if there's at least a title or link
162
- if item.get('title') or item.get('link'):
 
163
  output += f"{idx}. {item.get('title', 'No Title')}\n"
164
  if item.get('link'):
165
  output += f" Link: {item['link']}\n"
166
- if item.get('tags'):
167
- output += f" Tags: {', '.join(item['tags'])}\n"
168
- if item.get('excerpt'):
169
- output += f" Description: {item['excerpt'][:200]}...\n"
170
- if item.get('created'):
171
- created_date = item['created'][:10] # Get just the date part
172
- output += f" Created: {created_date}\n"
 
 
 
 
 
 
 
 
 
 
173
  output += "\n"
174
 
175
  return output
@@ -183,15 +273,20 @@ class RaindropSearchBot:
183
  search_query = self.generate_search_query(user_request)
184
  logger.info(f"Using search query: {search_query}")
185
 
186
- # Search Raindrop.io
187
- results = self.search_raindrop(search_query)
188
- logger.info(f"Found {len(results)} results")
 
 
 
 
 
189
 
190
  # Generate analysis
191
- analysis = self.analyze_results(results, user_request)
192
 
193
  # Format and return results
194
- return self.format_results(results, analysis)
195
 
196
  except Exception as e:
197
  logger.error(f"Error processing request: {e}", exc_info=True)
@@ -205,10 +300,13 @@ def chatbot_interface(user_input: str) -> str:
205
  return bot.process_request(user_input)
206
 
207
  # Define and launch the interface
208
- with gr.Blocks(title="Raindrop.io Search Assistant", theme=gr.themes.Soft()) as demo:
209
  gr.Markdown("""
210
- # πŸ” Raindrop.io Search Assistant
211
- Enter your search request in natural language, and I'll find and analyze relevant bookmarked information.
 
 
 
212
  """)
213
 
214
  with gr.Row():
@@ -224,7 +322,7 @@ with gr.Blocks(title="Raindrop.io Search Assistant", theme=gr.themes.Soft()) as
224
  with gr.Row():
225
  output_text = gr.Textbox(
226
  label="Analysis and Results",
227
- lines=15,
228
  interactive=False
229
  )
230
 
 
6
  import logging
7
  from typing import Dict, List
8
  from datetime import datetime
9
+ from bs4 import BeautifulSoup
10
+ from serpapi import GoogleSearch
11
+ from newsapi import NewsApiClient
12
 
13
  # Set up logging
14
  logging.basicConfig(
 
21
  def __init__(self):
22
  self.openai_api_key = os.getenv('openaikey')
23
  self.raindrop_api_token = os.getenv('raindroptoken')
24
+ self.serpapi_key = os.getenv('serpapikey')
25
+ self.newsapi_key = os.getenv('newsapikey')
26
+
27
+ if not all([self.openai_api_key, self.raindrop_api_token, self.serpapi_key, self.newsapi_key]):
28
  raise EnvironmentError(
29
+ "Missing required environment variables. Please ensure all API keys are set."
30
  )
31
+
32
  self.client = OpenAI(api_key=self.openai_api_key)
33
+ self.newsapi = NewsApiClient(api_key=self.newsapi_key)
34
+
35
+ def get_google_results(self, query: str, num_results: int = 5) -> List[Dict]:
36
+ """Get Google search results using SerpAPI."""
37
+ try:
38
+ params = {
39
+ "q": query,
40
+ "num": num_results,
41
+ "api_key": self.serpapi_key
42
+ }
43
+ search = GoogleSearch(params)
44
+ results = search.get_dict()
45
+
46
+ if 'organic_results' in results:
47
+ return results['organic_results']
48
+ return []
49
+
50
+ except Exception as e:
51
+ logger.error(f"Google search error: {e}")
52
+ return []
53
+
54
+ def get_news_results(self, query: str, num_results: int = 5) -> List[Dict]:
55
+ """Get news articles using NewsAPI."""
56
+ try:
57
+ news_results = self.newsapi.get_everything(
58
+ q=query,
59
+ language='en',
60
+ sort_by='relevancy',
61
+ page_size=num_results
62
+ )
63
+
64
+ return news_results.get('articles', [])
65
+
66
+ except Exception as e:
67
+ logger.error(f"News API error: {e}")
68
+ return []
69
 
70
  def generate_search_query(self, user_request: str) -> str:
71
  """Convert user request to optimized search terms."""
 
148
  logger.error(f"Search error: {e}")
149
  return []
150
 
151
+ def analyze_results(self, results: List[Dict], google_results: List[Dict],
152
+ news_results: List[Dict], user_query: str) -> str:
153
+ """Generate an analysis of all search results."""
154
+ if not any([results, google_results, news_results]):
155
  return "No relevant results found. Try modifying your search terms."
156
 
157
  # Create context for analysis
158
  context = f"Based on the search query: '{user_query}'\n\n"
159
+ context += "Analyze these sources:\n\n"
160
 
161
+ # Add Raindrop results
162
+ if results:
163
+ context += "Bookmarked Sources:\n"
164
+ for item in results:
165
+ context += f"Title: {item.get('title', 'No title')}\n"
166
+ if item.get('excerpt'):
167
+ context += f"Content: {item['excerpt'][:500]}...\n"
168
+ context += f"Created: {item.get('created', 'No date')}\n\n"
169
+
170
+ # Add Google results
171
+ if google_results:
172
+ context += "Web Sources:\n"
173
+ for item in google_results:
174
+ context += f"Title: {item.get('title', 'No title')}\n"
175
+ if item.get('snippet'):
176
+ context += f"Content: {item['snippet']}\n\n"
177
+
178
+ # Add News results
179
+ if news_results:
180
+ context += "News Sources:\n"
181
+ for item in news_results:
182
+ context += f"Title: {item.get('title', 'No title')}\n"
183
+ if item.get('description'):
184
+ context += f"Content: {item['description']}\n"
185
+ context += f"Published: {item.get('publishedAt', 'No date')}\n\n"
186
 
187
  try:
188
  prompt = f"""
189
+ Based on all available sources, provide a comprehensive analysis of {user_query}.
190
 
191
  Requirements:
192
+ 1. Focus on the most relevant and recent information
193
+ 2. Organize the response by key themes
194
  3. Include only factual information from the sources
195
  4. Highlight any significant developments or changes
196
+ 5. Note any conflicts or differences between sources
197
+ 6. Prioritize official sources and recent developments
198
 
199
  Context:
200
  {context}
 
213
  logger.error(f"Analysis generation error: {e}")
214
  return "Error generating analysis."
215
 
216
+ def format_results(self, results: List[Dict], google_results: List[Dict],
217
+ news_results: List[Dict], analysis: str) -> str:
218
+ """Format all search results with analysis."""
 
 
219
  output = f"{analysis}\n\n"
220
  output += "-------\n\n"
221
+
222
+ # Format Raindrop results
223
+ if results:
224
+ output += "πŸ” Bookmarked Sources:\n\n"
225
+ for idx, item in enumerate(results, 1):
226
+ if item.get('title') or item.get('link'):
227
+ output += f"{idx}. {item.get('title', 'No Title')}\n"
228
+ if item.get('link'):
229
+ output += f" Link: {item['link']}\n"
230
+ if item.get('tags'):
231
+ output += f" Tags: {', '.join(item['tags'])}\n"
232
+ if item.get('excerpt'):
233
+ output += f" Description: {item['excerpt'][:200]}...\n"
234
+ if item.get('created'):
235
+ created_date = item['created'][:10]
236
+ output += f" Created: {created_date}\n"
237
+ output += "\n"
238
 
239
+ # Format Google results
240
+ if google_results:
241
+ output += "🌐 Web Sources:\n\n"
242
+ for idx, item in enumerate(google_results, 1):
243
  output += f"{idx}. {item.get('title', 'No Title')}\n"
244
  if item.get('link'):
245
  output += f" Link: {item['link']}\n"
246
+ if item.get('snippet'):
247
+ output += f" Description: {item['snippet']}\n"
248
+ output += "\n"
249
+
250
+ # Format News results
251
+ if news_results:
252
+ output += "πŸ“° Recent News:\n\n"
253
+ for idx, item in enumerate(news_results, 1):
254
+ output += f"{idx}. {item.get('title', 'No Title')}\n"
255
+ if item.get('url'):
256
+ output += f" Link: {item['url']}\n"
257
+ if item.get('description'):
258
+ output += f" Description: {item['description']}\n"
259
+ if item.get('publishedAt'):
260
+ output += f" Published: {item['publishedAt'][:10]}\n"
261
+ if item.get('source', {}).get('name'):
262
+ output += f" Source: {item['source']['name']}\n"
263
  output += "\n"
264
 
265
  return output
 
273
  search_query = self.generate_search_query(user_request)
274
  logger.info(f"Using search query: {search_query}")
275
 
276
+ # Get results from all sources
277
+ raindrop_results = self.search_raindrop(search_query)
278
+ google_results = self.get_google_results(search_query)
279
+ news_results = self.get_news_results(search_query)
280
+
281
+ logger.info(f"Found {len(raindrop_results)} Raindrop results")
282
+ logger.info(f"Found {len(google_results)} Google results")
283
+ logger.info(f"Found {len(news_results)} News results")
284
 
285
  # Generate analysis
286
+ analysis = self.analyze_results(raindrop_results, google_results, news_results, user_request)
287
 
288
  # Format and return results
289
+ return self.format_results(raindrop_results, google_results, news_results, analysis)
290
 
291
  except Exception as e:
292
  logger.error(f"Error processing request: {e}", exc_info=True)
 
300
  return bot.process_request(user_input)
301
 
302
  # Define and launch the interface
303
+ with gr.Blocks(title="Enhanced Search Assistant", theme=gr.themes.Soft()) as demo:
304
  gr.Markdown("""
305
+ # πŸ” Enhanced Search Assistant
306
+ Enter your search request in natural language, and I'll find and analyze information from multiple sources:
307
+ - Your bookmarked content
308
+ - Web search results
309
+ - Recent news articles
310
  """)
311
 
312
  with gr.Row():
 
322
  with gr.Row():
323
  output_text = gr.Textbox(
324
  label="Analysis and Results",
325
+ lines=20,
326
  interactive=False
327
  )
328