siddhartharya commited on
Commit
5fa1ee3
·
verified ·
1 Parent(s): dd3a224

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -135
app.py CHANGED
@@ -14,7 +14,7 @@ import sys
14
  import threading
15
  from queue import Queue, Empty
16
  import json
17
- from concurrent.futures import ThreadPoolExecutor # Ensure this import is present
18
 
19
  # Import OpenAI library
20
  import openai
@@ -83,13 +83,10 @@ if not OPENAI_API_KEY:
83
  openai.api_key = OPENAI_API_KEY
84
  openai.api_base = "https://api.groq.com/openai/v1" # Ensure this is the correct base URL for your API
85
 
86
- # Initialize global variables for rate limiting
87
- api_lock = threading.Lock()
88
- last_api_call_time = 0
89
-
90
  # Rate Limiter Configuration
91
- RPM_LIMIT = 30 # Requests per minute
92
- TPM_LIMIT = 40000 # Tokens per minute
 
93
 
94
  # Implementing a Token Bucket Rate Limiter
95
  class TokenBucket:
@@ -115,7 +112,7 @@ class TokenBucket:
115
 
116
  def wait_for_token(self, tokens=1):
117
  while not self.consume(tokens):
118
- time.sleep(0.1)
119
 
120
  # Initialize rate limiters
121
  rpm_rate = RPM_LIMIT / 60 # tokens per second
@@ -238,137 +235,125 @@ def llm_worker():
238
  """
239
  logger.info("LLM worker started.")
240
  while True:
 
241
  try:
242
- bookmark = llm_queue.get(timeout=60) # Wait for a task
243
- except Empty:
244
- continue # No task, continue waiting
245
-
246
- if bookmark is None:
247
- logger.info("LLM worker shutting down.")
248
- break # Exit signal
249
-
250
- try:
251
- # Rate Limiting
252
- rpm_bucket.wait_for_token()
253
- # Estimate tokens: prompt + max_tokens
254
- # Here, we assume max_tokens=150
255
- tpm_bucket.wait_for_token(tokens=150)
256
-
257
- html_content = bookmark.get('html_content', '')
258
- soup = BeautifulSoup(html_content, 'html.parser')
259
- metadata = get_page_metadata(soup)
260
- main_content = extract_main_content(soup)
261
-
262
- # Prepare content for the prompt
263
- content_parts = []
264
- if metadata['title']:
265
- content_parts.append(f"Title: {metadata['title']}")
266
- if metadata['description']:
267
- content_parts.append(f"Description: {metadata['description']}")
268
- if metadata['keywords']:
269
- content_parts.append(f"Keywords: {metadata['keywords']}")
270
- if main_content:
271
- content_parts.append(f"Main Content: {main_content}")
272
-
273
- content_text = '\n'.join(content_parts)
274
-
275
- # Detect insufficient or erroneous content
276
- error_keywords = ['Access Denied', 'Security Check', 'Cloudflare', 'captcha', 'unusual traffic']
277
- if not content_text or len(content_text.split()) < 50:
278
- use_prior_knowledge = True
279
- logger.info(f"Content for {bookmark.get('url')} is insufficient. Instructing LLM to use prior knowledge.")
280
- elif any(keyword.lower() in content_text.lower() for keyword in error_keywords):
281
- use_prior_knowledge = True
282
- logger.info(f"Content for {bookmark.get('url')} contains error messages. Instructing LLM to use prior knowledge.")
283
- else:
284
- use_prior_knowledge = False
285
-
286
- if use_prior_knowledge:
287
- prompt = f"""
288
- You are a knowledgeable assistant with up-to-date information as of 2023.
289
- URL: {bookmark.get('url')}
290
- Provide:
291
- 1. A concise summary (max two sentences) about this website.
292
- 2. Assign the most appropriate category from the list below.
293
- Categories:
294
- {', '.join([f'"{cat}"' for cat in CATEGORIES])}
295
- Format:
296
- Please provide your response in the following JSON format:
297
- {{
298
- "summary": "Your summary here.",
299
- "category": "One category from the list."
300
- }}
301
- """
302
- else:
303
- prompt = f"""
304
- You are an assistant that creates concise webpage summaries and assigns categories.
305
- Content:
306
- {content_text}
307
- Provide:
308
- 1. A concise summary (max two sentences) focusing on the main topic.
309
- 2. Assign the most appropriate category from the list below.
310
- Categories:
311
- {', '.join([f'"{cat}"' for cat in CATEGORIES])}
312
- Format:
313
- Please provide your response in the following JSON format:
314
- {{
315
- "summary": "Your summary here.",
316
- "category": "One category from the list."
317
- }}
318
- """
319
-
320
- response = openai.ChatCompletion.create(
321
- model='llama-3.1-70b-versatile', # Ensure this model is correct and available
322
- messages=[
323
- {"role": "user", "content": prompt}
324
- ],
325
- max_tokens=150,
326
- temperature=0.5,
327
- )
328
 
329
- content = response['choices'][0]['message']['content'].strip()
330
- if not content:
331
- raise ValueError("Empty response received from the model.")
332
 
333
- # Parse JSON response
334
  try:
335
- json_response = json.loads(content)
336
- summary = json_response.get('summary', '').strip()
337
- category = json_response.get('category', '').strip()
338
-
339
- # Validate and assign
340
- if not summary:
341
- summary = metadata.get('description') or metadata.get('title') or 'No summary available.'
342
- bookmark['summary'] = summary
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
 
344
- if category in CATEGORIES:
345
- bookmark['category'] = category
346
- else:
347
- # Fallback to keyword-based categorization
348
- bookmark['category'] = categorize_based_on_summary(summary, bookmark['url'])
349
-
350
- except json.JSONDecodeError:
351
- logger.error(f"Failed to parse JSON response for {bookmark.get('url')}. Using fallback methods.")
352
- # Fallback methods
353
- bookmark['summary'] = metadata.get('description') or metadata.get('title') or 'No summary available.'
354
- bookmark['category'] = categorize_based_on_summary(bookmark['summary'], bookmark['url'])
355
-
356
- # Additional keyword-based validation
357
- bookmark['category'] = validate_category(bookmark)
358
-
359
- logger.info("Successfully generated summary and assigned category")
360
- except openai.error.RateLimitError as e:
361
- logger.warning(f"LLM Rate limit reached while processing {bookmark.get('url')}. Retrying later...")
362
- # Re-enqueue the bookmark for retry
363
- llm_queue.put(bookmark)
364
- time.sleep(60) # Wait before retrying
365
- except Exception as e:
366
- logger.error(f"Error generating summary and assigning category for {bookmark.get('url')}: {e}", exc_info=True)
367
- # Assign default values on failure
368
- bookmark['summary'] = 'No summary available.'
369
- bookmark['category'] = 'Uncategorized'
370
- finally:
371
- llm_queue.task_done()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
 
373
  def generate_summary_and_assign_category(bookmark):
374
  """
