perplexityai 0.22.3__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.
Files changed (64) hide show
  1. perplexity/__init__.py +102 -0
  2. perplexity/_base_client.py +2001 -0
  3. perplexity/_client.py +529 -0
  4. perplexity/_compat.py +219 -0
  5. perplexity/_constants.py +14 -0
  6. perplexity/_exceptions.py +108 -0
  7. perplexity/_files.py +123 -0
  8. perplexity/_models.py +857 -0
  9. perplexity/_qs.py +150 -0
  10. perplexity/_resource.py +43 -0
  11. perplexity/_response.py +832 -0
  12. perplexity/_streaming.py +371 -0
  13. perplexity/_types.py +261 -0
  14. perplexity/_utils/__init__.py +64 -0
  15. perplexity/_utils/_compat.py +45 -0
  16. perplexity/_utils/_datetime_parse.py +136 -0
  17. perplexity/_utils/_logs.py +25 -0
  18. perplexity/_utils/_proxy.py +65 -0
  19. perplexity/_utils/_reflection.py +42 -0
  20. perplexity/_utils/_resources_proxy.py +24 -0
  21. perplexity/_utils/_streams.py +12 -0
  22. perplexity/_utils/_sync.py +58 -0
  23. perplexity/_utils/_transform.py +457 -0
  24. perplexity/_utils/_typing.py +156 -0
  25. perplexity/_utils/_utils.py +421 -0
  26. perplexity/_version.py +4 -0
  27. perplexity/lib/.keep +4 -0
  28. perplexity/py.typed +0 -0
  29. perplexity/resources/__init__.py +47 -0
  30. perplexity/resources/async_/__init__.py +33 -0
  31. perplexity/resources/async_/async_.py +102 -0
  32. perplexity/resources/async_/chat/__init__.py +33 -0
  33. perplexity/resources/async_/chat/chat.py +102 -0
  34. perplexity/resources/async_/chat/completions.py +359 -0
  35. perplexity/resources/chat/__init__.py +33 -0
  36. perplexity/resources/chat/chat.py +102 -0
  37. perplexity/resources/chat/completions.py +900 -0
  38. perplexity/resources/search.py +228 -0
  39. perplexity/types/__init__.py +14 -0
  40. perplexity/types/async_/__init__.py +3 -0
  41. perplexity/types/async_/chat/__init__.py +9 -0
  42. perplexity/types/async_/chat/completion_create_params.py +242 -0
  43. perplexity/types/async_/chat/completion_create_response.py +30 -0
  44. perplexity/types/async_/chat/completion_get_params.py +25 -0
  45. perplexity/types/async_/chat/completion_get_response.py +30 -0
  46. perplexity/types/async_/chat/completion_list_response.py +31 -0
  47. perplexity/types/chat/__init__.py +5 -0
  48. perplexity/types/chat/completion_create_params.py +244 -0
  49. perplexity/types/search_create_params.py +40 -0
  50. perplexity/types/search_create_response.py +27 -0
  51. perplexity/types/shared/__init__.py +7 -0
  52. perplexity/types/shared/api_public_search_result.py +22 -0
  53. perplexity/types/shared/chat_message_input.py +176 -0
  54. perplexity/types/shared/chat_message_output.py +176 -0
  55. perplexity/types/shared/choice.py +19 -0
  56. perplexity/types/shared/usage_info.py +41 -0
  57. perplexity/types/shared_params/__init__.py +4 -0
  58. perplexity/types/shared_params/api_public_search_result.py +22 -0
  59. perplexity/types/shared_params/chat_message_input.py +178 -0
  60. perplexity/types/stream_chunk.py +33 -0
  61. perplexityai-0.22.3.dist-info/METADATA +548 -0
  62. perplexityai-0.22.3.dist-info/RECORD +64 -0
  63. perplexityai-0.22.3.dist-info/WHEEL +4 -0
  64. perplexityai-0.22.3.dist-info/licenses/LICENSE +201 -0
