exa-py 1.8.4__tar.gz → 1.8.6__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 exa-py might be problematic. Click here for more details.
- {exa_py-1.8.4/exa_py.egg-info → exa_py-1.8.6}/PKG-INFO +16 -14
- {exa_py-1.8.4 → exa_py-1.8.6}/README.md +6 -5
- {exa_py-1.8.4 → exa_py-1.8.6}/exa_py/api.py +135 -35
- {exa_py-1.8.4 → exa_py-1.8.6}/pyproject.toml +1 -1
- exa_py-1.8.4/PKG-INFO +0 -104
- exa_py-1.8.4/exa_py.egg-info/SOURCES.txt +0 -12
- exa_py-1.8.4/exa_py.egg-info/dependency_links.txt +0 -1
- exa_py-1.8.4/exa_py.egg-info/requires.txt +0 -3
- exa_py-1.8.4/exa_py.egg-info/top_level.txt +0 -1
- exa_py-1.8.4/setup.cfg +0 -4
- exa_py-1.8.4/setup.py +0 -30
- {exa_py-1.8.4 → exa_py-1.8.6}/exa_py/__init__.py +0 -0
- {exa_py-1.8.4 → exa_py-1.8.6}/exa_py/py.typed +0 -0
- {exa_py-1.8.4 → exa_py-1.8.6}/exa_py/utils.py +0 -0
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: exa-py
|
|
3
|
-
Version: 1.8.
|
|
3
|
+
Version: 1.8.6
|
|
4
4
|
Summary: Python SDK for Exa API.
|
|
5
|
-
|
|
6
|
-
Author: Exa
|
|
5
|
+
Author: Exa AI
|
|
7
6
|
Author-email: hello@exa.ai
|
|
8
|
-
|
|
9
|
-
Classifier:
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Typing :: Typed
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
7
|
+
Requires-Python: >=3.9,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
9
|
Classifier: Programming Language :: Python :: 3.9
|
|
14
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Requires-Dist: openai (>=1.48,<2.0)
|
|
15
|
+
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
|
16
|
+
Requires-Dist: typing-extensions (>=4.12.2,<5.0.0)
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
|
|
19
19
|
# Exa
|
|
@@ -91,14 +91,16 @@ exa = Exa(api_key="your-api-key")
|
|
|
91
91
|
# basic answer
|
|
92
92
|
response = exa.answer("This is a query to answer a question")
|
|
93
93
|
|
|
94
|
-
# answer with
|
|
95
|
-
response = exa.answer("This is a query to answer a question",
|
|
94
|
+
# answer with full text
|
|
95
|
+
response = exa.answer("This is a query to answer a question", text=True)
|
|
96
96
|
|
|
97
97
|
# answer with streaming
|
|
98
|
-
response = exa.
|
|
98
|
+
response = exa.stream_answer("This is a query to answer:")
|
|
99
99
|
|
|
100
|
-
# Print each chunk as it arrives when
|
|
100
|
+
# Print each chunk as it arrives when using the stream_answer method
|
|
101
101
|
for chunk in response:
|
|
102
|
-
print(chunk)
|
|
102
|
+
print(chunk, end='', flush=True)
|
|
103
|
+
|
|
103
104
|
```
|
|
104
105
|
|
|
106
|
+
|
|
@@ -73,14 +73,15 @@ exa = Exa(api_key="your-api-key")
|
|
|
73
73
|
# basic answer
|
|
74
74
|
response = exa.answer("This is a query to answer a question")
|
|
75
75
|
|
|
76
|
-
# answer with
|
|
77
|
-
response = exa.answer("This is a query to answer a question",
|
|
76
|
+
# answer with full text
|
|
77
|
+
response = exa.answer("This is a query to answer a question", text=True)
|
|
78
78
|
|
|
79
79
|
# answer with streaming
|
|
80
|
-
response = exa.
|
|
80
|
+
response = exa.stream_answer("This is a query to answer:")
|
|
81
81
|
|
|
82
|
-
# Print each chunk as it arrives when
|
|
82
|
+
# Print each chunk as it arrives when using the stream_answer method
|
|
83
83
|
for chunk in response:
|
|
84
|
-
print(chunk)
|
|
84
|
+
print(chunk, end='', flush=True)
|
|
85
|
+
|
|
85
86
|
```
|
|
86
87
|
|
|
@@ -17,8 +17,10 @@ from typing import (
|
|
|
17
17
|
Literal,
|
|
18
18
|
get_origin,
|
|
19
19
|
get_args,
|
|
20
|
+
Iterator,
|
|
20
21
|
)
|
|
21
22
|
from typing_extensions import TypedDict
|
|
23
|
+
import json
|
|
22
24
|
|
|
23
25
|
from openai import OpenAI
|
|
24
26
|
from openai.types.chat.chat_completion_message_param import ChatCompletionMessageParam
|
|
@@ -30,7 +32,6 @@ from exa_py.utils import (
|
|
|
30
32
|
maybe_get_query,
|
|
31
33
|
)
|
|
32
34
|
import os
|
|
33
|
-
from typing import Iterator
|
|
34
35
|
|
|
35
36
|
is_beta = os.getenv("IS_BETA") == "True"
|
|
36
37
|
|
|
@@ -517,15 +518,17 @@ class AnswerResult:
|
|
|
517
518
|
url: str
|
|
518
519
|
id: str
|
|
519
520
|
title: Optional[str] = None
|
|
520
|
-
published_date: Optional[str] = None
|
|
521
521
|
author: Optional[str] = None
|
|
522
|
+
published_date: Optional[str] = None
|
|
523
|
+
text: Optional[str] = None
|
|
522
524
|
|
|
523
525
|
def __init__(self, **kwargs):
|
|
524
|
-
self.url = kwargs[
|
|
525
|
-
self.id = kwargs[
|
|
526
|
-
self.title = kwargs.get(
|
|
527
|
-
self.
|
|
528
|
-
self.
|
|
526
|
+
self.url = kwargs['url']
|
|
527
|
+
self.id = kwargs['id']
|
|
528
|
+
self.title = kwargs.get('title')
|
|
529
|
+
self.author = kwargs.get('author')
|
|
530
|
+
self.published_date = kwargs.get('published_date')
|
|
531
|
+
self.text = kwargs.get('text')
|
|
529
532
|
|
|
530
533
|
def __str__(self):
|
|
531
534
|
return (
|
|
@@ -534,7 +537,34 @@ class AnswerResult:
|
|
|
534
537
|
f"ID: {self.id}\n"
|
|
535
538
|
f"Published Date: {self.published_date}\n"
|
|
536
539
|
f"Author: {self.author}\n"
|
|
540
|
+
f"Text: {self.text}\n\n"
|
|
537
541
|
)
|
|
542
|
+
|
|
543
|
+
@dataclass
|
|
544
|
+
class StreamChunk:
|
|
545
|
+
"""A class representing a single chunk of streaming data.
|
|
546
|
+
|
|
547
|
+
Attributes:
|
|
548
|
+
content (Optional[str]): The partial text content of the answer
|
|
549
|
+
sources (Optional[List[AnswerResult]]): List of sources if provided in this chunk
|
|
550
|
+
"""
|
|
551
|
+
content: Optional[str] = None
|
|
552
|
+
sources: Optional[List[AnswerResult]] = None
|
|
553
|
+
|
|
554
|
+
def has_data(self) -> bool:
|
|
555
|
+
"""Check if this chunk contains any data."""
|
|
556
|
+
return self.content is not None or self.sources is not None
|
|
557
|
+
|
|
558
|
+
def __str__(self) -> str:
|
|
559
|
+
"""Format the chunk data as a string."""
|
|
560
|
+
output = ""
|
|
561
|
+
if self.content:
|
|
562
|
+
output += self.content
|
|
563
|
+
if self.sources:
|
|
564
|
+
output += "\nSources:"
|
|
565
|
+
for source in self.sources:
|
|
566
|
+
output += f"\n{source}"
|
|
567
|
+
return output
|
|
538
568
|
|
|
539
569
|
|
|
540
570
|
@dataclass
|
|
@@ -550,11 +580,59 @@ class AnswerResponse:
|
|
|
550
580
|
sources: List[AnswerResult]
|
|
551
581
|
|
|
552
582
|
def __str__(self):
|
|
553
|
-
output = f"Answer: {self.answer}\n\nSources
|
|
554
|
-
|
|
583
|
+
output = f"Answer: {self.answer}\n\nSources:"
|
|
584
|
+
for source in self.sources:
|
|
585
|
+
output += f"\nTitle: {source.title}"
|
|
586
|
+
output += f"\nURL: {source.url}"
|
|
587
|
+
output += f"\nPublished: {source.published_date}"
|
|
588
|
+
output += f"\nAuthor: {source.author}"
|
|
589
|
+
if source.text:
|
|
590
|
+
output += f"\nText: {source.text}"
|
|
591
|
+
output += "\n"
|
|
555
592
|
return output
|
|
556
593
|
|
|
557
594
|
|
|
595
|
+
class StreamAnswerResponse:
|
|
596
|
+
"""A class representing a streaming answer response."""
|
|
597
|
+
def __init__(self, raw_response: requests.Response):
|
|
598
|
+
self._raw_response = raw_response
|
|
599
|
+
self._ensure_ok_status()
|
|
600
|
+
|
|
601
|
+
def _ensure_ok_status(self):
|
|
602
|
+
if self._raw_response.status_code != 200:
|
|
603
|
+
raise ValueError(
|
|
604
|
+
f"Request failed with status code {self._raw_response.status_code}: {self._raw_response.text}"
|
|
605
|
+
)
|
|
606
|
+
|
|
607
|
+
def __iter__(self) -> Iterator[StreamChunk]:
|
|
608
|
+
for line in self._raw_response.iter_lines():
|
|
609
|
+
if not line:
|
|
610
|
+
continue
|
|
611
|
+
decoded_line = line.decode("utf-8").removeprefix("data: ")
|
|
612
|
+
try:
|
|
613
|
+
chunk = json.loads(decoded_line)
|
|
614
|
+
except json.JSONDecodeError:
|
|
615
|
+
continue
|
|
616
|
+
|
|
617
|
+
content = None
|
|
618
|
+
sources = None
|
|
619
|
+
|
|
620
|
+
if "choices" in chunk and chunk["choices"]:
|
|
621
|
+
if "delta" in chunk["choices"][0]:
|
|
622
|
+
content = chunk["choices"][0]["delta"].get("content")
|
|
623
|
+
|
|
624
|
+
if "sources" in chunk and chunk["sources"] and chunk["sources"] != "null":
|
|
625
|
+
sources = [AnswerResult(**to_snake_case(s)) for s in chunk["sources"]]
|
|
626
|
+
|
|
627
|
+
stream_chunk = StreamChunk(content=content, sources=sources)
|
|
628
|
+
if stream_chunk.has_data():
|
|
629
|
+
yield stream_chunk
|
|
630
|
+
|
|
631
|
+
def close(self) -> None:
|
|
632
|
+
"""Close the underlying raw response to release the network socket."""
|
|
633
|
+
self._raw_response.close()
|
|
634
|
+
|
|
635
|
+
|
|
558
636
|
T = TypeVar("T")
|
|
559
637
|
|
|
560
638
|
|
|
@@ -608,7 +686,7 @@ class Exa:
|
|
|
608
686
|
self,
|
|
609
687
|
api_key: Optional[str],
|
|
610
688
|
base_url: str = "https://api.exa.ai",
|
|
611
|
-
user_agent: str = "exa-py 1.8.
|
|
689
|
+
user_agent: str = "exa-py 1.8.6",
|
|
612
690
|
):
|
|
613
691
|
"""Initialize the Exa client with the provided API key and optional base URL and user agent.
|
|
614
692
|
|
|
@@ -635,7 +713,7 @@ class Exa:
|
|
|
635
713
|
data (dict): The JSON payload to send.
|
|
636
714
|
|
|
637
715
|
Returns:
|
|
638
|
-
Union[dict,
|
|
716
|
+
Union[dict, requests.Response]: If streaming, returns the Response object.
|
|
639
717
|
Otherwise, returns the JSON-decoded response as a dict.
|
|
640
718
|
|
|
641
719
|
Raises:
|
|
@@ -643,9 +721,7 @@ class Exa:
|
|
|
643
721
|
"""
|
|
644
722
|
if data.get("stream"):
|
|
645
723
|
res = requests.post(self.base_url + endpoint, json=data, headers=self.headers, stream=True)
|
|
646
|
-
|
|
647
|
-
raise ValueError(f"Request failed with status code {res.status_code}: {res.text}")
|
|
648
|
-
return (line.decode("utf-8") for line in res.iter_lines() if line)
|
|
724
|
+
return res
|
|
649
725
|
|
|
650
726
|
res = requests.post(self.base_url + endpoint, json=data, headers=self.headers)
|
|
651
727
|
if res.status_code != 200:
|
|
@@ -727,6 +803,7 @@ class Exa:
|
|
|
727
803
|
livecrawl: Optional[LIVECRAWL_OPTIONS] = None,
|
|
728
804
|
filter_empty_results: Optional[bool] = None,
|
|
729
805
|
subpages: Optional[int] = None,
|
|
806
|
+
subpage_target: Optional[Union[str, List[str]]] = None,
|
|
730
807
|
extras: Optional[ExtrasOptions] = None,
|
|
731
808
|
) -> SearchResponse[ResultWithText]:
|
|
732
809
|
...
|
|
@@ -749,12 +826,11 @@ class Exa:
|
|
|
749
826
|
use_autoprompt: Optional[bool] = None,
|
|
750
827
|
type: Optional[str] = None,
|
|
751
828
|
category: Optional[str] = None,
|
|
752
|
-
flags: Optional[List[str]] = None,
|
|
753
|
-
moderation: Optional[bool] = None,
|
|
754
829
|
subpages: Optional[int] = None,
|
|
755
830
|
livecrawl_timeout: Optional[int] = None,
|
|
756
831
|
livecrawl: Optional[LIVECRAWL_OPTIONS] = None,
|
|
757
832
|
filter_empty_results: Optional[bool] = None,
|
|
833
|
+
subpage_target: Optional[Union[str, List[str]]] = None,
|
|
758
834
|
extras: Optional[ExtrasOptions] = None,
|
|
759
835
|
) -> SearchResponse[ResultWithText]:
|
|
760
836
|
...
|
|
@@ -898,8 +974,6 @@ class Exa:
|
|
|
898
974
|
category: Optional[str] = None,
|
|
899
975
|
subpages: Optional[int] = None,
|
|
900
976
|
subpage_target: Optional[Union[str, List[str]]] = None,
|
|
901
|
-
flags: Optional[List[str]] = None,
|
|
902
|
-
moderation: Optional[bool] = None,
|
|
903
977
|
livecrawl_timeout: Optional[int] = None,
|
|
904
978
|
livecrawl: Optional[LIVECRAWL_OPTIONS] = None,
|
|
905
979
|
filter_empty_results: Optional[bool] = None,
|
|
@@ -928,12 +1002,11 @@ class Exa:
|
|
|
928
1002
|
type: Optional[str] = None,
|
|
929
1003
|
category: Optional[str] = None,
|
|
930
1004
|
flags: Optional[List[str]] = None,
|
|
931
|
-
moderation: Optional[bool] = None,
|
|
932
1005
|
livecrawl_timeout: Optional[int] = None,
|
|
933
1006
|
livecrawl: Optional[LIVECRAWL_OPTIONS] = None,
|
|
1007
|
+
filter_empty_results: Optional[bool] = None,
|
|
934
1008
|
subpages: Optional[int] = None,
|
|
935
1009
|
subpage_target: Optional[Union[str, List[str]]] = None,
|
|
936
|
-
filter_empty_results: Optional[bool] = None,
|
|
937
1010
|
extras: Optional[ExtrasOptions] = None,
|
|
938
1011
|
) -> SearchResponse[ResultWithTextAndHighlightsAndSummary]:
|
|
939
1012
|
...
|
|
@@ -1581,33 +1654,36 @@ class Exa:
|
|
|
1581
1654
|
self,
|
|
1582
1655
|
query: str,
|
|
1583
1656
|
*,
|
|
1584
|
-
expanded_queries_limit: Optional[int] = 1,
|
|
1585
1657
|
stream: Optional[bool] = False,
|
|
1586
|
-
|
|
1587
|
-
) -> Union[AnswerResponse,
|
|
1658
|
+
text: Optional[bool] = False,
|
|
1659
|
+
) -> Union[AnswerResponse, StreamAnswerResponse]:
|
|
1588
1660
|
...
|
|
1589
1661
|
|
|
1590
1662
|
def answer(
|
|
1591
1663
|
self,
|
|
1592
1664
|
query: str,
|
|
1593
1665
|
*,
|
|
1594
|
-
expanded_queries_limit: Optional[int] = 1,
|
|
1595
1666
|
stream: Optional[bool] = False,
|
|
1596
|
-
|
|
1597
|
-
) -> Union[AnswerResponse,
|
|
1667
|
+
text: Optional[bool] = False,
|
|
1668
|
+
) -> Union[AnswerResponse, StreamAnswerResponse]:
|
|
1598
1669
|
"""Generate an answer to a query using Exa's search and LLM capabilities.
|
|
1599
1670
|
|
|
1600
1671
|
Args:
|
|
1601
1672
|
query (str): The query to answer.
|
|
1602
|
-
|
|
1603
|
-
stream (bool, optional): Whether to stream the response. Defaults to False.
|
|
1604
|
-
include_text (bool, optional): Whether to include full text in the results. Defaults to False.
|
|
1673
|
+
text (bool, optional): Whether to include full text in the results. Defaults to False.
|
|
1605
1674
|
|
|
1606
1675
|
Returns:
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1676
|
+
AnswerResponse: An object containing the answer and sources.
|
|
1677
|
+
|
|
1678
|
+
Raises:
|
|
1679
|
+
ValueError: If stream=True is provided. Use stream_answer() instead for streaming responses.
|
|
1610
1680
|
"""
|
|
1681
|
+
if stream:
|
|
1682
|
+
raise ValueError(
|
|
1683
|
+
"stream=True is not supported in `answer()`. "
|
|
1684
|
+
"Please use `stream_answer(...)` for streaming."
|
|
1685
|
+
)
|
|
1686
|
+
|
|
1611
1687
|
options = {
|
|
1612
1688
|
k: v
|
|
1613
1689
|
for k, v in locals().items()
|
|
@@ -1616,10 +1692,34 @@ class Exa:
|
|
|
1616
1692
|
options = to_camel_case(options)
|
|
1617
1693
|
response = self.request("/answer", options)
|
|
1618
1694
|
|
|
1619
|
-
if stream:
|
|
1620
|
-
return response
|
|
1621
|
-
|
|
1622
1695
|
return AnswerResponse(
|
|
1623
1696
|
response["answer"],
|
|
1624
1697
|
[AnswerResult(**to_snake_case(result)) for result in response["sources"]]
|
|
1625
1698
|
)
|
|
1699
|
+
|
|
1700
|
+
def stream_answer(
|
|
1701
|
+
self,
|
|
1702
|
+
query: str,
|
|
1703
|
+
*,
|
|
1704
|
+
text: bool = False,
|
|
1705
|
+
) -> StreamAnswerResponse:
|
|
1706
|
+
"""Generate a streaming answer response.
|
|
1707
|
+
|
|
1708
|
+
Args:
|
|
1709
|
+
query (str): The query to answer.
|
|
1710
|
+
text (bool): Whether to include full text in the results. Defaults to False.
|
|
1711
|
+
|
|
1712
|
+
Returns:
|
|
1713
|
+
StreamAnswerResponse: An object that can be iterated over to retrieve (partial text, partial sources).
|
|
1714
|
+
Each iteration yields a tuple of (Optional[str], Optional[List[AnswerResult]]).
|
|
1715
|
+
"""
|
|
1716
|
+
options = {
|
|
1717
|
+
k: v
|
|
1718
|
+
for k, v in locals().items()
|
|
1719
|
+
if k != "self" and v is not None
|
|
1720
|
+
}
|
|
1721
|
+
options = to_camel_case(options)
|
|
1722
|
+
options["stream"] = True
|
|
1723
|
+
raw_response = self.request("/answer", options)
|
|
1724
|
+
return StreamAnswerResponse(raw_response)
|
|
1725
|
+
|
exa_py-1.8.4/PKG-INFO
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: exa_py
|
|
3
|
-
Version: 1.8.4
|
|
4
|
-
Summary: Python SDK for Exa API.
|
|
5
|
-
Home-page: https://github.com/exa-labs/exa-py
|
|
6
|
-
Author: Exa
|
|
7
|
-
Author-email: hello@exa.ai
|
|
8
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
-
Classifier: Intended Audience :: Developers
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Typing :: Typed
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Description-Content-Type: text/markdown
|
|
18
|
-
|
|
19
|
-
# Exa
|
|
20
|
-
|
|
21
|
-
Exa (formerly Metaphor) API in Python
|
|
22
|
-
|
|
23
|
-
Note: This API is basically the same as `metaphor-python` but reflects new
|
|
24
|
-
features associated with Metaphor's rename to Exa. New site is https://exa.ai
|
|
25
|
-
|
|
26
|
-
## Installation
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
pip install exa_py
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Usage
|
|
33
|
-
|
|
34
|
-
Import the package and initialize the Exa client with your API key:
|
|
35
|
-
|
|
36
|
-
```python
|
|
37
|
-
from exa_py import Exa
|
|
38
|
-
|
|
39
|
-
exa = Exa(api_key="your-api-key")
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Common requests
|
|
43
|
-
```python
|
|
44
|
-
|
|
45
|
-
# basic search
|
|
46
|
-
results = exa.search("This is a Exa query:")
|
|
47
|
-
|
|
48
|
-
# autoprompted search
|
|
49
|
-
results = exa.search("autopromptable query", use_autoprompt=True)
|
|
50
|
-
|
|
51
|
-
# keyword search (non-neural)
|
|
52
|
-
results = exa.search("Google-style query", type="keyword")
|
|
53
|
-
|
|
54
|
-
# search with date filters
|
|
55
|
-
results = exa.search("This is a Exa query:", start_published_date="2019-01-01", end_published_date="2019-01-31")
|
|
56
|
-
|
|
57
|
-
# search with domain filters
|
|
58
|
-
results = exa.search("This is a Exa query:", include_domains=["www.cnn.com", "www.nytimes.com"])
|
|
59
|
-
|
|
60
|
-
# search and get text contents
|
|
61
|
-
results = exa.search_and_contents("This is a Exa query:")
|
|
62
|
-
|
|
63
|
-
# search and get highlights
|
|
64
|
-
results = exa.search_and_contents("This is a Exa query:", highlights=True)
|
|
65
|
-
|
|
66
|
-
# search and get contents with contents options
|
|
67
|
-
results = exa.search_and_contents("This is a Exa query:",
|
|
68
|
-
text={"include_html_tags": True, "max_characters": 1000},
|
|
69
|
-
highlights={"highlights_per_url": 2, "num_sentences": 1, "query": "This is the highlight query:"})
|
|
70
|
-
|
|
71
|
-
# find similar documents
|
|
72
|
-
results = exa.find_similar("https://example.com")
|
|
73
|
-
|
|
74
|
-
# find similar excluding source domain
|
|
75
|
-
results = exa.find_similar("https://example.com", exclude_source_domain=True)
|
|
76
|
-
|
|
77
|
-
# find similar with contents
|
|
78
|
-
results = exa.find_similar_and_contents("https://example.com", text=True, highlights=True)
|
|
79
|
-
|
|
80
|
-
# get text contents
|
|
81
|
-
results = exa.get_contents(["urls"])
|
|
82
|
-
|
|
83
|
-
# get highlights
|
|
84
|
-
results = exa.get_contents(["urls"], highlights=True)
|
|
85
|
-
|
|
86
|
-
# get contents with contents options
|
|
87
|
-
results = exa.get_contents(["urls"],
|
|
88
|
-
text={"include_html_tags": True, "max_characters": 1000},
|
|
89
|
-
highlights={"highlights_per_url": 2, "num_sentences": 1, "query": "This is the highlight query:"})
|
|
90
|
-
|
|
91
|
-
# basic answer
|
|
92
|
-
response = exa.answer("This is a query to answer a question")
|
|
93
|
-
|
|
94
|
-
# answer with expanded queries and full text
|
|
95
|
-
response = exa.answer("This is a query to answer a question", expanded_queries_limit=3, include_text=True)
|
|
96
|
-
|
|
97
|
-
# answer with streaming
|
|
98
|
-
response = exa.answer("This is a query to answer with streaming:", stream=True)
|
|
99
|
-
|
|
100
|
-
# Print each chunk as it arrives when answer streaming is enabled
|
|
101
|
-
for chunk in response:
|
|
102
|
-
print(chunk)
|
|
103
|
-
```
|
|
104
|
-
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
README.md
|
|
2
|
-
pyproject.toml
|
|
3
|
-
setup.py
|
|
4
|
-
exa_py/__init__.py
|
|
5
|
-
exa_py/api.py
|
|
6
|
-
exa_py/py.typed
|
|
7
|
-
exa_py/utils.py
|
|
8
|
-
exa_py.egg-info/PKG-INFO
|
|
9
|
-
exa_py.egg-info/SOURCES.txt
|
|
10
|
-
exa_py.egg-info/dependency_links.txt
|
|
11
|
-
exa_py.egg-info/requires.txt
|
|
12
|
-
exa_py.egg-info/top_level.txt
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
exa_py
|
exa_py-1.8.4/setup.cfg
DELETED
exa_py-1.8.4/setup.py
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from setuptools import setup, find_packages
|
|
2
|
-
|
|
3
|
-
setup(
|
|
4
|
-
name="exa_py",
|
|
5
|
-
version="1.8.4",
|
|
6
|
-
description="Python SDK for Exa API.",
|
|
7
|
-
long_description_content_type="text/markdown",
|
|
8
|
-
long_description=open("README.md").read(),
|
|
9
|
-
author="Exa",
|
|
10
|
-
author_email="hello@exa.ai",
|
|
11
|
-
package_data={"exa_py": ["py.typed"]},
|
|
12
|
-
url="https://github.com/exa-labs/exa-py",
|
|
13
|
-
packages=find_packages(),
|
|
14
|
-
install_requires=[
|
|
15
|
-
"requests",
|
|
16
|
-
"typing-extensions",
|
|
17
|
-
"openai>=1.10.0"
|
|
18
|
-
],
|
|
19
|
-
classifiers=[
|
|
20
|
-
"Development Status :: 5 - Production/Stable",
|
|
21
|
-
"Intended Audience :: Developers",
|
|
22
|
-
"License :: OSI Approved :: MIT License",
|
|
23
|
-
"Typing :: Typed",
|
|
24
|
-
"Programming Language :: Python :: 3.8",
|
|
25
|
-
"Programming Language :: Python :: 3.9",
|
|
26
|
-
"Programming Language :: Python :: 3.10",
|
|
27
|
-
"Programming Language :: Python :: 3.11",
|
|
28
|
-
"Programming Language :: Python :: 3.12",
|
|
29
|
-
],
|
|
30
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|