exa-py 1.14.9__py3-none-any.whl → 1.14.11__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 +391 -143
- exa_py/research/client.py +18 -4
- exa_py/utils.py +2 -2
- {exa_py-1.14.9.dist-info → exa_py-1.14.11.dist-info}/METADATA +3 -3
- {exa_py-1.14.9.dist-info → exa_py-1.14.11.dist-info}/RECORD +7 -7
- {exa_py-1.14.9.dist-info → exa_py-1.14.11.dist-info}/WHEEL +1 -1
- {exa_py-1.14.9.dist-info → exa_py-1.14.11.dist-info}/top_level.txt +0 -0
exa_py/api.py
CHANGED
|
@@ -362,17 +362,17 @@ class _Result:
|
|
|
362
362
|
subpages: Optional[List[_Result]] = None
|
|
363
363
|
extras: Optional[Dict] = None
|
|
364
364
|
|
|
365
|
-
def __init__(self,
|
|
366
|
-
self.url =
|
|
367
|
-
self.id =
|
|
368
|
-
self.title =
|
|
369
|
-
self.score =
|
|
370
|
-
self.published_date =
|
|
371
|
-
self.author =
|
|
372
|
-
self.image =
|
|
373
|
-
self.favicon =
|
|
374
|
-
self.subpages =
|
|
375
|
-
self.extras =
|
|
365
|
+
def __init__(self, url, id, title=None, score=None, published_date=None, author=None, image=None, favicon=None, subpages=None, extras=None):
|
|
366
|
+
self.url = url
|
|
367
|
+
self.id = id
|
|
368
|
+
self.title = title
|
|
369
|
+
self.score = score
|
|
370
|
+
self.published_date = published_date
|
|
371
|
+
self.author = author
|
|
372
|
+
self.image = image
|
|
373
|
+
self.favicon = favicon
|
|
374
|
+
self.subpages = subpages
|
|
375
|
+
self.extras = extras
|
|
376
376
|
|
|
377
377
|
def __str__(self):
|
|
378
378
|
return (
|
|
@@ -406,12 +406,12 @@ class Result(_Result):
|
|
|
406
406
|
highlight_scores: Optional[List[float]] = None
|
|
407
407
|
summary: Optional[str] = None
|
|
408
408
|
|
|
409
|
-
def __init__(self,
|
|
410
|
-
super().__init__(
|
|
411
|
-
self.text =
|
|
412
|
-
self.highlights =
|
|
413
|
-
self.highlight_scores =
|
|
414
|
-
self.summary =
|
|
409
|
+
def __init__(self, url, id, title=None, score=None, published_date=None, author=None, image=None, favicon=None, subpages=None, extras=None, text=None, highlights=None, highlight_scores=None, summary=None):
|
|
410
|
+
super().__init__(url, id, title, score, published_date, author, image, favicon, subpages, extras)
|
|
411
|
+
self.text = text
|
|
412
|
+
self.highlights = highlights
|
|
413
|
+
self.highlight_scores = highlight_scores
|
|
414
|
+
self.summary = summary
|
|
415
415
|
|
|
416
416
|
def __str__(self):
|
|
417
417
|
base_str = super().__str__()
|
|
@@ -434,9 +434,9 @@ class ResultWithText(_Result):
|
|
|
434
434
|
|
|
435
435
|
text: str = dataclasses.field(default_factory=str)
|
|
436
436
|
|
|
437
|
-
def __init__(self,
|
|
438
|
-
super().__init__(
|
|
439
|
-
self.text =
|
|
437
|
+
def __init__(self, url, id, title=None, score=None, published_date=None, author=None, image=None, favicon=None, subpages=None, extras=None, text=""):
|
|
438
|
+
super().__init__(url, id, title, score, published_date, author, image, favicon, subpages, extras)
|
|
439
|
+
self.text = text
|
|
440
440
|
|
|
441
441
|
def __str__(self):
|
|
442
442
|
base_str = super().__str__()
|
|
@@ -456,10 +456,10 @@ class ResultWithHighlights(_Result):
|
|
|
456
456
|
highlights: List[str] = dataclasses.field(default_factory=list)
|
|
457
457
|
highlight_scores: List[float] = dataclasses.field(default_factory=list)
|
|
458
458
|
|
|
459
|
-
def __init__(self,
|
|
460
|
-
super().__init__(
|
|
461
|
-
self.highlights =
|
|
462
|
-
self.highlight_scores =
|
|
459
|
+
def __init__(self, url, id, title=None, score=None, published_date=None, author=None, image=None, favicon=None, subpages=None, extras=None, highlights=None, highlight_scores=None):
|
|
460
|
+
super().__init__(url, id, title, score, published_date, author, image, favicon, subpages, extras)
|
|
461
|
+
self.highlights = highlights if highlights is not None else []
|
|
462
|
+
self.highlight_scores = highlight_scores if highlight_scores is not None else []
|
|
463
463
|
|
|
464
464
|
def __str__(self):
|
|
465
465
|
base_str = super().__str__()
|
|
@@ -484,11 +484,11 @@ class ResultWithTextAndHighlights(_Result):
|
|
|
484
484
|
highlights: List[str] = dataclasses.field(default_factory=list)
|
|
485
485
|
highlight_scores: List[float] = dataclasses.field(default_factory=list)
|
|
486
486
|
|
|
487
|
-
def __init__(self,
|
|
488
|
-
super().__init__(
|
|
489
|
-
self.text =
|
|
490
|
-
self.highlights =
|
|
491
|
-
self.highlight_scores =
|
|
487
|
+
def __init__(self, url, id, title=None, score=None, published_date=None, author=None, image=None, favicon=None, subpages=None, extras=None, text="", highlights=None, highlight_scores=None):
|
|
488
|
+
super().__init__(url, id, title, score, published_date, author, image, favicon, subpages, extras)
|
|
489
|
+
self.text = text
|
|
490
|
+
self.highlights = highlights if highlights is not None else []
|
|
491
|
+
self.highlight_scores = highlight_scores if highlight_scores is not None else []
|
|
492
492
|
|
|
493
493
|
def __str__(self):
|
|
494
494
|
base_str = super().__str__()
|
|
@@ -510,9 +510,9 @@ class ResultWithSummary(_Result):
|
|
|
510
510
|
|
|
511
511
|
summary: str = dataclasses.field(default_factory=str)
|
|
512
512
|
|
|
513
|
-
def __init__(self,
|
|
514
|
-
super().__init__(
|
|
515
|
-
self.summary =
|
|
513
|
+
def __init__(self, url, id, title=None, score=None, published_date=None, author=None, image=None, favicon=None, subpages=None, extras=None, summary=""):
|
|
514
|
+
super().__init__(url, id, title, score, published_date, author, image, favicon, subpages, extras)
|
|
515
|
+
self.summary = summary
|
|
516
516
|
|
|
517
517
|
def __str__(self):
|
|
518
518
|
base_str = super().__str__()
|
|
@@ -532,10 +532,10 @@ class ResultWithTextAndSummary(_Result):
|
|
|
532
532
|
text: str = dataclasses.field(default_factory=str)
|
|
533
533
|
summary: str = dataclasses.field(default_factory=str)
|
|
534
534
|
|
|
535
|
-
def __init__(self,
|
|
536
|
-
super().__init__(
|
|
537
|
-
self.text =
|
|
538
|
-
self.summary =
|
|
535
|
+
def __init__(self, url, id, title=None, score=None, published_date=None, author=None, image=None, favicon=None, subpages=None, extras=None, text="", summary=""):
|
|
536
|
+
super().__init__(url, id, title, score, published_date, author, image, favicon, subpages, extras)
|
|
537
|
+
self.text = text
|
|
538
|
+
self.summary = summary
|
|
539
539
|
|
|
540
540
|
def __str__(self):
|
|
541
541
|
base_str = super().__str__()
|
|
@@ -557,11 +557,11 @@ class ResultWithHighlightsAndSummary(_Result):
|
|
|
557
557
|
highlight_scores: List[float] = dataclasses.field(default_factory=list)
|
|
558
558
|
summary: str = dataclasses.field(default_factory=str)
|
|
559
559
|
|
|
560
|
-
def __init__(self,
|
|
561
|
-
super().__init__(
|
|
562
|
-
self.highlights =
|
|
563
|
-
self.highlight_scores =
|
|
564
|
-
self.summary =
|
|
560
|
+
def __init__(self, url, id, title=None, score=None, published_date=None, author=None, image=None, favicon=None, subpages=None, extras=None, highlights=None, highlight_scores=None, summary=""):
|
|
561
|
+
super().__init__(url, id, title, score, published_date, author, image, favicon, subpages, extras)
|
|
562
|
+
self.highlights = highlights if highlights is not None else []
|
|
563
|
+
self.highlight_scores = highlight_scores if highlight_scores is not None else []
|
|
564
|
+
self.summary = summary
|
|
565
565
|
|
|
566
566
|
def __str__(self):
|
|
567
567
|
base_str = super().__str__()
|
|
@@ -589,12 +589,12 @@ class ResultWithTextAndHighlightsAndSummary(_Result):
|
|
|
589
589
|
highlight_scores: List[float] = dataclasses.field(default_factory=list)
|
|
590
590
|
summary: str = dataclasses.field(default_factory=str)
|
|
591
591
|
|
|
592
|
-
def __init__(self,
|
|
593
|
-
super().__init__(
|
|
594
|
-
self.text =
|
|
595
|
-
self.highlights =
|
|
596
|
-
self.highlight_scores =
|
|
597
|
-
self.summary =
|
|
592
|
+
def __init__(self, url, id, title=None, score=None, published_date=None, author=None, image=None, favicon=None, subpages=None, extras=None, text="", highlights=None, highlight_scores=None, summary=""):
|
|
593
|
+
super().__init__(url, id, title, score, published_date, author, image, favicon, subpages, extras)
|
|
594
|
+
self.text = text
|
|
595
|
+
self.highlights = highlights if highlights is not None else []
|
|
596
|
+
self.highlight_scores = highlight_scores if highlight_scores is not None else []
|
|
597
|
+
self.summary = summary
|
|
598
598
|
|
|
599
599
|
def __str__(self):
|
|
600
600
|
base_str = super().__str__()
|
|
@@ -626,13 +626,13 @@ class AnswerResult:
|
|
|
626
626
|
author: Optional[str] = None
|
|
627
627
|
text: Optional[str] = None
|
|
628
628
|
|
|
629
|
-
def __init__(self,
|
|
630
|
-
self.id =
|
|
631
|
-
self.url =
|
|
632
|
-
self.title =
|
|
633
|
-
self.published_date =
|
|
634
|
-
self.author =
|
|
635
|
-
self.text =
|
|
629
|
+
def __init__(self, id, url, title=None, published_date=None, author=None, text=None):
|
|
630
|
+
self.id = id
|
|
631
|
+
self.url = url
|
|
632
|
+
self.title = title
|
|
633
|
+
self.published_date = published_date
|
|
634
|
+
self.author = author
|
|
635
|
+
self.text = text
|
|
636
636
|
|
|
637
637
|
def __str__(self):
|
|
638
638
|
return (
|
|
@@ -733,9 +733,17 @@ class StreamAnswerResponse:
|
|
|
733
733
|
and chunk["citations"]
|
|
734
734
|
and chunk["citations"] != "null"
|
|
735
735
|
):
|
|
736
|
-
citations = [
|
|
737
|
-
|
|
738
|
-
|
|
736
|
+
citations = []
|
|
737
|
+
for s in chunk["citations"]:
|
|
738
|
+
snake_s = to_snake_case(s)
|
|
739
|
+
citations.append(AnswerResult(
|
|
740
|
+
id=snake_s.get("id"),
|
|
741
|
+
url=snake_s.get("url"),
|
|
742
|
+
title=snake_s.get("title"),
|
|
743
|
+
published_date=snake_s.get("published_date"),
|
|
744
|
+
author=snake_s.get("author"),
|
|
745
|
+
text=snake_s.get("text")
|
|
746
|
+
))
|
|
739
747
|
|
|
740
748
|
stream_chunk = StreamChunk(content=content, citations=citations)
|
|
741
749
|
if stream_chunk.has_data():
|
|
@@ -782,9 +790,17 @@ class AsyncStreamAnswerResponse:
|
|
|
782
790
|
and chunk["citations"]
|
|
783
791
|
and chunk["citations"] != "null"
|
|
784
792
|
):
|
|
785
|
-
citations = [
|
|
786
|
-
|
|
787
|
-
|
|
793
|
+
citations = []
|
|
794
|
+
for s in chunk["citations"]:
|
|
795
|
+
snake_s = to_snake_case(s)
|
|
796
|
+
citations.append(AnswerResult(
|
|
797
|
+
id=snake_s.get("id"),
|
|
798
|
+
url=snake_s.get("url"),
|
|
799
|
+
title=snake_s.get("title"),
|
|
800
|
+
published_date=snake_s.get("published_date"),
|
|
801
|
+
author=snake_s.get("author"),
|
|
802
|
+
text=snake_s.get("text")
|
|
803
|
+
))
|
|
788
804
|
|
|
789
805
|
stream_chunk = StreamChunk(content=content, citations=citations)
|
|
790
806
|
if stream_chunk.has_data():
|
|
@@ -1008,8 +1024,27 @@ class Exa:
|
|
|
1008
1024
|
options = to_camel_case(options)
|
|
1009
1025
|
data = self.request("/search", options)
|
|
1010
1026
|
cost_dollars = parse_cost_dollars(data.get("costDollars"))
|
|
1027
|
+
results = []
|
|
1028
|
+
for result in data["results"]:
|
|
1029
|
+
snake_result = to_snake_case(result)
|
|
1030
|
+
results.append(Result(
|
|
1031
|
+
url=snake_result.get("url"),
|
|
1032
|
+
id=snake_result.get("id"),
|
|
1033
|
+
title=snake_result.get("title"),
|
|
1034
|
+
score=snake_result.get("score"),
|
|
1035
|
+
published_date=snake_result.get("published_date"),
|
|
1036
|
+
author=snake_result.get("author"),
|
|
1037
|
+
image=snake_result.get("image"),
|
|
1038
|
+
favicon=snake_result.get("favicon"),
|
|
1039
|
+
subpages=snake_result.get("subpages"),
|
|
1040
|
+
extras=snake_result.get("extras"),
|
|
1041
|
+
text=snake_result.get("text"),
|
|
1042
|
+
highlights=snake_result.get("highlights"),
|
|
1043
|
+
highlight_scores=snake_result.get("highlight_scores"),
|
|
1044
|
+
summary=snake_result.get("summary")
|
|
1045
|
+
))
|
|
1011
1046
|
return SearchResponse(
|
|
1012
|
-
|
|
1047
|
+
results,
|
|
1013
1048
|
data["autopromptString"] if "autopromptString" in data else None,
|
|
1014
1049
|
data["resolvedSearchType"] if "resolvedSearchType" in data else None,
|
|
1015
1050
|
data["autoDate"] if "autoDate" in data else None,
|
|
@@ -1245,7 +1280,10 @@ class Exa:
|
|
|
1245
1280
|
) -> SearchResponse[ResultWithTextAndHighlightsAndSummary]: ...
|
|
1246
1281
|
|
|
1247
1282
|
def search_and_contents(self, query: str, **kwargs):
|
|
1248
|
-
options = {
|
|
1283
|
+
options = {"query": query}
|
|
1284
|
+
for k, v in kwargs.items():
|
|
1285
|
+
if v is not None:
|
|
1286
|
+
options[k] = v
|
|
1249
1287
|
# If user didn't ask for any particular content, default to text
|
|
1250
1288
|
if (
|
|
1251
1289
|
"text" not in options
|
|
@@ -1255,14 +1293,11 @@ class Exa:
|
|
|
1255
1293
|
):
|
|
1256
1294
|
options["text"] = True
|
|
1257
1295
|
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
**CONTENTS_ENDPOINT_OPTIONS_TYPES,
|
|
1264
|
-
},
|
|
1265
|
-
)
|
|
1296
|
+
merged_options = {}
|
|
1297
|
+
merged_options.update(SEARCH_OPTIONS_TYPES)
|
|
1298
|
+
merged_options.update(CONTENTS_OPTIONS_TYPES)
|
|
1299
|
+
merged_options.update(CONTENTS_ENDPOINT_OPTIONS_TYPES)
|
|
1300
|
+
validate_search_options(options, merged_options)
|
|
1266
1301
|
|
|
1267
1302
|
# Nest the appropriate fields under "contents"
|
|
1268
1303
|
options = nest_fields(
|
|
@@ -1283,8 +1318,27 @@ class Exa:
|
|
|
1283
1318
|
options = to_camel_case(options)
|
|
1284
1319
|
data = self.request("/search", options)
|
|
1285
1320
|
cost_dollars = parse_cost_dollars(data.get("costDollars"))
|
|
1321
|
+
results = []
|
|
1322
|
+
for result in data["results"]:
|
|
1323
|
+
snake_result = to_snake_case(result)
|
|
1324
|
+
results.append(Result(
|
|
1325
|
+
url=snake_result.get("url"),
|
|
1326
|
+
id=snake_result.get("id"),
|
|
1327
|
+
title=snake_result.get("title"),
|
|
1328
|
+
score=snake_result.get("score"),
|
|
1329
|
+
published_date=snake_result.get("published_date"),
|
|
1330
|
+
author=snake_result.get("author"),
|
|
1331
|
+
image=snake_result.get("image"),
|
|
1332
|
+
favicon=snake_result.get("favicon"),
|
|
1333
|
+
subpages=snake_result.get("subpages"),
|
|
1334
|
+
extras=snake_result.get("extras"),
|
|
1335
|
+
text=snake_result.get("text"),
|
|
1336
|
+
highlights=snake_result.get("highlights"),
|
|
1337
|
+
highlight_scores=snake_result.get("highlight_scores"),
|
|
1338
|
+
summary=snake_result.get("summary")
|
|
1339
|
+
))
|
|
1286
1340
|
return SearchResponse(
|
|
1287
|
-
|
|
1341
|
+
results,
|
|
1288
1342
|
data["autopromptString"] if "autopromptString" in data else None,
|
|
1289
1343
|
data["resolvedSearchType"] if "resolvedSearchType" in data else None,
|
|
1290
1344
|
data["autoDate"] if "autoDate" in data else None,
|
|
@@ -1416,11 +1470,11 @@ class Exa:
|
|
|
1416
1470
|
) -> SearchResponse[ResultWithTextAndHighlightsAndSummary]: ...
|
|
1417
1471
|
|
|
1418
1472
|
def get_contents(self, urls: Union[str, List[str], List[_Result]], **kwargs):
|
|
1419
|
-
options = {
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1473
|
+
options = {"urls": urls}
|
|
1474
|
+
for k, v in kwargs.items():
|
|
1475
|
+
if k != "self" and v is not None:
|
|
1476
|
+
options[k] = v
|
|
1477
|
+
|
|
1424
1478
|
if (
|
|
1425
1479
|
"text" not in options
|
|
1426
1480
|
and "highlights" not in options
|
|
@@ -1429,16 +1483,41 @@ class Exa:
|
|
|
1429
1483
|
):
|
|
1430
1484
|
options["text"] = True
|
|
1431
1485
|
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
)
|
|
1486
|
+
merged_options = {}
|
|
1487
|
+
merged_options.update(CONTENTS_OPTIONS_TYPES)
|
|
1488
|
+
merged_options.update(CONTENTS_ENDPOINT_OPTIONS_TYPES)
|
|
1489
|
+
validate_search_options(options, merged_options)
|
|
1436
1490
|
options = to_camel_case(options)
|
|
1437
1491
|
data = self.request("/contents", options)
|
|
1438
1492
|
cost_dollars = parse_cost_dollars(data.get("costDollars"))
|
|
1439
|
-
statuses = [
|
|
1493
|
+
statuses = []
|
|
1494
|
+
for status in data.get("statuses", []):
|
|
1495
|
+
statuses.append(ContentStatus(
|
|
1496
|
+
id=status.get("id"),
|
|
1497
|
+
status=status.get("status"),
|
|
1498
|
+
source=status.get("source")
|
|
1499
|
+
))
|
|
1500
|
+
results = []
|
|
1501
|
+
for result in data["results"]:
|
|
1502
|
+
snake_result = to_snake_case(result)
|
|
1503
|
+
results.append(Result(
|
|
1504
|
+
url=snake_result.get("url"),
|
|
1505
|
+
id=snake_result.get("id"),
|
|
1506
|
+
title=snake_result.get("title"),
|
|
1507
|
+
score=snake_result.get("score"),
|
|
1508
|
+
published_date=snake_result.get("published_date"),
|
|
1509
|
+
author=snake_result.get("author"),
|
|
1510
|
+
image=snake_result.get("image"),
|
|
1511
|
+
favicon=snake_result.get("favicon"),
|
|
1512
|
+
subpages=snake_result.get("subpages"),
|
|
1513
|
+
extras=snake_result.get("extras"),
|
|
1514
|
+
text=snake_result.get("text"),
|
|
1515
|
+
highlights=snake_result.get("highlights"),
|
|
1516
|
+
highlight_scores=snake_result.get("highlight_scores"),
|
|
1517
|
+
summary=snake_result.get("summary")
|
|
1518
|
+
))
|
|
1440
1519
|
return SearchResponse(
|
|
1441
|
-
|
|
1520
|
+
results,
|
|
1442
1521
|
data.get("autopromptString"),
|
|
1443
1522
|
data.get("resolvedSearchType"),
|
|
1444
1523
|
data.get("autoDate"),
|
|
@@ -1489,8 +1568,27 @@ class Exa:
|
|
|
1489
1568
|
options = to_camel_case(options)
|
|
1490
1569
|
data = self.request("/findSimilar", options)
|
|
1491
1570
|
cost_dollars = parse_cost_dollars(data.get("costDollars"))
|
|
1571
|
+
results = []
|
|
1572
|
+
for result in data["results"]:
|
|
1573
|
+
snake_result = to_snake_case(result)
|
|
1574
|
+
results.append(Result(
|
|
1575
|
+
url=snake_result.get("url"),
|
|
1576
|
+
id=snake_result.get("id"),
|
|
1577
|
+
title=snake_result.get("title"),
|
|
1578
|
+
score=snake_result.get("score"),
|
|
1579
|
+
published_date=snake_result.get("published_date"),
|
|
1580
|
+
author=snake_result.get("author"),
|
|
1581
|
+
image=snake_result.get("image"),
|
|
1582
|
+
favicon=snake_result.get("favicon"),
|
|
1583
|
+
subpages=snake_result.get("subpages"),
|
|
1584
|
+
extras=snake_result.get("extras"),
|
|
1585
|
+
text=snake_result.get("text"),
|
|
1586
|
+
highlights=snake_result.get("highlights"),
|
|
1587
|
+
highlight_scores=snake_result.get("highlight_scores"),
|
|
1588
|
+
summary=snake_result.get("summary")
|
|
1589
|
+
))
|
|
1492
1590
|
return SearchResponse(
|
|
1493
|
-
|
|
1591
|
+
results,
|
|
1494
1592
|
data.get("autopromptString"),
|
|
1495
1593
|
data.get("resolvedSearchType"),
|
|
1496
1594
|
data.get("autoDate"),
|
|
@@ -1710,7 +1808,10 @@ class Exa:
|
|
|
1710
1808
|
) -> SearchResponse[ResultWithTextAndHighlightsAndSummary]: ...
|
|
1711
1809
|
|
|
1712
1810
|
def find_similar_and_contents(self, url: str, **kwargs):
|
|
1713
|
-
options = {
|
|
1811
|
+
options = {"url": url}
|
|
1812
|
+
for k, v in kwargs.items():
|
|
1813
|
+
if v is not None:
|
|
1814
|
+
options[k] = v
|
|
1714
1815
|
# Default to text if none specified
|
|
1715
1816
|
if (
|
|
1716
1817
|
"text" not in options
|
|
@@ -1719,14 +1820,11 @@ class Exa:
|
|
|
1719
1820
|
):
|
|
1720
1821
|
options["text"] = True
|
|
1721
1822
|
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
**CONTENTS_ENDPOINT_OPTIONS_TYPES,
|
|
1728
|
-
},
|
|
1729
|
-
)
|
|
1823
|
+
merged_options = {}
|
|
1824
|
+
merged_options.update(FIND_SIMILAR_OPTIONS_TYPES)
|
|
1825
|
+
merged_options.update(CONTENTS_OPTIONS_TYPES)
|
|
1826
|
+
merged_options.update(CONTENTS_ENDPOINT_OPTIONS_TYPES)
|
|
1827
|
+
validate_search_options(options, merged_options)
|
|
1730
1828
|
# We nest the content fields
|
|
1731
1829
|
options = nest_fields(
|
|
1732
1830
|
options,
|
|
@@ -1746,8 +1844,27 @@ class Exa:
|
|
|
1746
1844
|
options = to_camel_case(options)
|
|
1747
1845
|
data = self.request("/findSimilar", options)
|
|
1748
1846
|
cost_dollars = parse_cost_dollars(data.get("costDollars"))
|
|
1847
|
+
results = []
|
|
1848
|
+
for result in data["results"]:
|
|
1849
|
+
snake_result = to_snake_case(result)
|
|
1850
|
+
results.append(Result(
|
|
1851
|
+
url=snake_result.get("url"),
|
|
1852
|
+
id=snake_result.get("id"),
|
|
1853
|
+
title=snake_result.get("title"),
|
|
1854
|
+
score=snake_result.get("score"),
|
|
1855
|
+
published_date=snake_result.get("published_date"),
|
|
1856
|
+
author=snake_result.get("author"),
|
|
1857
|
+
image=snake_result.get("image"),
|
|
1858
|
+
favicon=snake_result.get("favicon"),
|
|
1859
|
+
subpages=snake_result.get("subpages"),
|
|
1860
|
+
extras=snake_result.get("extras"),
|
|
1861
|
+
text=snake_result.get("text"),
|
|
1862
|
+
highlights=snake_result.get("highlights"),
|
|
1863
|
+
highlight_scores=snake_result.get("highlight_scores"),
|
|
1864
|
+
summary=snake_result.get("summary")
|
|
1865
|
+
))
|
|
1749
1866
|
return SearchResponse(
|
|
1750
|
-
|
|
1867
|
+
results,
|
|
1751
1868
|
data.get("autopromptString"),
|
|
1752
1869
|
data.get("resolvedSearchType"),
|
|
1753
1870
|
data.get("autoDate"),
|
|
@@ -1813,10 +1930,8 @@ class Exa:
|
|
|
1813
1930
|
"flags": flags,
|
|
1814
1931
|
}
|
|
1815
1932
|
|
|
1816
|
-
create_kwargs = {
|
|
1817
|
-
|
|
1818
|
-
**openai_kwargs,
|
|
1819
|
-
}
|
|
1933
|
+
create_kwargs = {"model": model}
|
|
1934
|
+
create_kwargs.update(openai_kwargs)
|
|
1820
1935
|
|
|
1821
1936
|
return self._create_with_tool(
|
|
1822
1937
|
create_fn=func,
|
|
@@ -1871,7 +1986,23 @@ class Exa:
|
|
|
1871
1986
|
)
|
|
1872
1987
|
|
|
1873
1988
|
# We do a search_and_contents automatically
|
|
1874
|
-
exa_result = self.search_and_contents(
|
|
1989
|
+
exa_result = self.search_and_contents(
|
|
1990
|
+
query=query,
|
|
1991
|
+
num_results=exa_kwargs.get("num_results"),
|
|
1992
|
+
include_domains=exa_kwargs.get("include_domains"),
|
|
1993
|
+
exclude_domains=exa_kwargs.get("exclude_domains"),
|
|
1994
|
+
highlights=exa_kwargs.get("highlights"),
|
|
1995
|
+
start_crawl_date=exa_kwargs.get("start_crawl_date"),
|
|
1996
|
+
end_crawl_date=exa_kwargs.get("end_crawl_date"),
|
|
1997
|
+
start_published_date=exa_kwargs.get("start_published_date"),
|
|
1998
|
+
end_published_date=exa_kwargs.get("end_published_date"),
|
|
1999
|
+
include_text=exa_kwargs.get("include_text"),
|
|
2000
|
+
exclude_text=exa_kwargs.get("exclude_text"),
|
|
2001
|
+
use_autoprompt=exa_kwargs.get("use_autoprompt"),
|
|
2002
|
+
type=exa_kwargs.get("type"),
|
|
2003
|
+
category=exa_kwargs.get("category"),
|
|
2004
|
+
flags=exa_kwargs.get("flags")
|
|
2005
|
+
)
|
|
1875
2006
|
exa_str = format_exa_result(exa_result, max_len=max_len)
|
|
1876
2007
|
new_messages = add_message_to_messages(completion, messages, exa_str)
|
|
1877
2008
|
completion = create_fn(messages=new_messages, **create_kwargs)
|
|
@@ -1909,7 +2040,7 @@ class Exa:
|
|
|
1909
2040
|
query (str): The query to answer.
|
|
1910
2041
|
text (bool, optional): Whether to include full text in the results. Defaults to False.
|
|
1911
2042
|
system_prompt (str, optional): A system prompt to guide the LLM's behavior when generating the answer.
|
|
1912
|
-
model (str, optional): The model to use for answering.
|
|
2043
|
+
model (str, optional): The model to use for answering. Defaults to None.
|
|
1913
2044
|
output_schema (dict[str, Any], optional): JSON schema describing the desired answer structure.
|
|
1914
2045
|
|
|
1915
2046
|
Returns:
|
|
@@ -1928,10 +2059,18 @@ class Exa:
|
|
|
1928
2059
|
options = to_camel_case(options)
|
|
1929
2060
|
response = self.request("/answer", options)
|
|
1930
2061
|
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
2062
|
+
citations = []
|
|
2063
|
+
for result in response["citations"]:
|
|
2064
|
+
snake_result = to_snake_case(result)
|
|
2065
|
+
citations.append(AnswerResult(
|
|
2066
|
+
id=snake_result.get("id"),
|
|
2067
|
+
url=snake_result.get("url"),
|
|
2068
|
+
title=snake_result.get("title"),
|
|
2069
|
+
published_date=snake_result.get("published_date"),
|
|
2070
|
+
author=snake_result.get("author"),
|
|
2071
|
+
text=snake_result.get("text")
|
|
2072
|
+
))
|
|
2073
|
+
return AnswerResponse(response["answer"], citations)
|
|
1935
2074
|
|
|
1936
2075
|
def stream_answer(
|
|
1937
2076
|
self,
|
|
@@ -1948,7 +2087,7 @@ class Exa:
|
|
|
1948
2087
|
query (str): The query to answer.
|
|
1949
2088
|
text (bool): Whether to include full text in the results. Defaults to False.
|
|
1950
2089
|
system_prompt (str, optional): A system prompt to guide the LLM's behavior when generating the answer.
|
|
1951
|
-
model (str, optional): The model to use for answering.
|
|
2090
|
+
model (str, optional): The model to use for answering. Defaults to None.
|
|
1952
2091
|
output_schema (dict[str, Any], optional): JSON schema describing the desired answer structure.
|
|
1953
2092
|
Returns:
|
|
1954
2093
|
StreamAnswerResponse: An object that can be iterated over to retrieve (partial text, partial citations).
|
|
@@ -2053,8 +2192,27 @@ class AsyncExa(Exa):
|
|
|
2053
2192
|
options = to_camel_case(options)
|
|
2054
2193
|
data = await self.async_request("/search", options)
|
|
2055
2194
|
cost_dollars = parse_cost_dollars(data.get("costDollars"))
|
|
2195
|
+
results = []
|
|
2196
|
+
for result in data["results"]:
|
|
2197
|
+
snake_result = to_snake_case(result)
|
|
2198
|
+
results.append(Result(
|
|
2199
|
+
url=snake_result.get("url"),
|
|
2200
|
+
id=snake_result.get("id"),
|
|
2201
|
+
title=snake_result.get("title"),
|
|
2202
|
+
score=snake_result.get("score"),
|
|
2203
|
+
published_date=snake_result.get("published_date"),
|
|
2204
|
+
author=snake_result.get("author"),
|
|
2205
|
+
image=snake_result.get("image"),
|
|
2206
|
+
favicon=snake_result.get("favicon"),
|
|
2207
|
+
subpages=snake_result.get("subpages"),
|
|
2208
|
+
extras=snake_result.get("extras"),
|
|
2209
|
+
text=snake_result.get("text"),
|
|
2210
|
+
highlights=snake_result.get("highlights"),
|
|
2211
|
+
highlight_scores=snake_result.get("highlight_scores"),
|
|
2212
|
+
summary=snake_result.get("summary")
|
|
2213
|
+
))
|
|
2056
2214
|
return SearchResponse(
|
|
2057
|
-
|
|
2215
|
+
results,
|
|
2058
2216
|
data["autopromptString"] if "autopromptString" in data else None,
|
|
2059
2217
|
data["resolvedSearchType"] if "resolvedSearchType" in data else None,
|
|
2060
2218
|
data["autoDate"] if "autoDate" in data else None,
|
|
@@ -2062,7 +2220,10 @@ class AsyncExa(Exa):
|
|
|
2062
2220
|
)
|
|
2063
2221
|
|
|
2064
2222
|
async def search_and_contents(self, query: str, **kwargs):
|
|
2065
|
-
options = {
|
|
2223
|
+
options = {"query": query}
|
|
2224
|
+
for k, v in kwargs.items():
|
|
2225
|
+
if v is not None:
|
|
2226
|
+
options[k] = v
|
|
2066
2227
|
# If user didn't ask for any particular content, default to text
|
|
2067
2228
|
if (
|
|
2068
2229
|
"text" not in options
|
|
@@ -2072,14 +2233,11 @@ class AsyncExa(Exa):
|
|
|
2072
2233
|
):
|
|
2073
2234
|
options["text"] = True
|
|
2074
2235
|
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
**CONTENTS_ENDPOINT_OPTIONS_TYPES,
|
|
2081
|
-
},
|
|
2082
|
-
)
|
|
2236
|
+
merged_options = {}
|
|
2237
|
+
merged_options.update(SEARCH_OPTIONS_TYPES)
|
|
2238
|
+
merged_options.update(CONTENTS_OPTIONS_TYPES)
|
|
2239
|
+
merged_options.update(CONTENTS_ENDPOINT_OPTIONS_TYPES)
|
|
2240
|
+
validate_search_options(options, merged_options)
|
|
2083
2241
|
|
|
2084
2242
|
# Nest the appropriate fields under "contents"
|
|
2085
2243
|
options = nest_fields(
|
|
@@ -2100,8 +2258,27 @@ class AsyncExa(Exa):
|
|
|
2100
2258
|
options = to_camel_case(options)
|
|
2101
2259
|
data = await self.async_request("/search", options)
|
|
2102
2260
|
cost_dollars = parse_cost_dollars(data.get("costDollars"))
|
|
2261
|
+
results = []
|
|
2262
|
+
for result in data["results"]:
|
|
2263
|
+
snake_result = to_snake_case(result)
|
|
2264
|
+
results.append(Result(
|
|
2265
|
+
url=snake_result.get("url"),
|
|
2266
|
+
id=snake_result.get("id"),
|
|
2267
|
+
title=snake_result.get("title"),
|
|
2268
|
+
score=snake_result.get("score"),
|
|
2269
|
+
published_date=snake_result.get("published_date"),
|
|
2270
|
+
author=snake_result.get("author"),
|
|
2271
|
+
image=snake_result.get("image"),
|
|
2272
|
+
favicon=snake_result.get("favicon"),
|
|
2273
|
+
subpages=snake_result.get("subpages"),
|
|
2274
|
+
extras=snake_result.get("extras"),
|
|
2275
|
+
text=snake_result.get("text"),
|
|
2276
|
+
highlights=snake_result.get("highlights"),
|
|
2277
|
+
highlight_scores=snake_result.get("highlight_scores"),
|
|
2278
|
+
summary=snake_result.get("summary")
|
|
2279
|
+
))
|
|
2103
2280
|
return SearchResponse(
|
|
2104
|
-
|
|
2281
|
+
results,
|
|
2105
2282
|
data["autopromptString"] if "autopromptString" in data else None,
|
|
2106
2283
|
data["resolvedSearchType"] if "resolvedSearchType" in data else None,
|
|
2107
2284
|
data["autoDate"] if "autoDate" in data else None,
|
|
@@ -2110,11 +2287,11 @@ class AsyncExa(Exa):
|
|
|
2110
2287
|
)
|
|
2111
2288
|
|
|
2112
2289
|
async def get_contents(self, urls: Union[str, List[str], List[_Result]], **kwargs):
|
|
2113
|
-
options = {
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2290
|
+
options = {"urls": urls}
|
|
2291
|
+
for k, v in kwargs.items():
|
|
2292
|
+
if k != "self" and v is not None:
|
|
2293
|
+
options[k] = v
|
|
2294
|
+
|
|
2118
2295
|
if (
|
|
2119
2296
|
"text" not in options
|
|
2120
2297
|
and "highlights" not in options
|
|
@@ -2123,16 +2300,41 @@ class AsyncExa(Exa):
|
|
|
2123
2300
|
):
|
|
2124
2301
|
options["text"] = True
|
|
2125
2302
|
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
)
|
|
2303
|
+
merged_options = {}
|
|
2304
|
+
merged_options.update(CONTENTS_OPTIONS_TYPES)
|
|
2305
|
+
merged_options.update(CONTENTS_ENDPOINT_OPTIONS_TYPES)
|
|
2306
|
+
validate_search_options(options, merged_options)
|
|
2130
2307
|
options = to_camel_case(options)
|
|
2131
2308
|
data = await self.async_request("/contents", options)
|
|
2132
2309
|
cost_dollars = parse_cost_dollars(data.get("costDollars"))
|
|
2133
|
-
statuses = [
|
|
2310
|
+
statuses = []
|
|
2311
|
+
for status in data.get("statuses", []):
|
|
2312
|
+
statuses.append(ContentStatus(
|
|
2313
|
+
id=status.get("id"),
|
|
2314
|
+
status=status.get("status"),
|
|
2315
|
+
source=status.get("source")
|
|
2316
|
+
))
|
|
2317
|
+
results = []
|
|
2318
|
+
for result in data["results"]:
|
|
2319
|
+
snake_result = to_snake_case(result)
|
|
2320
|
+
results.append(Result(
|
|
2321
|
+
url=snake_result.get("url"),
|
|
2322
|
+
id=snake_result.get("id"),
|
|
2323
|
+
title=snake_result.get("title"),
|
|
2324
|
+
score=snake_result.get("score"),
|
|
2325
|
+
published_date=snake_result.get("published_date"),
|
|
2326
|
+
author=snake_result.get("author"),
|
|
2327
|
+
image=snake_result.get("image"),
|
|
2328
|
+
favicon=snake_result.get("favicon"),
|
|
2329
|
+
subpages=snake_result.get("subpages"),
|
|
2330
|
+
extras=snake_result.get("extras"),
|
|
2331
|
+
text=snake_result.get("text"),
|
|
2332
|
+
highlights=snake_result.get("highlights"),
|
|
2333
|
+
highlight_scores=snake_result.get("highlight_scores"),
|
|
2334
|
+
summary=snake_result.get("summary")
|
|
2335
|
+
))
|
|
2134
2336
|
return SearchResponse(
|
|
2135
|
-
|
|
2337
|
+
results,
|
|
2136
2338
|
data.get("autopromptString"),
|
|
2137
2339
|
data.get("resolvedSearchType"),
|
|
2138
2340
|
data.get("autoDate"),
|
|
@@ -2183,8 +2385,27 @@ class AsyncExa(Exa):
|
|
|
2183
2385
|
options = to_camel_case(options)
|
|
2184
2386
|
data = await self.async_request("/findSimilar", options)
|
|
2185
2387
|
cost_dollars = parse_cost_dollars(data.get("costDollars"))
|
|
2388
|
+
results = []
|
|
2389
|
+
for result in data["results"]:
|
|
2390
|
+
snake_result = to_snake_case(result)
|
|
2391
|
+
results.append(Result(
|
|
2392
|
+
url=snake_result.get("url"),
|
|
2393
|
+
id=snake_result.get("id"),
|
|
2394
|
+
title=snake_result.get("title"),
|
|
2395
|
+
score=snake_result.get("score"),
|
|
2396
|
+
published_date=snake_result.get("published_date"),
|
|
2397
|
+
author=snake_result.get("author"),
|
|
2398
|
+
image=snake_result.get("image"),
|
|
2399
|
+
favicon=snake_result.get("favicon"),
|
|
2400
|
+
subpages=snake_result.get("subpages"),
|
|
2401
|
+
extras=snake_result.get("extras"),
|
|
2402
|
+
text=snake_result.get("text"),
|
|
2403
|
+
highlights=snake_result.get("highlights"),
|
|
2404
|
+
highlight_scores=snake_result.get("highlight_scores"),
|
|
2405
|
+
summary=snake_result.get("summary")
|
|
2406
|
+
))
|
|
2186
2407
|
return SearchResponse(
|
|
2187
|
-
|
|
2408
|
+
results,
|
|
2188
2409
|
data.get("autopromptString"),
|
|
2189
2410
|
data.get("resolvedSearchType"),
|
|
2190
2411
|
data.get("autoDate"),
|
|
@@ -2192,7 +2413,10 @@ class AsyncExa(Exa):
|
|
|
2192
2413
|
)
|
|
2193
2414
|
|
|
2194
2415
|
async def find_similar_and_contents(self, url: str, **kwargs):
|
|
2195
|
-
options = {
|
|
2416
|
+
options = {"url": url}
|
|
2417
|
+
for k, v in kwargs.items():
|
|
2418
|
+
if v is not None:
|
|
2419
|
+
options[k] = v
|
|
2196
2420
|
# Default to text if none specified
|
|
2197
2421
|
if (
|
|
2198
2422
|
"text" not in options
|
|
@@ -2201,14 +2425,11 @@ class AsyncExa(Exa):
|
|
|
2201
2425
|
):
|
|
2202
2426
|
options["text"] = True
|
|
2203
2427
|
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
**CONTENTS_ENDPOINT_OPTIONS_TYPES,
|
|
2210
|
-
},
|
|
2211
|
-
)
|
|
2428
|
+
merged_options = {}
|
|
2429
|
+
merged_options.update(FIND_SIMILAR_OPTIONS_TYPES)
|
|
2430
|
+
merged_options.update(CONTENTS_OPTIONS_TYPES)
|
|
2431
|
+
merged_options.update(CONTENTS_ENDPOINT_OPTIONS_TYPES)
|
|
2432
|
+
validate_search_options(options, merged_options)
|
|
2212
2433
|
# We nest the content fields
|
|
2213
2434
|
options = nest_fields(
|
|
2214
2435
|
options,
|
|
@@ -2228,8 +2449,27 @@ class AsyncExa(Exa):
|
|
|
2228
2449
|
options = to_camel_case(options)
|
|
2229
2450
|
data = await self.async_request("/findSimilar", options)
|
|
2230
2451
|
cost_dollars = parse_cost_dollars(data.get("costDollars"))
|
|
2452
|
+
results = []
|
|
2453
|
+
for result in data["results"]:
|
|
2454
|
+
snake_result = to_snake_case(result)
|
|
2455
|
+
results.append(Result(
|
|
2456
|
+
url=snake_result.get("url"),
|
|
2457
|
+
id=snake_result.get("id"),
|
|
2458
|
+
title=snake_result.get("title"),
|
|
2459
|
+
score=snake_result.get("score"),
|
|
2460
|
+
published_date=snake_result.get("published_date"),
|
|
2461
|
+
author=snake_result.get("author"),
|
|
2462
|
+
image=snake_result.get("image"),
|
|
2463
|
+
favicon=snake_result.get("favicon"),
|
|
2464
|
+
subpages=snake_result.get("subpages"),
|
|
2465
|
+
extras=snake_result.get("extras"),
|
|
2466
|
+
text=snake_result.get("text"),
|
|
2467
|
+
highlights=snake_result.get("highlights"),
|
|
2468
|
+
highlight_scores=snake_result.get("highlight_scores"),
|
|
2469
|
+
summary=snake_result.get("summary")
|
|
2470
|
+
))
|
|
2231
2471
|
return SearchResponse(
|
|
2232
|
-
|
|
2472
|
+
results,
|
|
2233
2473
|
data.get("autopromptString"),
|
|
2234
2474
|
data.get("resolvedSearchType"),
|
|
2235
2475
|
data.get("autoDate"),
|
|
@@ -2253,7 +2493,7 @@ class AsyncExa(Exa):
|
|
|
2253
2493
|
query (str): The query to answer.
|
|
2254
2494
|
text (bool, optional): Whether to include full text in the results. Defaults to False.
|
|
2255
2495
|
system_prompt (str, optional): A system prompt to guide the LLM's behavior when generating the answer.
|
|
2256
|
-
model (str, optional): The model to use for answering.
|
|
2496
|
+
model (str, optional): The model to use for answering. Defaults to None.
|
|
2257
2497
|
output_schema (dict[str, Any], optional): JSON schema describing the desired answer structure.
|
|
2258
2498
|
|
|
2259
2499
|
Returns:
|
|
@@ -2272,10 +2512,18 @@ class AsyncExa(Exa):
|
|
|
2272
2512
|
options = to_camel_case(options)
|
|
2273
2513
|
response = await self.async_request("/answer", options)
|
|
2274
2514
|
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2515
|
+
citations = []
|
|
2516
|
+
for result in response["citations"]:
|
|
2517
|
+
snake_result = to_snake_case(result)
|
|
2518
|
+
citations.append(AnswerResult(
|
|
2519
|
+
id=snake_result.get("id"),
|
|
2520
|
+
url=snake_result.get("url"),
|
|
2521
|
+
title=snake_result.get("title"),
|
|
2522
|
+
published_date=snake_result.get("published_date"),
|
|
2523
|
+
author=snake_result.get("author"),
|
|
2524
|
+
text=snake_result.get("text")
|
|
2525
|
+
))
|
|
2526
|
+
return AnswerResponse(response["answer"], citations)
|
|
2279
2527
|
|
|
2280
2528
|
async def stream_answer(
|
|
2281
2529
|
self,
|
|
@@ -2292,7 +2540,7 @@ class AsyncExa(Exa):
|
|
|
2292
2540
|
query (str): The query to answer.
|
|
2293
2541
|
text (bool): Whether to include full text in the results. Defaults to False.
|
|
2294
2542
|
system_prompt (str, optional): A system prompt to guide the LLM's behavior when generating the answer.
|
|
2295
|
-
model (str, optional): The model to use for answering.
|
|
2543
|
+
model (str, optional): The model to use for answering. Defaults to None.
|
|
2296
2544
|
output_schema (dict[str, Any], optional): JSON schema describing the desired answer structure.
|
|
2297
2545
|
Returns:
|
|
2298
2546
|
AsyncStreamAnswerResponse: An object that can be iterated over to retrieve (partial text, partial citations).
|
exa_py/research/client.py
CHANGED
|
@@ -322,10 +322,24 @@ def _build_research_task(raw: Dict[str, Any]):
|
|
|
322
322
|
from ..api import _Result, to_snake_case # noqa: WPS433 – runtime import
|
|
323
323
|
|
|
324
324
|
citations_raw = raw.get("citations", {}) or {}
|
|
325
|
-
citations_parsed = {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
325
|
+
citations_parsed = {}
|
|
326
|
+
for key, cites in citations_raw.items():
|
|
327
|
+
results = []
|
|
328
|
+
for c in cites:
|
|
329
|
+
snake_c = to_snake_case(c)
|
|
330
|
+
results.append(_Result(
|
|
331
|
+
url=snake_c.get("url"),
|
|
332
|
+
id=snake_c.get("id"),
|
|
333
|
+
title=snake_c.get("title"),
|
|
334
|
+
score=snake_c.get("score"),
|
|
335
|
+
published_date=snake_c.get("published_date"),
|
|
336
|
+
author=snake_c.get("author"),
|
|
337
|
+
image=snake_c.get("image"),
|
|
338
|
+
favicon=snake_c.get("favicon"),
|
|
339
|
+
subpages=snake_c.get("subpages"),
|
|
340
|
+
extras=snake_c.get("extras")
|
|
341
|
+
))
|
|
342
|
+
citations_parsed[key] = results
|
|
329
343
|
|
|
330
344
|
return ResearchTask(
|
|
331
345
|
id=raw["id"],
|
exa_py/utils.py
CHANGED
|
@@ -54,8 +54,8 @@ def format_exa_result(exa_result, max_len: int=-1):
|
|
|
54
54
|
|
|
55
55
|
class ExaOpenAICompletion(ChatCompletion):
|
|
56
56
|
"""Exa wrapper for OpenAI completion."""
|
|
57
|
-
def __init__(self, exa_result: Optional["SearchResponse[ResultWithText]"],
|
|
58
|
-
super().__init__(
|
|
57
|
+
def __init__(self, exa_result: Optional["SearchResponse[ResultWithText]"], id, choices, created, model, object, system_fingerprint=None, usage=None):
|
|
58
|
+
super().__init__(id=id, choices=choices, created=created, model=model, object=object, system_fingerprint=system_fingerprint, usage=usage)
|
|
59
59
|
self.exa_result = exa_result
|
|
60
60
|
|
|
61
61
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: exa-py
|
|
3
|
-
Version: 1.14.
|
|
3
|
+
Version: 1.14.11
|
|
4
4
|
Summary: Python SDK for Exa API.
|
|
5
5
|
Home-page: https://github.com/exa-labs/exa-py
|
|
6
6
|
Author: Exa
|
|
@@ -81,8 +81,8 @@ exa = Exa(api_key="your-api-key")
|
|
|
81
81
|
# basic answer
|
|
82
82
|
response = exa.answer("This is a query to answer a question")
|
|
83
83
|
|
|
84
|
-
# answer with full text
|
|
85
|
-
response = exa.answer("This is a query to answer a question", text=True
|
|
84
|
+
# answer with full text
|
|
85
|
+
response = exa.answer("This is a query to answer a question", text=True)
|
|
86
86
|
|
|
87
87
|
# answer with streaming
|
|
88
88
|
response = exa.stream_answer("This is a query to answer:")
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
exa_py/__init__.py,sha256=M2GC9oSdoV6m2msboW0vMWWl8wrth4o6gmEV4MYLGG8,66
|
|
2
|
-
exa_py/api.py,sha256=
|
|
2
|
+
exa_py/api.py,sha256=IrToa0zN39SREpwwcyuFvnoE_-pIc9uWVDkEw07IN9I,99737
|
|
3
3
|
exa_py/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
exa_py/utils.py,sha256=
|
|
4
|
+
exa_py/utils.py,sha256=sq1KOajuMWI1lygYeb9MqjXn8yqVyK0BtFZZmTwSaMY,2580
|
|
5
5
|
exa_py/research/__init__.py,sha256=QeY-j6bP4QP5tF9ytX0IeQhJvd0Wn4cJCD69U8pP7kA,271
|
|
6
|
-
exa_py/research/client.py,sha256=
|
|
6
|
+
exa_py/research/client.py,sha256=x9b299ROfbhdMrdto6jZCHGRJE5U5V2fWHsSlnnNkWo,12471
|
|
7
7
|
exa_py/research/models.py,sha256=j7YgRoMRp2MLgnaij7775x_hJEeV5gksKpfLwmawqxY,3704
|
|
8
8
|
exa_py/websets/__init__.py,sha256=6HQWR8_ABPeZx2sHfwGV4QQf1Eh8MRaO-kzoIO_1ua8,126
|
|
9
9
|
exa_py/websets/client.py,sha256=nP0XZAEMIFvinb1DJ6gNF-8jCnKMUmBun5wZ9EgeZ0M,4891
|
|
@@ -24,7 +24,7 @@ exa_py/websets/searches/__init__.py,sha256=_0Zx8ES5fFTEL3T8mhLxq_xK2t0JONx6ad6At
|
|
|
24
24
|
exa_py/websets/searches/client.py,sha256=X3f7axWGfecmxf-2tBTX0Yf_--xToz1X8ZHbbudEzy0,1790
|
|
25
25
|
exa_py/websets/webhooks/__init__.py,sha256=iTPBCxFd73z4RifLQMX6iRECx_6pwlI5qscLNjMOUHE,77
|
|
26
26
|
exa_py/websets/webhooks/client.py,sha256=zsIRMTeJU65yj-zo7Zz-gG02Prtzgcx6utGFSoY4HQQ,4222
|
|
27
|
-
exa_py-1.14.
|
|
28
|
-
exa_py-1.14.
|
|
29
|
-
exa_py-1.14.
|
|
30
|
-
exa_py-1.14.
|
|
27
|
+
exa_py-1.14.11.dist-info/METADATA,sha256=ndNf4lDM1Vz44xlJO29qVVHGl6vvb9ozXiq3L6XOmpw,3719
|
|
28
|
+
exa_py-1.14.11.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
29
|
+
exa_py-1.14.11.dist-info/top_level.txt,sha256=Mfkmscdw9HWR1PtVhU1gAiVo6DHu_tyiVdb89gfZBVI,7
|
|
30
|
+
exa_py-1.14.11.dist-info/RECORD,,
|
|
File without changes
|