exa-py 1.12.0__py3-none-any.whl → 1.13.0__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 +95 -1
- exa_py/websets/types.py +8 -8
- {exa_py-1.12.0.dist-info → exa_py-1.13.0.dist-info}/METADATA +17 -33
- {exa_py-1.12.0.dist-info → exa_py-1.13.0.dist-info}/RECORD +6 -6
- {exa_py-1.12.0.dist-info → exa_py-1.13.0.dist-info}/WHEEL +2 -1
- exa_py-1.13.0.dist-info/top_level.txt +1 -0
- exa_py/websets/_generator/pydantic/BaseModel.jinja2 +0 -42
exa_py/api.py
CHANGED
|
@@ -834,6 +834,36 @@ def nest_fields(original_dict: Dict, fields_to_nest: List[str], new_key: str):
|
|
|
834
834
|
|
|
835
835
|
return original_dict
|
|
836
836
|
|
|
837
|
+
@dataclass
|
|
838
|
+
class ResearchTaskResponse:
|
|
839
|
+
"""A class representing the response for a research task.
|
|
840
|
+
|
|
841
|
+
Attributes:
|
|
842
|
+
id (str): The unique identifier for the research request.
|
|
843
|
+
status (str): Status of the research request.
|
|
844
|
+
output (Optional[Dict[str, Any]]): The answer structured as JSON, if available.
|
|
845
|
+
citations (Optional[Dict[str, List[_Result]]]): List of citations used to generate the answer, grouped by root field in the output schema.
|
|
846
|
+
"""
|
|
847
|
+
|
|
848
|
+
id: str
|
|
849
|
+
status: str
|
|
850
|
+
output: Optional[Dict[str, Any]]
|
|
851
|
+
citations: Dict[str, List[_Result]]
|
|
852
|
+
|
|
853
|
+
def __str__(self):
|
|
854
|
+
output_repr = (
|
|
855
|
+
json.dumps(self.output, indent=2, ensure_ascii=False)
|
|
856
|
+
if self.output is not None
|
|
857
|
+
else "None"
|
|
858
|
+
)
|
|
859
|
+
citations_str = "\n\n".join(str(src) for src in self.citations)
|
|
860
|
+
return (
|
|
861
|
+
f"ID: {self.id}\n"
|
|
862
|
+
f"Status: {self.status}\n"
|
|
863
|
+
f"Output: {output_repr}\n\n"
|
|
864
|
+
f"Citations:\n{citations_str}"
|
|
865
|
+
)
|
|
866
|
+
|
|
837
867
|
|
|
838
868
|
class Exa:
|
|
839
869
|
"""A client for interacting with Exa API."""
|
|
@@ -842,7 +872,7 @@ class Exa:
|
|
|
842
872
|
self,
|
|
843
873
|
api_key: Optional[str],
|
|
844
874
|
base_url: str = "https://api.exa.ai",
|
|
845
|
-
user_agent: str = "exa-py 1.12.
|
|
875
|
+
user_agent: str = "exa-py 1.12.1",
|
|
846
876
|
):
|
|
847
877
|
"""Initialize the Exa client with the provided API key and optional base URL and user agent.
|
|
848
878
|
|
|
@@ -1911,6 +1941,37 @@ class Exa:
|
|
|
1911
1941
|
raw_response = self.request("/answer", options)
|
|
1912
1942
|
return StreamAnswerResponse(raw_response)
|
|
1913
1943
|
|
|
1944
|
+
def researchTask(
|
|
1945
|
+
self,
|
|
1946
|
+
*,
|
|
1947
|
+
input_instructions: str,
|
|
1948
|
+
output_schema: Dict[str, Any],
|
|
1949
|
+
) -> ResearchTaskResponse:
|
|
1950
|
+
"""Submit a research request to Exa.
|
|
1951
|
+
|
|
1952
|
+
Args:
|
|
1953
|
+
input_instructions (str): The instructions for the research task.
|
|
1954
|
+
output_schema (Dict[str, Any]): JSON schema describing the desired answer structure.
|
|
1955
|
+
"""
|
|
1956
|
+
# Build the request payload expected by the Exa API
|
|
1957
|
+
options = {
|
|
1958
|
+
"input": {"instructions": input_instructions},
|
|
1959
|
+
"output": {"schema": output_schema},
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
response = self.request("/research/tasks", options)
|
|
1963
|
+
|
|
1964
|
+
return ResearchTaskResponse(
|
|
1965
|
+
id=response["id"],
|
|
1966
|
+
status=response["status"],
|
|
1967
|
+
output=response.get("output"),
|
|
1968
|
+
citations={
|
|
1969
|
+
key: [_Result(**to_snake_case(citation)) for citation in citations_list]
|
|
1970
|
+
for key, citations_list in response.get("citations", {}).items()
|
|
1971
|
+
},
|
|
1972
|
+
)
|
|
1973
|
+
|
|
1974
|
+
|
|
1914
1975
|
class AsyncExa(Exa):
|
|
1915
1976
|
def __init__(self, api_key: str, api_base: str = "https://api.exa.ai"):
|
|
1916
1977
|
super().__init__(api_key, api_base)
|
|
@@ -2244,3 +2305,36 @@ class AsyncExa(Exa):
|
|
|
2244
2305
|
options["stream"] = True
|
|
2245
2306
|
raw_response = await self.async_request("/answer", options)
|
|
2246
2307
|
return AsyncStreamAnswerResponse(raw_response)
|
|
2308
|
+
|
|
2309
|
+
async def researchTask(
|
|
2310
|
+
self,
|
|
2311
|
+
*,
|
|
2312
|
+
input_instructions: str,
|
|
2313
|
+
output_schema: Dict[str, Any],
|
|
2314
|
+
) -> ResearchTaskResponse:
|
|
2315
|
+
"""Asynchronously submit a research request to Exa.
|
|
2316
|
+
|
|
2317
|
+
Args:
|
|
2318
|
+
input_instructions (str): The instructions for the research task.
|
|
2319
|
+
output_schema (Dict[str, Any]): JSON schema describing the desired answer structure.
|
|
2320
|
+
|
|
2321
|
+
Returns:
|
|
2322
|
+
ResearchTaskResponse: The parsed response from the Exa API.
|
|
2323
|
+
"""
|
|
2324
|
+
# Build the request payload expected by the Exa API
|
|
2325
|
+
options = {
|
|
2326
|
+
"input": {"instructions": input_instructions},
|
|
2327
|
+
"output": {"schema": output_schema},
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
response = await self.async_request("/research/tasks", options)
|
|
2331
|
+
|
|
2332
|
+
return ResearchTaskResponse(
|
|
2333
|
+
id=response["id"],
|
|
2334
|
+
status=response["status"],
|
|
2335
|
+
output=response.get("output"),
|
|
2336
|
+
citations={
|
|
2337
|
+
key: [_Result(**to_snake_case(citation)) for citation in citations_list]
|
|
2338
|
+
for key, citations_list in response.get("citations", {}).items()
|
|
2339
|
+
},
|
|
2340
|
+
)
|
exa_py/websets/types.py
CHANGED
|
@@ -18,14 +18,14 @@ class CanceledReason(Enum):
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class CreateCriterionParameters(ExaBaseModel):
|
|
21
|
-
description: constr(min_length=1
|
|
21
|
+
description: constr(min_length=1)
|
|
22
22
|
"""
|
|
23
23
|
The description of the criterion
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class CreateEnrichmentParameters(ExaBaseModel):
|
|
28
|
-
description: constr(min_length=1
|
|
28
|
+
description: constr(min_length=1)
|
|
29
29
|
"""
|
|
30
30
|
Provide a description of the enrichment task you want to perform to each Webset Item.
|
|
31
31
|
"""
|
|
@@ -88,7 +88,7 @@ class CreateWebsetSearchParameters(ExaBaseModel):
|
|
|
88
88
|
|
|
89
89
|
The actual number of Items found may be less than this number depending on the query complexity.
|
|
90
90
|
"""
|
|
91
|
-
query: constr(min_length=1
|
|
91
|
+
query: constr(min_length=1) = Field(
|
|
92
92
|
...,
|
|
93
93
|
examples=[
|
|
94
94
|
'Marketing agencies based in the US, that focus on consumer products. Get brands worked with and city'
|
|
@@ -136,7 +136,7 @@ class CreateWebsetSearchParameters(ExaBaseModel):
|
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
class Criterion(ExaBaseModel):
|
|
139
|
-
description: constr(min_length=1
|
|
139
|
+
description: constr(min_length=1)
|
|
140
140
|
"""
|
|
141
141
|
The description of the criterion
|
|
142
142
|
"""
|
|
@@ -338,7 +338,7 @@ class Search(ExaBaseModel):
|
|
|
338
338
|
Create initial search for the Webset.
|
|
339
339
|
"""
|
|
340
340
|
|
|
341
|
-
query: constr(min_length=1
|
|
341
|
+
query: constr(min_length=1) = Field(
|
|
342
342
|
...,
|
|
343
343
|
examples=[
|
|
344
344
|
'Marketing agencies based in the US, that focus on consumer products.'
|
|
@@ -405,7 +405,7 @@ class UpdateWebhookParameters(ExaBaseModel):
|
|
|
405
405
|
|
|
406
406
|
|
|
407
407
|
class UpdateWebsetRequest(ExaBaseModel):
|
|
408
|
-
metadata: Optional[Dict[str,
|
|
408
|
+
metadata: Optional[Dict[str, str]] = None
|
|
409
409
|
"""
|
|
410
410
|
Set of key-value pairs you want to associate with this object.
|
|
411
411
|
"""
|
|
@@ -564,7 +564,7 @@ class WebsetCreatedEvent(ExaBaseModel):
|
|
|
564
564
|
|
|
565
565
|
class WebsetCustomEntity(ExaBaseModel):
|
|
566
566
|
type: Literal['custom']
|
|
567
|
-
description: constr(min_length=2
|
|
567
|
+
description: constr(min_length=2)
|
|
568
568
|
"""
|
|
569
569
|
When you decide to use a custom entity, this is the description of the entity.
|
|
570
570
|
|
|
@@ -972,7 +972,7 @@ class WebsetSearch(ExaBaseModel):
|
|
|
972
972
|
"""
|
|
973
973
|
The status of the search
|
|
974
974
|
"""
|
|
975
|
-
query: constr(min_length=1
|
|
975
|
+
query: constr(min_length=1)
|
|
976
976
|
"""
|
|
977
977
|
The query used to create the search.
|
|
978
978
|
"""
|
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: exa-py
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.13.0
|
|
4
4
|
Summary: Python SDK for Exa API.
|
|
5
|
+
Home-page: https://github.com/exa-labs/exa-py
|
|
6
|
+
Author: Exa
|
|
7
|
+
Author-email: Exa AI <hello@exa.ai>
|
|
5
8
|
License: MIT
|
|
6
|
-
Author: Exa AI
|
|
7
|
-
Author-email: hello@exa.ai
|
|
8
9
|
Requires-Python: >=3.9
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
-
Requires-Dist: httpx (>=0.28.1)
|
|
17
|
-
Requires-Dist: openai (>=1.48)
|
|
18
|
-
Requires-Dist: pydantic (>=2.10.6)
|
|
19
|
-
Requires-Dist: pytest-mock (>=3.14.0)
|
|
20
|
-
Requires-Dist: requests (>=2.32.3)
|
|
21
|
-
Requires-Dist: typing-extensions (>=4.12.2)
|
|
22
10
|
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: requests>=2.32.3
|
|
12
|
+
Requires-Dist: typing-extensions>=4.12.2
|
|
13
|
+
Requires-Dist: openai>=1.48
|
|
14
|
+
Requires-Dist: pydantic>=2.10.6
|
|
15
|
+
Requires-Dist: pytest-mock>=3.14.0
|
|
16
|
+
Requires-Dist: httpx>=0.28.1
|
|
17
|
+
Dynamic: author
|
|
18
|
+
Dynamic: home-page
|
|
23
19
|
|
|
24
20
|
# Exa
|
|
25
21
|
|
|
@@ -50,9 +46,6 @@ exa = Exa(api_key="your-api-key")
|
|
|
50
46
|
# basic search
|
|
51
47
|
results = exa.search("This is a Exa query:")
|
|
52
48
|
|
|
53
|
-
# autoprompted search
|
|
54
|
-
results = exa.search("autopromptable query", use_autoprompt=True)
|
|
55
|
-
|
|
56
49
|
# keyword search (non-neural)
|
|
57
50
|
results = exa.search("Google-style query", type="keyword")
|
|
58
51
|
|
|
@@ -65,13 +58,9 @@ exa = Exa(api_key="your-api-key")
|
|
|
65
58
|
# search and get text contents
|
|
66
59
|
results = exa.search_and_contents("This is a Exa query:")
|
|
67
60
|
|
|
68
|
-
# search and get highlights
|
|
69
|
-
results = exa.search_and_contents("This is a Exa query:", highlights=True)
|
|
70
|
-
|
|
71
61
|
# search and get contents with contents options
|
|
72
62
|
results = exa.search_and_contents("This is a Exa query:",
|
|
73
|
-
text={"include_html_tags": True, "max_characters": 1000}
|
|
74
|
-
highlights={"highlights_per_url": 2, "num_sentences": 1, "query": "This is the highlight query:"})
|
|
63
|
+
text={"include_html_tags": True, "max_characters": 1000})
|
|
75
64
|
|
|
76
65
|
# find similar documents
|
|
77
66
|
results = exa.find_similar("https://example.com")
|
|
@@ -80,18 +69,14 @@ exa = Exa(api_key="your-api-key")
|
|
|
80
69
|
results = exa.find_similar("https://example.com", exclude_source_domain=True)
|
|
81
70
|
|
|
82
71
|
# find similar with contents
|
|
83
|
-
results = exa.find_similar_and_contents("https://example.com", text=True
|
|
72
|
+
results = exa.find_similar_and_contents("https://example.com", text=True)
|
|
84
73
|
|
|
85
74
|
# get text contents
|
|
86
|
-
results = exa.get_contents(["
|
|
87
|
-
|
|
88
|
-
# get highlights
|
|
89
|
-
results = exa.get_contents(["urls"], highlights=True)
|
|
75
|
+
results = exa.get_contents(["tesla.com"])
|
|
90
76
|
|
|
91
77
|
# get contents with contents options
|
|
92
78
|
results = exa.get_contents(["urls"],
|
|
93
|
-
text={"include_html_tags": True, "max_characters": 1000}
|
|
94
|
-
highlights={"highlights_per_url": 2, "num_sentences": 1, "query": "This is the highlight query:"})
|
|
79
|
+
text={"include_html_tags": True, "max_characters": 1000})
|
|
95
80
|
|
|
96
81
|
# basic answer
|
|
97
82
|
response = exa.answer("This is a query to answer a question")
|
|
@@ -108,4 +93,3 @@ exa = Exa(api_key="your-api-key")
|
|
|
108
93
|
|
|
109
94
|
```
|
|
110
95
|
|
|
111
|
-
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
exa_py/__init__.py,sha256=M2GC9oSdoV6m2msboW0vMWWl8wrth4o6gmEV4MYLGG8,66
|
|
2
|
-
exa_py/api.py,sha256=
|
|
2
|
+
exa_py/api.py,sha256=0Xa2s-ZhOI4mynqZ6zZQW5tWwRK_SNQNUvmwhEPPk4s,87147
|
|
3
3
|
exa_py/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
exa_py/utils.py,sha256=Rc1FJjoR9LQ7L_OJM91Sd1GNkbHjcLyEvJENhRix6gc,2405
|
|
5
5
|
exa_py/websets/__init__.py,sha256=uOBAb9VrIHrPKoddGOp2ai2KgWlyUVCLMZqfbGOlboA,70
|
|
6
|
-
exa_py/websets/_generator/pydantic/BaseModel.jinja2,sha256=RUDCmPZVamoVx1WudylscYFfDhGoNNtRYlpTvKjAiuA,1276
|
|
7
6
|
exa_py/websets/client.py,sha256=GWHebkvfiGY46sIuksAhYE1RLJrHQVS2PGhlA3xbxhE,4757
|
|
7
|
+
exa_py/websets/types.py,sha256=jKnJFAHTFN55EzsusgDce-yux71zVbdSJ1m8utR4EjU,28096
|
|
8
8
|
exa_py/websets/core/__init__.py,sha256=xOyrFaqtBocMUu321Jpbk7IzIQRNZufSIGJXrKoG-Bg,323
|
|
9
9
|
exa_py/websets/core/base.py,sha256=2vCkPLEKI2K2U7d-76kqVL7qyye007iDdp15GseJN1c,3936
|
|
10
10
|
exa_py/websets/enrichments/__init__.py,sha256=5dJIEKKceUost3RnI6PpCSB3VjUCBzxseEsIXu-ZY-Y,83
|
|
@@ -13,9 +13,9 @@ exa_py/websets/items/__init__.py,sha256=DCWZJVtRmUjnMEkKdb5gW1LT9cHcb-J8lENMnyyB
|
|
|
13
13
|
exa_py/websets/items/client.py,sha256=oZoYr52WrE76Ox6GyoS9rMn7bTrIpno0FKgIWFtb57U,2796
|
|
14
14
|
exa_py/websets/searches/__init__.py,sha256=_0Zx8ES5fFTEL3T8mhLxq_xK2t0JONx6ad6AtbvClsE,77
|
|
15
15
|
exa_py/websets/searches/client.py,sha256=X3f7axWGfecmxf-2tBTX0Yf_--xToz1X8ZHbbudEzy0,1790
|
|
16
|
-
exa_py/websets/types.py,sha256=3AUOFKSKFhqKzXfnvHdj19vI7l6uxinhNpEmqHa-62w,28232
|
|
17
16
|
exa_py/websets/webhooks/__init__.py,sha256=iTPBCxFd73z4RifLQMX6iRECx_6pwlI5qscLNjMOUHE,77
|
|
18
17
|
exa_py/websets/webhooks/client.py,sha256=zsIRMTeJU65yj-zo7Zz-gG02Prtzgcx6utGFSoY4HQQ,4222
|
|
19
|
-
exa_py-1.
|
|
20
|
-
exa_py-1.
|
|
21
|
-
exa_py-1.
|
|
18
|
+
exa_py-1.13.0.dist-info/METADATA,sha256=gRNplBW67MFSW6rKGHP-i_1R6VhyNy68Yxjh4n07rsA,2726
|
|
19
|
+
exa_py-1.13.0.dist-info/WHEEL,sha256=FBI2p9UMPaLApXXRpz7jgjcaDrkbla1BGsqZ5aB70OM,97
|
|
20
|
+
exa_py-1.13.0.dist-info/top_level.txt,sha256=Mfkmscdw9HWR1PtVhU1gAiVo6DHu_tyiVdb89gfZBVI,7
|
|
21
|
+
exa_py-1.13.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
exa_py
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
{% for decorator in decorators -%}
|
|
2
|
-
{{ decorator }}
|
|
3
|
-
{% endfor -%}
|
|
4
|
-
class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comment }}{% endif %}
|
|
5
|
-
{%- if description %}
|
|
6
|
-
"""
|
|
7
|
-
{{ description | indent(4) }}
|
|
8
|
-
"""
|
|
9
|
-
{%- endif %}
|
|
10
|
-
{%- if not fields and not description %}
|
|
11
|
-
pass
|
|
12
|
-
{%- endif %}
|
|
13
|
-
{%- if config %}
|
|
14
|
-
{%- filter indent(4) %}
|
|
15
|
-
{%- endfilter %}
|
|
16
|
-
{%- endif %}
|
|
17
|
-
{%- for field in fields -%}
|
|
18
|
-
{%- if field.name == "type" and field.field %}
|
|
19
|
-
type: Literal['{{ field.default }}']
|
|
20
|
-
{%- elif field.name == "object" and field.field %}
|
|
21
|
-
object: Literal['{{ field.default }}']
|
|
22
|
-
{%- elif not field.annotated and field.field %}
|
|
23
|
-
{{ field.name }}: {{ field.type_hint }} = {{ field.field }}
|
|
24
|
-
{%- else %}
|
|
25
|
-
{%- if field.annotated %}
|
|
26
|
-
{{ field.name }}: {{ field.annotated }}
|
|
27
|
-
{%- else %}
|
|
28
|
-
{{ field.name }}: {{ field.type_hint }}
|
|
29
|
-
{%- endif %}
|
|
30
|
-
{%- if not (field.required or (field.represented_default == 'None' and field.strip_default_none)) or field.data_type.is_optional
|
|
31
|
-
%} = {{ field.represented_default }}
|
|
32
|
-
{%- endif -%}
|
|
33
|
-
{%- endif %}
|
|
34
|
-
{%- if field.docstring %}
|
|
35
|
-
"""
|
|
36
|
-
{{ field.docstring | indent(4) }}
|
|
37
|
-
"""
|
|
38
|
-
{%- endif %}
|
|
39
|
-
{%- for method in methods -%}
|
|
40
|
-
{{ method }}
|
|
41
|
-
{%- endfor -%}
|
|
42
|
-
{%- endfor -%}
|