Guiyom commited on
Commit
3cbcbb2
·
verified ·
1 Parent(s): 036735b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +101 -46
app.py CHANGED
@@ -3,12 +3,26 @@ from openai import OpenAI
3
  import requests
4
  import json
5
  import os
 
6
  from typing import Dict, List
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  OPENAI_API_KEY = os.getenv('openaikey')
9
  RAINDROP_TOKEN = os.getenv('raindroptoken')
10
 
11
  if not OPENAI_API_KEY or not RAINDROP_TOKEN:
 
12
  raise EnvironmentError(
13
  "Missing required environment variables. Please ensure 'openaikey' and 'raindroptoken' are set."
14
  )
@@ -18,8 +32,10 @@ class RaindropSearchBot:
18
  self.openai_api_key = OPENAI_API_KEY
19
  self.raindrop_api_token = RAINDROP_TOKEN
20
  self.client = OpenAI(api_key=self.openai_api_key)
 
21
 
22
  def generate_search_query(self, user_request: str) -> str:
 
23
  prompt = f"""
24
  Convert the following request into a focused search query for Raindrop.io.
25
  Extract key concepts and create a search query that will work well with the Raindrop API.
@@ -30,53 +46,75 @@ class RaindropSearchBot:
30
  Format the search query for maximum relevance and recall.
31
  """
32
 
33
- response = self.client.chat.completions.create(
34
- model="gpt-4o-mini",
35
- messages=[{"role": "user", "content": prompt}],
36
- temperature=0.5,
37
- max_tokens=1000
38
- )
39
- return response.choices[0].message.content
 
 
 
 
 
 
40
 
41
  def search_raindrop(self, search_query: str) -> List[Dict]:
 
 
42
  headers = {
43
  "Authorization": f"Bearer {self.raindrop_api_token}",
44
  "Content-Type": "application/json"
45
  }
46
 
47
- # Get all collections first
48
- collections_response = requests.get(
49
- "https://api.raindrop.io/rest/v1/collections",
50
- headers=headers
51
- )
52
-
53
- params = {
54
- "search": search_query,
55
- "page": 0,
56
- "perpage": 50, # Increased from 10 to 50
57
- "sort": "-created" # Sort by newest first
58
- }
59
-
60
- # Search in all collections (0)
61
- response = requests.get(
62
- "https://api.raindrop.io/rest/v1/raindrops/0",
63
- headers=headers,
64
- params=params
65
- )
66
-
67
- if response.status_code == 200:
68
- items = response.json().get("items", [])
69
- # Get filters to enhance search context
70
- filters_response = requests.get(
71
- "https://api.raindrop.io/rest/v1/filters/0",
72
  headers=headers,
73
- params={"search": search_query}
74
  )
75
- return items
76
- return []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  def generate_summary(self, item: Dict) -> str:
79
- """Generate a summary for a single bookmark using GPT-4."""
80
  content = f"""
81
  Title: {item.get('title', 'No Title')}
82
  Description: {item.get('excerpt', '')}
@@ -97,48 +135,64 @@ class RaindropSearchBot:
97
  temperature=0.3,
98
  max_tokens=150
99
  )
100
- return response.choices[0].message.content
 
 
101
  except Exception as e:
 
102
  return "Summary generation failed"
103
 
104
  def format_results(self, results: List[Dict]) -> str:
 
 
105
  if not results:
 
106
  return "No results found."
107
 
108
  formatted_output = "🔍 Search Results:\n\n"
109
  for idx, item in enumerate(results, 1):
 
 
110
  formatted_output += f"{idx}. {item.get('title', 'No Title')}\n"
111
  formatted_output += f" Link: {item.get('link', 'No Link')}\n"
112
 
113
- # Add tags if present
114
  if item.get('tags'):
115
  formatted_output += f" Tags: {', '.join(item['tags'])}\n"
116
 
117
- # Add type and created date
118
  formatted_output += f" Type: {item.get('type', 'unknown')} | Created: {item.get('created', 'unknown')}\n"
119
 
120
- # Add summary
121
  summary = self.generate_summary(item)
122
- formatted_output += f" Summary: {summary}\n"
123
-
124
- formatted_output += "\n"
125
 
 
126
  return formatted_output
127
 
128
  def process_request(self, user_request: str) -> str:
 
129
  try:
130
  search_query = self.generate_search_query(user_request)
 
 
131
  results = self.search_raindrop(search_query)
132
- return self.format_results(results)
 
 
 
 
 
133
  except Exception as e:
134
- return f"An error occurred: {str(e)}"
 
135
 
136
  # Initialize the bot
137
  bot = RaindropSearchBot()
138
 
139
  # Create Gradio interface
140
  def chatbot_interface(user_input: str) -> str:
141
- return bot.process_request(user_input)
 
 
 
142
 
143
  # Define and launch the Gradio interface
144
  with gr.Blocks(title="Raindrop.io Link Search Assistant", theme=gr.themes.Soft()) as demo:
@@ -184,4 +238,5 @@ with gr.Blocks(title="Raindrop.io Link Search Assistant", theme=gr.themes.Soft()
184
  """)