perplexity/_client.py ADDED
@@ -0,0 +1,529 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from typing import TYPE_CHECKING, Any, Mapping
7
+ from typing_extensions import Self, override
8
+
9
+ import httpx
10
+
11
+ from . import _exceptions
12
+ from ._qs import Querystring
13
+ from ._types import (
14
+ Omit,
15
+ Timeout,
16
+ NotGiven,
17
+ Transport,
18
+ ProxiesTypes,
19
+ RequestOptions,
20
+ not_given,
21
+ )
22
+ from ._utils import is_given, get_async_library
23
+ from ._compat import cached_property
24
+ from ._version import __version__
25
+ from ._streaming import Stream as Stream, AsyncStream as AsyncStream
26
+ from ._exceptions import APIStatusError, PerplexityError
27
+ from ._base_client import (
28
+ DEFAULT_MAX_RETRIES,
29
+ SyncAPIClient,
30
+ AsyncAPIClient,
31
+ )
32
+
33
+ if TYPE_CHECKING:
34
+ from .resources import chat, async_, search
35
+ from .resources.search import SearchResource, AsyncSearchResource
36
+ from .resources.chat.chat import ChatResource, AsyncChatResource
37
+ from .resources.async_.async_ import AsyncResource, AsyncAsyncResource
38
+
39
+ __all__ = [
40
+ "Timeout",
41
+ "Transport",
42
+ "ProxiesTypes",
43
+ "RequestOptions",
44
+ "Perplexity",
45
+ "AsyncPerplexity",
46
+ "Client",
47
+ "AsyncClient",
48
+ ]
49
+
50
+
51
+ class Perplexity(SyncAPIClient):
52
+ # client options
53
+ api_key: str
54
+
55
+ def __init__(
56
+ self,
57
+ *,
58
+ api_key: str | None = None,
59
+ base_url: str | httpx.URL | None = None,
60
+ timeout: float | Timeout | None | NotGiven = not_given,
61
+ max_retries: int = DEFAULT_MAX_RETRIES,
62
+ default_headers: Mapping[str, str] | None = None,
63
+ default_query: Mapping[str, object] | None = None,
64
+ # Configure a custom httpx client.
65
+ # We provide a `DefaultHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`.
66
+ # See the [httpx documentation](https://www.python-httpx.org/api/#client) for more details.
67
+ http_client: httpx.Client | None = None,
68
+ # Enable or disable schema validation for data returned by the API.
69
+ # When enabled an error APIResponseValidationError is raised
70
+ # if the API responds with invalid data for the expected schema.
71
+ #
72
+ # This parameter may be removed or changed in the future.
73
+ # If you rely on this feature, please open a GitHub issue
74
+ # outlining your use-case to help us decide if it should be
75
+ # part of our public interface in the future.
76
+ _strict_response_validation: bool = False,
77
+ ) -> None:
78
+ """Construct a new synchronous Perplexity client instance.
79
+
80
+ This automatically infers the `api_key` argument from the `PERPLEXITY_API_KEY` environment variable if it is not provided.
81
+ """
82
+ if api_key is None:
83
+ api_key = os.environ.get("PERPLEXITY_API_KEY")
84
+ if api_key is None:
85
+ raise PerplexityError(
86
+ "The api_key client option must be set either by passing api_key to the client or by setting the PERPLEXITY_API_KEY environment variable"
87
+ )
88
+ self.api_key = api_key
89
+
90
+ if base_url is None:
91
+ base_url = os.environ.get("PERPLEXITY_BASE_URL")
92
+ if base_url is None:
93
+ base_url = f"https://api.perplexity.ai"
94
+
95
+ super().__init__(
96
+ version=__version__,
97
+ base_url=base_url,
98
+ max_retries=max_retries,
99
+ timeout=timeout,
100
+ http_client=http_client,
101
+ custom_headers=default_headers,
102
+ custom_query=default_query,
103
+ _strict_response_validation=_strict_response_validation,
104
+ )
105
+
106
+ self._default_stream_cls = Stream
107
+
108
+ @cached_property
109
+ def chat(self) -> ChatResource:
110
+ from .resources.chat import ChatResource
111
+
112
+ return ChatResource(self)
113
+
114
+ @cached_property
115
+ def search(self) -> SearchResource:
116
+ from .resources.search import SearchResource
117
+
118
+ return SearchResource(self)
119
+
120
+ @cached_property
121
+ def async_(self) -> AsyncResource:
122
+ from .resources.async_ import AsyncResource
123
+
124
+ return AsyncResource(self)
125
+
126
+ @cached_property
127
+ def with_raw_response(self) -> PerplexityWithRawResponse:
128
+ return PerplexityWithRawResponse(self)
129
+
130
+ @cached_property
131
+ def with_streaming_response(self) -> PerplexityWithStreamedResponse:
132
+ return PerplexityWithStreamedResponse(self)
133
+
134
+ @property
135
+ @override
136
+ def qs(self) -> Querystring:
137
+ return Querystring(array_format="comma")
138
+
139
+ @property
140
+ @override
141
+ def auth_headers(self) -> dict[str, str]:
142
+ api_key = self.api_key
143
+ return {"Authorization": f"Bearer {api_key}"}
144
+
145
+ @property
146
+ @override
147
+ def default_headers(self) -> dict[str, str | Omit]:
148
+ return {
149
+ **super().default_headers,
150
+ "X-Stainless-Async": "false",
151
+ **self._custom_headers,
152
+ }
153
+
154
+ def copy(
155
+ self,
156
+ *,
157
+ api_key: str | None = None,
158
+ base_url: str | httpx.URL | None = None,
159
+ timeout: float | Timeout | None | NotGiven = not_given,
160
+ http_client: httpx.Client | None = None,
161
+ max_retries: int | NotGiven = not_given,
162
+ default_headers: Mapping[str, str] | None = None,
163
+ set_default_headers: Mapping[str, str] | None = None,
164
+ default_query: Mapping[str, object] | None = None,
165
+ set_default_query: Mapping[str, object] | None = None,
166
+ _extra_kwargs: Mapping[str, Any] = {},
167
+ ) -> Self:
168
+ """
169
+ Create a new client instance re-using the same options given to the current client with optional overriding.
170
+ """
171
+ if default_headers is not None and set_default_headers is not None:
172
+ raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive")
173
+
174
+ if default_query is not None and set_default_query is not None:
175
+ raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive")
176
+
177
+ headers = self._custom_headers
178
+ if default_headers is not None:
179
+ headers = {**headers, **default_headers}
180
+ elif set_default_headers is not None:
181
+ headers = set_default_headers
182
+
183
+ params = self._custom_query
184
+ if default_query is not None:
185
+ params = {**params, **default_query}
186
+ elif set_default_query is not None:
187
+ params = set_default_query
188
+
189
+ http_client = http_client or self._client
190
+ return self.__class__(
191
+ api_key=api_key or self.api_key,
192
+ base_url=base_url or self.base_url,
193
+ timeout=self.timeout if isinstance(timeout, NotGiven) else timeout,
194
+ http_client=http_client,
195
+ max_retries=max_retries if is_given(max_retries) else self.max_retries,
196
+ default_headers=headers,
197
+ default_query=params,
198
+ **_extra_kwargs,
199
+ )
200
+
201
+ # Alias for `copy` for nicer inline usage, e.g.
202
+ # client.with_options(timeout=10).foo.create(...)
203
+ with_options = copy
204
+
205
+ @override
206
+ def _make_status_error(
207
+ self,
208
+ err_msg: str,
209
+ *,
210
+ body: object,
211
+ response: httpx.Response,
212
+ ) -> APIStatusError:
213
+ if response.status_code == 400:
214
+ return _exceptions.BadRequestError(err_msg, response=response, body=body)
215
+
216
+ if response.status_code == 401:
217
+ return _exceptions.AuthenticationError(err_msg, response=response, body=body)
218
+
219
+ if response.status_code == 403:
220
+ return _exceptions.PermissionDeniedError(err_msg, response=response, body=body)
221
+
222
+ if response.status_code == 404:
223
+ return _exceptions.NotFoundError(err_msg, response=response, body=body)
224
+
225
+ if response.status_code == 409:
226
+ return _exceptions.ConflictError(err_msg, response=response, body=body)
227
+
228
+ if response.status_code == 422:
229
+ return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body)
230
+
231
+ if response.status_code == 429:
232
+ return _exceptions.RateLimitError(err_msg, response=response, body=body)
233
+
234
+ if response.status_code >= 500:
235
+ return _exceptions.InternalServerError(err_msg, response=response, body=body)
236
+ return APIStatusError(err_msg, response=response, body=body)
237
+
238
+
239
+ class AsyncPerplexity(AsyncAPIClient):
240
+ # client options
241
+ api_key: str
242
+
243
+ def __init__(
244
+ self,
245
+ *,
246
+ api_key: str | None = None,
247
+ base_url: str | httpx.URL | None = None,
248
+ timeout: float | Timeout | None | NotGiven = not_given,
249
+ max_retries: int = DEFAULT_MAX_RETRIES,
250
+ default_headers: Mapping[str, str] | None = None,
251
+ default_query: Mapping[str, object] | None = None,
252
+ # Configure a custom httpx client.
253
+ # We provide a `DefaultAsyncHttpxClient` class that you can pass to retain the default values we use for `limits`, `timeout` & `follow_redirects`.
254
+ # See the [httpx documentation](https://www.python-httpx.org/api/#asyncclient) for more details.
255
+ http_client: httpx.AsyncClient | None = None,
256
+ # Enable or disable schema validation for data returned by the API.
257
+ # When enabled an error APIResponseValidationError is raised
258
+ # if the API responds with invalid data for the expected schema.
259
+ #
260
+ # This parameter may be removed or changed in the future.
261
+ # If you rely on this feature, please open a GitHub issue
262
+ # outlining your use-case to help us decide if it should be
263
+ # part of our public interface in the future.
264
+ _strict_response_validation: bool = False,
265
+ ) -> None:
266
+ """Construct a new async AsyncPerplexity client instance.
267
+
268
+ This automatically infers the `api_key` argument from the `PERPLEXITY_API_KEY` environment variable if it is not provided.
269
+ """
270
+ if api_key is None:
271
+ api_key = os.environ.get("PERPLEXITY_API_KEY")
272
+ if api_key is None:
273
+ raise PerplexityError(
274
+ "The api_key client option must be set either by passing api_key to the client or by setting the PERPLEXITY_API_KEY environment variable"
275
+ )
276
+ self.api_key = api_key
277
+
278
+ if base_url is None:
279
+ base_url = os.environ.get("PERPLEXITY_BASE_URL")
280
+ if base_url is None:
281
+ base_url = f"https://api.perplexity.ai"
282
+
283
+ super().__init__(
284
+ version=__version__,
285
+ base_url=base_url,
286
+ max_retries=max_retries,
287
+ timeout=timeout,
288
+ http_client=http_client,
289
+ custom_headers=default_headers,
290
+ custom_query=default_query,
291
+ _strict_response_validation=_strict_response_validation,
292
+ )
293
+
294
+ self._default_stream_cls = AsyncStream
295
+
296
+ @cached_property
297
+ def chat(self) -> AsyncChatResource:
298
+ from .resources.chat import AsyncChatResource
299
+
300
+ return AsyncChatResource(self)
301
+
302
+ @cached_property
303
+ def search(self) -> AsyncSearchResource:
304
+ from .resources.search import AsyncSearchResource
305
+
306
+ return AsyncSearchResource(self)
307
+
308
+ @cached_property
309
+ def async_(self) -> AsyncAsyncResource:
310
+ from .resources.async_ import AsyncAsyncResource
311
+
312
+ return AsyncAsyncResource(self)
313
+
314
+ @cached_property
315
+ def with_raw_response(self) -> AsyncPerplexityWithRawResponse:
316
+ return AsyncPerplexityWithRawResponse(self)
317
+
318
+ @cached_property
319
+ def with_streaming_response(self) -> AsyncPerplexityWithStreamedResponse:
320
+ return AsyncPerplexityWithStreamedResponse(self)
321
+
322
+ @property
323
+ @override
324
+ def qs(self) -> Querystring:
325
+ return Querystring(array_format="comma")
326
+
327
+ @property
328
+ @override
329
+ def auth_headers(self) -> dict[str, str]:
330
+ api_key = self.api_key
331
+ return {"Authorization": f"Bearer {api_key}"}
332
+
333
+ @property
334
+ @override
335
+ def default_headers(self) -> dict[str, str | Omit]:
336
+ return {
337
+ **super().default_headers,
338
+ "X-Stainless-Async": f"async:{get_async_library()}",
339
+ **self._custom_headers,
340
+ }
341
+
342
+ def copy(
343
+ self,
344
+ *,
345
+ api_key: str | None = None,
346
+ base_url: str | httpx.URL | None = None,
347
+ timeout: float | Timeout | None | NotGiven = not_given,
348
+ http_client: httpx.AsyncClient | None = None,
349
+ max_retries: int | NotGiven = not_given,
350
+ default_headers: Mapping[str, str] | None = None,
351
+ set_default_headers: Mapping[str, str] | None = None,
352
+ default_query: Mapping[str, object] | None = None,
353
+ set_default_query: Mapping[str, object] | None = None,
354
+ _extra_kwargs: Mapping[str, Any] = {},
355
+ ) -> Self:
356
+ """
357
+ Create a new client instance re-using the same options given to the current client with optional overriding.
358
+ """
359
+ if default_headers is not None and set_default_headers is not None:
360
+ raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive")
361
+
362
+ if default_query is not None and set_default_query is not None:
363
+ raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive")
364
+
365
+ headers = self._custom_headers
366
+ if default_headers is not None:
367
+ headers = {**headers, **default_headers}
368
+ elif set_default_headers is not None:
369
+ headers = set_default_headers
370
+
371
+ params = self._custom_query
372
+ if default_query is not None:
373
+ params = {**params, **default_query}
374
+ elif set_default_query is not None:
375
+ params = set_default_query
376
+
377
+ http_client = http_client or self._client
378
+ return self.__class__(
379
+ api_key=api_key or self.api_key,
380
+ base_url=base_url or self.base_url,
381
+ timeout=self.timeout if isinstance(timeout, NotGiven) else timeout,
382
+ http_client=http_client,
383
+ max_retries=max_retries if is_given(max_retries) else self.max_retries,
384
+ default_headers=headers,
385
+ default_query=params,
386
+ **_extra_kwargs,
387
+ )
388
+
389
+ # Alias for `copy` for nicer inline usage, e.g.
390
+ # client.with_options(timeout=10).foo.create(...)
391
+ with_options = copy
392
+
393
+ @override
394
+ def _make_status_error(
395
+ self,
396
+ err_msg: str,
397
+ *,
398
+ body: object,
399
+ response: httpx.Response,
400
+ ) -> APIStatusError:
401
+ if response.status_code == 400:
402
+ return _exceptions.BadRequestError(err_msg, response=response, body=body)
403
+
404
+ if response.status_code == 401:
405
+ return _exceptions.AuthenticationError(err_msg, response=response, body=body)
406
+
407
+ if response.status_code == 403:
408
+ return _exceptions.PermissionDeniedError(err_msg, response=response, body=body)
409
+
410
+ if response.status_code == 404:
411
+ return _exceptions.NotFoundError(err_msg, response=response, body=body)
412
+
413
+ if response.status_code == 409:
414
+ return _exceptions.ConflictError(err_msg, response=response, body=body)
415
+
416
+ if response.status_code == 422:
417
+ return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body)
418
+
419
+ if response.status_code == 429:
420
+ return _exceptions.RateLimitError(err_msg, response=response, body=body)
421
+
422
+ if response.status_code >= 500:
423
+ return _exceptions.InternalServerError(err_msg, response=response, body=body)
424
+ return APIStatusError(err_msg, response=response, body=body)
425
+
426
+
427
+ class PerplexityWithRawResponse:
428
+ _client: Perplexity
429
+
430
+ def __init__(self, client: Perplexity) -> None:
431
+ self._client = client
432
+
433
+ @cached_property
434
+ def chat(self) -> chat.ChatResourceWithRawResponse:
435
+ from .resources.chat import ChatResourceWithRawResponse
436
+
437
+ return ChatResourceWithRawResponse(self._client.chat)
438
+
439
+ @cached_property
440
+ def search(self) -> search.SearchResourceWithRawResponse:
441
+ from .resources.search import SearchResourceWithRawResponse
442
+
443
+ return SearchResourceWithRawResponse(self._client.search)
444
+
445
+ @cached_property
446
+ def async_(self) -> async_.AsyncResourceWithRawResponse:
447
+ from .resources.async_ import AsyncResourceWithRawResponse
448
+
449
+ return AsyncResourceWithRawResponse(self._client.async_)
450
+
451
+
452
+ class AsyncPerplexityWithRawResponse:
453
+ _client: AsyncPerplexity
454
+
455
+ def __init__(self, client: AsyncPerplexity) -> None:
456
+ self._client = client
457
+
458
+ @cached_property
459
+ def chat(self) -> chat.AsyncChatResourceWithRawResponse:
460
+ from .resources.chat import AsyncChatResourceWithRawResponse
461
+
462
+ return AsyncChatResourceWithRawResponse(self._client.chat)
463
+
464
+ @cached_property
465
+ def search(self) -> search.AsyncSearchResourceWithRawResponse:
466
+ from .resources.search import AsyncSearchResourceWithRawResponse
467
+
468
+ return AsyncSearchResourceWithRawResponse(self._client.search)
469
+
470
+ @cached_property
471
+ def async_(self) -> async_.AsyncAsyncResourceWithRawResponse:
472
+ from .resources.async_ import AsyncAsyncResourceWithRawResponse
473
+
474
+ return AsyncAsyncResourceWithRawResponse(self._client.async_)
475
+
476
+
477
+ class PerplexityWithStreamedResponse:
478
+ _client: Perplexity
479
+
480
+ def __init__(self, client: Perplexity) -> None:
481
+ self._client = client
482
+
483
+ @cached_property
484
+ def chat(self) -> chat.ChatResourceWithStreamingResponse:
485
+ from .resources.chat import ChatResourceWithStreamingResponse
486
+
487
+ return ChatResourceWithStreamingResponse(self._client.chat)
488
+
489
+ @cached_property
490
+ def search(self) -> search.SearchResourceWithStreamingResponse:
491
+ from .resources.search import SearchResourceWithStreamingResponse
492
+
493
+ return SearchResourceWithStreamingResponse(self._client.search)
494
+
495
+ @cached_property
496
+ def async_(self) -> async_.AsyncResourceWithStreamingResponse:
497
+ from .resources.async_ import AsyncResourceWithStreamingResponse
498
+
499
+ return AsyncResourceWithStreamingResponse(self._client.async_)
500
+
501
+
502
+ class AsyncPerplexityWithStreamedResponse:
503
+ _client: AsyncPerplexity
504
+
505
+ def __init__(self, client: AsyncPerplexity) -> None:
506
+ self._client = client
507
+
508
+ @cached_property
509
+ def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
510
+ from .resources.chat import AsyncChatResourceWithStreamingResponse
511
+
512
+ return AsyncChatResourceWithStreamingResponse(self._client.chat)
513
+
514
+ @cached_property
515
+ def search(self) -> search.AsyncSearchResourceWithStreamingResponse:
516
+ from .resources.search import AsyncSearchResourceWithStreamingResponse
517
+
518
+ return AsyncSearchResourceWithStreamingResponse(self._client.search)
519
+
520
+ @cached_property
521
+ def async_(self) -> async_.AsyncAsyncResourceWithStreamingResponse:
522
+ from .resources.async_ import AsyncAsyncResourceWithStreamingResponse
523
+
524
+ return AsyncAsyncResourceWithStreamingResponse(self._client.async_)
525
+
526
+
527
+ Client = Perplexity
528
+
529
+ AsyncClient = AsyncPerplexity