exa-py 1.0.14__py3-none-any.whl → 1.0.15__py3-none-any.whl

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 exa-py might be problematic. Click here for more details.

exa_py/api.py CHANGED
@@ -18,7 +18,6 @@ from typing import (
18
18
  )
19
19
  from typing_extensions import TypedDict
20
20
 
21
- import httpx
22
21
  from openai import OpenAI
23
22
  from openai.types.chat.chat_completion_message_param import ChatCompletionMessageParam
24
23
  from openai.types.chat_model import ChatModel
@@ -30,8 +29,6 @@ from exa_py.utils import (
30
29
  )
31
30
 
32
31
 
33
-
34
-
35
32
  def snake_to_camel(snake_str: str) -> str:
36
33
  """Convert snake_case string to camelCase.
37
34
 
@@ -123,6 +120,7 @@ CONTENTS_OPTIONS_TYPES = {
123
120
  "ids": [list],
124
121
  "text": [dict, bool],
125
122
  "highlights": [dict, bool],
123
+ "summary": [dict, bool],
126
124
  }
127
125
 
128
126
 
@@ -172,6 +170,14 @@ class HighlightsContentsOptions(TypedDict, total=False):
172
170
  num_sentences: int
173
171
  highlights_per_url: int
174
172
 
173
+ class SummaryContentsOptions(TypedDict, total=False):
174
+ """A class representing the options that you can specify when requesting summary
175
+
176
+ Attributes:
177
+ query (str): The query string for the summary. Summary will bias towards answering the query.
178
+ """
179
+
180
+ query: str
175
181
 
176
182
  @dataclass
177
183
  class _Result:
@@ -213,11 +219,13 @@ class Result(_Result):
213
219
  text (str, optional): The text of the search result page.
214
220
  highlights (List[str], optional): The highlights of the search result.
215
221
  highlight_scores (List[float], optional): The scores of the highlights of the search result.
222
+ summary (str, optional): The summary of the search result.
216
223
  """
217
224
 
218
225
  text: Optional[str] = None
219
226
  highlights: Optional[List[str]] = None
220
227
  highlight_scores: Optional[List[float]] = None
228
+ summary: Optional[str] = None
221
229
 
222
230
  def __str__(self):
223
231
  base_str = super().__str__()
@@ -225,6 +233,7 @@ class Result(_Result):
225
233
  f"Text: {self.text}\n"
226
234
  f"Highlights: {self.highlights}\n"
227
235
  f"Highlight Scores: {self.highlight_scores}\n"
236
+ f"Summary: {self.summary}\n"
228
237
  )
229
238
 
230
239
 
@@ -288,6 +297,86 @@ class ResultWithTextAndHighlights(_Result):
288
297
  f"Highlight Scores: {self.highlight_scores}\n"
289
298
  )
290
299
 