@@ -704,7 +689,9 @@ def chatbot_response(user_query, chat_history):
704
 
705
  # Rate Limiting
706
  rpm_bucket.wait_for_token()
707
- tpm_bucket.wait_for_token(tokens=300) # Assuming max_tokens=300 per request
 
 
708
 
709
  query_vector = embedding_model.encode([user_query]).astype('float32')
710
  k = 5
 
14
  import threading
15
  from queue import Queue, Empty
16
  import json
17
+ from concurrent.futures import ThreadPoolExecutor
18
 
19
  # Import OpenAI library
20
  import openai
 
83
  openai.api_key = OPENAI_API_KEY
84
  openai.api_base = "https://api.groq.com/openai/v1" # Ensure this is the correct base URL for your API
85
 
 
 
 
 
86
  # Rate Limiter Configuration
87
+ RPM_LIMIT = 60 # Requests per minute (adjust based on your API's limit)
88
+ TPM_LIMIT = 60000 # Tokens per minute (adjust based on your API's limit)
89
+ BATCH_SIZE = 5 # Number of bookmarks per batch
90
 
91
  # Implementing a Token Bucket Rate Limiter
92
  class TokenBucket:
 
112
 
113
  def wait_for_token(self, tokens=1):
114
  while not self.consume(tokens):
115
+ time.sleep(0.05)
116
 
117
  # Initialize rate limiters
118
  rpm_rate = RPM_LIMIT / 60 # tokens per second
 
