exa-py 1.0.1__tar.gz → 1.0.5__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.0.5/PKG-INFO +113 -0
- {exa_py-1.0.1 → exa_py-1.0.5}/exa_py/api.py +44 -42
- exa_py-1.0.5/exa_py.egg-info/PKG-INFO +113 -0
- {exa_py-1.0.1 → exa_py-1.0.5}/setup.py +7 -1
- exa_py-1.0.1/PKG-INFO +0 -13
- exa_py-1.0.1/exa_py.egg-info/PKG-INFO +0 -13
- {exa_py-1.0.1 → exa_py-1.0.5}/README.md +0 -0
- {exa_py-1.0.1 → exa_py-1.0.5}/exa_py/__init__.py +0 -0
- {exa_py-1.0.1 → exa_py-1.0.5}/exa_py.egg-info/SOURCES.txt +0 -0
- {exa_py-1.0.1 → exa_py-1.0.5}/exa_py.egg-info/dependency_links.txt +0 -0
- {exa_py-1.0.1 → exa_py-1.0.5}/exa_py.egg-info/requires.txt +0 -0
- {exa_py-1.0.1 → exa_py-1.0.5}/exa_py.egg-info/top_level.txt +0 -0
- {exa_py-1.0.1 → exa_py-1.0.5}/setup.cfg +0 -0
exa_py-1.0.5/PKG-INFO
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: exa_py
|
|
3
|
+
Version: 1.0.5
|
|
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.7
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# Exa
|
|
21
|
+
|
|
22
|
+
Exa API in Python
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install exa_py
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
Import the package and initialize the Exa client with your API key:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from exa_py import Exa
|
|
36
|
+
|
|
37
|
+
exa = Exa(api_key="your-api-key")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Search Request
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
|
|
44
|
+
response = exa.search("funny article about silicon valley tech culture",
|
|
45
|
+
num_results=5,
|
|
46
|
+
include_domains=["nytimes.com", "wsj.com"],
|
|
47
|
+
start_published_date="2023-06-12"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
for result in response.results:
|
|
51
|
+
print(result.title, result.url)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Find Similar
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
response = exa.find_similar("https://waitbutwhy.com/2014/05/fermi-paradox.html", num_results=5)
|
|
58
|
+
|
|
59
|
+
for result in response.results:
|
|
60
|
+
print(result.title, result.url)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Retrieve Document Contents
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
ids = ["8U71IlQ5DUTdsZFherhhYA", "X3wd0PbJmAvhu_DQjDKA7A"]
|
|
67
|
+
response = exa.get_contents(ids)
|
|
68
|
+
|
|
69
|
+
for content in response.contents:
|
|
70
|
+
print(content.title, content.url)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Reference
|
|
74
|
+
|
|
75
|
+
### `exa.search()`
|
|
76
|
+
|
|
77
|
+
This function performs a search on the Exa API.
|
|
78
|
+
|
|
79
|
+
#### Args
|
|
80
|
+
|
|
81
|
+
- query (str): The search query.
|
|
82
|
+
- **options**: Additional search options. Valid options are:
|
|
83
|
+
- `num_results` (int): The number of search results to return.
|
|
84
|
+
- `include_domains` (list): A list of domains to include in the search.
|
|
85
|
+
- `exclude_domains` (list): A list of domains to exclude from the search.
|
|
86
|
+
- `start_crawl_date` (str): The start date for the crawl (in YYYY-MM-DD format).
|
|
87
|
+
- `end_crawl_date` (str): The end date for the crawl (in YYYY-MM-DD format).
|
|
88
|
+
- `start_published_date` (str): The start date for when the document was published (in YYYY-MM-DD format).
|
|
89
|
+
- `end_published_date` (str): The end date for when the document was published (in YYYY-MM-DD format).
|
|
90
|
+
- `use_autoprompt` (bool): Whether to use autoprompt for the search.
|
|
91
|
+
- `type` (str): The type of search, 'keyword' or 'neural'. Default: neural
|
|
92
|
+
|
|
93
|
+
#### Returns
|
|
94
|
+
`SearchResponse`: A dataclass containing the search results.
|
|
95
|
+
|
|
96
|
+
### `exa.find_similar()`
|
|
97
|
+
|
|
98
|
+
#### Args:
|
|
99
|
+
- url (str): The base url to find similar links with.
|
|
100
|
+
- **options**: Additional search options. Valid options are:
|
|
101
|
+
- `num_results` (int): The number of search results to return.
|
|
102
|
+
- `include_domains` (list): A list of domains to include in the search.
|
|
103
|
+
- `exclude_domains` (list): A list of domains to exclude from the search.
|
|
104
|
+
- `start_crawl_date` (str): The start date for the crawl (in YYYY-MM-DD format).
|
|
105
|
+
- `end_crawl_date` (str): The end date for the crawl (in YYYY-MM-DD format).
|
|
106
|
+
- `start_published_date` (str): The start date for when the document was published (in YYYY-MM-DD format).
|
|
107
|
+
- `end_published_date` (str): The end date for when the document was published (in YYYY-MM-DD format).
|
|
108
|
+
|
|
109
|
+
#### Returns
|
|
110
|
+
`SearchResponse`: A dataclass containing the search results.
|
|
111
|
+
|
|
112
|
+
# Contribution
|
|
113
|
+
Contributions to exa-py are very welcome! Feel free to submit pull requests or raise issues.
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
import dataclasses
|
|
2
4
|
import re
|
|
3
5
|
import requests
|
|
4
6
|
from typing import (
|
|
@@ -13,6 +15,7 @@ from typing import (
|
|
|
13
15
|
Literal,
|
|
14
16
|
)
|
|
15
17
|
|
|
18
|
+
|
|
16
19
|
def snake_to_camel(snake_str: str) -> str:
|
|
17
20
|
"""Convert snake_case string to camelCase.
|
|
18
21
|
|
|
@@ -25,6 +28,7 @@ def snake_to_camel(snake_str: str) -> str:
|
|
|
25
28
|
components = snake_str.split("_")
|
|
26
29
|
return components[0] + "".join(x.title() for x in components[1:])
|
|
27
30
|
|
|
31
|
+
|
|
28
32
|
def to_camel_case(data: dict) -> dict:
|
|
29
33
|
"""Convert keys in a dictionary from snake_case to camelCase.
|
|
30
34
|
|
|
@@ -36,6 +40,7 @@ def to_camel_case(data: dict) -> dict:
|
|
|
36
40
|
"""
|
|
37
41
|
return {snake_to_camel(k): v for k, v in data.items() if v is not None}
|
|
38
42
|
|
|
43
|
+
|
|
39
44
|
def camel_to_snake(camel_str: str) -> str:
|
|
40
45
|
"""Convert camelCase string to snake_case.
|
|
41
46
|
|
|
@@ -48,6 +53,7 @@ def camel_to_snake(camel_str: str) -> str:
|
|
|
48
53
|
snake_str = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", camel_str)
|
|
49
54
|
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", snake_str).lower()
|
|
50
55
|
|
|
56
|
+
|
|
51
57
|
def to_snake_case(data: dict) -> dict:
|
|
52
58
|
"""Convert keys in a dictionary from camelCase to snake_case.
|
|
53
59
|
|
|
@@ -59,8 +65,6 @@ def to_snake_case(data: dict) -> dict:
|
|
|
59
65
|
"""
|
|
60
66
|
return {camel_to_snake(k): v for k, v in data.items()}
|
|
61
67
|
|
|
62
|
-
from dataclasses import dataclass
|
|
63
|
-
|
|
64
68
|
SEARCH_OPTIONS_TYPES = {
|
|
65
69
|
"query": str, # The query string.
|
|
66
70
|
"num_results": int, # Number of results (Default: 10, Max for basic: 10).
|
|
@@ -88,7 +92,8 @@ FIND_SIMILAR_OPTIONS_TYPES = {
|
|
|
88
92
|
"category": str,
|
|
89
93
|
}
|
|
90
94
|
|
|
91
|
-
CONTENTS_OPTIONS_TYPES = {"ids": list, "text": dict
|
|
95
|
+
CONTENTS_OPTIONS_TYPES = {"ids": list, "text": Union[dict, bool], "highlights": Union[dict, bool]}
|
|
96
|
+
|
|
92
97
|
|
|
93
98
|
def validate_search_options(
|
|
94
99
|
options: Dict[str, Optional[object]], expected: dict
|
|
@@ -115,10 +120,10 @@ class TextContentsOptions(TypedDict, total=False):
|
|
|
115
120
|
"""A class representing the options that you can specify when requesting text
|
|
116
121
|
|
|
117
122
|
Attributes:
|
|
118
|
-
|
|
123
|
+
max_characters (int): The maximum number of characters to return. Default: None (no limit).
|
|
119
124
|
include_html_tags (bool): If true, include HTML tags in the returned text. Default false.
|
|
120
125
|
"""
|
|
121
|
-
|
|
126
|
+
max_characters: int
|
|
122
127
|
include_html_tags: bool
|
|
123
128
|
|
|
124
129
|
|
|
@@ -130,6 +135,7 @@ class HighlightsContentsOptions(TypedDict, total=False):
|
|
|
130
135
|
num_sentences (int): Size of highlights to return, in sentences. Default: 5
|
|
131
136
|
highlights_per_url (int): The number of highlights to return per URL. Default: 1
|
|
132
137
|
"""
|
|
138
|
+
|
|
133
139
|
query: str
|
|
134
140
|
num_sentences: int
|
|
135
141
|
highlights_per_url: int
|
|
@@ -148,12 +154,12 @@ class _Result:
|
|
|
148
154
|
author (str, optional): If available, the author of the content.
|
|
149
155
|
"""
|
|
150
156
|
|
|
151
|
-
title: str
|
|
152
157
|
url: str
|
|
153
158
|
id: str
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
title: Optional[str] = None
|
|
160
|
+
score: Optional[float] = None
|
|
161
|
+
published_date: Optional[str] = None
|
|
162
|
+
author: Optional[str] = None
|
|
157
163
|
|
|
158
164
|
def __str__(self):
|
|
159
165
|
return (
|
|
@@ -198,7 +204,8 @@ class ResultWithText(_Result):
|
|
|
198
204
|
Attributes:
|
|
199
205
|
text (str): The text of the search result page.
|
|
200
206
|
"""
|
|
201
|
-
|
|
207
|
+
|
|
208
|
+
text: str = dataclasses.field(default_factory=str)
|
|
202
209
|
|
|
203
210
|
def __str__(self):
|
|
204
211
|
base_str = super().__str__()
|
|
@@ -214,8 +221,9 @@ class ResultWithHighlights(_Result):
|
|
|
214
221
|
highlights (List[str]): The highlights of the search result.
|
|
215
222
|
highlight_scores (List[float]): The scores of the highlights of the search result.
|
|
216
223
|
"""
|
|
217
|
-
|
|
218
|
-
|
|
224
|
+
|
|
225
|
+
highlights: List[str] = dataclasses.field(default_factory=list)
|
|
226
|
+
highlight_scores: List[float] = dataclasses.field(default_factory=list)
|
|
219
227
|
|
|
220
228
|
def __str__(self):
|
|
221
229
|
base_str = super().__str__()
|
|
@@ -235,9 +243,10 @@ class ResultWithTextAndHighlights(_Result):
|
|
|
235
243
|
highlights (List[str): The highlights of the search result.
|
|
236
244
|
highlight_scores (List[float]): The scores of the highlights of the search result.
|
|
237
245
|
"""
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
246
|
+
|
|
247
|
+
text: str = dataclasses.field(default_factory=str)
|
|
248
|
+
highlights: List[str] = dataclasses.field(default_factory=list)
|
|
249
|
+
highlight_scores: List[float] = dataclasses.field(default_factory=list)
|
|
241
250
|
|
|
242
251
|
def __str__(self):
|
|
243
252
|
base_str = super().__str__()
|
|
@@ -257,16 +266,16 @@ class SearchResponse(Generic[T]):
|
|
|
257
266
|
|
|
258
267
|
Attributes:
|
|
259
268
|
results (List[Result]): A list of search results.
|
|
260
|
-
|
|
269
|
+
autoprompt_string (str, optional): The Exa query created by the autoprompt functionality.
|
|
261
270
|
"""
|
|
262
271
|
|
|
263
272
|
results: List[T]
|
|
264
|
-
|
|
273
|
+
autoprompt_string: Optional[str]
|
|
265
274
|
|
|
266
275
|
def __str__(self):
|
|
267
276
|
output = "\n\n".join(str(result) for result in self.results)
|
|
268
|
-
if self.
|
|
269
|
-
output += f"\n\nAutoprompt String: {self.
|
|
277
|
+
if self.autoprompt_string:
|
|
278
|
+
output += f"\n\nAutoprompt String: {self.autoprompt_string}"
|
|
270
279
|
return output
|
|
271
280
|
|
|
272
281
|
|
|
@@ -290,7 +299,7 @@ def nest_fields(original_dict: Dict, fields_to_nest: List[str], new_key: str):
|
|
|
290
299
|
class Exa:
|
|
291
300
|
"""A client for interacting with Exa API."""
|
|
292
301
|
|
|
293
|
-
def __init__(self, api_key: Optional[str], base_url: str = "https://api.exa.ai"):
|
|
302
|
+
def __init__(self, api_key: Optional[str], base_url: str = "https://api.exa.ai", user_agent: str = "metaphor-python 1.0.2"):
|
|
294
303
|
"""Initialize the Exa client with the provided API key and optional base URL and user agent.
|
|
295
304
|
|
|
296
305
|
Args:
|
|
@@ -306,7 +315,7 @@ class Exa:
|
|
|
306
315
|
"API key must be provided as argument or in EXA_API_KEY environment variable"
|
|
307
316
|
)
|
|
308
317
|
self.base_url = base_url
|
|
309
|
-
self.headers = {"x-api-key": api_key}
|
|
318
|
+
self.headers = {"x-api-key": api_key, "User-Agent": user_agent}
|
|
310
319
|
|
|
311
320
|
def request(self, endpoint: str, data):
|
|
312
321
|
res = requests.post(self.base_url + endpoint, json=data, headers=self.headers)
|
|
@@ -362,8 +371,6 @@ class Exa:
|
|
|
362
371
|
self,
|
|
363
372
|
query: str,
|
|
364
373
|
*,
|
|
365
|
-
text: Optional[Literal[False]] = None,
|
|
366
|
-
highlights: Optional[Literal[False]] = None,
|
|
367
374
|
num_results: Optional[int] = None,
|
|
368
375
|
include_domains: Optional[List[str]] = None,
|
|
369
376
|
exclude_domains: Optional[List[str]] = None,
|
|
@@ -374,7 +381,7 @@ class Exa:
|
|
|
374
381
|
use_autoprompt: Optional[bool] = None,
|
|
375
382
|
type: Optional[str] = None,
|
|
376
383
|
category: Optional[str] = None,
|
|
377
|
-
) -> SearchResponse[
|
|
384
|
+
) -> SearchResponse[ResultWithText]:
|
|
378
385
|
...
|
|
379
386
|
|
|
380
387
|
@overload
|
|
@@ -383,7 +390,6 @@ class Exa:
|
|
|
383
390
|
query: str,
|
|
384
391
|
*,
|
|
385
392
|
text: Union[TextContentsOptions, Literal[True]],
|
|
386
|
-
highlights: Optional[Literal[False]] = None,
|
|
387
393
|
num_results: Optional[int] = None,
|
|
388
394
|
include_domains: Optional[List[str]] = None,
|
|
389
395
|
exclude_domains: Optional[List[str]] = None,
|
|
@@ -402,7 +408,6 @@ class Exa:
|
|
|
402
408
|
self,
|
|
403
409
|
query: str,
|
|
404
410
|
*,
|
|
405
|
-
text: Optional[Literal[False]] = None,
|
|
406
411
|
highlights: Union[HighlightsContentsOptions, Literal[True]],
|
|
407
412
|
num_results: Optional[int] = None,
|
|
408
413
|
include_domains: Optional[List[str]] = None,
|
|
@@ -443,6 +448,8 @@ class Exa:
|
|
|
443
448
|
for k, v in {"query": query, **kwargs}.items()
|
|
444
449
|
if k != "self" and v is not None
|
|
445
450
|
}
|
|
451
|
+
if "text" not in options and "highlights" not in options:
|
|
452
|
+
options["text"] = True
|
|
446
453
|
validate_search_options(
|
|
447
454
|
options, {**SEARCH_OPTIONS_TYPES, **CONTENTS_OPTIONS_TYPES}
|
|
448
455
|
)
|
|
@@ -455,37 +462,32 @@ class Exa:
|
|
|
455
462
|
)
|
|
456
463
|
|
|
457
464
|
@overload
|
|
458
|
-
def
|
|
465
|
+
def get_contents(
|
|
459
466
|
self,
|
|
460
467
|
ids: Union[str, List[str], List[_Result]],
|
|
461
|
-
|
|
462
|
-
text: Optional[Literal[False]] = None,
|
|
463
|
-
highlights: Optional[Literal[False]] = None,
|
|
464
|
-
) -> SearchResponse[_Result]:
|
|
468
|
+
) -> SearchResponse[ResultWithText]:
|
|
465
469
|
...
|
|
466
470
|
|
|
467
471
|
@overload
|
|
468
|
-
def
|
|
472
|
+
def get_contents(
|
|
469
473
|
self,
|
|
470
474
|
ids: Union[str, List[str], List[_Result]],
|
|
471
475
|
*,
|
|
472
476
|
text: Union[TextContentsOptions, Literal[True]],
|
|
473
|
-
highlights: Optional[Literal[False]] = None,
|
|
474
477
|
) -> SearchResponse[ResultWithText]:
|
|
475
478
|
...
|
|
476
479
|
|
|
477
480
|
@overload
|
|
478
|
-
def
|
|
481
|
+
def get_contents(
|
|
479
482
|
self,
|
|
480
483
|
ids: Union[str, List[str], List[_Result]],
|
|
481
484
|
*,
|
|
482
|
-
text: Optional[Literal[False]] = None,
|
|
483
485
|
highlights: Union[HighlightsContentsOptions, Literal[True]],
|
|
484
486
|
) -> SearchResponse[ResultWithHighlights]:
|
|
485
487
|
...
|
|
486
488
|
|
|
487
489
|
@overload
|
|
488
|
-
def
|
|
490
|
+
def get_contents(
|
|
489
491
|
self,
|
|
490
492
|
ids: Union[str, List[str], List[_Result]],
|
|
491
493
|
*,
|
|
@@ -494,12 +496,14 @@ class Exa:
|
|
|
494
496
|
) -> SearchResponse[ResultWithTextAndHighlights]:
|
|
495
497
|
...
|
|
496
498
|
|
|
497
|
-
def
|
|
499
|
+
def get_contents(self, ids: Union[str, List[str], List[_Result]], **kwargs):
|
|
498
500
|
options = {
|
|
499
501
|
k: v
|
|
500
502
|
for k, v in {"ids": ids, **kwargs}.items()
|
|
501
503
|
if k != "self" and v is not None
|
|
502
504
|
}
|
|
505
|
+
if "text" not in options and "highlights" not in options:
|
|
506
|
+
options["text"] = True
|
|
503
507
|
validate_search_options(options, {**CONTENTS_OPTIONS_TYPES})
|
|
504
508
|
options = to_camel_case(options)
|
|
505
509
|
data = self.request("/contents", options)
|
|
@@ -536,8 +540,6 @@ class Exa:
|
|
|
536
540
|
self,
|
|
537
541
|
url: str,
|
|
538
542
|
*,
|
|
539
|
-
text: Optional[Literal[False]] = None,
|
|
540
|
-
highlights: Optional[Literal[False]] = None,
|
|
541
543
|
num_results: Optional[int] = None,
|
|
542
544
|
include_domains: Optional[List[str]] = None,
|
|
543
545
|
exclude_domains: Optional[List[str]] = None,
|
|
@@ -547,7 +549,7 @@ class Exa:
|
|
|
547
549
|
end_published_date: Optional[str] = None,
|
|
548
550
|
exclude_source_domain: Optional[bool] = None,
|
|
549
551
|
category: Optional[str] = None,
|
|
550
|
-
) -> SearchResponse[
|
|
552
|
+
) -> SearchResponse[ResultWithText]:
|
|
551
553
|
...
|
|
552
554
|
|
|
553
555
|
@overload
|
|
@@ -556,7 +558,6 @@ class Exa:
|
|
|
556
558
|
url: str,
|
|
557
559
|
*,
|
|
558
560
|
text: Union[TextContentsOptions, Literal[True]],
|
|
559
|
-
highlights: Optional[Literal[False]] = None,
|
|
560
561
|
num_results: Optional[int] = None,
|
|
561
562
|
include_domains: Optional[List[str]] = None,
|
|
562
563
|
exclude_domains: Optional[List[str]] = None,
|
|
@@ -574,7 +575,6 @@ class Exa:
|
|
|
574
575
|
self,
|
|
575
576
|
url: str,
|
|
576
577
|
*,
|
|
577
|
-
text: Optional[Literal[False]] = None,
|
|
578
578
|
highlights: Union[HighlightsContentsOptions, Literal[True]],
|
|
579
579
|
num_results: Optional[int] = None,
|
|
580
580
|
include_domains: Optional[List[str]] = None,
|
|
@@ -613,6 +613,8 @@ class Exa:
|
|
|
613
613
|
for k, v in {"url": url, **kwargs}.items()
|
|
614
614
|
if k != "self" and v is not None
|
|
615
615
|
}
|
|
616
|
+
if "text" not in options and "highlights" not in options:
|
|
617
|
+
options["text"] = True
|
|
616
618
|
validate_search_options(
|
|
617
619
|
options, {**FIND_SIMILAR_OPTIONS_TYPES, **CONTENTS_OPTIONS_TYPES}
|
|
618
620
|
)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: exa-py
|
|
3
|
+
Version: 1.0.5
|
|
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.7
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# Exa
|
|
21
|
+
|
|
22
|
+
Exa API in Python
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install exa_py
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
Import the package and initialize the Exa client with your API key:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from exa_py import Exa
|
|
36
|
+
|
|
37
|
+
exa = Exa(api_key="your-api-key")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Search Request
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
|
|
44
|
+
response = exa.search("funny article about silicon valley tech culture",
|
|
45
|
+
num_results=5,
|
|
46
|
+
include_domains=["nytimes.com", "wsj.com"],
|
|
47
|
+
start_published_date="2023-06-12"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
for result in response.results:
|
|
51
|
+
print(result.title, result.url)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Find Similar
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
response = exa.find_similar("https://waitbutwhy.com/2014/05/fermi-paradox.html", num_results=5)
|
|
58
|
+
|
|
59
|
+
for result in response.results:
|
|
60
|
+
print(result.title, result.url)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Retrieve Document Contents
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
ids = ["8U71IlQ5DUTdsZFherhhYA", "X3wd0PbJmAvhu_DQjDKA7A"]
|
|
67
|
+
response = exa.get_contents(ids)
|
|
68
|
+
|
|
69
|
+
for content in response.contents:
|
|
70
|
+
print(content.title, content.url)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Reference
|
|
74
|
+
|
|
75
|
+
### `exa.search()`
|
|
76
|
+
|
|
77
|
+
This function performs a search on the Exa API.
|
|
78
|
+
|
|
79
|
+
#### Args
|
|
80
|
+
|
|
81
|
+
- query (str): The search query.
|
|
82
|
+
- **options**: Additional search options. Valid options are:
|
|
83
|
+
- `num_results` (int): The number of search results to return.
|
|
84
|
+
- `include_domains` (list): A list of domains to include in the search.
|
|
85
|
+
- `exclude_domains` (list): A list of domains to exclude from the search.
|
|
86
|
+
- `start_crawl_date` (str): The start date for the crawl (in YYYY-MM-DD format).
|
|
87
|
+
- `end_crawl_date` (str): The end date for the crawl (in YYYY-MM-DD format).
|
|
88
|
+
- `start_published_date` (str): The start date for when the document was published (in YYYY-MM-DD format).
|
|
89
|
+
- `end_published_date` (str): The end date for when the document was published (in YYYY-MM-DD format).
|
|
90
|
+
- `use_autoprompt` (bool): Whether to use autoprompt for the search.
|
|
91
|
+
- `type` (str): The type of search, 'keyword' or 'neural'. Default: neural
|
|
92
|
+
|
|
93
|
+
#### Returns
|
|
94
|
+
`SearchResponse`: A dataclass containing the search results.
|
|
95
|
+
|
|
96
|
+
### `exa.find_similar()`
|
|
97
|
+
|
|
98
|
+
#### Args:
|
|
99
|
+
- url (str): The base url to find similar links with.
|
|
100
|
+
- **options**: Additional search options. Valid options are:
|
|
101
|
+
- `num_results` (int): The number of search results to return.
|
|
102
|
+
- `include_domains` (list): A list of domains to include in the search.
|
|
103
|
+
- `exclude_domains` (list): A list of domains to exclude from the search.
|
|
104
|
+
- `start_crawl_date` (str): The start date for the crawl (in YYYY-MM-DD format).
|
|
105
|
+
- `end_crawl_date` (str): The end date for the crawl (in YYYY-MM-DD format).
|
|
106
|
+
- `start_published_date` (str): The start date for when the document was published (in YYYY-MM-DD format).
|
|
107
|
+
- `end_published_date` (str): The end date for when the document was published (in YYYY-MM-DD format).
|
|
108
|
+
|
|
109
|
+
#### Returns
|
|
110
|
+
`SearchResponse`: A dataclass containing the search results.
|
|
111
|
+
|
|
112
|
+
# Contribution
|
|
113
|
+
Contributions to exa-py are very welcome! Feel free to submit pull requests or raise issues.
|
|
@@ -2,8 +2,10 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name='exa_py',
|
|
5
|
-
version='1.0.
|
|
5
|
+
version='1.0.5',
|
|
6
6
|
description='Python SDK for Exa API.',
|
|
7
|
+
long_description_content_type='text/markdown',
|
|
8
|
+
long_description=open('README.md').read(),
|
|
7
9
|
author='Exa',
|
|
8
10
|
author_email='hello@exa.ai',
|
|
9
11
|
package_data={"exa_py": ["py.typed"]},
|
|
@@ -17,7 +19,11 @@ setup(
|
|
|
17
19
|
'Intended Audience :: Developers',
|
|
18
20
|
'License :: OSI Approved :: MIT License',
|
|
19
21
|
"Typing :: Typed",
|
|
22
|
+
'Programming Language :: Python :: 3.7',
|
|
20
23
|
'Programming Language :: Python :: 3.8',
|
|
21
24
|
'Programming Language :: Python :: 3.9',
|
|
25
|
+
'Programming Language :: Python :: 3.10',
|
|
26
|
+
'Programming Language :: Python :: 3.11',
|
|
27
|
+
'Programming Language :: Python :: 3.12',
|
|
22
28
|
],
|
|
23
29
|
)
|
exa_py-1.0.1/PKG-INFO
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: exa_py
|
|
3
|
-
Version: 1.0.1
|
|
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
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: exa-py
|
|
3
|
-
Version: 1.0.1
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|