300
+ @dataclass
301
+ class ResultWithSummary(_Result):
302
+ """
303
+ A class representing a search result with summary present.
304
+
305
+ Attributes:
306
+ summary (str): The summary of the search result.
307
+ """
308
+
309
+ summary: str = dataclasses.field(default_factory=str)
310
+
311
+ def __str__(self):
312
+ base_str = super().__str__()
313
+ return base_str + f"Summary: {self.summary}\n"
314
+
315
+ @dataclass
316
+ class ResultWithTextAndSummary(_Result):
317
+ """
318
+ A class representing a search result with text and summary present.
319
+
320
+ Attributes:
321
+ text (str): The text of the search result page.
322
+ summary (str): The summary of the search result.
323
+ """
324
+
325
+ text: str = dataclasses.field(default_factory=str)
326
+ summary: str = dataclasses.field(default_factory=str)
327
+
328
+ def __str__(self):
329
+ base_str = super().__str__()
330
+ return base_str + f"Text: {self.text}\n" + f"Summary: {self.summary}\n"
331
+
332
+ @dataclass
333
+ class ResultWithHighlightsAndSummary(_Result):
334
+ """
335
+ A class representing a search result with highlights and summary present.
336
+
337
+ Attributes:
338
+ highlights (List[str]): The highlights of the search result.
339
+ highlight_scores (List[float]): The scores of the highlights of the search result.
340
+ summary (str): The summary of the search result.
341
+ """
342
+
343
+ highlights: List[str] = dataclasses.field(default_factory=list)
344
+ highlight_scores: List[float] = dataclasses.field(default_factory=list)
345
+ summary: str = dataclasses.field(default_factory=str)
346
+
347
+ def __str__(self):
348
+ base_str = super().__str__()
349
+ return base_str + (
350
+ f"Highlights: {self.highlights}\n"
351
+ f"Highlight Scores: {self.highlight_scores}\n"
352
+ f"Summary: {self.summary}\n"
353
+ )
354
+
355
+ @dataclass
356
+ class ResultWithTextAndHighlightsAndSummary(_Result):
357
+ """
358
+ A class representing a search result with text, highlights, and summary present.
359
+
360
+ Attributes:
361
+ text (str): The text of the search result page.
362
+ highlights (List[str]): The highlights of the search result.
363
+ highlight_scores (List[float]): The scores of the highlights of the search result.
364
+ summary (str): The summary of the search result.
365
+ """
366
+
367
+ text: str = dataclasses.field(default_factory=str)
368
+ highlights: List[str] = dataclasses.field(default_factory=list)
369
+ highlight_scores: List[float] = dataclasses.field(default_factory=list)
370
+ summary: str = dataclasses.field(default_factory=str)
371
+
372
+ def __str__(self):
373
+ base_str = super().__str__()
374
+ return base_str + (
375
+ f"Text: {self.text}\n"
376
+ f"Highlights: {self.highlights}\n"
377
+ f"Highlight Scores: {self.highlight_scores}\n"
378
+ f"Summary: {self.summary}\n"
379
+ )
291
380
 
292
381
  T = TypeVar("T")
293
382
 
@@ -335,7 +424,7 @@ class Exa:
335
424
  self,
336
425
  api_key: Optional[str],
337
426
  base_url: str = "https://api.exa.ai",
338
- user_agent: str = "exa-py 1.0.14",
427
+ user_agent: str = "exa-py 1.0.15",
339
428
  ):