185
 
186
  if __name__ == "__main__":
 
187
  demo.launch(share=True)
 
3
  import requests
4
  import json
5
  import os
6
+ import logging
7
  from typing import Dict, List
8
+ from datetime import datetime
9
+
10
+ # Set up logging
11
+ logging.basicConfig(
12
+ level=logging.DEBUG,
13
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
14
+ handlers=[
15
+ logging.FileHandler(f'raindrop_search_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log'),
16
+ logging.StreamHandler()
17
+ ]
18
+ )
19
+ logger = logging.getLogger('RaindropSearchBot')
20
 
21
  OPENAI_API_KEY = os.getenv('openaikey')
22
  RAINDROP_TOKEN = os.getenv('raindroptoken')
23
 
24
  if not OPENAI_API_KEY or not RAINDROP_TOKEN:
25
+ logger.error("Missing environment variables")
26
  raise EnvironmentError(
27
  "Missing required environment variables. Please ensure 'openaikey' and 'raindroptoken' are set."
28
  )
 
32
  self.openai_api_key = OPENAI_API_KEY
33
  self.raindrop_api_token = RAINDROP_TOKEN
34
  self.client = OpenAI(api_key=self.openai_api_key)
35
+ logger.info("RaindropSearchBot initialized")
36
 
37
  def generate_search_query(self, user_request: str) -> str:
38
+ logger.info(f"Generating search query for request: {user_request}")
39
  prompt = f"""
40
  Convert the following request into a focused search query for Raindrop.io.
41
  Extract key concepts and create a search query that will work well with the Raindrop API.
 
46
  Format the search query for maximum relevance and recall.
47
  """
48
 
49
+ try:
50
+ response = self.client.chat.completions.create(
51
+ model="gpt-4o-mini",
52
+ messages=[{"role": "user", "content": prompt}],
53
+ temperature=0.5,
54
+ max_tokens=1000
55
+ )
56
+ generated_query = response.choices[0].message.content
57
+ logger.info(f"Generated search query: {generated_query}")
58
+ return generated_query
59
+ except Exception as e:
60
+ logger.error(f"Error generating search query: {str(e)}")
61
+ raise
62
 
63
  def search_raindrop(self, search_query: str) -> List[Dict]:
64
+ logger.info(f"Searching Raindrop with query: {search_query}")
65
+
66
  headers = {
67
  "Authorization": f"Bearer {self.raindrop_api_token}",
68
  "Content-Type": "application/json"
69
  }
70
 
71
+ try:
72
+ # First, let's test the API connection and token
73
+ test_response = requests.get(
74
+ "https://api.raindrop.io/rest/v1/user",
75
+ headers=headers
76
+ )
77
+ logger.info(f"API test response status: {test_response.status_code}")
78
+ if test_response.status_code != 200:
79
+ logger.error(f"API test failed: {test_response.text}")
80
+ return []
81
+
82
+ # Search parameters
83
+ params = {
84
+ "search": search_query,
85
+ "page": 0,
86
+ "perpage": 50,
87
+ "sort": "-created"
88
+ }
89
+
90
+ # Log the full request details
91
+ logger.info(f"Making request to Raindrop API with params: {params}")
92
+
93
+ # Make the search request
94
+ response = requests.get(
95
+ "https://api.raindrop.io/rest/v1/raindrops/0",
96
  headers=headers,
97
+ params=params
98
  )
