tavily-python 0.7.18__tar.gz → 0.7.20__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.
Files changed (23) hide show
  1. {tavily_python-0.7.18 → tavily_python-0.7.20}/PKG-INFO +1 -1
  2. {tavily_python-0.7.18 → tavily_python-0.7.20}/setup.py +1 -1
  3. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily/async_tavily.py +4 -4
  4. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily/tavily.py +72 -124
  5. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily_python.egg-info/PKG-INFO +1 -1
  6. {tavily_python-0.7.18 → tavily_python-0.7.20}/LICENSE +0 -0
  7. {tavily_python-0.7.18 → tavily_python-0.7.20}/README.md +0 -0
  8. {tavily_python-0.7.18 → tavily_python-0.7.20}/setup.cfg +0 -0
  9. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily/__init__.py +0 -0
  10. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily/config.py +0 -0
  11. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily/errors.py +0 -0
  12. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily/hybrid_rag/__init__.py +0 -0
  13. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily/hybrid_rag/hybrid_rag.py +0 -0
  14. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily/utils.py +0 -0
  15. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily_python.egg-info/SOURCES.txt +0 -0
  16. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily_python.egg-info/dependency_links.txt +0 -0
  17. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily_python.egg-info/requires.txt +0 -0
  18. {tavily_python-0.7.18 → tavily_python-0.7.20}/tavily_python.egg-info/top_level.txt +0 -0
  19. {tavily_python-0.7.18 → tavily_python-0.7.20}/tests/test_crawl.py +0 -0
  20. {tavily_python-0.7.18 → tavily_python-0.7.20}/tests/test_errors.py +0 -0
  21. {tavily_python-0.7.18 → tavily_python-0.7.20}/tests/test_map.py +0 -0
  22. {tavily_python-0.7.18 → tavily_python-0.7.20}/tests/test_research.py +0 -0
  23. {tavily_python-0.7.18 → tavily_python-0.7.20}/tests/test_search.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tavily-python
3
- Version: 0.7.18
3
+ Version: 0.7.20
4
4
  Summary: Python wrapper for the Tavily API
5
5
  Home-page: https://github.com/tavily-ai/tavily-python
6
6
  Author: Tavily AI
@@ -5,7 +5,7 @@ with open('README.md', 'r', encoding='utf-8') as f:
5
5
 
6
6
  setup(
7
7
  name='tavily-python',
8
- version='0.7.18',
8
+ version='0.7.20',
9
9
  url='https://github.com/tavily-ai/tavily-python',
10
10
  author='Tavily AI',
11
11
  author_email='support@tavily.com',
@@ -157,7 +157,7 @@ class AsyncTavilyClient:
157
157
  **kwargs, # Accept custom arguments
158
158
  ) -> dict:
159
159
  """
160
- Combined search method. Set search_depth to either "basic" or "advanced".
160
+ Combined search method. Set search_depth to either "basic", "advanced", "fast", or "ultra-fast".
161
161
  """
162
162
  timeout = min(timeout, 120)