340
429
  """Initialize the Exa client with the provided API key and optional base URL and user agent.
341
430
 
@@ -479,18 +568,98 @@ class Exa:
479
568
  ) -> SearchResponse[ResultWithTextAndHighlights]:
480
569
  ...
481
570
 
571
+ @overload
572
+ def search_and_contents(
573
+ self,
574
+ query: str,
575
+ *,
576
+ summary: Union[SummaryContentsOptions, Literal[True]],
577
+ num_results: Optional[int] = None,
578
+ include_domains: Optional[List[str]] = None,
579
+ exclude_domains: Optional[List[str]] = None,
580
+ start_crawl_date: Optional[str] = None,
581
+ end_crawl_date: Optional[str] = None,
582
+ start_published_date: Optional[str] = None,
583
+ end_published_date: Optional[str] = None,
584
+ use_autoprompt: Optional[bool] = None,
585
+ type: Optional[str] = None,
586
+ category: Optional[str] = None,
587
+ ) -> SearchResponse[ResultWithSummary]:
588
+ ...
589
+
590
+ @overload
591
+ def search_and_contents(
592
+ self,
593
+ query: str,
594
+ *,
595
+ text: Union[TextContentsOptions, Literal[True]],
596
+ summary: Union[SummaryContentsOptions, Literal[True]],
597
+ num_results: Optional[int] = None,
598
+ include_domains: Optional[List[str]] = None,
599
+ exclude_domains: Optional[List[str]] = None,
600
+ start_crawl_date: Optional[str] = None,
601
+ end_crawl_date: Optional[str] = None,
602
+ start_published_date: Optional[str] = None,
603
+ end_published_date: Optional[str] = None,
604
+ use_autoprompt: Optional[bool] = None,
605
+ type: Optional[str] = None,
606
+ category: Optional[str] = None,
607
+ ) -> SearchResponse[ResultWithTextAndSummary]:
608
+ ...
609
+
610
+ @overload
611
+ def search_and_contents(
612
+ self,
613
+ query: str,
614
+ *,
615
+ highlights: Union[HighlightsContentsOptions, Literal[True]],
616
+ summary: Union[SummaryContentsOptions, Literal[True]],
617
+ num_results: Optional[int] = None,
618
+ include_domains: Optional[List[str]] = None,
619
+ exclude_domains: Optional[List[str]] = None,
620
+ start_crawl_date: Optional[str] = None,
621
+ end_crawl_date: Optional[str] = None,
622
+ start_published_date: Optional[str] = None,
623
+ end_published_date: Optional[str] = None,
624
+ use_autoprompt: Optional[bool] = None,
625
+ type: Optional[str] = None,
626
+ category: Optional[str] = None,
627
+ ) -> SearchResponse[ResultWithHighlightsAndSummary]:
628
+ ...
629
+
630
+ @overload
631
+ def search_and_contents(
632
+ self,
633
+ query: str,
634
+ *,
635
+ text: Union[TextContentsOptions, Literal[True]],
636
+ highlights: Union[HighlightsContentsOptions, Literal[True]],
637
+ summary: Union[SummaryContentsOptions, Literal[True]],
638
+ num_results: Optional[int] = None,
639
+ include_domains: Optional[List[str]] = None,
640
+ exclude_domains: Optional[List[str]] = None,
641
+ start_crawl_date: Optional[str] = None,
642
+ end_crawl_date: Optional[str] = None,
643
+ start_published_date: Optional[str] = None,
644
+ end_published_date: Optional[str] = None,
645
+ use_autoprompt: Optional[bool] = None,
646
+ type: Optional[str] = None,
647
+ category: Optional[str] = None,
648
+ ) -> SearchResponse[ResultWithTextAndHighlightsAndSummary]:
649
+ ...
650
+
482
651
  def search_and_contents(self, query: str, **kwargs):
483
652
  options = {
484
653
  k: v
485
654
  for k, v in {"query": query, **kwargs}.items()
486
655
  if k != "self" and v is not None
487
656
  }
488
- if "text" not in options and "highlights" not in options:
657
+ if "text" not in options and "highlights" not in options and "summary" not in options:
489
658
  options["text"] = True
490
659
  validate_search_options(
491
660
  options, {**SEARCH_OPTIONS_TYPES, **CONTENTS_OPTIONS_TYPES}
492
661
  )
493
- options = nest_fields(options, ["text", "highlights"], "contents")
662
+ options = nest_fields(options, ["text", "highlights", "summary"], "contents")
494
663
  options = to_camel_case(options)
495
664
  data = self.request("/search", options)
496
665
  return SearchResponse(
@@ -533,13 +702,53 @@ class Exa:
533
702
  ) -> SearchResponse[ResultWithTextAndHighlights]:
534
703
  ...
535
704
 
705
+ @overload
706
+ def get_contents(
707
+ self,
708
+ ids: Union[str, List[str], List[_Result]],
709
+ *,
710
+ summary: Union[SummaryContentsOptions, Literal[True]],
711
+ ) -> SearchResponse[ResultWithSummary]:
712
+ ...
713
+
714
+ @overload
715
+ def get_contents(
716
+ self,
717
+ ids: Union[str, List[str], List[_Result]],
718
+ *,
719
+ text: Union[TextContentsOptions, Literal[True]],
720
+ summary: Union[SummaryContentsOptions, Literal[True]],
721
+ ) -> SearchResponse[ResultWithTextAndSummary]:
722
+ ...
723
+
724
+ @overload
725
+ def get_contents(
726
+ self,
727
+ ids: Union[str, List[str], List[_Result]],
728
+ *,
729
+ highlights: Union[HighlightsContentsOptions, Literal[True]],
730
+ summary: Union[SummaryContentsOptions, Literal[True]],
731
+ ) -> SearchResponse[ResultWithHighlightsAndSummary]:
732
+ ...
733
+
734
+ @overload
735
+ def get_contents(
736
+ self,
737
+ ids: Union[str, List[str], List[_Result]],
738
+ *,
739
+ text: Union[TextContentsOptions, Literal[True]],
740
+ highlights: Union[HighlightsContentsOptions, Literal[True]],
741
+ summary: Union[SummaryContentsOptions, Literal[True]],
742
+ ) -> SearchResponse[ResultWithTextAndHighlightsAndSummary]:
743
+ ...
744
+
536
745
  def get_contents(self, ids: Union[str, List[str], List[_Result]], **kwargs):
537
746
  options = {
538
747
  k: v
539
748
  for k, v in {"ids": ids, **kwargs}.items()
540
749
  if k != "self" and v is not None
541
750
  }
542
- if "text" not in options and "highlights" not in options:
751
+ if "text" not in options and "highlights" not in options and "summary" not in options:
543
752
  options["text"] = True
544
753
  validate_search_options(options, {**CONTENTS_OPTIONS_TYPES})
545
754
  options = to_camel_case(options)
@@ -644,6 +853,82 @@ class Exa:
644
853
  ) -> SearchResponse[ResultWithTextAndHighlights]:
645
854
  ...
646
855
 
856
+ @overload
857
+ def find_similar_and_contents(
858
+ self,
859
+ url: str,
860
+ *,
861
+ summary: Union[SummaryContentsOptions, Literal[True]],
862
+ num_results: Optional[int] = None,
863
+ include_domains: Optional[List[str]] = None,
864
+ exclude_domains: Optional[List[str]] = None,
865
+ start_crawl_date: Optional[str] = None,
866
+ end_crawl_date: Optional[str] = None,
867
+ start_published_date: Optional[str] = None,
868
+ end_published_date: Optional[str] = None,
869
+ exclude_source_domain: Optional[bool] = None,
870
+ category: Optional[str] = None,
871
+ ) -> SearchResponse[ResultWithSummary]:
872
+ ...
873
+
874
+ @overload
875
+ def find_similar_and_contents(
876
+ self,
877
+ url: str,
878
+ *,
879
+ text: Union[TextContentsOptions, Literal[True]],
880
+ summary: Union[SummaryContentsOptions, Literal[True]],
881
+ num_results: Optional[int] = None,
882
+ include_domains: Optional[List[str]] = None,
883
+ exclude_domains: Optional[List[str]] = None,
884
+ start_crawl_date: Optional[str] = None,
885
+ end_crawl_date: Optional[str] = None,
886
+ start_published_date: Optional[str] = None,
887
+ end_published_date: Optional[str] = None,
888
+ exclude_source_domain: Optional[bool] = None,
889
+ category: Optional[str] = None,
890
+ ) -> SearchResponse[ResultWithTextAndSummary]:
891
+ ...
892
+
893
+ @overload
894
+ def find_similar_and_contents(
895
+ self,
896
+ url: str,
897
+ *,
898
+ highlights: Union[HighlightsContentsOptions, Literal[True]],
899
+ summary: Union[SummaryContentsOptions, Literal[True]],
900
+ num_results: Optional[int] = None,
901
+ include_domains: Optional[List[str]] = None,
902
+ exclude_domains: Optional[List[str]] = None,
903
+ start_crawl_date: Optional[str] = None,
904
+ end_crawl_date: Optional[str] = None,
905
+ start_published_date: Optional[str] = None,
906
+ end_published_date: Optional[str] = None,
907
+ exclude_source_domain: Optional[bool] = None,
908
+ category: Optional[str] = None,
909
+ ) -> SearchResponse[ResultWithHighlightsAndSummary]:
910
+ ...
911
+
912
+ @overload
913
+ def find_similar_and_contents(
914
+ self,
915
+ url: str,
916
+ *,
917
+ text: Union[TextContentsOptions, Literal[True]],
918
+ highlights: Union[HighlightsContentsOptions, Literal[True]],
919
+ summary: Union[SummaryContentsOptions, Literal[True]],
920
+ num_results: Optional[int] = None,
921
+ include_domains: Optional[List[str]] = None,
922
+ exclude_domains: Optional[List[str]] = None,
923
+ start_crawl_date: Optional[str] = None,
924
+ end_crawl_date: Optional[str] = None,
925
+ start_published_date: Optional[str] = None,
926
+ end_published_date: Optional[str] = None,
927
+ exclude_source_domain: Optional[bool] = None,
928
+ category: Optional[str] = None,
929
+ ) -> SearchResponse[ResultWithTextAndHighlightsAndSummary]:
930
+ ...
931
+
647
932
  def find_similar_and_contents(self, url: str, **kwargs):
648
933
  options = {
649
934
  k: v
@@ -656,12 +941,13 @@ class Exa:
656
941
  options, {**FIND_SIMILAR_OPTIONS_TYPES, **CONTENTS_OPTIONS_TYPES}
657
942
  )
658
943
  options = to_camel_case(options)
659
- options = nest_fields(options, ["text", "highlights"], "contents")
944
+ options = nest_fields(options, ["text", "highlights", "summary"], "contents")
660
945
  data = self.request("/findSimilar", options)
661
946
  return SearchResponse(
662
947
  [Result(**to_snake_case(result)) for result in data["results"]],
663
948
  data["autopromptString"] if "autopromptString" in data else None,
664
949
  )
950
+
665
951
  def wrap(self, client: OpenAI):
666
952
  """Wrap an OpenAI client with Exa functionality.
