webscout 4.8__tar.gz → 5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of webscout might be problematic. Click here for more details.

Files changed (91) hide show
  1. {webscout-4.8/webscout.egg-info → webscout-5.0}/PKG-INFO +25 -74
  2. {webscout-4.8 → webscout-5.0}/README.md +22 -73
  3. {webscout-4.8 → webscout-5.0}/setup.py +3 -1
  4. webscout-5.0/webscout/Agents/functioncall.py +142 -0
  5. webscout-5.0/webscout/Bing_search.py +124 -0
  6. webscout-5.0/webscout/DWEBS.py +157 -0
  7. webscout-5.0/webscout/Provider/Cloudflare.py +286 -0
  8. {webscout-4.8 → webscout-5.0}/webscout/Provider/DiscordRocks.py +5 -4
  9. {webscout-4.8 → webscout-5.0}/webscout/Provider/Farfalle.py +3 -3
  10. {webscout-4.8 → webscout-5.0}/webscout/Provider/Llama3.py +3 -3
  11. webscout-5.0/webscout/Provider/PI.py +208 -0
  12. webscout-5.0/webscout/Provider/Youchat.py +247 -0
  13. {webscout-4.8 → webscout-5.0}/webscout/Provider/__init__.py +16 -2
  14. webscout-5.0/webscout/Provider/felo_search.py +238 -0
  15. webscout-5.0/webscout/Provider/julius.py +263 -0
  16. webscout-5.0/webscout/Provider/turboseek.py +237 -0
  17. webscout-5.0/webscout/Provider/xdash.py +202 -0
  18. webscout-5.0/webscout/Provider/yep.py +258 -0
  19. {webscout-4.8 → webscout-5.0}/webscout/__init__.py +1 -59
  20. {webscout-4.8 → webscout-5.0/webscout.egg-info}/PKG-INFO +25 -74
  21. {webscout-4.8 → webscout-5.0}/webscout.egg-info/SOURCES.txt +10 -2
  22. {webscout-4.8 → webscout-5.0}/webscout.egg-info/requires.txt +2 -0
  23. webscout-4.8/webscout/Agents/functioncall.py +0 -186
  24. webscout-4.8/webscout/DWEBS.py +0 -793
  25. webscout-4.8/webscout/GoogleS.py +0 -342
  26. {webscout-4.8 → webscout-5.0}/LICENSE.md +0 -0
  27. {webscout-4.8 → webscout-5.0}/setup.cfg +0 -0
  28. {webscout-4.8 → webscout-5.0}/webscout/AIauto.py +0 -0
  29. {webscout-4.8 → webscout-5.0}/webscout/AIbase.py +0 -0
  30. {webscout-4.8 → webscout-5.0}/webscout/AIutel.py +0 -0
  31. {webscout-4.8 → webscout-5.0}/webscout/Agents/Onlinesearcher.py +0 -0
  32. {webscout-4.8 → webscout-5.0}/webscout/Agents/__init__.py +0 -0
  33. {webscout-4.8 → webscout-5.0}/webscout/Bard.py +0 -0
  34. {webscout-4.8 → webscout-5.0}/webscout/Extra/__init__.py +0 -0
  35. {webscout-4.8 → webscout-5.0}/webscout/Extra/autollama.py +0 -0
  36. {webscout-4.8 → webscout-5.0}/webscout/Extra/gguf.py +0 -0
  37. {webscout-4.8 → webscout-5.0}/webscout/Extra/weather.py +0 -0
  38. {webscout-4.8 → webscout-5.0}/webscout/Extra/weather_ascii.py +0 -0
  39. {webscout-4.8 → webscout-5.0}/webscout/LLM.py +0 -0
  40. {webscout-4.8 → webscout-5.0}/webscout/Local/__init__.py +0 -0
  41. {webscout-4.8 → webscout-5.0}/webscout/Local/_version.py +0 -0
  42. {webscout-4.8 → webscout-5.0}/webscout/Local/formats.py +0 -0
  43. {webscout-4.8 → webscout-5.0}/webscout/Local/model.py +0 -0
  44. {webscout-4.8 → webscout-5.0}/webscout/Local/rawdog.py +0 -0
  45. {webscout-4.8 → webscout-5.0}/webscout/Local/samplers.py +0 -0
  46. {webscout-4.8 → webscout-5.0}/webscout/Local/thread.py +0 -0
  47. {webscout-4.8 → webscout-5.0}/webscout/Local/utils.py +0 -0
  48. {webscout-4.8 → webscout-5.0}/webscout/Provider/Andi.py +0 -0
  49. {webscout-4.8 → webscout-5.0}/webscout/Provider/BasedGPT.py +0 -0
  50. {webscout-4.8 → webscout-5.0}/webscout/Provider/Berlin4h.py +0 -0
  51. {webscout-4.8 → webscout-5.0}/webscout/Provider/Blackboxai.py +0 -0
  52. {webscout-4.8 → webscout-5.0}/webscout/Provider/Cohere.py +0 -0
  53. {webscout-4.8 → webscout-5.0}/webscout/Provider/DARKAI.py +0 -0
  54. {webscout-4.8 → webscout-5.0}/webscout/Provider/Deepinfra.py +0 -0
  55. {webscout-4.8 → webscout-5.0}/webscout/Provider/Deepseek.py +0 -0
  56. {webscout-4.8 → webscout-5.0}/webscout/Provider/Gemini.py +0 -0
  57. {webscout-4.8 → webscout-5.0}/webscout/Provider/Groq.py +0 -0
  58. {webscout-4.8 → webscout-5.0}/webscout/Provider/Koboldai.py +0 -0
  59. {webscout-4.8 → webscout-5.0}/webscout/Provider/Llama.py +0 -0
  60. {webscout-4.8 → webscout-5.0}/webscout/Provider/OLLAMA.py +0 -0
  61. {webscout-4.8 → webscout-5.0}/webscout/Provider/Openai.py +0 -0
  62. {webscout-4.8 → webscout-5.0}/webscout/Provider/Perplexity.py +0 -0
  63. {webscout-4.8 → webscout-5.0}/webscout/Provider/Phind.py +0 -0
  64. {webscout-4.8 → webscout-5.0}/webscout/Provider/PizzaGPT.py +0 -0
  65. {webscout-4.8 → webscout-5.0}/webscout/Provider/Poe.py +0 -0
  66. {webscout-4.8 → webscout-5.0}/webscout/Provider/RUBIKSAI.py +0 -0
  67. {webscout-4.8 → webscout-5.0}/webscout/Provider/Reka.py +0 -0
  68. {webscout-4.8 → webscout-5.0}/webscout/Provider/ThinkAnyAI.py +0 -0
  69. {webscout-4.8 → webscout-5.0}/webscout/Provider/ai4chat.py +0 -0
  70. {webscout-4.8 → webscout-5.0}/webscout/Provider/koala.py +0 -0
  71. {webscout-4.8 → webscout-5.0}/webscout/Provider/liaobots.py +0 -0
  72. {webscout-4.8 → webscout-5.0}/webscout/Provider/meta.py +0 -0
  73. {webscout-4.8 → webscout-5.0}/webscout/YTdownloader.py +0 -0
  74. {webscout-4.8 → webscout-5.0}/webscout/__main__.py +0 -0
  75. {webscout-4.8 → webscout-5.0}/webscout/async_providers.py +0 -0
  76. {webscout-4.8 → webscout-5.0}/webscout/cli.py +0 -0
  77. {webscout-4.8 → webscout-5.0}/webscout/exceptions.py +0 -0
  78. {webscout-4.8 → webscout-5.0}/webscout/g4f.py +0 -0
  79. {webscout-4.8 → webscout-5.0}/webscout/models.py +0 -0
  80. {webscout-4.8 → webscout-5.0}/webscout/tempid.py +0 -0
  81. {webscout-4.8 → webscout-5.0}/webscout/transcriber.py +0 -0
  82. {webscout-4.8 → webscout-5.0}/webscout/utils.py +0 -0
  83. {webscout-4.8 → webscout-5.0}/webscout/version.py +0 -0
  84. {webscout-4.8 → webscout-5.0}/webscout/voice.py +0 -0
  85. {webscout-4.8 → webscout-5.0}/webscout/webai.py +0 -0
  86. {webscout-4.8 → webscout-5.0}/webscout/webscout_search.py +0 -0
  87. {webscout-4.8 → webscout-5.0}/webscout/webscout_search_async.py +0 -0
  88. {webscout-4.8 → webscout-5.0}/webscout/websx_search.py +0 -0
  89. {webscout-4.8 → webscout-5.0}/webscout.egg-info/dependency_links.txt +0 -0
  90. {webscout-4.8 → webscout-5.0}/webscout.egg-info/entry_points.txt +0 -0
  91. {webscout-4.8 → webscout-5.0}/webscout.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: webscout