235
  """
236
  logger.info("LLM worker started.")
237
  while True:
238
+ batch = []
239
  try:
240
+ # Collect bookmarks up to BATCH_SIZE
241
+ while len(batch) < BATCH_SIZE:
242
+ bookmark = llm_queue.get(timeout=1)
243
+ if bookmark is None:
244
+ # Shutdown signal
245
+ logger.info("LLM worker shutting down.")
246
+ return
247
+ if not bookmark.get('dead_link') and not bookmark.get('slow_link'):
248
+ batch.append(bookmark)
249
+ else:
250
+ # Skip processing for dead or slow links
251
+ bookmark['summary'] = 'No summary available.'
252
+ bookmark['category'] = 'Uncategorized'
253
+ llm_queue.task_done()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
 
255
+ except Empty:
256
+ pass # No more bookmarks at the moment
 
257
 
258
+ if batch:
259
  try:
260
+ # Rate Limiting
261
+ rpm_bucket.wait_for_token()
262
+ # Estimate tokens: prompt + max_tokens
263
+ # Here, we assume max_tokens=150 per bookmark
264
+ total_tokens = 150 * len(batch)
265
+ tpm_bucket.wait_for_token(tokens=total_tokens)
266
+
267
+ # Prepare prompt
268
+ prompt = "You are an assistant that creates concise webpage summaries and assigns categories.\n\n"
269
+ prompt += "Provide summaries and categories for the following bookmarks:\n\n"
270
+
271
+ for idx, bookmark in enumerate(batch, 1):
272
+ prompt += f"Bookmark {idx}:\nURL: {bookmark['url']}\nTitle: {bookmark['title']}\n\n"
273
+
274
+ prompt += f"Categories:\n{', '.join([f'\"{cat}\"' for cat in CATEGORIES])}\n\n"
275
+ prompt += "Format your response as a JSON object where each key is the bookmark URL and the value is another JSON object containing 'summary' and 'category'.\n\n"
276
+ prompt += "Example:\n"
277
+ prompt += "{\n"
278
+ prompt += " \"https://example.com\": {\n"
279
+ prompt += " \"summary\": \"This is an example summary.\",\n"
280
+ prompt += " \"category\": \"Technology\"\n"
281
+ prompt += " }\n"
282
+ prompt += "}\n\n"
283
+ prompt += "Now, provide the summaries and categories for the bookmarks listed above."
284
+
285
+ response = openai.ChatCompletion.create(
286
+ model='llama-3.1-70b-versatile', # Ensure this model is correct and available
287
+ messages=[
288
+ {"role": "user", "content": prompt}
289
+ ],
290
+ max_tokens=150 * len(batch),
291
+ temperature=0.5,
292
+ )
293
 
294
+ content = response['choices'][0]['message']['content'].strip()
295
+ if not content:
296
+ raise ValueError("Empty response received from the model.")
297
+
298
+ # Parse JSON response
299
+ try:
300
+ json_response = json.loads(content)
301
+ for bookmark in batch:
302
+ url = bookmark['url']
303
+ if url in json_response:
304
+ summary = json_response[url].get('summary', '').strip()
305
+ category = json_response[url].get('category', '').strip()
306
+
307
+ if not summary:
308
+ summary = 'No summary available.'
309
+ bookmark['summary'] = summary
310
+
311
+ if category in CATEGORIES:
312
+ bookmark['category'] = category
313
+ else:
314
+ # Fallback to keyword-based categorization
315
+ bookmark['category'] = categorize_based_on_summary(summary, url)
316
+ else:
317
+ logger.warning(f"No data returned for {url}. Using fallback methods.")
318
+ bookmark['summary'] = 'No summary available.'
319
+ bookmark['category'] = 'Uncategorized'
320
+
321
+ # Additional keyword-based validation
322
+ bookmark['category'] = validate_category(bookmark)
323
+
324
+ logger.info(f"Processed bookmark: {url}")
325
+
326
+ except json.JSONDecodeError:
327
+ logger.error("Failed to parse JSON response from LLM. Using fallback methods.")
328
+ for bookmark in batch:
329
+ bookmark['summary'] = 'No summary available.'
330
+ bookmark['category'] = categorize_based_on_summary(bookmark.get('summary', ''), bookmark['url'])
331
+ bookmark['category'] = validate_category(bookmark)
332
+
333
+ except Exception as e:
334
+ logger.error(f"Error processing LLM response: {e}", exc_info=True)
335
+ for bookmark in batch:
336
+ bookmark['summary'] = 'No summary available.'
337
+ bookmark['category'] = 'Uncategorized'
338
+
339
+ except openai.error.RateLimitError as e:
340
+ logger.warning(f"LLM Rate limit reached. Retrying after 60 seconds.")
341
+ # Re-enqueue the entire batch for retry
342
+ for bookmark in batch:
343
+ llm_queue.put(bookmark)
344
+ time.sleep(60) # Wait before retrying
345
+ continue # Skip the rest and retry
346
+
347
+ except Exception as e:
348
+ logger.error(f"Error during LLM processing: {e}", exc_info=True)
349
+ for bookmark in batch:
350
+ bookmark['summary'] = 'No summary available.'
351
+ bookmark['category'] = 'Uncategorized'
352
+
353
+ finally:
354
+ # Mark all bookmarks in the batch as done
355
+ for _ in batch:
356
+ llm_queue.task_done()
357
 
358
  def generate_summary_and_assign_category(bookmark):
359
  """
 
689
 
690
  # Rate Limiting
691
  rpm_bucket.wait_for_token()
692
+ # Estimate tokens: prompt + max_tokens
693
+ # Here, we assume max_tokens=300 per chatbot response
694
+ tpm_bucket.wait_for_token(tokens=300)
695
 
696
  query_vector = embedding_model.encode([user_query]).astype('float32')
697
  k = 5