667
953
 
@@ -767,7 +1053,7 @@ class Exa:
767
1053
  create_kwargs["tools"] = tools
768
1054
 
769
1055
  completion = create_fn(messages=messages, **create_kwargs)
770
-
1056
+
771
1057
  query = maybe_get_query(completion)
772
1058
 
773
1059
  if not query:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: exa-py
3
- Version: 1.0.14
3
+ Version: 1.0.15
4
4
  Summary: Python SDK for Exa API.
5
5
  Home-page: https://github.com/exa-labs/exa-py
6
6
  Author: Exa
@@ -0,0 +1,8 @@
1
+ exa_py/__init__.py,sha256=aVF1zB_UV3dagJ5Vn2WrdcInzibdIW61M89sjwRCU_g,29
2
+ exa_py/api.py,sha256=QT0gp-cow6aDDmHJARIgKfi-TFUngxmpr4PWKVyYZRc,38176
3
+ exa_py/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ exa_py/utils.py,sha256=Rc1FJjoR9LQ7L_OJM91Sd1GNkbHjcLyEvJENhRix6gc,2405
5
+ exa_py-1.0.15.dist-info/METADATA,sha256=agZ-1DeqIjSwZlWzrs2YOGN5DD_-QHGPMKHvgoEiFkY,3083
6
+ exa_py-1.0.15.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
7
+ exa_py-1.0.15.dist-info/top_level.txt,sha256=Mfkmscdw9HWR1PtVhU1gAiVo6DHu_tyiVdb89gfZBVI,7
8
+ exa_py-1.0.15.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- exa_py/__init__.py,sha256=aVF1zB_UV3dagJ5Vn2WrdcInzibdIW61M89sjwRCU_g,29
2
- exa_py/api.py,sha256=YGLbt-auwLRUeIRJOo3DSkM10M4eIgTNhS-nOF52YQI,27818
3
- exa_py/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- exa_py/utils.py,sha256=Rc1FJjoR9LQ7L_OJM91Sd1GNkbHjcLyEvJENhRix6gc,2405
5
- exa_py-1.0.14.dist-info/METADATA,sha256=oQKt39AT19Yhp9rVnbHq-00OtL2CDM2Kht8qksaeDtU,3083
6
- exa_py-1.0.14.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
7
- exa_py-1.0.14.dist-info/top_level.txt,sha256=Mfkmscdw9HWR1PtVhU1gAiVo6DHu_tyiVdb89gfZBVI,7
8
- exa_py-1.0.14.dist-info/RECORD,,