promptlayer 1.0.71__tar.gz → 1.0.73__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 promptlayer might be problematic. Click here for more details.
- {promptlayer-1.0.71 → promptlayer-1.0.73}/PKG-INFO +3 -1
- promptlayer-1.0.73/promptlayer/__init__.py +39 -0
- promptlayer-1.0.73/promptlayer/exceptions.py +119 -0
- promptlayer-1.0.73/promptlayer/groups/__init__.py +24 -0
- promptlayer-1.0.73/promptlayer/groups/groups.py +9 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/promptlayer.py +76 -28
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/promptlayer_base.py +19 -9
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/promptlayer_mixins.py +5 -3
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/span_exporter.py +16 -9
- promptlayer-1.0.73/promptlayer/templates.py +39 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/track/__init__.py +18 -10
- promptlayer-1.0.73/promptlayer/track/track.py +107 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/utils.py +717 -306
- {promptlayer-1.0.71 → promptlayer-1.0.73}/pyproject.toml +3 -2
- promptlayer-1.0.71/promptlayer/__init__.py +0 -4
- promptlayer-1.0.71/promptlayer/groups/__init__.py +0 -20
- promptlayer-1.0.71/promptlayer/groups/groups.py +0 -11
- promptlayer-1.0.71/promptlayer/templates.py +0 -35
- promptlayer-1.0.71/promptlayer/track/track.py +0 -82
- {promptlayer-1.0.71 → promptlayer-1.0.73}/LICENSE +0 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/README.md +0 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/streaming/__init__.py +0 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/streaming/blueprint_builder.py +0 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/streaming/response_handlers.py +0 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/streaming/stream_processor.py +0 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/types/__init__.py +0 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/types/prompt_template.py +0 -0
- {promptlayer-1.0.71 → promptlayer-1.0.73}/promptlayer/types/request_log.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: promptlayer
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.73
|
|
4
4
|
Summary: PromptLayer is a platform for prompt engineering and tracks your LLM requests.
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -17,11 +17,13 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.14
|
|
18
18
|
Requires-Dist: ably (>=2.0.11,<3.0.0)
|
|
19
19
|
Requires-Dist: aiohttp (>=3.10.10,<4.0.0)
|
|
20
|
+
Requires-Dist: centrifuge-python (>=0.4.1,<0.5.0)
|
|
20
21
|
Requires-Dist: httpx (>=0.28.1,<0.29.0)
|
|
21
22
|
Requires-Dist: nest-asyncio (>=1.6.0,<2.0.0)
|
|
22
23
|
Requires-Dist: opentelemetry-api (>=1.26.0,<2.0.0)
|
|
23
24
|
Requires-Dist: opentelemetry-sdk (>=1.26.0,<2.0.0)
|
|
24
25
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
26
|
+
Requires-Dist: tenacity (>=9.1.2,<10.0.0)
|
|
25
27
|
Description-Content-Type: text/markdown
|
|
26
28
|
|
|
27
29
|
<div align="center">
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from .exceptions import (
|
|
2
|
+
PromptLayerAPIConnectionError,
|
|
3
|
+
PromptLayerAPIError,
|
|
4
|
+
PromptLayerAPIStatusError,
|
|
5
|
+
PromptLayerAPITimeoutError,
|
|
6
|
+
PromptLayerAuthenticationError,
|
|
7
|
+
PromptLayerBadRequestError,
|
|
8
|
+
PromptLayerConflictError,
|
|
9
|
+
PromptLayerError,
|
|
10
|
+
PromptLayerInternalServerError,
|
|
11
|
+
PromptLayerNotFoundError,
|
|
12
|
+
PromptLayerPermissionDeniedError,
|
|
13
|
+
PromptLayerRateLimitError,
|
|
14
|
+
PromptLayerUnprocessableEntityError,
|
|
15
|
+
PromptLayerValidationError,
|
|
16
|
+
)
|
|
17
|
+
from .promptlayer import AsyncPromptLayer, PromptLayer
|
|
18
|
+
|
|
19
|
+
__version__ = "1.0.73"
|
|
20
|
+
__all__ = [
|
|
21
|
+
"PromptLayer",
|
|
22
|
+
"AsyncPromptLayer",
|
|
23
|
+
"__version__",
|
|
24
|
+
# Exceptions
|
|
25
|
+
"PromptLayerError",
|
|
26
|
+
"PromptLayerAPIError",
|
|
27
|
+
"PromptLayerBadRequestError",
|
|
28
|
+
"PromptLayerAuthenticationError",
|
|
29
|
+
"PromptLayerPermissionDeniedError",
|
|
30
|
+
"PromptLayerNotFoundError",
|
|
31
|
+
"PromptLayerConflictError",
|
|
32
|
+
"PromptLayerUnprocessableEntityError",
|
|
33
|
+
"PromptLayerRateLimitError",
|
|
34
|
+
"PromptLayerInternalServerError",
|
|
35
|
+
"PromptLayerAPIStatusError",
|
|
36
|
+
"PromptLayerAPIConnectionError",
|
|
37
|
+
"PromptLayerAPITimeoutError",
|
|
38
|
+
"PromptLayerValidationError",
|
|
39
|
+
]
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
class PromptLayerError(Exception):
|
|
2
|
+
"""Base exception for all PromptLayer SDK errors."""
|
|
3
|
+
|
|
4
|
+
def __init__(self, message: str, response=None, body=None):
|
|
5
|
+
super().__init__(message)
|
|
6
|
+
self.message = message
|
|
7
|
+
self.response = response
|
|
8
|
+
self.body = body
|
|
9
|
+
|
|
10
|
+
def __str__(self):
|
|
11
|
+
return self.message
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PromptLayerAPIError(PromptLayerError):
|
|
15
|
+
"""Base exception for API-related errors."""
|
|
16
|
+
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PromptLayerBadRequestError(PromptLayerAPIError):
|
|
21
|
+
"""Exception raised for 400 Bad Request errors.
|
|
22
|
+
|
|
23
|
+
Indicates that the request was malformed or contained invalid parameters.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PromptLayerAuthenticationError(PromptLayerAPIError):
|
|
30
|
+
"""Exception raised for 401 Unauthorized errors.
|
|
31
|
+
|
|
32
|
+
Indicates that the API key is missing, invalid, or expired.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class PromptLayerPermissionDeniedError(PromptLayerAPIError):
|
|
39
|
+
"""Exception raised for 403 Forbidden errors.
|
|
40
|
+
|
|
41
|
+
Indicates that the API key doesn't have permission to perform the requested operation.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class PromptLayerNotFoundError(PromptLayerAPIError):
|
|
48
|
+
"""Exception raised for 404 Not Found errors.
|
|
49
|
+
|
|
50
|
+
Indicates that the requested resource (e.g., prompt template) was not found.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class PromptLayerConflictError(PromptLayerAPIError):
|
|
57
|
+
"""Exception raised for 409 Conflict errors.
|
|
58
|
+
|
|
59
|
+
Indicates that the request conflicts with the current state of the resource.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class PromptLayerUnprocessableEntityError(PromptLayerAPIError):
|
|
66
|
+
"""Exception raised for 422 Unprocessable Entity errors.
|
|
67
|
+
|
|
68
|
+
Indicates that the request was well-formed but contains semantic errors.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class PromptLayerRateLimitError(PromptLayerAPIError):
|
|
75
|
+
"""Exception raised for 429 Too Many Requests errors.
|
|
76
|
+
|
|
77
|
+
Indicates that the API rate limit has been exceeded.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
pass
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class PromptLayerInternalServerError(PromptLayerAPIError):
|
|
84
|
+
"""Exception raised for 500+ Internal Server errors.
|
|
85
|
+
|
|
86
|
+
Indicates that the PromptLayer API encountered an internal error.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class PromptLayerAPIStatusError(PromptLayerAPIError):
|
|
93
|
+
"""Exception raised for other API errors not covered by specific exception classes."""
|
|
94
|
+
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class PromptLayerAPIConnectionError(PromptLayerError):
|
|
99
|
+
"""Exception raised when unable to connect to the API.
|
|
100
|
+
|
|
101
|
+
This can be due to network issues, timeouts, or connection errors.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
pass
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class PromptLayerAPITimeoutError(PromptLayerError):
|
|
108
|
+
"""Exception raised when an API request times out."""
|
|
109
|
+
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class PromptLayerValidationError(PromptLayerError):
|
|
114
|
+
"""Exception raised when input validation fails.
|
|
115
|
+
|
|
116
|
+
This can be due to invalid types, out of range values, or malformed data.
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
pass
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from promptlayer.groups.groups import acreate, create
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class GroupManager:
|
|
5
|
+
def __init__(self, api_key: str, base_url: str, throw_on_error: bool):
|
|
6
|
+
self.api_key = api_key
|
|
7
|
+
self.base_url = base_url
|
|
8
|
+
self.throw_on_error = throw_on_error
|
|
9
|
+
|
|
10
|
+
def create(self):
|
|
11
|
+
return create(self.api_key, self.base_url, self.throw_on_error)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AsyncGroupManager:
|
|
15
|
+
def __init__(self, api_key: str, base_url: str, throw_on_error: bool):
|
|
16
|
+
self.api_key = api_key
|
|
17
|
+
self.base_url = base_url
|
|
18
|
+
self.throw_on_error = throw_on_error
|
|
19
|
+
|
|
20
|
+
async def create(self):
|
|
21
|
+
return await acreate(self.api_key, self.base_url, self.throw_on_error)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
__all__ = ["GroupManager", "AsyncGroupManager"]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from promptlayer.utils import apromptlayer_create_group, promptlayer_create_group
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def create(api_key: str, base_url: str, throw_on_error: bool):
|
|
5
|
+
return promptlayer_create_group(api_key, base_url, throw_on_error)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
async def acreate(api_key: str, base_url: str, throw_on_error: bool):
|
|
9
|
+
return await apromptlayer_create_group(api_key, base_url, throw_on_error)
|
|
@@ -6,6 +6,7 @@ from typing import Any, Dict, List, Literal, Optional, Union
|
|
|
6
6
|
|
|
7
7
|
import nest_asyncio
|
|
8
8
|
|
|
9
|
+
from promptlayer import exceptions as _exceptions
|
|
9
10
|
from promptlayer.groups import AsyncGroupManager, GroupManager
|
|
10
11
|
from promptlayer.promptlayer_base import PromptLayerBase
|
|
11
12
|
from promptlayer.promptlayer_mixins import PromptLayerMixin
|
|
@@ -26,6 +27,10 @@ from promptlayer.utils import (
|
|
|
26
27
|
logger = logging.getLogger(__name__)
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
def get_base_url(base_url: Union[str, None]):
|
|
31
|
+
return base_url or os.environ.get("PROMPTLAYER_BASE_URL", "https://api.promptlayer.com")
|
|
32
|
+
|
|
33
|
+
|
|
29
34
|
def is_workflow_results_dict(obj: Any) -> bool:
|
|
30
35
|
if not isinstance(obj, dict):
|
|
31
36
|
return False
|
|
@@ -50,8 +55,10 @@ def is_workflow_results_dict(obj: Any) -> bool:
|
|
|
50
55
|
class PromptLayer(PromptLayerMixin):
|
|
51
56
|
def __init__(
|
|
52
57
|
self,
|
|
53
|
-
api_key: str = None,
|
|
58
|
+
api_key: Union[str, None] = None,
|
|
54
59
|
enable_tracing: bool = False,
|
|
60
|
+
base_url: Union[str, None] = None,
|
|
61
|
+
throw_on_error: bool = True,
|
|
55
62
|
):
|
|
56
63
|
if api_key is None:
|
|
57
64
|
api_key = os.environ.get("PROMPTLAYER_API_KEY")
|
|
@@ -62,11 +69,15 @@ class PromptLayer(PromptLayerMixin):
|
|
|
62
69
|
"Please set the PROMPTLAYER_API_KEY environment variable or pass the api_key parameter."
|
|
63
70
|
)
|
|
64
71
|
|
|
72
|
+
self.base_url = get_base_url(base_url)
|
|
65
73
|
self.api_key = api_key
|
|
66
|
-
self.
|
|
67
|
-
self.
|
|
68
|
-
self.
|
|
69
|
-
self.
|
|
74
|
+
self.throw_on_error = throw_on_error
|
|
75
|
+
self.templates = TemplateManager(api_key, self.base_url, self.throw_on_error)
|
|
76
|
+
self.group = GroupManager(api_key, self.base_url, self.throw_on_error)
|
|
77
|
+
self.tracer_provider, self.tracer = self._initialize_tracer(
|
|
78
|
+
api_key, self.base_url, self.throw_on_error, enable_tracing
|
|
79
|
+
)
|
|
80
|
+
self.track = TrackManager(api_key, self.base_url, self.throw_on_error)
|
|
70
81
|
|
|
71
82
|
def __getattr__(
|
|
72
83
|
self,
|
|
@@ -75,15 +86,18 @@ class PromptLayer(PromptLayerMixin):
|
|
|
75
86
|
if name == "openai":
|
|
76
87
|
import openai as openai_module
|
|
77
88
|
|
|
78
|
-
return PromptLayerBase(
|
|
89
|
+
return PromptLayerBase(
|
|
90
|
+
self.api_key, self.base_url, openai_module, function_name="openai", tracer=self.tracer
|
|
91
|
+
)
|
|
79
92
|
elif name == "anthropic":
|
|
80
93
|
import anthropic as anthropic_module
|
|
81
94
|
|
|
82
95
|
return PromptLayerBase(
|
|
96
|
+
self.api_key,
|
|
97
|
+
self.base_url,
|
|
83
98
|
anthropic_module,
|
|
84
99
|
function_name="anthropic",
|
|
85
100
|
provider_type="anthropic",
|
|
86
|
-
api_key=self.api_key,
|
|
87
101
|
tracer=self.tracer,
|
|
88
102
|
)
|
|
89
103
|
else:
|
|
@@ -108,7 +122,7 @@ class PromptLayer(PromptLayerMixin):
|
|
|
108
122
|
pl_run_span_id,
|
|
109
123
|
**body,
|
|
110
124
|
)
|
|
111
|
-
return track_request(**track_request_kwargs)
|
|
125
|
+
return track_request(self.base_url, self.throw_on_error, **track_request_kwargs)
|
|
112
126
|
|
|
113
127
|
return _track_request
|
|
114
128
|
|
|
@@ -138,6 +152,12 @@ class PromptLayer(PromptLayerMixin):
|
|
|
138
152
|
model_parameter_overrides=model_parameter_overrides,
|
|
139
153
|
)
|
|
140
154
|
prompt_blueprint = self.templates.get(prompt_name, get_prompt_template_params)
|
|
155
|
+
if not prompt_blueprint:
|
|
156
|
+
raise _exceptions.PromptLayerNotFoundError(
|
|
157
|
+
f"Prompt template '{prompt_name}' not found.",
|
|
158
|
+
response=None,
|
|
159
|
+
body=None,
|
|
160
|
+
)
|
|
141
161
|
prompt_blueprint_model = self._validate_and_extract_model_from_prompt_blueprint(
|
|
142
162
|
prompt_blueprint=prompt_blueprint, prompt_name=prompt_name
|
|
143
163
|
)
|
|
@@ -212,7 +232,7 @@ class PromptLayer(PromptLayerMixin):
|
|
|
212
232
|
metadata=metadata,
|
|
213
233
|
**body,
|
|
214
234
|
)
|
|
215
|
-
return track_request(**track_request_kwargs)
|
|
235
|
+
return track_request(self.base_url, self.throw_on_error, **track_request_kwargs)
|
|
216
236
|
|
|
217
237
|
def run(
|
|
218
238
|
self,
|
|
@@ -277,12 +297,14 @@ class PromptLayer(PromptLayerMixin):
|
|
|
277
297
|
|
|
278
298
|
results = asyncio.run(
|
|
279
299
|
arun_workflow_request(
|
|
300
|
+
api_key=self.api_key,
|
|
301
|
+
base_url=self.base_url,
|
|
302
|
+
throw_on_error=self.throw_on_error,
|
|
280
303
|
workflow_id_or_name=_get_workflow_workflow_id_or_name(workflow_id_or_name, workflow_name),
|
|
281
304
|
input_variables=input_variables or {},
|
|
282
305
|
metadata=metadata,
|
|
283
306
|
workflow_label_name=workflow_label_name,
|
|
284
307
|
workflow_version_number=workflow_version,
|
|
285
|
-
api_key=self.api_key,
|
|
286
308
|
return_all_outputs=return_all_outputs,
|
|
287
309
|
)
|
|
288
310
|
)
|
|
@@ -290,10 +312,16 @@ class PromptLayer(PromptLayerMixin):
|
|
|
290
312
|
if not return_all_outputs and is_workflow_results_dict(results):
|
|
291
313
|
output_nodes = [node_data for node_data in results.values() if node_data.get("is_output_node")]
|
|
292
314
|
if not output_nodes:
|
|
293
|
-
raise
|
|
315
|
+
raise _exceptions.PromptLayerNotFoundError(
|
|
316
|
+
f"Output nodes not found: {json.dumps(results, indent=4)}", response=None, body=results
|
|
317
|
+
)
|
|
294
318
|
|
|
295
319
|
if not any(node.get("status") == "SUCCESS" for node in output_nodes):
|
|
296
|
-
raise
|
|
320
|
+
raise _exceptions.PromptLayerAPIError(
|
|
321
|
+
f"None of the output nodes have succeeded: {json.dumps(results, indent=4)}",
|
|
322
|
+
response=None,
|
|
323
|
+
body=results,
|
|
324
|
+
)
|
|
297
325
|
|
|
298
326
|
return results
|
|
299
327
|
except Exception as ex:
|
|
@@ -301,7 +329,9 @@ class PromptLayer(PromptLayerMixin):
|
|
|
301
329
|
if RERAISE_ORIGINAL_EXCEPTION:
|
|
302
330
|
raise
|
|
303
331
|
else:
|
|
304
|
-
raise
|
|
332
|
+
raise _exceptions.PromptLayerAPIError(
|
|
333
|
+
f"Error running workflow: {str(ex)}", response=None, body=None
|
|
334
|
+
) from ex
|
|
305
335
|
|
|
306
336
|
def log_request(
|
|
307
337
|
self,
|
|
@@ -330,6 +360,8 @@ class PromptLayer(PromptLayerMixin):
|
|
|
330
360
|
):
|
|
331
361
|
return util_log_request(
|
|
332
362
|
self.api_key,
|
|
363
|
+
self.base_url,
|
|
364
|
+
throw_on_error=self.throw_on_error,
|
|
333
365
|
provider=provider,
|
|
334
366
|
model=model,
|
|
335
367
|
input=input,
|
|
@@ -355,8 +387,10 @@ class PromptLayer(PromptLayerMixin):
|
|
|
355
387
|
class AsyncPromptLayer(PromptLayerMixin):
|
|
356
388
|
def __init__(
|
|
357
389
|
self,
|
|
358
|
-
api_key: str = None,
|
|
390
|
+
api_key: Union[str, None] = None,
|
|
359
391
|
enable_tracing: bool = False,
|
|
392
|
+
base_url: Union[str, None] = None,
|
|
393
|
+
throw_on_error: bool = True,
|
|
360
394
|
):
|
|
361
395
|
if api_key is None:
|
|
362
396
|
api_key = os.environ.get("PROMPTLAYER_API_KEY")
|
|
@@ -367,31 +401,33 @@ class AsyncPromptLayer(PromptLayerMixin):
|
|
|
367
401
|
"Please set the PROMPTLAYER_API_KEY environment variable or pass the api_key parameter."
|
|
368
402
|
)
|
|
369
403
|
|
|
404
|
+
self.base_url = get_base_url(base_url)
|
|
370
405
|
self.api_key = api_key
|
|
371
|
-
self.
|
|
372
|
-
self.
|
|
373
|
-
self.
|
|
374
|
-
self.
|
|
406
|
+
self.throw_on_error = throw_on_error
|
|
407
|
+
self.templates = AsyncTemplateManager(api_key, self.base_url, self.throw_on_error)
|
|
408
|
+
self.group = AsyncGroupManager(api_key, self.base_url, self.throw_on_error)
|
|
409
|
+
self.tracer_provider, self.tracer = self._initialize_tracer(
|
|
410
|
+
api_key, self.base_url, self.throw_on_error, enable_tracing
|
|
411
|
+
)
|
|
412
|
+
self.track = AsyncTrackManager(api_key, self.base_url, self.throw_on_error)
|
|
375
413
|
|
|
376
414
|
def __getattr__(self, name: Union[Literal["openai"], Literal["anthropic"], Literal["prompts"]]):
|
|
377
415
|
if name == "openai":
|
|
378
416
|
import openai as openai_module
|
|
379
417
|
|
|
380
418
|
openai = PromptLayerBase(
|
|
381
|
-
openai_module,
|
|
382
|
-
function_name="openai",
|
|
383
|
-
api_key=self.api_key,
|
|
384
|
-
tracer=self.tracer,
|
|
419
|
+
self.api_key, self.base_url, openai_module, function_name="openai", tracer=self.tracer
|
|
385
420
|
)
|
|
386
421
|
return openai
|
|
387
422
|
elif name == "anthropic":
|
|
388
423
|
import anthropic as anthropic_module
|
|
389
424
|
|
|
390
425
|
anthropic = PromptLayerBase(
|
|
426
|
+
self.api_key,
|
|
427
|
+
self.base_url,
|
|
391
428
|
anthropic_module,
|
|
392
429
|
function_name="anthropic",
|
|
393
430
|
provider_type="anthropic",
|
|
394
|
-
api_key=self.api_key,
|
|
395
431
|
tracer=self.tracer,
|
|
396
432
|
)
|
|
397
433
|
return anthropic
|
|
@@ -413,12 +449,14 @@ class AsyncPromptLayer(PromptLayerMixin):
|
|
|
413
449
|
) -> Union[Dict[str, Any], Any]:
|
|
414
450
|
try:
|
|
415
451
|
return await arun_workflow_request(
|
|
452
|
+
api_key=self.api_key,
|
|
453
|
+
base_url=self.base_url,
|
|
454
|
+
throw_on_error=self.throw_on_error,
|
|
416
455
|
workflow_id_or_name=_get_workflow_workflow_id_or_name(workflow_id_or_name, workflow_name),
|
|
417
456
|
input_variables=input_variables or {},
|
|
418
457
|
metadata=metadata,
|
|
419
458
|
workflow_label_name=workflow_label_name,
|
|
420
459
|
workflow_version_number=workflow_version,
|
|
421
|
-
api_key=self.api_key,
|
|
422
460
|
return_all_outputs=return_all_outputs,
|
|
423
461
|
)
|
|
424
462
|
except Exception as ex:
|
|
@@ -426,7 +464,9 @@ class AsyncPromptLayer(PromptLayerMixin):
|
|
|
426
464
|
if RERAISE_ORIGINAL_EXCEPTION:
|
|
427
465
|
raise
|
|
428
466
|
else:
|
|
429
|
-
raise
|
|
467
|
+
raise _exceptions.PromptLayerAPIError(
|
|
468
|
+
f"Error running workflow: {str(ex)}", response=None, body=None
|
|
469
|
+
) from ex
|
|
430
470
|
|
|
431
471
|
async def run(
|
|
432
472
|
self,
|
|
@@ -491,6 +531,8 @@ class AsyncPromptLayer(PromptLayerMixin):
|
|
|
491
531
|
):
|
|
492
532
|
return await autil_log_request(
|
|
493
533
|
self.api_key,
|
|
534
|
+
self.base_url,
|
|
535
|
+
throw_on_error=self.throw_on_error,
|
|
494
536
|
provider=provider,
|
|
495
537
|
model=model,
|
|
496
538
|
input=input,
|
|
@@ -530,7 +572,7 @@ class AsyncPromptLayer(PromptLayerMixin):
|
|
|
530
572
|
pl_run_span_id,
|
|
531
573
|
**body,
|
|
532
574
|
)
|
|
533
|
-
return await atrack_request(**track_request_kwargs)
|
|
575
|
+
return await atrack_request(self.base_url, self.throw_on_error, **track_request_kwargs)
|
|
534
576
|
|
|
535
577
|
return _track_request
|
|
536
578
|
|
|
@@ -554,7 +596,7 @@ class AsyncPromptLayer(PromptLayerMixin):
|
|
|
554
596
|
metadata=metadata,
|
|
555
597
|
**body,
|
|
556
598
|
)
|
|
557
|
-
return await atrack_request(**track_request_kwargs)
|
|
599
|
+
return await atrack_request(self.base_url, self.throw_on_error, **track_request_kwargs)
|
|
558
600
|
|
|
559
601
|
async def _run_internal(
|
|
560
602
|
self,
|
|
@@ -582,6 +624,12 @@ class AsyncPromptLayer(PromptLayerMixin):
|
|
|
582
624
|
model_parameter_overrides=model_parameter_overrides,
|
|
583
625
|
)
|
|
584
626
|
prompt_blueprint = await self.templates.get(prompt_name, get_prompt_template_params)
|
|
627
|
+
if not prompt_blueprint:
|
|
628
|
+
raise _exceptions.PromptLayerNotFoundError(
|
|
629
|
+
f"Prompt template '{prompt_name}' not found.",
|
|
630
|
+
response=None,
|
|
631
|
+
body=None,
|
|
632
|
+
)
|
|
585
633
|
prompt_blueprint_model = self._validate_and_extract_model_from_prompt_blueprint(
|
|
586
634
|
prompt_blueprint=prompt_blueprint, prompt_name=prompt_name
|
|
587
635
|
)
|
|
@@ -631,6 +679,6 @@ class AsyncPromptLayer(PromptLayerMixin):
|
|
|
631
679
|
|
|
632
680
|
return {
|
|
633
681
|
"request_id": request_log.get("request_id", None),
|
|
634
|
-
"raw_response":
|
|
682
|
+
"raw_response": response,
|
|
635
683
|
"prompt_blueprint": request_log.get("prompt_blueprint", None),
|
|
636
684
|
}
|
|
@@ -2,6 +2,7 @@ import datetime
|
|
|
2
2
|
import inspect
|
|
3
3
|
import re
|
|
4
4
|
|
|
5
|
+
from promptlayer import exceptions as _exceptions
|
|
5
6
|
from promptlayer.utils import async_wrapper, promptlayer_api_handler
|
|
6
7
|
|
|
7
8
|
|
|
@@ -13,14 +14,16 @@ class PromptLayerBase(object):
|
|
|
13
14
|
"_provider_type",
|
|
14
15
|
"_api_key",
|
|
15
16
|
"_tracer",
|
|
17
|
+
"_base_url",
|
|
16
18
|
]
|
|
17
19
|
|
|
18
|
-
def __init__(self, obj, function_name="", provider_type="openai",
|
|
20
|
+
def __init__(self, api_key: str, base_url: str, obj, function_name="", provider_type="openai", tracer=None):
|
|
19
21
|
object.__setattr__(self, "_obj", obj)
|
|
20
22
|
object.__setattr__(self, "_function_name", function_name)
|
|
21
23
|
object.__setattr__(self, "_provider_type", provider_type)
|
|
22
24
|
object.__setattr__(self, "_api_key", api_key)
|
|
23
25
|
object.__setattr__(self, "_tracer", tracer)
|
|
26
|
+
object.__setattr__(self, "_base_url", base_url)
|
|
24
27
|
|
|
25
28
|
def __getattr__(self, name):
|
|
26
29
|
attr = getattr(object.__getattribute__(self, "_obj"), name)
|
|
@@ -41,10 +44,11 @@ class PromptLayerBase(object):
|
|
|
41
44
|
)
|
|
42
45
|
):
|
|
43
46
|
return PromptLayerBase(
|
|
47
|
+
object.__getattribute__(self, "_api_key"),
|
|
48
|
+
object.__getattribute__(self, "_base_url"),
|
|
44
49
|
attr,
|
|
45
50
|
function_name=f"{object.__getattribute__(self, '_function_name')}.{name}",
|
|
46
51
|
provider_type=object.__getattribute__(self, "_provider_type"),
|
|
47
|
-
api_key=object.__getattribute__(self, "_api_key"),
|
|
48
52
|
tracer=object.__getattribute__(self, "_tracer"),
|
|
49
53
|
)
|
|
50
54
|
return attr
|
|
@@ -58,7 +62,7 @@ class PromptLayerBase(object):
|
|
|
58
62
|
def __call__(self, *args, **kwargs):
|
|
59
63
|
tags = kwargs.pop("pl_tags", None)
|
|
60
64
|
if tags is not None and not isinstance(tags, list):
|
|
61
|
-
raise
|
|
65
|
+
raise _exceptions.PromptLayerValidationError("pl_tags must be a list of strings.", response=None, body=None)
|
|
62
66
|
|
|
63
67
|
return_pl_id = kwargs.pop("return_pl_id", False)
|
|
64
68
|
request_start_time = datetime.datetime.now().timestamp()
|
|
@@ -75,10 +79,11 @@ class PromptLayerBase(object):
|
|
|
75
79
|
|
|
76
80
|
if inspect.isclass(function_object):
|
|
77
81
|
result = PromptLayerBase(
|
|
82
|
+
object.__getattribute__(self, "_api_key"),
|
|
83
|
+
object.__getattribute__(self, "_base_url"),
|
|
78
84
|
function_object(*args, **kwargs),
|
|
79
85
|
function_name=function_name,
|
|
80
86
|
provider_type=object.__getattribute__(self, "_provider_type"),
|
|
81
|
-
api_key=object.__getattribute__(self, "_api_key"),
|
|
82
87
|
tracer=tracer,
|
|
83
88
|
)
|
|
84
89
|
llm_request_span.set_attribute("function_output", str(result))
|
|
@@ -88,13 +93,14 @@ class PromptLayerBase(object):
|
|
|
88
93
|
|
|
89
94
|
if inspect.iscoroutinefunction(function_object) or inspect.iscoroutine(function_response):
|
|
90
95
|
return async_wrapper(
|
|
96
|
+
object.__getattribute__(self, "_api_key"),
|
|
97
|
+
object.__getattribute__(self, "_base_url"),
|
|
91
98
|
function_response,
|
|
92
99
|
return_pl_id,
|
|
93
100
|
request_start_time,
|
|
94
101
|
function_name,
|
|
95
102
|
object.__getattribute__(self, "_provider_type"),
|
|
96
103
|
tags,
|
|
97
|
-
api_key=object.__getattribute__(self, "_api_key"),
|
|
98
104
|
llm_request_span_id=llm_request_span_id,
|
|
99
105
|
tracer=tracer, # Pass the tracer to async_wrapper
|
|
100
106
|
*args,
|
|
@@ -103,6 +109,8 @@ class PromptLayerBase(object):
|
|
|
103
109
|
|
|
104
110
|
request_end_time = datetime.datetime.now().timestamp()
|
|
105
111
|
result = promptlayer_api_handler(
|
|
112
|
+
object.__getattribute__(self, "_api_key"),
|
|
113
|
+
object.__getattribute__(self, "_base_url"),
|
|
106
114
|
function_name,
|
|
107
115
|
object.__getattribute__(self, "_provider_type"),
|
|
108
116
|
args,
|
|
@@ -111,7 +119,6 @@ class PromptLayerBase(object):
|
|
|
111
119
|
function_response,
|
|
112
120
|
request_start_time,
|
|
113
121
|
request_end_time,
|
|
114
|
-
object.__getattribute__(self, "_api_key"),
|
|
115
122
|
return_pl_id=return_pl_id,
|
|
116
123
|
llm_request_span_id=llm_request_span_id,
|
|
117
124
|
)
|
|
@@ -121,29 +128,33 @@ class PromptLayerBase(object):
|
|
|
121
128
|
# Without tracing
|
|
122
129
|
if inspect.isclass(function_object):
|
|
123
130
|
return PromptLayerBase(
|
|
131
|
+
object.__getattribute__(self, "_api_key"),
|
|
132
|
+
object.__getattribute__(self, "_base_url"),
|
|
124
133
|
function_object(*args, **kwargs),
|
|
125
134
|
function_name=function_name,
|
|
126
135
|
provider_type=object.__getattribute__(self, "_provider_type"),
|
|
127
|
-
api_key=object.__getattribute__(self, "_api_key"),
|
|
128
136
|
)
|
|
129
137
|
|
|
130
138
|
function_response = function_object(*args, **kwargs)
|
|
131
139
|
|
|
132
140
|
if inspect.iscoroutinefunction(function_object) or inspect.iscoroutine(function_response):
|
|
133
141
|
return async_wrapper(
|
|
142
|
+
object.__getattribute__(self, "_api_key"),
|
|
143
|
+
object.__getattribute__(self, "_base_url"),
|
|
134
144
|
function_response,
|
|
135
145
|
return_pl_id,
|
|
136
146
|
request_start_time,
|
|
137
147
|
function_name,
|
|
138
148
|
object.__getattribute__(self, "_provider_type"),
|
|
139
149
|
tags,
|
|
140
|
-
api_key=object.__getattribute__(self, "_api_key"),
|
|
141
150
|
*args,
|
|
142
151
|
**kwargs,
|
|
143
152
|
)
|
|
144
153
|
|
|
145
154
|
request_end_time = datetime.datetime.now().timestamp()
|
|
146
155
|
return promptlayer_api_handler(
|
|
156
|
+
object.__getattribute__(self, "_api_key"),
|
|
157
|
+
object.__getattribute__(self, "_base_url"),
|
|
147
158
|
function_name,
|
|
148
159
|
object.__getattribute__(self, "_provider_type"),
|
|
149
160
|
args,
|
|
@@ -152,6 +163,5 @@ class PromptLayerBase(object):
|
|
|
152
163
|
function_response,
|
|
153
164
|
request_start_time,
|
|
154
165
|
request_end_time,
|
|
155
|
-
object.__getattribute__(self, "_api_key"),
|
|
156
166
|
return_pl_id=return_pl_id,
|
|
157
167
|
)
|
|
@@ -262,11 +262,13 @@ AMAP_PROVIDER_TO_FUNCTION = {
|
|
|
262
262
|
|
|
263
263
|
class PromptLayerMixin:
|
|
264
264
|
@staticmethod
|
|
265
|
-
def _initialize_tracer(api_key: str
|
|
265
|
+
def _initialize_tracer(api_key: str, base_url: str, throw_on_error: bool, enable_tracing: bool = False):
|
|
266
266
|
if enable_tracing:
|
|
267
267
|
resource = Resource(attributes={ResourceAttributes.SERVICE_NAME: "prompt-layer-library"})
|
|
268
268
|
tracer_provider = TracerProvider(resource=resource)
|
|
269
|
-
promptlayer_exporter = PromptLayerSpanExporter(
|
|
269
|
+
promptlayer_exporter = PromptLayerSpanExporter(
|
|
270
|
+
api_key=api_key, base_url=base_url, throw_on_error=throw_on_error
|
|
271
|
+
)
|
|
270
272
|
span_processor = BatchSpanProcessor(promptlayer_exporter)
|
|
271
273
|
tracer_provider.add_span_processor(span_processor)
|
|
272
274
|
tracer = tracer_provider.get_tracer(__name__)
|
|
@@ -317,7 +319,7 @@ class PromptLayerMixin:
|
|
|
317
319
|
function_kwargs = deepcopy(prompt_blueprint["llm_kwargs"])
|
|
318
320
|
function_kwargs["stream"] = stream
|
|
319
321
|
provider = prompt_blueprint_model["provider"]
|
|
320
|
-
api_type = prompt_blueprint_model
|
|
322
|
+
api_type = prompt_blueprint_model.get("api_type", "chat-completions")
|
|
321
323
|
|
|
322
324
|
if custom_provider := prompt_blueprint.get("custom_provider"):
|
|
323
325
|
provider = custom_provider["client"]
|