99
+
100
+ logger.info(f"Search response status code: {response.status_code}")
101
+
102
+ if response.status_code == 200:
103
+ data = response.json()
104
+ items = data.get("items", [])
105
+ logger.info(f"Found {len(items)} results")
106
+ logger.debug(f"Response data: {json.dumps(data, indent=2)}")
107
+ return items
108
+ else:
109
+ logger.error(f"Search failed with status {response.status_code}: {response.text}")
110
+ return []
111
+
112
+ except Exception as e:
113
+ logger.error(f"Error during Raindrop search: {str(e)}", exc_info=True)
114
+ return []
115
 
116
  def generate_summary(self, item: Dict) -> str:
117
+ logger.info(f"Generating summary for item: {item.get('title', 'No Title')}")
118
  content = f"""
119
  Title: {item.get('title', 'No Title')}
120
  Description: {item.get('excerpt', '')}
 
135
  temperature=0.3,
136
  max_tokens=150
137
  )
138
+ summary = response.choices[0].message.content
139
+ logger.info(f"Generated summary: {summary}")
140
+ return summary
141
  except Exception as e:
142
+ logger.error(f"Error generating summary: {str(e)}")
143
  return "Summary generation failed"
144
 
145
  def format_results(self, results: List[Dict]) -> str:
146
+ logger.info(f"Formatting {len(results)} results")
147
+
148
  if not results:
149
+ logger.warning("No results to format")
150
  return "No results found."
151
 
152
  formatted_output = "🔍 Search Results:\n\n"
153
  for idx, item in enumerate(results, 1):
154
+ logger.debug(f"Formatting item {idx}: {item.get('title', 'No Title')}")
155
+
156
  formatted_output += f"{idx}. {item.get('title', 'No Title')}\n"
157
  formatted_output += f" Link: {item.get('link', 'No Link')}\n"
158
 
 
159
  if item.get('tags'):
160
  formatted_output += f" Tags: {', '.join(item['tags'])}\n"
161
 
 
162
  formatted_output += f" Type: {item.get('type', 'unknown')} | Created: {item.get('created', 'unknown')}\n"
163
 
 
164
  summary = self.generate_summary(item)
165
+ formatted_output += f" Summary: {summary}\n\n"
 
 
166
 
167
+ logger.info("Results formatting completed")
168
  return formatted_output
169
 
170
  def process_request(self, user_request: str) -> str:
171
+ logger.info(f"Processing new request: {user_request}")
172
  try:
173
  search_query = self.generate_search_query(user_request)
174
+ logger.info(f"Using search query: {search_query}")
175
+
176
  results = self.search_raindrop(search_query)
177
+ logger.info(f"Found {len(results)} results")
178
+
179
+ formatted_results = self.format_results(results)
180
+ logger.info("Request processing completed")
181
+ return formatted_results
182
+
183
  except Exception as e:
184
+ logger.error(f"Error processing request: {str(e)}", exc_info=True)
185
+ return f"An error occurred: {str(e)}\nPlease check the logs for more details."
186
 
187
  # Initialize the bot
188
  bot = RaindropSearchBot()
189
 
190
  # Create Gradio interface
191
  def chatbot_interface(user_input: str) -> str:
192
+ logger.info(f"New interface request received: {user_input}")
193
+ result = bot.process_request(user_input)
194
+ logger.info("Interface request completed")
195
+ return result
196
 
197
  # Define and launch the Gradio interface
198
  with gr.Blocks(title="Raindrop.io Link Search Assistant", theme=gr.themes.Soft()) as demo:
 
238
  """)
239
 
240
  if __name__ == "__main__":
241
+ logger.info("Starting Gradio interface")
242
  demo.launch(share=True)