3
- Version: 4.8
3
+ Version: 5.0
4
4
  Summary: Search for anything using Google, DuckDuckGo, brave, qwant, phind.com, Contains AI models, can transcribe yt videos, temporary email and phone number generation, has TTS support, webai (terminal gpt and open interpreter) and offline LLMs and more
5
5
  Author: OEvortex
6
6
  Author-email: helpingai5@gmail.com
@@ -64,6 +64,8 @@ Requires-Dist: yaspin
64
64
  Requires-Dist: pillow
65
65
  Requires-Dist: requests_html
66
66
  Requires-Dist: bson
67
+ Requires-Dist: cloudscraper
68
+ Requires-Dist: emoji
67
69
  Provides-Extra: dev
68
70
  Requires-Dist: ruff>=0.1.6; extra == "dev"
69
71
  Requires-Dist: pytest>=7.4.2; extra == "dev"
@@ -208,7 +210,7 @@ python -m webscout --help
208
210
 
209
211
 
210
212
  [Go To TOP](#TOP)
211
- ## YTdownloader -webscout can now download yt videos
213
+ ## YTdownloader
212
214
 
213
215
  ```python
214
216
  from os import rename, getcwd
@@ -232,7 +234,7 @@ if __name__ == "__main__":
232
234
  download_video("https://www.youtube.com/watch?v=c0tMvzB0OKw")
233
235
  ```
234
236
 
235
- ## Weather - webscout can now forcast weather
237
+ ## Weather
236
238
  1. weather
237
239
  ```python
238
240
  from webscout import weather as w
@@ -331,6 +333,7 @@ async def main() -> None:
331
333
  if __name__ == '__main__':
332
334
  asyncio.run(main())
333
335
  ```
336
+
334
337
  ## Transcriber
335
338
  The transcriber function in webscout is a handy tool that transcribes YouTube videos. Here's an example code demonstrating its usage:
336
339
  ```python
@@ -387,77 +390,25 @@ if __name__ == "__main__":
387
390
  main()
388
391
  ```
389
392
 
390
- ## DWEBS: Advanced Web Searches
391
-
392
- `DWEBS` is a standalone feature designed to perform advanced web searches with enhanced capabilities. It is particularly powerful in extracting relevant information directly from webpages and Search engine, focusing exclusively on text (web) searches. Unlike the `WEBS` , which provides a broader range of search functionalities, `DWEBS` is specifically tailored for in-depth web searches.
393
-
394
- ### Activating DWEBS
395
-
396
- To utilize the `DWEBS` feature, you must first create an instance of the `DWEBS` . This is designed to be used independently of the `WEBS` , offering a focused approach to web searches.
397
-
398
- ### Point to remember before using `DWEBS`
399
- As `DWEBS` is designed to extract relevant information directly from webpages and Search engine, It extracts html from webpages and saves them to folder named files
400
-
401
- ### Usage Example
402
-
403
- Here's a basic example of how to use the `DWEBS` :
393
+ ## GoogleS -- formerly DWEBS
404
394
  ```python
405
- from webscout import DWEBS
406
-
407
- def finalextractor(extract_webpage=True):
408
- print('---------------Here Running for GoogleSearch--------------------')
409
- # 1. Google Search
410
- google_searcher = DWEBS.GoogleSearcher()
411
- query_html_path = google_searcher.search(
412
- query='HelpingAI-9B',
413
- result_num=10,
414
- safe=False,
415
- overwrite=False,
416
- )
417
-
418
- # 2. Search Result Extraction
419
- query_results_extractor = DWEBS.QueryResultsExtractor()
420
- query_search_results = query_results_extractor.extract(query_html_path)
421
-
422
- if extract_webpage:
423
- print('---------------Batch Webpage Fetcher--------------------')
424
- # 3. Batch Webpage Fetching
425
- batch_webpage_fetcher = DWEBS.BatchWebpageFetcher()
426
- urls = [query_extracts['url'] for query_extracts in query_search_results['query_results']]
427
- url_and_html_path_list = batch_webpage_fetcher.fetch(
428
- urls,
429
- overwrite=False,
430
- output_parent=query_search_results["query"],
431
- )
432
-
433
- print('---------------Batch Webpage Extractor--------------------')
434
- # 4. Batch Webpage Content Extraction
435
- batch_webpage_content_extractor = DWEBS.BatchWebpageContentExtractor()
436
- webpageurls = [url_and_html['html_path'] for url_and_html in url_and_html_path_list]
437
- html_path_and_extracted_content_list = batch_webpage_content_extractor.extract(webpageurls)
438
-
439
- # 5. Printing Extracted Content
440
- for html_path_and_extracted_content in html_path_and_extracted_content_list:
441
- print(html_path_and_extracted_content['extracted_content'])
442
- else:
443
- # Print only search results if extract_webpage is False
444
- for result in query_search_results['query_results']:
445
- DWEBS.logger.mesg(
446
- f"{result['title']}\n"
447
- f" - {result['site']}\n"
448
- f" - {result['url']}\n"
449
- f" - {result['abstract']}\n"
450
- f"\n"
451
- )
452
-
453
- DWEBS.logger.success(f"- {len(query_search_results['query_results'])} query results")
454
- DWEBS.logger.success(f"- {len(query_search_results['related_questions'])} related questions")
455
-
456
- # Example usage:
457
- finalextractor(extract_webpage=True) # Extract webpage content
458
- finalextractor(extract_webpage=False) # Skip webpage extraction and print search results only
459
-
395
+ from webscout import GoogleS
396
+ from rich import print
397
+ searcher = GoogleS()
398
+ results = searcher.search("HelpingAI-9B", max_results=20, extract_webpage_text=False, max_extract_characters=100)
399
+ for result in results:
400
+ print(result)
460
401
  ```
402
+ ### BingS
403
+ ```python
404
+ from webscout import BingS
405
+ from rich import print
406
+ searcher = BingS()
407
+ results = searcher.search("Python development tools", max_results=30)
408
+ for result in results:
409
+ print(result)
410
+ ```
411
+
461
412
  ## Text-to-Speech:
462
413
  ```python
463
414
  from webscout import play_audio
@@ -1406,7 +1357,7 @@ from webscout import AndiSearch
1406
1357
  a = AndiSearch()
1407
1358
  print(a.chat("HelpingAI-9B"))
1408
1359
  ```
1409
- ### Function calling-bete
1360
+ ### Function calling-beta
1410
1361
  ```python
1411
1362
  import json
1412
1363
  import logging
@@ -1519,7 +1470,7 @@ if "error" not in function_call_data:
1519
1470
  else:
1520
1471
  print(f"Error: {function_call_data['error']}")
1521
1472
  ```
1522
- ### LLAMA3, pizzagpt, RUBIKSAI, Koala, Darkai, AI4Chat, Farfalle
1473
+ ### LLAMA3, pizzagpt, RUBIKSAI, Koala, Darkai, AI4Chat, Farfalle, PIAI, Felo, XDASH, Julius, YouChat, YEPCHAT, Cloudflare, TurboSeek,
1523
1474
  code similar to other provider
1524
1475
  ### `LLM`
1525
1476
  ```python
@@ -133,7 +133,7 @@ python -m webscout --help
133
133
 
134
134
 
135
135
  [Go To TOP](#TOP)
136
- ## YTdownloader -webscout can now download yt videos
136
+ ## YTdownloader
137
137
 
138
138
  ```python
139
139
  from os import rename, getcwd
@@ -157,7 +157,7 @@ if __name__ == "__main__":
157
157
  download_video("https://www.youtube.com/watch?v=c0tMvzB0OKw")
158
158
  ```
159
159
 
160
- ## Weather - webscout can now forcast weather
160
+ ## Weather
161
161
  1. weather
162
162
  ```python
163
163
  from webscout import weather as w
@@ -256,6 +256,7 @@ async def main() -> None:
256
256
  if __name__ == '__main__':
257
257
  asyncio.run(main())
258
258
  ```
259
+
259
260
  ## Transcriber
260
261
  The transcriber function in webscout is a handy tool that transcribes YouTube videos. Here's an example code demonstrating its usage:
261
262
  ```python
@@ -312,77 +313,25 @@ if __name__ == "__main__":
312
313
  main()
313
314
  ```
314
315
 
315
- ## DWEBS: Advanced Web Searches
316
-
317
- `DWEBS` is a standalone feature designed to perform advanced web searches with enhanced capabilities. It is particularly powerful in extracting relevant information directly from webpages and Search engine, focusing exclusively on text (web) searches. Unlike the `WEBS` , which provides a broader range of search functionalities, `DWEBS` is specifically tailored for in-depth web searches.
318
-
319
- ### Activating DWEBS
320
-
321
- To utilize the `DWEBS` feature, you must first create an instance of the `DWEBS` . This is designed to be used independently of the `WEBS` , offering a focused approach to web searches.
322
-
323
- ### Point to remember before using `DWEBS`
324
- As `DWEBS` is designed to extract relevant information directly from webpages and Search engine, It extracts html from webpages and saves them to folder named files
325
-
326
- ### Usage Example
327
-
328
- Here's a basic example of how to use the `DWEBS` :
316
+ ## GoogleS -- formerly DWEBS
329
317
  ```python
330
- from webscout import DWEBS
331
-
332
- def finalextractor(extract_webpage=True):
333
- print('---------------Here Running for GoogleSearch--------------------')
334
- # 1. Google Search
335
- google_searcher = DWEBS.GoogleSearcher()
336
- query_html_path = google_searcher.search(
337
- query='HelpingAI-9B',
338
- result_num=10,
339
- safe=False,
340
- overwrite=False,
341
- )
342
-
343
- # 2. Search Result Extraction
344
- query_results_extractor = DWEBS.QueryResultsExtractor()
345
- query_search_results = query_results_extractor.extract(query_html_path)
346
-
347
- if extract_webpage:
348
- print('---------------Batch Webpage Fetcher--------------------')
349
- # 3. Batch Webpage Fetching
350
- batch_webpage_fetcher = DWEBS.BatchWebpageFetcher()
351
- urls = [query_extracts['url'] for query_extracts in query_search_results['query_results']]
352
- url_and_html_path_list = batch_webpage_fetcher.fetch(
353
- urls,
354
- overwrite=False,
355
- output_parent=query_search_results["query"],
356
- )
357
-
358
- print('---------------Batch Webpage Extractor--------------------')
359
- # 4. Batch Webpage Content Extraction
360
- batch_webpage_content_extractor = DWEBS.BatchWebpageContentExtractor()
361
- webpageurls = [url_and_html['html_path'] for url_and_html in url_and_html_path_list]
362
- html_path_and_extracted_content_list = batch_webpage_content_extractor.extract(webpageurls)
363
-
364
- # 5. Printing Extracted Content
365
- for html_path_and_extracted_content in html_path_and_extracted_content_list:
366
- print(html_path_and_extracted_content['extracted_content'])
367
- else:
368
- # Print only search results if extract_webpage is False
369
- for result in query_search_results['query_results']:
370
- DWEBS.logger.mesg(
371
- f"{result['title']}\n"
372
- f" - {result['site']}\n"
373
- f" - {result['url']}\n"
374
- f" - {result['abstract']}\n"
375
- f"\n"
376
- )
377
-
378
- DWEBS.logger.success(f"- {len(query_search_results['query_results'])} query results")
379
- DWEBS.logger.success(f"- {len(query_search_results['related_questions'])} related questions")
380
-
381
- # Example usage:
382
- finalextractor(extract_webpage=True) # Extract webpage content
383
- finalextractor(extract_webpage=False) # Skip webpage extraction and print search results only
384
-
318
+ from webscout import GoogleS
319
+ from rich import print
320
+ searcher = GoogleS()
321
+ results = searcher.search("HelpingAI-9B", max_results=20, extract_webpage_text=False, max_extract_characters=100)
322
+ for result in results:
323
+ print(result)
385
324
  ```
325
+ ### BingS
326
+ ```python
327
+ from webscout import BingS
328
+ from rich import print
329
+ searcher = BingS()
330
+ results = searcher.search("Python development tools", max_results=30)
331
+ for result in results:
332
+ print(result)
333
+ ```
334
+
386
335
  ## Text-to-Speech:
387
336
  ```python
388
337
  from webscout import play_audio
@@ -1331,7 +1280,7 @@ from webscout import AndiSearch
1331
1280
  a = AndiSearch()
1332
1281
  print(a.chat("HelpingAI-9B"))
1333
1282
  ```
1334
- ### Function calling-bete
1283
+ ### Function calling-beta
1335
1284
  ```python
1336
1285
  import json
1337
1286
  import logging
@@ -1444,7 +1393,7 @@ if "error" not in function_call_data:
1444
1393
  else:
1445
1394
  print(f"Error: {function_call_data['error']}")
1446
1395
  ```
1447
- ### LLAMA3, pizzagpt, RUBIKSAI, Koala, Darkai, AI4Chat, Farfalle
1396
+ ### LLAMA3, pizzagpt, RUBIKSAI, Koala, Darkai, AI4Chat, Farfalle, PIAI, Felo, XDASH, Julius, YouChat, YEPCHAT, Cloudflare, TurboSeek,
1448
1397
  code similar to other provider
1449
1398
  ### `LLM`
1450
1399
  ```python
@@ -5,7 +5,7 @@ with open("README.md", encoding="utf-8") as f:
5
5
 
6
6
  setup(
7
7
  name="webscout",
8
- version="4.8",
8
+ version="5.0",
9
9
  description="Search for anything using Google, DuckDuckGo, brave, qwant, phind.com, Contains AI models, can transcribe yt videos, temporary email and phone number generation, has TTS support, webai (terminal gpt and open interpreter) and offline LLMs and more",
10
10
  long_description=README,
11
11
  long_description_content_type="text/markdown",
@@ -68,6 +68,8 @@ setup(
68
68
  "pillow",
69
69
  "requests_html",
70
70
  "bson",
71
+ "cloudscraper",
72
+ "emoji"
71
73
  ],
72
74
  entry_points={
73
75
  "console_scripts": [
@@ -0,0 +1,142 @@
1
+ import json
2
+ import logging
3
+ from webscout import LLAMA3, WEBS
4
+
5
+ class FunctionCallingAgent:
6
+ def __init__(self, model: str = "llama3-8b",
7
+ system_prompt: str = 'You are a helpful assistant that will always answer what the user wants',
8
+ tools: list = None):
9
+ self.LLAMA3 = LLAMA3(model=model, system=system_prompt, timeout=300)
10
+ self.tools = tools if tools is not None else []
11
+ self.webs = WEBS()
12
+
13
+ def function_call_handler(self, message_text: str) -> dict:
14
+ system_message = self._generate_system_message(message_text)
15
+ response = self.LLAMA3.chat(system_message)
16
+ # logging.info(f"Raw response: {response}")
17
+ return self._parse_function_call(response)
18
+
19
+ def _generate_system_message(self, user_message: str) -> str:
20
+ tools_description = '\n'.join([f"- {tool['function']['name']}: {tool['function'].get('description', '')}" for tool in self.tools])
21
+ return (
22
+ "You are an AI assistant capable of understanding user requests and using tools to fulfill them. "
23
+ "Always respond using the JSON format specified below, even if you're not sure about the answer. "
24
+ f"Available tools:\n{tools_description}\n\n"
25
+ "Instructions:\n"
26
+ "1. Analyze the user's request.\n"
27
+ "2. Choose the most appropriate tool based on the request.\n"
28
+ "3. Respond ONLY with a JSON object in this exact format:\n"
29
+ "{\n"
30
+ ' "tool_name": "name_of_the_tool",\n'
31
+ ' "tool_input": {\n'
32
+ ' "param1": "value1",\n'
33
+ ' "param2": "value2"\n'
34
+ " }\n"
35
+ "}\n\n"
36
+ "If you can't determine a suitable tool, use the 'general_ai' tool with the user's message as the 'question' parameter.\n\n"
37
+ f"User request: {user_message}\n\n"
38
+ "Your response (in JSON format):"
39
+ )
40
+
41
+ def _parse_function_call(self, response: str) -> dict:
42
+ try:
43
+ # Find the JSON-like part of the response
44
+ start_idx = response.find("{")
45
+ end_idx = response.rfind("}") + 1
46
+
47
+ if start_idx == -1 or end_idx == -1:
48
+ raise ValueError("No valid JSON structure found in the response.")
49
+
50
+ response_json_str = response[start_idx:end_idx]
51
+
52
+ # Attempt to load the JSON string
53
+ return json.loads(response_json_str)
54
+
55
+ except (ValueError, json.JSONDecodeError) as e:
56
+ logging.error(f"Error parsing function call: {e}")
57
+ return {"error": str(e)}
58
+
59
+ def execute_function(self, function_call_data: dict) -> str:
60
+ function_name = function_call_data.get("tool_name")
61
+ arguments = function_call_data.get("tool_input", {})
62
+
63
+ if not isinstance(arguments, dict):
64
+ logging.error("Invalid arguments format.")
65
+ return "Invalid arguments format."
66
+
67
+ logging.info(f"Executing function: {function_name} with arguments: {arguments}")
68
+
69
+ # if function_name == "web_search":
70
+ # return self._handle_web_search(arguments)
71
+ # elif function_name == "general_ai":
72
+ # return self._handle_general_ai(arguments)
73
+ # else:
74
+ # return f"Function '{function_name}' is not implemented."
75
+
76
+ # def _handle_web_search(self, arguments: dict) -> str:
77
+ # query = arguments.get("query")
78
+ # if not query:
79
+ # return "Please provide a search query."
80
+
81
+ # search_results = self.webs.text(query, max_results=3)
82
+ # formatted_results = "\n\n".join(
83
+ # f"{i+1}. {result['title']}\n{result['body']}\nURL: {result['href']}"
84
+ # for i, result in enumerate(search_results)
85
+ # )
86
+ # return f"Here's what I found:\n\n{formatted_results}"
87
+
88
+ # def _handle_general_ai(self, arguments: dict) -> str:
89
+ # question = arguments.get("question")
90
+ # if not question:
91
+ # return "Please provide a question for the AI to answer."
92
+
93
+ # response = self.LLAMA3.chat(question)
94
+ # return response
95
+
96
+ # Example usage
97
+ if __name__ == "__main__":
98
+ tools = [
99
+ {
100
+ "type": "function",
101
+ "function": {
102
+ "name": "web_search",
103
+ "description": "Search query on Google",
104
+ "parameters": {
105
+ "type": "object",
106
+ "properties": {
107
+ "query": {
108
+ "type": "string",
109
+ "description": "web search query"
110
+ }
111
+ },
112
+ "required": ["query"]
113
+ }
114
+ }
115
+ },
116
+ {
117
+ "type": "function",
118
+ "function": {
119
+ "name": "general_ai",
120
+ "description": "Use AI to answer a general question",
121
+ "parameters": {
122
+ "type": "object",
123
+ "properties": {
124
+ "question": {
125
+ "type": "string",
126
+ "description": "The question to be answered by the AI"
127
+ }
128
+ },
129
+ "required": ["question"]
130
+ }
131
+ }
132
+ }
133
+ ]
134
+
135
+ agent = FunctionCallingAgent(tools=tools)
136
+ message = "open yt"
137
+ function_call_data = agent.function_call_handler(message)
138
+ print(f"Function Call Data: {function_call_data}")
139
+
140
+ if "error" not in function_call_data:
141
+ result = agent.execute_function(function_call_data)
142
+ print(f"Function Execution Result: {result}")
@@ -0,0 +1,124 @@
1
+ from bs4 import BeautifulSoup
2
+ import requests
3
+ from typing import Dict, List, Optional, Union
4
+ from concurrent.futures import ThreadPoolExecutor, as_completed
5
+ from urllib.parse import urlparse
6
+ from termcolor import colored
7
+ import time
8
+ import random
9
+
10
+ class BingS:
11
+ """Bing search class to get search results from bing.com."""
12
+
13
+ _executor: ThreadPoolExecutor = ThreadPoolExecutor(max_workers=10)
14
+
15
+ def __init__(
16
+ self,
17
+ headers: Optional[Dict[str, str]] = None,
18
+ proxy: Optional[str] = None,
19
+ timeout: Optional[int] = 10,
20
+ ) -> None:
21
+ """Initialize the BingS object."""
22
+ self.proxy: Optional[str] = proxy
23
+ self.headers = headers if headers else {
24
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.62"
25
+ }
26
+ self.headers["Referer"] = "https://www.bing.com/"
27
+ self.client = requests.Session()
28
+ self.client.headers.update(self.headers)
29
+ self.client.proxies.update({"http": self.proxy, "https": self.proxy})
30
+ self.timeout = timeout
31
+
32
+ def __enter__(self) -> "BingS":
33
+ return self
34
+
35
+ def __exit__(self, exc_type, exc_val, exc_tb):
36
+ self.client.close()
37
+
38
+ def _get_url(
39
+ self,
40
+ method: str,
41
+ url: str,
42
+ params: Optional[Dict[str, str]] = None,
43
+ data: Optional[Union[Dict[str, str], bytes]] = None,
44
+ ) -> bytes:
45
+ try:
46
+ resp = self.client.request(method, url, params=params, data=data, timeout=self.timeout)
47
+ except Exception as ex:
48
+ raise Exception(f"{url} {type(ex).__name__}: {ex}") from ex
49
+ if resp.status_code == 200:
50
+ return resp.content
51
+ raise Exception(f"{resp.url} returned status code {resp.status_code}. {params=} {data=}")
52
+
53
+ def search(
54
+ self,
55
+ keywords: str,
56
+ region: str = "us-EN", # Bing uses us-EN
57
+ lang: str = "en",
58
+ safe: str = "off",
59
+ timelimit: Optional[str] = None, # Not directly supported by Bing
60
+ max_results: Optional[int] = None,
61
+ ) -> List[Dict[str, str]]:
62
+ """Bing text search."""
63
+ assert keywords, "keywords is mandatory"
64
+
65
+ results = []
66
+ start = 1 # Bing uses 1-based indexing for pages
67
+ while len(results) < (max_results or float('inf')):
68
+ params = {
69
+ "q": keywords,
70
+ "count": 10, # Number of results per page
71
+ "mkt": region,
72
+ "setlang": lang,
73
+ "safeSearch": safe,
74
+ "first": start, # Bing uses 'first' for pagination
75
+ }
76
+
77
+ try:
78
+ resp_content = self._get_url("GET", "https://www.bing.com/search", params=params)
79
+ soup = BeautifulSoup(resp_content, "html.parser")
80
+ result_block = soup.find_all("li", class_="b_algo")
81
+
82
+ if not result_block:
83
+ break
84
+
85
+ for result in result_block:
86
+ try:
87
+ link = result.find("a", href=True)
88
+ if link:
89
+ initial_url = link["href"]
90
+
91
+ title = result.find("h2").text if result.find("h2") else ""
92
+ description = result.find("p").text.strip() if result.find("p") else "" # Strip whitespace
93
+
94
+ # Remove 'WEB' prefix if present
95
+ if description.startswith("WEB"):
96
+ description = description[4:] # Skip the first 4 characters ('WEB ')
97
+
98
+ results.append({
99
+ "title": title,
100
+ "href": initial_url,
101
+ "abstract": description,
102
+ "index": len(results),
103
+ "type": "web",
104
+ })
105
+
106
+ if len(results) >= max_results:
107
+ return results
108
+
109
+ except Exception as e:
110
+ print(f"Error extracting result: {e}")
111
+
112
+ except Exception as e:
113
+ print(f"Error fetching URL: {e}")
114
+
115
+ start += 10
116
+
117
+ return results
118
+
119
+ if __name__ == "__main__":
120
+ from rich import print
121
+ searcher = BingS()
122
+ results = searcher.search("Python development tools", max_results=30)
123
+ for result in results:
124
+ print(result)