prompty 0.1.33__py3-none-any.whl → 0.1.36__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.
- prompty/azure/processor.py +2 -0
- prompty/azure_beta/__init__.py +11 -0
- prompty/azure_beta/executor.py +281 -0
- prompty/serverless/executor.py +91 -4
- prompty/serverless/processor.py +38 -3
- prompty/tracer.py +16 -20
- {prompty-0.1.33.dist-info → prompty-0.1.36.dist-info}/METADATA +4 -3
- {prompty-0.1.33.dist-info → prompty-0.1.36.dist-info}/RECORD +11 -9
- {prompty-0.1.33.dist-info → prompty-0.1.36.dist-info}/WHEEL +0 -0
- {prompty-0.1.33.dist-info → prompty-0.1.36.dist-info}/entry_points.txt +0 -0
- {prompty-0.1.33.dist-info → prompty-0.1.36.dist-info}/licenses/LICENSE +0 -0
prompty/azure/processor.py
CHANGED
@@ -9,6 +9,8 @@ from openai.types.create_embedding_response import CreateEmbeddingResponse
|
|
9
9
|
|
10
10
|
@InvokerFactory.register_processor("azure")
|
11
11
|
@InvokerFactory.register_processor("azure_openai")
|
12
|
+
@InvokerFactory.register_processor("azure_beta")
|
13
|
+
@InvokerFactory.register_processor("azure_openai_beta")
|
12
14
|
class AzureOpenAIProcessor(Invoker):
|
13
15
|
"""Azure OpenAI Processor"""
|
14
16
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# __init__.py
|
2
|
+
from prompty.invoker import InvokerException
|
3
|
+
|
4
|
+
try:
|
5
|
+
from .executor import AzureOpenAIBetaExecutor
|
6
|
+
# Reuse the common Azure OpenAI Processor
|
7
|
+
from ..azure.processor import AzureOpenAIProcessor
|
8
|
+
except ImportError:
|
9
|
+
raise InvokerException(
|
10
|
+
"Error registering AzureOpenAIBetaExecutor and AzureOpenAIProcessor", "azure_beta"
|
11
|
+
)
|
@@ -0,0 +1,281 @@
|
|
1
|
+
import azure.identity
|
2
|
+
import importlib.metadata
|
3
|
+
from typing import AsyncIterator, Iterator
|
4
|
+
from openai import AzureOpenAI, AsyncAzureOpenAI
|
5
|
+
|
6
|
+
from prompty.tracer import Tracer
|
7
|
+
from ..core import AsyncPromptyStream, Prompty, PromptyStream
|
8
|
+
from ..invoker import Invoker, InvokerFactory
|
9
|
+
import re
|
10
|
+
from datetime import datetime
|
11
|
+
|
12
|
+
def extract_date(data: str) -> datetime:
|
13
|
+
"""Extract date from a string
|
14
|
+
|
15
|
+
Parameters
|
16
|
+
----------
|
17
|
+
data : str
|
18
|
+
The string containing the date
|
19
|
+
|
20
|
+
Returns
|
21
|
+
-------
|
22
|
+
datetime
|
23
|
+
The extracted date as a datetime object
|
24
|
+
"""
|
25
|
+
|
26
|
+
# Regular expression to find dates in the format YYYY-MM-DD
|
27
|
+
date_pattern = re.compile(r'\b\d{4}-\d{2}-\d{2}\b')
|
28
|
+
match = date_pattern.search(data)
|
29
|
+
if match:
|
30
|
+
date_str = match.group(0)
|
31
|
+
# Validate the date format
|
32
|
+
try:
|
33
|
+
return datetime.strptime(date_str, '%Y-%m-%d')
|
34
|
+
except ValueError:
|
35
|
+
pass
|
36
|
+
return None
|
37
|
+
|
38
|
+
def is_structured_output_available(api_version: str) -> bool:
|
39
|
+
"""Check if the structured output API is available for the given API version
|
40
|
+
|
41
|
+
Parameters
|
42
|
+
----------
|
43
|
+
api_version : datetime
|
44
|
+
The API version
|
45
|
+
|
46
|
+
Returns
|
47
|
+
-------
|
48
|
+
bool
|
49
|
+
True if the structured output API is available, False otherwise
|
50
|
+
"""
|
51
|
+
|
52
|
+
# Define the threshold date
|
53
|
+
threshold_api_version_date = datetime(2024, 8, 1)
|
54
|
+
|
55
|
+
api_version_date = extract_date(api_version)
|
56
|
+
|
57
|
+
# Check if the API version are on or after the threshold date
|
58
|
+
if api_version_date >= threshold_api_version_date:
|
59
|
+
return True
|
60
|
+
return False
|
61
|
+
|
62
|
+
VERSION = importlib.metadata.version("prompty")
|
63
|
+
|
64
|
+
|
65
|
+
@InvokerFactory.register_executor("azure_beta")
|
66
|
+
@InvokerFactory.register_executor("azure_openai_beta")
|
67
|
+
class AzureOpenAIBetaExecutor(Invoker):
|
68
|
+
"""Azure OpenAI Beta Executor"""
|
69
|
+
|
70
|
+
def __init__(self, prompty: Prompty) -> None:
|
71
|
+
super().__init__(prompty)
|
72
|
+
self.kwargs = {
|
73
|
+
key: value
|
74
|
+
for key, value in self.prompty.model.configuration.items()
|
75
|
+
if key != "type"
|
76
|
+
}
|
77
|
+
|
78
|
+
# no key, use default credentials
|
79
|
+
if "api_key" not in self.kwargs:
|
80
|
+
# managed identity if client id
|
81
|
+
if "client_id" in self.kwargs:
|
82
|
+
default_credential = azure.identity.ManagedIdentityCredential(
|
83
|
+
client_id=self.kwargs.pop("client_id"),
|
84
|
+
)
|
85
|
+
# default credential
|
86
|
+
else:
|
87
|
+
default_credential = azure.identity.DefaultAzureCredential(
|
88
|
+
exclude_shared_token_cache_credential=True
|
89
|
+
)
|
90
|
+
|
91
|
+
self.kwargs["azure_ad_token_provider"] = (
|
92
|
+
azure.identity.get_bearer_token_provider(
|
93
|
+
default_credential, "https://cognitiveservices.azure.com/.default"
|
94
|
+
)
|
95
|
+
)
|
96
|
+
|
97
|
+
self.api = self.prompty.model.api
|
98
|
+
self.api_version = self.prompty.model.configuration["api_version"]
|
99
|
+
self.deployment = self.prompty.model.configuration["azure_deployment"]
|
100
|
+
self.parameters = self.prompty.model.parameters
|
101
|
+
|
102
|
+
def invoke(self, data: any) -> any:
|
103
|
+
"""Invoke the Azure OpenAI API
|
104
|
+
|
105
|
+
Parameters
|
106
|
+
----------
|
107
|
+
data : any
|
108
|
+
The data to send to the Azure OpenAI API
|
109
|
+
|
110
|
+
Returns
|
111
|
+
-------
|
112
|
+
any
|
113
|
+
The response from the Azure OpenAI API
|
114
|
+
"""
|
115
|
+
|
116
|
+
with Tracer.start("AzureOpenAI") as trace:
|
117
|
+
trace("type", "LLM")
|
118
|
+
trace("signature", "AzureOpenAI.ctor")
|
119
|
+
trace("description", "Azure OpenAI Constructor")
|
120
|
+
trace("inputs", self.kwargs)
|
121
|
+
client = AzureOpenAI(
|
122
|
+
default_headers={
|
123
|
+
"User-Agent": f"prompty/{VERSION}",
|
124
|
+
"x-ms-useragent": f"prompty/{VERSION}",
|
125
|
+
},
|
126
|
+
**self.kwargs,
|
127
|
+
)
|
128
|
+
trace("result", client)
|
129
|
+
|
130
|
+
with Tracer.start("create") as trace:
|
131
|
+
trace("type", "LLM")
|
132
|
+
trace("description", "Azure OpenAI Client")
|
133
|
+
|
134
|
+
if self.api == "chat":
|
135
|
+
# We can only verify the API version as the model and its version are not part of prompty configuration
|
136
|
+
# Should be gpt-4o and 2024-08-06 or later
|
137
|
+
choose_beta = is_structured_output_available(self.api_version)
|
138
|
+
if choose_beta:
|
139
|
+
trace("signature", "AzureOpenAI.beta.chat.completions.parse")
|
140
|
+
else:
|
141
|
+
trace("signature", "AzureOpenAI.chat.completions.create")
|
142
|
+
|
143
|
+
args = {
|
144
|
+
"model": self.deployment,
|
145
|
+
"messages": data if isinstance(data, list) else [data],
|
146
|
+
**self.parameters,
|
147
|
+
}
|
148
|
+
trace("inputs", args)
|
149
|
+
if choose_beta:
|
150
|
+
response = client.beta.chat.completions.parse(**args)
|
151
|
+
else:
|
152
|
+
response = client.chat.completions.create(**args)
|
153
|
+
trace("result", response)
|
154
|
+
|
155
|
+
elif self.api == "completion":
|
156
|
+
trace("signature", "AzureOpenAI.completions.create")
|
157
|
+
args = {
|
158
|
+
"prompt": data,
|
159
|
+
"model": self.deployment,
|
160
|
+
**self.parameters,
|
161
|
+
}
|
162
|
+
trace("inputs", args)
|
163
|
+
response = client.completions.create(**args)
|
164
|
+
trace("result", response)
|
165
|
+
|
166
|
+
elif self.api == "embedding":
|
167
|
+
trace("signature", "AzureOpenAI.embeddings.create")
|
168
|
+
args = {
|
169
|
+
"input": data if isinstance(data, list) else [data],
|
170
|
+
"model": self.deployment,
|
171
|
+
**self.parameters,
|
172
|
+
}
|
173
|
+
trace("inputs", args)
|
174
|
+
response = client.embeddings.create(**args)
|
175
|
+
trace("result", response)
|
176
|
+
|
177
|
+
elif self.api == "image":
|
178
|
+
trace("signature", "AzureOpenAI.images.generate")
|
179
|
+
args = {
|
180
|
+
"prompt": data,
|
181
|
+
"model": self.deployment,
|
182
|
+
**self.parameters,
|
183
|
+
}
|
184
|
+
trace("inputs", args)
|
185
|
+
response = client.images.generate.create(**args)
|
186
|
+
trace("result", response)
|
187
|
+
|
188
|
+
# stream response
|
189
|
+
if isinstance(response, Iterator):
|
190
|
+
if self.api == "chat":
|
191
|
+
# TODO: handle the case where there might be no usage in the stream
|
192
|
+
return PromptyStream("AzureOpenAIBetaExecutor", response)
|
193
|
+
else:
|
194
|
+
return PromptyStream("AzureOpenAIBetaExecutor", response)
|
195
|
+
else:
|
196
|
+
return response
|
197
|
+
|
198
|
+
async def invoke_async(self, data: str) -> str:
|
199
|
+
"""Invoke the Prompty Chat Parser (Async)
|
200
|
+
|
201
|
+
Parameters
|
202
|
+
----------
|
203
|
+
data : str
|
204
|
+
The data to parse
|
205
|
+
|
206
|
+
Returns
|
207
|
+
-------
|
208
|
+
str
|
209
|
+
The parsed data
|
210
|
+
"""
|
211
|
+
with Tracer.start("AzureOpenAIAsync") as trace:
|
212
|
+
trace("type", "LLM")
|
213
|
+
trace("signature", "AzureOpenAIAsync.ctor")
|
214
|
+
trace("description", "Async Azure OpenAI Constructor")
|
215
|
+
trace("inputs", self.kwargs)
|
216
|
+
client = AsyncAzureOpenAI(
|
217
|
+
default_headers={
|
218
|
+
"User-Agent": f"prompty/{VERSION}",
|
219
|
+
"x-ms-useragent": f"prompty/{VERSION}",
|
220
|
+
},
|
221
|
+
**self.kwargs,
|
222
|
+
)
|
223
|
+
trace("result", client)
|
224
|
+
|
225
|
+
with Tracer.start("create") as trace:
|
226
|
+
trace("type", "LLM")
|
227
|
+
trace("description", "Azure OpenAI Client")
|
228
|
+
|
229
|
+
if self.api == "chat":
|
230
|
+
trace("signature", "AzureOpenAIAsync.chat.completions.create")
|
231
|
+
args = {
|
232
|
+
"model": self.deployment,
|
233
|
+
"messages": data if isinstance(data, list) else [data],
|
234
|
+
**self.parameters,
|
235
|
+
}
|
236
|
+
trace("inputs", args)
|
237
|
+
response = await client.chat.completions.create(**args)
|
238
|
+
trace("result", response)
|
239
|
+
|
240
|
+
elif self.api == "completion":
|
241
|
+
trace("signature", "AzureOpenAIAsync.completions.create")
|
242
|
+
args = {
|
243
|
+
"prompt": data,
|
244
|
+
"model": self.deployment,
|
245
|
+
**self.parameters,
|
246
|
+
}
|
247
|
+
trace("inputs", args)
|
248
|
+
response = await client.completions.create(**args)
|
249
|
+
trace("result", response)
|
250
|
+
|
251
|
+
elif self.api == "embedding":
|
252
|
+
trace("signature", "AzureOpenAIAsync.embeddings.create")
|
253
|
+
args = {
|
254
|
+
"input": data if isinstance(data, list) else [data],
|
255
|
+
"model": self.deployment,
|
256
|
+
**self.parameters,
|
257
|
+
}
|
258
|
+
trace("inputs", args)
|
259
|
+
response = await client.embeddings.create(**args)
|
260
|
+
trace("result", response)
|
261
|
+
|
262
|
+
elif self.api == "image":
|
263
|
+
trace("signature", "AzureOpenAIAsync.images.generate")
|
264
|
+
args = {
|
265
|
+
"prompt": data,
|
266
|
+
"model": self.deployment,
|
267
|
+
**self.parameters,
|
268
|
+
}
|
269
|
+
trace("inputs", args)
|
270
|
+
response = await client.images.generate.create(**args)
|
271
|
+
trace("result", response)
|
272
|
+
|
273
|
+
# stream response
|
274
|
+
if isinstance(response, AsyncIterator):
|
275
|
+
if self.api == "chat":
|
276
|
+
# TODO: handle the case where there might be no usage in the stream
|
277
|
+
return AsyncPromptyStream("AzureOpenAIBetaExecutorAsync", response)
|
278
|
+
else:
|
279
|
+
return AsyncPromptyStream("AzureOpenAIBetaExecutorAsync", response)
|
280
|
+
else:
|
281
|
+
return response
|
prompty/serverless/executor.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import azure.identity
|
1
2
|
import importlib.metadata
|
2
3
|
from typing import Iterator
|
3
4
|
from azure.core.credentials import AzureKeyCredential
|
@@ -5,6 +6,11 @@ from azure.ai.inference import (
|
|
5
6
|
ChatCompletionsClient,
|
6
7
|
EmbeddingsClient,
|
7
8
|
)
|
9
|
+
|
10
|
+
from azure.ai.inference.aio import (
|
11
|
+
ChatCompletionsClient as AsyncChatCompletionsClient,
|
12
|
+
EmbeddingsClient as AsyncEmbeddingsClient,
|
13
|
+
)
|
8
14
|
from azure.ai.inference.models import (
|
9
15
|
StreamingChatCompletions,
|
10
16
|
AsyncStreamingChatCompletions,
|
@@ -24,10 +30,18 @@ class ServerlessExecutor(Invoker):
|
|
24
30
|
def __init__(self, prompty: Prompty) -> None:
|
25
31
|
super().__init__(prompty)
|
26
32
|
|
27
|
-
# serverless configuration
|
28
33
|
self.endpoint = self.prompty.model.configuration["endpoint"]
|
29
34
|
self.model = self.prompty.model.configuration["model"]
|
30
|
-
|
35
|
+
|
36
|
+
# no key, use default credentials
|
37
|
+
if "key" not in self.kwargs:
|
38
|
+
self.credential = azure.identity.DefaultAzureCredential(
|
39
|
+
exclude_shared_token_cache_credential=True
|
40
|
+
)
|
41
|
+
else:
|
42
|
+
self.credential = AzureKeyCredential(
|
43
|
+
self.prompty.model.configuration["key"]
|
44
|
+
)
|
31
45
|
|
32
46
|
# api type
|
33
47
|
self.api = self.prompty.model.api
|
@@ -64,7 +78,7 @@ class ServerlessExecutor(Invoker):
|
|
64
78
|
|
65
79
|
cargs = {
|
66
80
|
"endpoint": self.endpoint,
|
67
|
-
"credential":
|
81
|
+
"credential": self.credential,
|
68
82
|
}
|
69
83
|
|
70
84
|
if self.api == "chat":
|
@@ -150,4 +164,77 @@ class ServerlessExecutor(Invoker):
|
|
150
164
|
str
|
151
165
|
The parsed data
|
152
166
|
"""
|
153
|
-
|
167
|
+
cargs = {
|
168
|
+
"endpoint": self.endpoint,
|
169
|
+
"credential": self.credential,
|
170
|
+
}
|
171
|
+
|
172
|
+
if self.api == "chat":
|
173
|
+
with Tracer.start("ChatCompletionsClient") as trace:
|
174
|
+
trace("type", "LLM")
|
175
|
+
trace("signature", "azure.ai.inference.aio.ChatCompletionsClient.ctor")
|
176
|
+
trace(
|
177
|
+
"description", "Azure Unified Inference SDK Async Chat Completions Client"
|
178
|
+
)
|
179
|
+
trace("inputs", cargs)
|
180
|
+
client = AsyncChatCompletionsClient(
|
181
|
+
user_agent=f"prompty/{VERSION}",
|
182
|
+
**cargs,
|
183
|
+
)
|
184
|
+
trace("result", client)
|
185
|
+
|
186
|
+
with Tracer.start("complete") as trace:
|
187
|
+
trace("type", "LLM")
|
188
|
+
trace("signature", "azure.ai.inference.ChatCompletionsClient.complete")
|
189
|
+
trace(
|
190
|
+
"description", "Azure Unified Inference SDK Async Chat Completions Client"
|
191
|
+
)
|
192
|
+
eargs = {
|
193
|
+
"model": self.model,
|
194
|
+
"messages": data if isinstance(data, list) else [data],
|
195
|
+
**self.prompty.model.parameters,
|
196
|
+
}
|
197
|
+
trace("inputs", eargs)
|
198
|
+
r = await client.complete(**eargs)
|
199
|
+
trace("result", r)
|
200
|
+
|
201
|
+
response = self._response(r)
|
202
|
+
|
203
|
+
elif self.api == "completion":
|
204
|
+
raise NotImplementedError(
|
205
|
+
"Serverless Completions API is not implemented yet"
|
206
|
+
)
|
207
|
+
|
208
|
+
elif self.api == "embedding":
|
209
|
+
with Tracer.start("EmbeddingsClient") as trace:
|
210
|
+
trace("type", "LLM")
|
211
|
+
trace("signature", "azure.ai.inference.aio.EmbeddingsClient.ctor")
|
212
|
+
trace("description", "Azure Unified Inference SDK Async Embeddings Client")
|
213
|
+
trace("inputs", cargs)
|
214
|
+
client = AsyncEmbeddingsClient(
|
215
|
+
user_agent=f"prompty/{VERSION}",
|
216
|
+
**cargs,
|
217
|
+
)
|
218
|
+
trace("result", client)
|
219
|
+
|
220
|
+
with Tracer.start("complete") as trace:
|
221
|
+
trace("type", "LLM")
|
222
|
+
trace("signature", "azure.ai.inference.ChatCompletionsClient.complete")
|
223
|
+
trace(
|
224
|
+
"description", "Azure Unified Inference SDK Chat Completions Client"
|
225
|
+
)
|
226
|
+
eargs = {
|
227
|
+
"model": self.model,
|
228
|
+
"input": data if isinstance(data, list) else [data],
|
229
|
+
**self.prompty.model.parameters,
|
230
|
+
}
|
231
|
+
trace("inputs", eargs)
|
232
|
+
r = await client.complete(**eargs)
|
233
|
+
trace("result", r)
|
234
|
+
|
235
|
+
response = self._response(r)
|
236
|
+
|
237
|
+
elif self.api == "image":
|
238
|
+
raise NotImplementedError("Azure OpenAI Image API is not implemented yet")
|
239
|
+
|
240
|
+
return response
|
prompty/serverless/processor.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
from typing import Iterator
|
1
|
+
from typing import AsyncIterator, Iterator
|
2
2
|
from ..invoker import Invoker, InvokerFactory
|
3
|
-
from ..core import Prompty, PromptyStream, ToolCall
|
3
|
+
from ..core import AsyncPromptyStream, Prompty, PromptyStream, ToolCall
|
4
4
|
|
5
5
|
from azure.ai.inference.models import ChatCompletions, EmbeddingsResult
|
6
6
|
|
@@ -75,4 +75,39 @@ class ServerlessProcessor(Invoker):
|
|
75
75
|
str
|
76
76
|
The parsed data
|
77
77
|
"""
|
78
|
-
|
78
|
+
if isinstance(data, ChatCompletions):
|
79
|
+
response = data.choices[0].message
|
80
|
+
# tool calls available in response
|
81
|
+
if response.tool_calls:
|
82
|
+
return [
|
83
|
+
ToolCall(
|
84
|
+
id=tool_call.id,
|
85
|
+
name=tool_call.function.name,
|
86
|
+
arguments=tool_call.function.arguments,
|
87
|
+
)
|
88
|
+
for tool_call in response.tool_calls
|
89
|
+
]
|
90
|
+
else:
|
91
|
+
return response.content
|
92
|
+
|
93
|
+
elif isinstance(data, EmbeddingsResult):
|
94
|
+
if len(data.data) == 0:
|
95
|
+
raise ValueError("Invalid data")
|
96
|
+
elif len(data.data) == 1:
|
97
|
+
return data.data[0].embedding
|
98
|
+
else:
|
99
|
+
return [item.embedding for item in data.data]
|
100
|
+
elif isinstance(data, AsyncIterator):
|
101
|
+
|
102
|
+
async def generator():
|
103
|
+
async for chunk in data:
|
104
|
+
if (
|
105
|
+
len(chunk.choices) == 1
|
106
|
+
and chunk.choices[0].delta.content != None
|
107
|
+
):
|
108
|
+
content = chunk.choices[0].delta.content
|
109
|
+
yield content
|
110
|
+
|
111
|
+
return AsyncPromptyStream("ServerlessProcessor", generator())
|
112
|
+
else:
|
113
|
+
return data
|
prompty/tracer.py
CHANGED
@@ -93,7 +93,9 @@ def _name(func: Callable, args):
|
|
93
93
|
if core_invoker:
|
94
94
|
name = type(args[0]).__name__
|
95
95
|
if signature.endswith("async"):
|
96
|
-
signature =
|
96
|
+
signature = (
|
97
|
+
f"{args[0].__module__}.{args[0].__class__.__name__}.invoke_async"
|
98
|
+
)
|
97
99
|
else:
|
98
100
|
signature = f"{args[0].__module__}.{args[0].__class__.__name__}.invoke"
|
99
101
|
else:
|
@@ -116,20 +118,19 @@ def _results(result: Any) -> dict:
|
|
116
118
|
|
117
119
|
|
118
120
|
def _trace_sync(
|
119
|
-
func: Callable = None,
|
121
|
+
func: Callable = None, **okwargs: Any
|
120
122
|
) -> Callable:
|
121
|
-
description = description or ""
|
122
123
|
|
123
124
|
@wraps(func)
|
124
125
|
def wrapper(*args, **kwargs):
|
125
126
|
name, signature = _name(func, args)
|
126
127
|
with Tracer.start(name) as trace:
|
127
128
|
trace("signature", signature)
|
128
|
-
if description and description != "":
|
129
|
-
trace("description", description)
|
130
129
|
|
131
|
-
|
132
|
-
|
130
|
+
# support arbitrary keyword
|
131
|
+
# arguments for trace decorator
|
132
|
+
for k, v in okwargs.items():
|
133
|
+
trace(k, to_dict(v))
|
133
134
|
|
134
135
|
inputs = _inputs(func, args, kwargs)
|
135
136
|
trace("inputs", inputs)
|
@@ -161,20 +162,19 @@ def _trace_sync(
|
|
161
162
|
|
162
163
|
|
163
164
|
def _trace_async(
|
164
|
-
func: Callable = None,
|
165
|
+
func: Callable = None, **okwargs: Any
|
165
166
|
) -> Callable:
|
166
|
-
description = description or ""
|
167
167
|
|
168
168
|
@wraps(func)
|
169
169
|
async def wrapper(*args, **kwargs):
|
170
170
|
name, signature = _name(func, args)
|
171
171
|
with Tracer.start(name) as trace:
|
172
172
|
trace("signature", signature)
|
173
|
-
if description and description != "":
|
174
|
-
trace("description", description)
|
175
173
|
|
176
|
-
|
177
|
-
|
174
|
+
# support arbitrary keyword
|
175
|
+
# arguments for trace decorator
|
176
|
+
for k, v in okwargs.items():
|
177
|
+
trace(k, to_dict(v))
|
178
178
|
|
179
179
|
inputs = _inputs(func, args, kwargs)
|
180
180
|
trace("inputs", inputs)
|
@@ -204,15 +204,11 @@ def _trace_async(
|
|
204
204
|
return wrapper
|
205
205
|
|
206
206
|
|
207
|
-
def trace(
|
208
|
-
func: Callable = None, *, description: str = None, itemtype: str = None
|
209
|
-
) -> Callable:
|
207
|
+
def trace(func: Callable = None, **kwargs: Any) -> Callable:
|
210
208
|
if func is None:
|
211
|
-
return partial(trace,
|
212
|
-
|
209
|
+
return partial(trace, **kwargs)
|
213
210
|
wrapped_method = _trace_async if inspect.iscoroutinefunction(func) else _trace_sync
|
214
|
-
|
215
|
-
return wrapped_method(func, description=description, itemtype=itemtype)
|
211
|
+
return wrapped_method(func, **kwargs)
|
216
212
|
|
217
213
|
|
218
214
|
class PromptyTracer:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: prompty
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.36
|
4
4
|
Summary: Prompty is a new asset class and format for LLM prompts that aims to provide observability, understandability, and portability for developers. It includes spec, tooling, and a runtime. This Prompty runtime supports Python
|
5
5
|
Author-Email: Seth Juarez <seth.juarez@microsoft.com>
|
6
6
|
License: MIT
|
@@ -13,10 +13,11 @@ Requires-Dist: click>=8.1.7
|
|
13
13
|
Requires-Dist: aiofiles>=24.1.0
|
14
14
|
Provides-Extra: azure
|
15
15
|
Requires-Dist: azure-identity>=1.17.1; extra == "azure"
|
16
|
-
Requires-Dist: openai>=1.
|
16
|
+
Requires-Dist: openai>=1.43.0; extra == "azure"
|
17
17
|
Provides-Extra: openai
|
18
|
-
Requires-Dist: openai>=1.
|
18
|
+
Requires-Dist: openai>=1.43.0; extra == "openai"
|
19
19
|
Provides-Extra: serverless
|
20
|
+
Requires-Dist: azure-identity>=1.17.1; extra == "serverless"
|
20
21
|
Requires-Dist: azure-ai-inference>=1.0.0b3; extra == "serverless"
|
21
22
|
Description-Content-Type: text/markdown
|
22
23
|
|
@@ -1,11 +1,13 @@
|
|
1
|
-
prompty-0.1.
|
2
|
-
prompty-0.1.
|
3
|
-
prompty-0.1.
|
4
|
-
prompty-0.1.
|
1
|
+
prompty-0.1.36.dist-info/METADATA,sha256=hkRNP31HOI6NKNO8EW3juLAZOOc1EPhrV-XTE6CtjYA,9164
|
2
|
+
prompty-0.1.36.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
|
3
|
+
prompty-0.1.36.dist-info/entry_points.txt,sha256=a3i7Kvf--3DOkkv9VQpstwaNKgsnXwDGaPL18lPpKeI,60
|
4
|
+
prompty-0.1.36.dist-info/licenses/LICENSE,sha256=KWSC4z9cfML_t0xThoQYjzTdcZQj86Y_mhXdatzU-KM,1052
|
5
5
|
prompty/__init__.py,sha256=HCAvInBgNcIDO54rR4-RDIF4KUmGVQ2TRam_dS7xHEk,16561
|
6
6
|
prompty/azure/__init__.py,sha256=WI8qeNWfxqggj21bznL-mxGUS-v67bUrunX0Lf2hsI8,295
|
7
7
|
prompty/azure/executor.py,sha256=RJXMB0W7KcVvQ7l3xJaau7YM8PqOCQwuN4IwIe0sTLg,7930
|
8
|
-
prompty/azure/processor.py,sha256
|
8
|
+
prompty/azure/processor.py,sha256=-CWc_1h4xdb0nyHwUkaI40NtzTxxenCXkgjJTh76AOk,5079
|
9
|
+
prompty/azure_beta/__init__.py,sha256=QF4qcILpsryBLl1nvc1AhRzkKI2uqc6OAU_fA3LISNE,361
|
10
|
+
prompty/azure_beta/executor.py,sha256=PIPfeOTLk9YEM80adktL2zxpa51gO4itlQzUDoq0QVg,9896
|
9
11
|
prompty/cli.py,sha256=k8Rxm41fMFNvmnsX737UiN6v-7756tpoJPN4rPXMNcU,3726
|
10
12
|
prompty/core.py,sha256=EvkXV_mH7Mj1skT21XMZ4VX-Jlwx6AF-WEJ9yPc50AE,13061
|
11
13
|
prompty/invoker.py,sha256=O77E5iQ1552wQXxL8FhZGERbCi_0O3mDTd5Ozqw-O-E,8593
|
@@ -15,8 +17,8 @@ prompty/openai/processor.py,sha256=l9-91_CCgRtYvkwMO-jV6rkgeCA4gV_MFamQcvoNGQ0,2
|
|
15
17
|
prompty/parsers.py,sha256=zHqcRpFPUDG6BOI7ipaJf6yGc6ZbKnsLmO7jKEYNct4,5013
|
16
18
|
prompty/renderers.py,sha256=80HNtCp3osgaLfhKxkG4j1kiRhJ727ITzT_yL5JLjEQ,1104
|
17
19
|
prompty/serverless/__init__.py,sha256=xoXOTRXO8C631swNKaa-ek5_R3X-87bJpTm0z_Rsg6A,282
|
18
|
-
prompty/serverless/executor.py,sha256=
|
19
|
-
prompty/serverless/processor.py,sha256=
|
20
|
-
prompty/tracer.py,sha256=
|
20
|
+
prompty/serverless/executor.py,sha256=PUDJsYcJLQx9JSTh-R3HdJd0ehEC6w2Ch5OEqz52uVI,8395
|
21
|
+
prompty/serverless/processor.py,sha256=ZSL9y8JC-G4qbtWOSbQAqEcFMWEaLskyOr5VjLthelU,3660
|
22
|
+
prompty/tracer.py,sha256=WUR7PsvhBLQf7WcnKQPOeLeii9l4xPKB2owjvJ50d0E,10907
|
21
23
|
prompty/utils.py,sha256=jm7HEzOGk3zz8d5aquXK3zWIQWuDpBpJTzlz5sswtdg,2836
|
22
|
-
prompty-0.1.
|
24
|
+
prompty-0.1.36.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|