163
163
  response_dict = await self._search(query,
@@ -508,7 +508,7 @@ class AsyncTavilyClient:
508
508
 
509
509
  async def get_search_context(self,
510
510
  query: str,
511
- search_depth: Literal["basic", "advanced"] = "basic",
511
+ search_depth: Literal["basic", "advanced", "fast", "ultra-fast"] = "basic",
512
512
  topic: Literal["general", "news", "finance"] = "general",
513
513
  days: int = 7,
514
514
  max_results: int = 5,
@@ -550,7 +550,7 @@ class AsyncTavilyClient:
550
550
 
551
551
  async def qna_search(self,
552
552
  query: str,
553
- search_depth: Literal["basic", "advanced"] = "advanced",
553
+ search_depth: Literal["basic", "advanced", "fast", "ultra-fast"] = "advanced",
554
554
  topic: Literal["general", "news", "finance"] = "general",
555
555
  days: int = 7,
556
556
  max_results: int = 5,
@@ -584,7 +584,7 @@ class AsyncTavilyClient:
584
584
 
585
585
  async def get_company_info(self,
586
586
  query: str,
587
- search_depth: Literal["basic", "advanced"] = "advanced",
587
+ search_depth: Literal["basic", "advanced", "fast", "ultra-fast"] = "advanced",
588
588
  max_results: int = 5,
589
589
  timeout: float = 60,
590
590
  country: str = None,
@@ -3,7 +3,6 @@ import json
3
3
  import os
4
4
  import warnings
5
5
  from typing import Literal, Sequence, Optional, List, Union, Generator
6
- from concurrent.futures import ThreadPoolExecutor, as_completed
7
6
  from .utils import get_max_items_from_list
8
7
  from .errors import UsageLimitExceededError, InvalidAPIKeyError, MissingAPIKeyError, BadRequestError, ForbiddenError, TimeoutError
9
8
 
@@ -38,6 +37,21 @@ class TavilyClient:
38
37
  **({"X-Project-ID": tavily_project} if tavily_project else {})
39
38
  }
40
39
 
40
+ self.session = requests.Session()
41
+ self.session.headers.update(self.headers)
42
+ if self.proxies:
43
+ self.session.proxies.update(self.proxies)
44
+
45
+ def close(self):
46
+ """Close the session and release resources."""
47
+ self.session.close()
48
+
49
+ def __enter__(self):
50
+ return self
51
+
52
+ def __exit__(self, exc_type, exc_val, exc_tb):
53
+ self.close()
54
+
41
55
  def _search(self,
42
56
  query: str,
43
57
  search_depth: Literal["basic", "advanced", "fast", "ultra-fast"] = None,
@@ -89,9 +103,11 @@ class TavilyClient:
89
103
  data.update(kwargs)
90
104
 
91
105
  timeout = min(timeout, 120)
106
+ url = self.base_url + "/search"
107
+ payload = json.dumps(data)
92
108
 
93
109
  try:
94
- response = requests.post(self.base_url + "/search", data=json.dumps(data), headers=self.headers, timeout=timeout, proxies=self.proxies)
110
+ response = self.session.post(url, data=payload, timeout=timeout)
95
111
  except requests.exceptions.Timeout:
96
112
  raise TimeoutError(timeout)
97
113
 
@@ -106,13 +122,12 @@ class TavilyClient:
106
122
 
107
123
  if response.status_code == 429:
108
124
  raise UsageLimitExceededError(detail)
109
- elif response.status_code in [403,432,433]:
125
+ elif response.status_code in [403, 432, 433]:
110
126
  raise ForbiddenError(detail)
111
127
  elif response.status_code == 401:
112
128
  raise InvalidAPIKeyError(detail)
113
129
  elif response.status_code == 400:
114
130
  raise BadRequestError(detail)
115
-
116
131
  else:
117
132
  raise response.raise_for_status()
118
133
 
@@ -160,13 +175,8 @@ class TavilyClient:
160
175
  auto_parameters=auto_parameters,
161
176
  include_favicon=include_favicon,
162
177
  include_usage=include_usage,
163
- **kwargs,
164
- )
165
-
166
- tavily_results = response_dict.get("results", [])
167
-
168
- response_dict["results"] = tavily_results
169
-
178
+ **kwargs)
179
+ response_dict.setdefault("results", [])
170
180
  return response_dict
171
181
 
172
182
  def _extract(self,
@@ -202,7 +212,7 @@ class TavilyClient:
202
212
  data.update(kwargs)
203
213
 
204
214
  try:
205
- response = requests.post(self.base_url + "/extract", data=json.dumps(data), headers=self.headers, timeout=timeout, proxies=self.proxies)
215
+ response = self.session.post(self.base_url + "/extract", data=json.dumps(data), timeout=timeout)
206
216
  except requests.exceptions.Timeout:
207
217
  raise TimeoutError(timeout)
208
218
 
@@ -217,7 +227,7 @@ class TavilyClient:
217
227
 
218
228
  if response.status_code == 429:
219
229
  raise UsageLimitExceededError(detail)
220
- elif response.status_code in [403,432,433]:
230
+ elif response.status_code in [403, 432, 433]:
221
231
  raise ForbiddenError(detail)
222
232
  elif response.status_code == 401:
223
233
  raise InvalidAPIKeyError(detail)
@@ -251,13 +261,8 @@ class TavilyClient:
251
261
  query=query,
252
262
  chunks_per_source=chunks_per_source,
253
263
  **kwargs)
254
-
255
- tavily_results = response_dict.get("results", [])
256
- failed_results = response_dict.get("failed_results", [])
257
-
258
- response_dict["results"] = tavily_results
259
- response_dict["failed_results"] = failed_results
260
-
264
+ response_dict.setdefault("results", [])
265
+ response_dict.setdefault("failed_results", [])
261
266
  return response_dict
262
267
 
263
268
  def _crawl(self,
@@ -310,8 +315,7 @@ class TavilyClient:
310
315
  data = {k: v for k, v in data.items() if v is not None}
311
316
 
312
317
  try:
313
- response = requests.post(
314
- self.base_url + "/crawl", data=json.dumps(data), headers=self.headers, timeout=timeout, proxies=self.proxies)
318
+ response = self.session.post(self.base_url + "/crawl", data=json.dumps(data), timeout=timeout)
315
319
  except requests.exceptions.Timeout:
316
320
  raise TimeoutError(timeout)
317
321
 
@@ -326,7 +330,7 @@ class TavilyClient:
326
330
 
327
331
  if response.status_code == 429:
328
332
  raise UsageLimitExceededError(detail)
329
- elif response.status_code in [403,432,433]:
333
+ elif response.status_code in [403, 432, 433]:
330
334
  raise ForbiddenError(detail)
331
335
  elif response.status_code == 401:
332
336
  raise InvalidAPIKeyError(detail)
@@ -359,26 +363,24 @@ class TavilyClient:
359
363
  Combined crawl method.
360
364
  include_favicon: If True, include the favicon in the crawl results.
361
365
  """
362
- response_dict = self._crawl(url,
363
- max_depth=max_depth,
364
- max_breadth=max_breadth,
365
- limit=limit,
366
- instructions=instructions,
367
- select_paths=select_paths,
368
- select_domains=select_domains,
369
- exclude_paths=exclude_paths,
370
- exclude_domains=exclude_domains,
371
- allow_external=allow_external,
372
- include_images=include_images,
373
- extract_depth=extract_depth,
374
- format=format,
375
- timeout=timeout,
376
- include_favicon=include_favicon,
377
- include_usage=include_usage,
378
- chunks_per_source=chunks_per_source,
379
- **kwargs)
380
-
381
- return response_dict
366
+ return self._crawl(url,
367
+ max_depth=max_depth,
368
+ max_breadth=max_breadth,
369
+ limit=limit,
370
+ instructions=instructions,
371
+ select_paths=select_paths,
372
+ select_domains=select_domains,
373
+ exclude_paths=exclude_paths,
374
+ exclude_domains=exclude_domains,
375
+ allow_external=allow_external,
376
+ include_images=include_images,
377
+ extract_depth=extract_depth,
378
+ format=format,
379
+ timeout=timeout,
380
+ include_favicon=include_favicon,
381
+ include_usage=include_usage,
382
+ chunks_per_source=chunks_per_source,
383
+ **kwargs)
382
384
 
383
385
  def _map(self,
384
386
  url: str,
@@ -421,8 +423,7 @@ class TavilyClient:
421
423
  data = {k: v for k, v in data.items() if v is not None}
422
424
 
423
425
  try:
424
- response = requests.post(
425
- self.base_url + "/map", data=json.dumps(data), headers=self.headers, timeout=timeout, proxies=self.proxies)
426
+ response = self.session.post(self.base_url + "/map", data=json.dumps(data), timeout=timeout)
426
427
  except requests.exceptions.Timeout:
427
428
  raise TimeoutError(timeout)
428
429
 
@@ -437,7 +438,7 @@ class TavilyClient:
437
438
 
438
439
  if response.status_code == 429:
439
440
  raise UsageLimitExceededError(detail)
440
- elif response.status_code in [403,432,433]:
441
+ elif response.status_code in [403, 432, 433]:
441
442
  raise ForbiddenError(detail)
442
443
  elif response.status_code == 401:
443
444
  raise InvalidAPIKeyError(detail)
@@ -466,26 +467,24 @@ class TavilyClient:
466
467
  Combined map method.
467
468
 
468
469
  """
469
- response_dict = self._map(url,
470
- max_depth=max_depth,
471
- max_breadth=max_breadth,
472
- limit=limit,
473
- instructions=instructions,
474
- select_paths=select_paths,
475
- select_domains=select_domains,
476
- exclude_paths=exclude_paths,
477
- exclude_domains=exclude_domains,
478
- allow_external=allow_external,
479
- include_images=include_images,
480
- timeout=timeout,
481
- include_usage=include_usage,
482
- **kwargs)
483
-
484
- return response_dict
470
+ return self._map(url,
471
+ max_depth=max_depth,
472
+ max_breadth=max_breadth,
473
+ limit=limit,
474
+ instructions=instructions,
475
+ select_paths=select_paths,
476
+ select_domains=select_domains,
477
+ exclude_paths=exclude_paths,
478
+ exclude_domains=exclude_domains,
479
+ allow_external=allow_external,
480
+ include_images=include_images,
481
+ timeout=timeout,
482
+ include_usage=include_usage,
483
+ **kwargs)
485
484
 
486
485
  def get_search_context(self,
487
486
  query: str,
488
- search_depth: Literal["basic", "advanced"] = "basic",
487
+ search_depth: Literal["basic", "advanced", "fast", "ultra-fast"] = "basic",
489
488
  topic: Literal["general", "news", "finance"] = "general",
490
489
  days: int = 7,
491
490
  max_results: int = 5,
@@ -530,7 +529,7 @@ class TavilyClient:
530
529
 
531
530
  def qna_search(self,
532
531
  query: str,
533
- search_depth: Literal["basic", "advanced"] = "advanced",
532
+ search_depth: Literal["basic", "advanced", "fast", "ultra-fast"] = "advanced",
534
533
  topic: Literal["general", "news", "finance"] = "general",
535
534
  days: int = 7,
536
535
  max_results: int = 5,
@@ -563,45 +562,6 @@ class TavilyClient:
563
562
  )
564
563
  return response_dict.get("answer", "")
565
564
 
566
- def get_company_info(self,
567
- query: str,
568
- search_depth: Literal["basic",
569
- "advanced"] = "advanced",
570
- max_results: int = 5,
571
- timeout: float = 60,
572
- country: str = None,
573
- ) -> Sequence[dict]:
574
- """ Company information search method. Search depth is advanced by default to get the best answer. """
575
- warnings.warn("get_company_info is deprecated and will be removed in future versions.",
576
- DeprecationWarning, stacklevel=2)
577
- def _perform_search(topic):
578
- return self._search(query,
579
- search_depth=search_depth,
580
- topic=topic,
581
- max_results=max_results,
582
- include_answer=False,
583
- timeout=timeout,
584
- country=country)
585
-
586
- with ThreadPoolExecutor() as executor:
587
- # Initiate the search for each topic in parallel
588
- future_to_topic = {executor.submit(_perform_search, topic): topic for topic in
589
- ["news", "general", "finance"]}
590
-
591
- all_results = []
592
-
593
- # Process the results as they become available
594
- for future in as_completed(future_to_topic):
595
- data = future.result()
596
- if 'results' in data:
597
- all_results.extend(data['results'])
598
-
599
- # Sort all the results by score in descending order and take the top 'max_results' items
600
- sorted_results = sorted(all_results, key=lambda x: x['score'], reverse=True)[
601
- :max_results]
602
-
603
- return sorted_results
604
-
605
565
  def _research(self,
606
566
  input: str,
607
567
  model: Literal["mini", "pro", "auto"] = None,
@@ -629,12 +589,10 @@ class TavilyClient:
629
589
 
630
590
  if stream:
631
591
  try:
632
- response = requests.post(
592
+ response = self.session.post(
633
593
  self.base_url + "/research",
634
594
  data=json.dumps(data),
635
- headers=self.headers,
636
595
  timeout=timeout,
637
- proxies=self.proxies,
638
596
  stream=True
639
597
  )
640
598
  except requests.exceptions.Timeout:
@@ -649,7 +607,7 @@ class TavilyClient:
649
607
 
650
608
  if response.status_code == 429:
651
609
  raise UsageLimitExceededError(detail)
652
- elif response.status_code in [403,432,433]:
610
+ elif response.status_code in [403, 432, 433]:
653
611
  raise ForbiddenError(detail)
654
612
  elif response.status_code == 401:
655
613
  raise InvalidAPIKeyError(detail)
@@ -669,12 +627,10 @@ class TavilyClient:
669
627
  return stream_generator()
670
628
  else:
671
629
  try:
672
- response = requests.post(
630
+ response = self.session.post(
673
631
  self.base_url + "/research",
674
632
  data=json.dumps(data),
675
- headers=self.headers,
676
- timeout=timeout,
677
- proxies=self.proxies
633
+ timeout=timeout
678
634
  )
679
635
  except requests.exceptions.Timeout:
680
636
  raise TimeoutError(timeout)
@@ -690,7 +646,7 @@ class TavilyClient:
690
646
 
691
647
  if response.status_code == 429:
692
648
  raise UsageLimitExceededError(detail)
693
- elif response.status_code in [403,432,433]:
649
+ elif response.status_code in [403, 432, 433]:
694
650
  raise ForbiddenError(detail)
695
651
  elif response.status_code == 401:
696
652
  raise InvalidAPIKeyError(detail)
@@ -724,8 +680,7 @@ class TavilyClient:
724
680
  dict: Response containing request_id, created_at, status, input, and model.
725
681
  """
726
682
 
727
-
728
- response_dict = self._research(
683
+ return self._research(
729
684
  input=input,
730
685
  model=model,
731
686
  output_schema=output_schema,
@@ -735,8 +690,6 @@ class TavilyClient:
735
690
  **kwargs
736
691
  )
737
692
 
738
- return response_dict
739
-
740
693
  def get_research(self,
741
694
  request_id: str
742
695
  ) -> dict:
@@ -750,17 +703,12 @@ class TavilyClient:
750
703
  dict: Research response containing request_id, created_at, completed_at, status, content, and sources.
751
704
  """
752
705
  try:
753
- response = requests.get(
754
- self.base_url + f"/research/{request_id}",
755
- headers=self.headers,
756
- proxies=self.proxies,
757
- )
706
+ response = self.session.get(self.base_url + f"/research/{request_id}")
758
707
  except Exception as e:
759
708
  raise Exception(f"Error getting research: {e}")
760
709
 
761
710
  if response.status_code in (200, 202):
762
- data = response.json()
763
- return data
711
+ return response.json()
764
712
  else:
765
713
  detail = ""
766
714
  try:
@@ -770,7 +718,7 @@ class TavilyClient:
770
718
 
771
719
  if response.status_code == 429:
772
720
  raise UsageLimitExceededError(detail)
773
- elif response.status_code in [403,432,433]:
721
+ elif response.status_code in [403, 432, 433]:
774
722
  raise ForbiddenError(detail)
775
723
  elif response.status_code == 401:
776
724
  raise InvalidAPIKeyError(detail)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tavily-python
3
- Version: 0.7.18
3
+ Version: 0.7.20
4
4
  Summary: Python wrapper for the Tavily API
5
5
  Home-page: https://github.com/tavily-ai/tavily-python
6
6
  Author: Tavily AI
File without changes
File without changes
File without changes