payi 0.1.0a72__py3-none-any.whl → 0.1.0a74__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 payi might be problematic. Click here for more details.
- payi/_version.py +1 -1
- payi/lib/AnthropicInstrumentor.py +23 -12
- payi/lib/OpenAIInstrumentor.py +210 -52
- payi/lib/helpers.py +15 -5
- payi/lib/instrument.py +73 -33
- {payi-0.1.0a72.dist-info → payi-0.1.0a74.dist-info}/METADATA +1 -1
- {payi-0.1.0a72.dist-info → payi-0.1.0a74.dist-info}/RECORD +9 -9
- {payi-0.1.0a72.dist-info → payi-0.1.0a74.dist-info}/WHEEL +0 -0
- {payi-0.1.0a72.dist-info → payi-0.1.0a74.dist-info}/licenses/LICENSE +0 -0
payi/_version.py
CHANGED
|
@@ -11,7 +11,13 @@ from payi.types.ingest_units_params import Units
|
|
|
11
11
|
from .instrument import _IsStreaming, _ProviderRequest, _PayiInstrumentor
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class
|
|
14
|
+
class AnthropicInstrumentor:
|
|
15
|
+
@staticmethod
|
|
16
|
+
def is_vertex(instance: Any) -> bool:
|
|
17
|
+
from anthropic import AnthropicVertex, AsyncAnthropicVertex # type: ignore # noqa: I001
|
|
18
|
+
|
|
19
|
+
return isinstance(instance._client, (AsyncAnthropicVertex, AnthropicVertex))
|
|
20
|
+
|
|
15
21
|
@staticmethod
|
|
16
22
|
def instrument(instrumentor: _PayiInstrumentor) -> None:
|
|
17
23
|
try:
|
|
@@ -20,25 +26,25 @@ class AnthropicIntrumentor:
|
|
|
20
26
|
wrap_function_wrapper(
|
|
21
27
|
"anthropic.resources.messages",
|
|
22
28
|
"Messages.create",
|
|
23
|
-
|
|
29
|
+
messages_wrapper(instrumentor),
|
|
24
30
|
)
|
|
25
31
|
|
|
26
32
|
wrap_function_wrapper(
|
|
27
33
|
"anthropic.resources.messages",
|
|
28
34
|
"Messages.stream",
|
|
29
|
-
|
|
35
|
+
messages_wrapper(instrumentor),
|
|
30
36
|
)
|
|
31
37
|
|
|
32
38
|
wrap_function_wrapper(
|
|
33
39
|
"anthropic.resources.messages",
|
|
34
40
|
"AsyncMessages.create",
|
|
35
|
-
|
|
41
|
+
amessages_wrapper(instrumentor),
|
|
36
42
|
)
|
|
37
43
|
|
|
38
44
|
wrap_function_wrapper(
|
|
39
45
|
"anthropic.resources.messages",
|
|
40
46
|
"AsyncMessages.stream",
|
|
41
|
-
|
|
47
|
+
amessages_wrapper(instrumentor),
|
|
42
48
|
)
|
|
43
49
|
|
|
44
50
|
except Exception as e:
|
|
@@ -47,7 +53,7 @@ class AnthropicIntrumentor:
|
|
|
47
53
|
|
|
48
54
|
|
|
49
55
|
@_PayiInstrumentor.payi_wrapper
|
|
50
|
-
def
|
|
56
|
+
def messages_wrapper(
|
|
51
57
|
instrumentor: _PayiInstrumentor,
|
|
52
58
|
wrapped: Any,
|
|
53
59
|
instance: Any,
|
|
@@ -55,7 +61,7 @@ def chat_wrapper(
|
|
|
55
61
|
**kwargs: Any,
|
|
56
62
|
) -> Any:
|
|
57
63
|
return instrumentor.invoke_wrapper(
|
|
58
|
-
_AnthropicProviderRequest(instrumentor),
|
|
64
|
+
_AnthropicProviderRequest(instrumentor, instance),
|
|
59
65
|
_IsStreaming.kwargs,
|
|
60
66
|
wrapped,
|
|
61
67
|
instance,
|
|
@@ -64,7 +70,7 @@ def chat_wrapper(
|
|
|
64
70
|
)
|
|
65
71
|
|
|
66
72
|
@_PayiInstrumentor.payi_awrapper
|
|
67
|
-
async def
|
|
73
|
+
async def amessages_wrapper(
|
|
68
74
|
instrumentor: _PayiInstrumentor,
|
|
69
75
|
wrapped: Any,
|
|
70
76
|
instance: Any,
|
|
@@ -72,7 +78,7 @@ async def achat_wrapper(
|
|
|
72
78
|
**kwargs: Any,
|
|
73
79
|
) -> Any:
|
|
74
80
|
return await instrumentor.async_invoke_wrapper(
|
|
75
|
-
_AnthropicProviderRequest(instrumentor),
|
|
81
|
+
_AnthropicProviderRequest(instrumentor, instance),
|
|
76
82
|
_IsStreaming.kwargs,
|
|
77
83
|
wrapped,
|
|
78
84
|
instance,
|
|
@@ -81,8 +87,12 @@ async def achat_wrapper(
|
|
|
81
87
|
)
|
|
82
88
|
|
|
83
89
|
class _AnthropicProviderRequest(_ProviderRequest):
|
|
84
|
-
def __init__(self, instrumentor: _PayiInstrumentor):
|
|
85
|
-
|
|
90
|
+
def __init__(self, instrumentor: _PayiInstrumentor, instance: Any = None) -> None:
|
|
91
|
+
self._vertex: bool = AnthropicInstrumentor.is_vertex(instance)
|
|
92
|
+
super().__init__(
|
|
93
|
+
instrumentor=instrumentor,
|
|
94
|
+
category=PayiCategories.google_vertex if self._vertex else PayiCategories.anthropic
|
|
95
|
+
)
|
|
86
96
|
|
|
87
97
|
@override
|
|
88
98
|
def process_chunk(self, chunk: Any) -> bool:
|
|
@@ -138,7 +148,8 @@ class _AnthropicProviderRequest(_ProviderRequest):
|
|
|
138
148
|
|
|
139
149
|
@override
|
|
140
150
|
def process_request(self, instance: Any, extra_headers: 'dict[str, str]', args: Sequence[Any], kwargs: Any) -> bool:
|
|
141
|
-
self._ingest["resource"] = kwargs.get("model", "")
|
|
151
|
+
self._ingest["resource"] = ("anthropic." if self._vertex else "") + kwargs.get("model", "")
|
|
152
|
+
|
|
142
153
|
messages = kwargs.get("messages")
|
|
143
154
|
if messages:
|
|
144
155
|
estimated_token_count = 0
|
payi/lib/OpenAIInstrumentor.py
CHANGED
|
@@ -7,7 +7,6 @@ from importlib.metadata import version
|
|
|
7
7
|
import tiktoken # type: ignore
|
|
8
8
|
from wrapt import wrap_function_wrapper # type: ignore
|
|
9
9
|
|
|
10
|
-
from payi.types import IngestUnitsParams
|
|
11
10
|
from payi.lib.helpers import PayiCategories, PayiHeaderNames
|
|
12
11
|
from payi.types.ingest_units_params import Units
|
|
13
12
|
|
|
@@ -50,6 +49,18 @@ class OpenAiInstrumentor:
|
|
|
50
49
|
aembeddings_wrapper(instrumentor),
|
|
51
50
|
)
|
|
52
51
|
|
|
52
|
+
wrap_function_wrapper(
|
|
53
|
+
"openai.resources.responses",
|
|
54
|
+
"Responses.create",
|
|
55
|
+
responses_wrapper(instrumentor),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
wrap_function_wrapper(
|
|
59
|
+
"openai.resources.responses",
|
|
60
|
+
"AsyncResponses.create",
|
|
61
|
+
aresponses_wrapper(instrumentor),
|
|
62
|
+
)
|
|
63
|
+
|
|
53
64
|
except Exception as e:
|
|
54
65
|
logging.debug(f"Error instrumenting openai: {e}")
|
|
55
66
|
return
|
|
@@ -122,10 +133,55 @@ async def achat_wrapper(
|
|
|
122
133
|
args,
|
|
123
134
|
kwargs,
|
|
124
135
|
)
|
|
136
|
+
|
|
137
|
+
@_PayiInstrumentor.payi_wrapper
|
|
138
|
+
def responses_wrapper(
|
|
139
|
+
instrumentor: _PayiInstrumentor,
|
|
140
|
+
wrapped: Any,
|
|
141
|
+
instance: Any,
|
|
142
|
+
*args: Any,
|
|
143
|
+
**kwargs: Any,
|
|
144
|
+
) -> Any:
|
|
145
|
+
return instrumentor.invoke_wrapper(
|
|
146
|
+
_OpenAiResponsesProviderRequest(instrumentor),
|
|
147
|
+
_IsStreaming.kwargs,
|
|
148
|
+
wrapped,
|
|
149
|
+
instance,
|
|
150
|
+
args,
|
|
151
|
+
kwargs,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
@_PayiInstrumentor.payi_awrapper
|
|
155
|
+
async def aresponses_wrapper(
|
|
156
|
+
instrumentor: _PayiInstrumentor,
|
|
157
|
+
wrapped: Any,
|
|
158
|
+
instance: Any,
|
|
159
|
+
*args: Any,
|
|
160
|
+
**kwargs: Any,
|
|
161
|
+
) -> Any:
|
|
162
|
+
return await instrumentor.async_invoke_wrapper(
|
|
163
|
+
_OpenAiResponsesProviderRequest(instrumentor),
|
|
164
|
+
_IsStreaming.kwargs,
|
|
165
|
+
wrapped,
|
|
166
|
+
instance,
|
|
167
|
+
args,
|
|
168
|
+
kwargs,
|
|
169
|
+
)
|
|
125
170
|
|
|
126
171
|
class _OpenAiProviderRequest(_ProviderRequest):
|
|
127
|
-
|
|
172
|
+
chat_input_tokens_key: str = "prompt_tokens"
|
|
173
|
+
chat_output_tokens_key: str = "completion_tokens"
|
|
174
|
+
chat_input_tokens_details_key: str = "prompt_tokens_details"
|
|
175
|
+
|
|
176
|
+
responses_input_tokens_key: str = "input_tokens"
|
|
177
|
+
responses_output_tokens_key: str = "output_tokens"
|
|
178
|
+
responses_input_tokens_details_key: str = "input_tokens_details"
|
|
179
|
+
|
|
180
|
+
def __init__(self, instrumentor: _PayiInstrumentor, input_tokens_key: str, output_tokens_key: str, input_tokens_details_key: str) -> None:
|
|
128
181
|
super().__init__(instrumentor=instrumentor, category=PayiCategories.openai)
|
|
182
|
+
self._input_tokens_key = input_tokens_key
|
|
183
|
+
self._output_tokens_key = output_tokens_key
|
|
184
|
+
self._input_tokens_details_key = input_tokens_details_key
|
|
129
185
|
|
|
130
186
|
@override
|
|
131
187
|
def process_request(self, instance: Any, extra_headers: 'dict[str, str]', args: Sequence[Any], kwargs: Any) -> bool: # type: ignore
|
|
@@ -135,16 +191,19 @@ class _OpenAiProviderRequest(_ProviderRequest):
|
|
|
135
191
|
return True
|
|
136
192
|
|
|
137
193
|
context = self._instrumentor.get_context_safe()
|
|
138
|
-
|
|
194
|
+
price_as_category = extra_headers.get(PayiHeaderNames.price_as_category) or context.get("price_as_category")
|
|
195
|
+
price_as_resource = extra_headers.get(PayiHeaderNames.price_as_resource) or context.get("price_as_resource")
|
|
139
196
|
resource_scope = extra_headers.get(PayiHeaderNames.resource_scope) or context.get("resource_scope")
|
|
140
197
|
|
|
141
|
-
if PayiHeaderNames.
|
|
142
|
-
del extra_headers[PayiHeaderNames.
|
|
198
|
+
if PayiHeaderNames.price_as_category in extra_headers:
|
|
199
|
+
del extra_headers[PayiHeaderNames.price_as_category]
|
|
200
|
+
if PayiHeaderNames.price_as_resource in extra_headers:
|
|
201
|
+
del extra_headers[PayiHeaderNames.price_as_resource]
|
|
143
202
|
if PayiHeaderNames.resource_scope in extra_headers:
|
|
144
203
|
del extra_headers[PayiHeaderNames.resource_scope]
|
|
145
204
|
|
|
146
|
-
if not
|
|
147
|
-
logging.error("Azure OpenAI
|
|
205
|
+
if not price_as_resource and not price_as_category:
|
|
206
|
+
logging.error("Azure OpenAI requires price as resource and/or category to be specified, not ingesting")
|
|
148
207
|
return False
|
|
149
208
|
|
|
150
209
|
if resource_scope:
|
|
@@ -157,8 +216,13 @@ class _OpenAiProviderRequest(_ProviderRequest):
|
|
|
157
216
|
self._category = PayiCategories.azure_openai
|
|
158
217
|
|
|
159
218
|
self._ingest["category"] = self._category
|
|
160
|
-
|
|
161
|
-
|
|
219
|
+
|
|
220
|
+
if price_as_category:
|
|
221
|
+
# price as category overrides default
|
|
222
|
+
self._ingest["category"] = price_as_category
|
|
223
|
+
if price_as_resource:
|
|
224
|
+
self._ingest["resource"] = price_as_resource
|
|
225
|
+
|
|
162
226
|
return True
|
|
163
227
|
|
|
164
228
|
@override
|
|
@@ -193,9 +257,59 @@ class _OpenAiProviderRequest(_ProviderRequest):
|
|
|
193
257
|
|
|
194
258
|
return True
|
|
195
259
|
|
|
260
|
+
def process_synchronous_response_worker(
|
|
261
|
+
self,
|
|
262
|
+
response: str,
|
|
263
|
+
log_prompt_and_response: bool,
|
|
264
|
+
) -> Any:
|
|
265
|
+
response_dict = model_to_dict(response)
|
|
266
|
+
|
|
267
|
+
self.add_usage_units(response_dict.get("usage", {}))
|
|
268
|
+
|
|
269
|
+
if log_prompt_and_response:
|
|
270
|
+
self._ingest["provider_response_json"] = [json.dumps(response_dict)]
|
|
271
|
+
|
|
272
|
+
if "id" in response_dict:
|
|
273
|
+
self._ingest["provider_response_id"] = response_dict["id"]
|
|
274
|
+
|
|
275
|
+
return None
|
|
276
|
+
|
|
277
|
+
def add_usage_units(self, usage: "dict[str, Any]",) -> None:
|
|
278
|
+
units = self._ingest["units"]
|
|
279
|
+
|
|
280
|
+
input = usage[self._input_tokens_key] if self._input_tokens_key in usage else 0
|
|
281
|
+
output = usage[self._output_tokens_key] if self._output_tokens_key in usage else 0
|
|
282
|
+
input_cache = 0
|
|
283
|
+
|
|
284
|
+
prompt_tokens_details = usage.get(self._input_tokens_details_key)
|
|
285
|
+
if prompt_tokens_details:
|
|
286
|
+
input_cache = prompt_tokens_details.get("cached_tokens", 0)
|
|
287
|
+
if input_cache != 0:
|
|
288
|
+
units["text_cache_read"] = Units(input=input_cache, output=0)
|
|
289
|
+
|
|
290
|
+
input = _PayiInstrumentor.update_for_vision(input - input_cache, units, self._estimated_prompt_tokens)
|
|
291
|
+
|
|
292
|
+
units["text"] = Units(input=input, output=output)
|
|
293
|
+
|
|
294
|
+
@staticmethod
|
|
295
|
+
def has_image_and_get_texts(encoding: tiktoken.Encoding, content: Union[str, 'list[Any]'], image_type: str = "image_url", text_type:str = "text") -> 'tuple[bool, int]':
|
|
296
|
+
if isinstance(content, str):
|
|
297
|
+
return False, 0
|
|
298
|
+
elif isinstance(content, list): # type: ignore
|
|
299
|
+
has_image = any(item.get("type") == image_type for item in content)
|
|
300
|
+
if has_image is False:
|
|
301
|
+
return has_image, 0
|
|
302
|
+
|
|
303
|
+
token_count = sum(len(encoding.encode(item.get("text", ""))) for item in content if item.get("type") == text_type)
|
|
304
|
+
return has_image, token_count
|
|
305
|
+
|
|
196
306
|
class _OpenAiEmbeddingsProviderRequest(_OpenAiProviderRequest):
|
|
197
307
|
def __init__(self, instrumentor: _PayiInstrumentor):
|
|
198
|
-
super().__init__(
|
|
308
|
+
super().__init__(
|
|
309
|
+
instrumentor=instrumentor,
|
|
310
|
+
input_tokens_key=_OpenAiProviderRequest.chat_input_tokens_key,
|
|
311
|
+
output_tokens_key=_OpenAiProviderRequest.chat_output_tokens_key,
|
|
312
|
+
input_tokens_details_key=_OpenAiProviderRequest.chat_input_tokens_details_key)
|
|
199
313
|
|
|
200
314
|
@override
|
|
201
315
|
def process_synchronous_response(
|
|
@@ -203,11 +317,16 @@ class _OpenAiEmbeddingsProviderRequest(_OpenAiProviderRequest):
|
|
|
203
317
|
response: Any,
|
|
204
318
|
log_prompt_and_response: bool,
|
|
205
319
|
kwargs: Any) -> Any:
|
|
206
|
-
return
|
|
320
|
+
return self.process_synchronous_response_worker(response, log_prompt_and_response)
|
|
207
321
|
|
|
208
322
|
class _OpenAiChatProviderRequest(_OpenAiProviderRequest):
|
|
209
323
|
def __init__(self, instrumentor: _PayiInstrumentor):
|
|
210
|
-
super().__init__(
|
|
324
|
+
super().__init__(
|
|
325
|
+
instrumentor=instrumentor,
|
|
326
|
+
input_tokens_key=_OpenAiProviderRequest.chat_input_tokens_key,
|
|
327
|
+
output_tokens_key=_OpenAiProviderRequest.chat_output_tokens_key,
|
|
328
|
+
input_tokens_details_key=_OpenAiProviderRequest.chat_input_tokens_details_key)
|
|
329
|
+
|
|
211
330
|
self._include_usage_added = False
|
|
212
331
|
|
|
213
332
|
@override
|
|
@@ -223,9 +342,9 @@ class _OpenAiChatProviderRequest(_OpenAiProviderRequest):
|
|
|
223
342
|
|
|
224
343
|
usage = model.get("usage")
|
|
225
344
|
if usage:
|
|
226
|
-
add_usage_units(usage
|
|
345
|
+
self.add_usage_units(usage)
|
|
227
346
|
|
|
228
|
-
# If we
|
|
347
|
+
# If we added "include_usage" in the request on behalf of the client, do not return the extra
|
|
229
348
|
# packet which contains the usage to the client as they are not expecting the data
|
|
230
349
|
if self._include_usage_added:
|
|
231
350
|
send_chunk_to_client = False
|
|
@@ -249,7 +368,7 @@ class _OpenAiChatProviderRequest(_OpenAiProviderRequest):
|
|
|
249
368
|
enc = tiktoken.get_encoding("o200k_base") # type: ignore
|
|
250
369
|
|
|
251
370
|
for message in messages:
|
|
252
|
-
msg_has_image, msg_prompt_tokens = has_image_and_get_texts(enc, message.get('content', ''))
|
|
371
|
+
msg_has_image, msg_prompt_tokens = self.has_image_and_get_texts(enc, message.get('content', ''))
|
|
253
372
|
if msg_has_image:
|
|
254
373
|
has_image = True
|
|
255
374
|
estimated_token_count += msg_prompt_tokens
|
|
@@ -276,20 +395,86 @@ class _OpenAiChatProviderRequest(_OpenAiProviderRequest):
|
|
|
276
395
|
response: Any,
|
|
277
396
|
log_prompt_and_response: bool,
|
|
278
397
|
kwargs: Any) -> Any:
|
|
279
|
-
|
|
398
|
+
return self.process_synchronous_response_worker(response, log_prompt_and_response)
|
|
399
|
+
|
|
400
|
+
class _OpenAiResponsesProviderRequest(_OpenAiProviderRequest):
|
|
401
|
+
def __init__(self, instrumentor: _PayiInstrumentor):
|
|
402
|
+
super().__init__(
|
|
403
|
+
instrumentor=instrumentor,
|
|
404
|
+
input_tokens_key=_OpenAiProviderRequest.responses_input_tokens_key,
|
|
405
|
+
output_tokens_key=_OpenAiProviderRequest.responses_output_tokens_key,
|
|
406
|
+
input_tokens_details_key=_OpenAiProviderRequest.responses_input_tokens_details_key)
|
|
280
407
|
|
|
281
|
-
|
|
282
|
-
|
|
408
|
+
@override
|
|
409
|
+
def process_chunk(self, chunk: Any) -> bool:
|
|
410
|
+
model = model_to_dict(chunk)
|
|
411
|
+
response: dict[str, Any] = model.get("response", {})
|
|
412
|
+
|
|
413
|
+
if "provider_response_id" not in self._ingest:
|
|
414
|
+
response_id = response.get("id", None)
|
|
415
|
+
if response_id:
|
|
416
|
+
self._ingest["provider_response_id"] = response_id
|
|
417
|
+
|
|
418
|
+
usage = response.get("usage")
|
|
419
|
+
if usage:
|
|
420
|
+
self.add_usage_units(usage)
|
|
421
|
+
|
|
422
|
+
return True
|
|
283
423
|
|
|
284
|
-
|
|
424
|
+
@override
|
|
425
|
+
def process_request(self, instance: Any, extra_headers: 'dict[str, str]', args: Sequence[Any], kwargs: Any) -> bool:
|
|
426
|
+
result = super().process_request(instance, extra_headers, args, kwargs)
|
|
427
|
+
if result is False:
|
|
428
|
+
return result
|
|
429
|
+
|
|
430
|
+
input: ResponseInputParam = kwargs.get("input", None) # type: ignore
|
|
431
|
+
if not input or isinstance(input, str) or not isinstance(input, list):
|
|
432
|
+
return True
|
|
433
|
+
|
|
434
|
+
estimated_token_count = 0
|
|
435
|
+
has_image = False
|
|
285
436
|
|
|
286
|
-
|
|
287
|
-
|
|
437
|
+
try:
|
|
438
|
+
enc = tiktoken.encoding_for_model(kwargs.get("model")) # type: ignore
|
|
439
|
+
except KeyError:
|
|
440
|
+
enc = tiktoken.get_encoding("o200k_base") # type: ignore
|
|
441
|
+
|
|
442
|
+
# find each content..type="input_text" and count tokens
|
|
443
|
+
# input=[{
|
|
444
|
+
# "role": "user",
|
|
445
|
+
# "content": [
|
|
446
|
+
# {
|
|
447
|
+
# "type": "input_text",
|
|
448
|
+
# "text": "what's in this image?"
|
|
449
|
+
# },
|
|
450
|
+
# {
|
|
451
|
+
# "type": "input_image",
|
|
452
|
+
# "image_url": ...
|
|
453
|
+
# },
|
|
454
|
+
# ],
|
|
455
|
+
# }]
|
|
456
|
+
for item in input: # type: ignore
|
|
457
|
+
if isinstance(item, dict):
|
|
458
|
+
for key, value in item.items(): # type: ignore
|
|
459
|
+
if key == "content":
|
|
460
|
+
if isinstance(value, list):
|
|
461
|
+
msg_has_image, msg_prompt_tokens = self.has_image_and_get_texts(enc, value, image_type="input_image", text_type="input_text") # type: ignore
|
|
462
|
+
if msg_has_image:
|
|
463
|
+
has_image = True
|
|
464
|
+
estimated_token_count += msg_prompt_tokens
|
|
465
|
+
|
|
466
|
+
if has_image and estimated_token_count > 0:
|
|
467
|
+
self._estimated_prompt_tokens = estimated_token_count
|
|
288
468
|
|
|
289
|
-
|
|
290
|
-
ingest["provider_response_id"] = response_dict["id"]
|
|
469
|
+
return True
|
|
291
470
|
|
|
292
|
-
|
|
471
|
+
@override
|
|
472
|
+
def process_synchronous_response(
|
|
473
|
+
self,
|
|
474
|
+
response: Any,
|
|
475
|
+
log_prompt_and_response: bool,
|
|
476
|
+
kwargs: Any) -> Any:
|
|
477
|
+
return self.process_synchronous_response_worker(response, log_prompt_and_response)
|
|
293
478
|
|
|
294
479
|
def model_to_dict(model: Any) -> Any:
|
|
295
480
|
if version("pydantic") < "2.0.0":
|
|
@@ -299,31 +484,4 @@ def model_to_dict(model: Any) -> Any:
|
|
|
299
484
|
elif hasattr(model, "parse"): # Raw API response
|
|
300
485
|
return model_to_dict(model.parse())
|
|
301
486
|
else:
|
|
302
|
-
return model
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
def add_usage_units(usage: "dict[str, Any]", units: "dict[str, Units]", estimated_prompt_tokens: Optional[int]) -> None:
|
|
306
|
-
input = usage["prompt_tokens"] if "prompt_tokens" in usage else 0
|
|
307
|
-
output = usage["completion_tokens"] if "completion_tokens" in usage else 0
|
|
308
|
-
input_cache = 0
|
|
309
|
-
|
|
310
|
-
prompt_tokens_details = usage.get("prompt_tokens_details")
|
|
311
|
-
if prompt_tokens_details:
|
|
312
|
-
input_cache = prompt_tokens_details.get("cached_tokens", 0)
|
|
313
|
-
if input_cache != 0:
|
|
314
|
-
units["text_cache_read"] = Units(input=input_cache, output=0)
|
|
315
|
-
|
|
316
|
-
input = _PayiInstrumentor.update_for_vision(input - input_cache, units, estimated_prompt_tokens)
|
|
317
|
-
|
|
318
|
-
units["text"] = Units(input=input, output=output)
|
|
319
|
-
|
|
320
|
-
def has_image_and_get_texts(encoding: tiktoken.Encoding, content: Union[str, 'list[Any]']) -> 'tuple[bool, int]':
|
|
321
|
-
if isinstance(content, str):
|
|
322
|
-
return False, 0
|
|
323
|
-
elif isinstance(content, list): # type: ignore
|
|
324
|
-
has_image = any(item.get("type") == "image_url" for item in content)
|
|
325
|
-
if has_image is False:
|
|
326
|
-
return has_image, 0
|
|
327
|
-
|
|
328
|
-
token_count = sum(len(encoding.encode(item.get("text", ""))) for item in content if item.get("type") == "text")
|
|
329
|
-
return has_image, token_count
|
|
487
|
+
return model
|
payi/lib/helpers.py
CHANGED
|
@@ -11,8 +11,10 @@ class PayiHeaderNames:
|
|
|
11
11
|
use_case_id:str = "xProxy-UseCase-ID"
|
|
12
12
|
use_case_name:str = "xProxy-UseCase-Name"
|
|
13
13
|
use_case_version:str = "xProxy-UseCase-Version"
|
|
14
|
+
use_case_step:str = "xProxy-UseCase-Step"
|
|
14
15
|
user_id:str = "xProxy-User-ID"
|
|
15
|
-
|
|
16
|
+
price_as_category:str = "xProxy-PriceAs-Category"
|
|
17
|
+
price_as_resource:str = "xProxy-PriceAs-Resource"
|
|
16
18
|
provider_base_uri = "xProxy-Provider-BaseUri"
|
|
17
19
|
resource_scope:str = "xProxy-Resource-Scope"
|
|
18
20
|
api_key:str = "xProxy-Api-Key"
|
|
@@ -32,7 +34,6 @@ def create_limit_header_from_ids(limit_ids: List[str]) -> Dict[str, str]:
|
|
|
32
34
|
|
|
33
35
|
return { PayiHeaderNames.limit_ids: ",".join(valid_ids) } if valid_ids else {}
|
|
34
36
|
|
|
35
|
-
|
|
36
37
|
def create_request_header_from_tags(request_tags: List[str]) -> Dict[str, str]:
|
|
37
38
|
if not isinstance(request_tags, list): # type: ignore
|
|
38
39
|
raise TypeError("request_tags must be a list")
|
|
@@ -50,7 +51,9 @@ def create_headers(
|
|
|
50
51
|
use_case_id: Union[str, None] = None,
|
|
51
52
|
use_case_name: Union[str, None] = None,
|
|
52
53
|
use_case_version: Union[int, None] = None,
|
|
53
|
-
|
|
54
|
+
use_case_step: Union[str, None] = None,
|
|
55
|
+
price_as_category: Union[str, None] = None,
|
|
56
|
+
price_as_resource: Union[str, None] = None,
|
|
54
57
|
resource_scope: Union[str, None] = None,
|
|
55
58
|
) -> Dict[str, str]:
|
|
56
59
|
headers: Dict[str, str] = {}
|
|
@@ -71,8 +74,12 @@ def create_headers(
|
|
|
71
74
|
headers.update({ PayiHeaderNames.use_case_name: use_case_name})
|
|
72
75
|
if use_case_version:
|
|
73
76
|
headers.update({ PayiHeaderNames.use_case_version: str(use_case_version)})
|
|
74
|
-
if
|
|
75
|
-
headers.update({ PayiHeaderNames.
|
|
77
|
+
if use_case_step:
|
|
78
|
+
headers.update({ PayiHeaderNames.use_case_step: use_case_step})
|
|
79
|
+
if price_as_category:
|
|
80
|
+
headers.update({ PayiHeaderNames.price_as_category: price_as_category})
|
|
81
|
+
if price_as_resource:
|
|
82
|
+
headers.update({ PayiHeaderNames.price_as_resource: price_as_resource})
|
|
76
83
|
if resource_scope:
|
|
77
84
|
headers.update({ PayiHeaderNames.resource_scope: resource_scope })
|
|
78
85
|
return headers
|
|
@@ -99,3 +106,6 @@ def payi_azure_openai_url(payi_base_url: Union[str, None] = None) -> str:
|
|
|
99
106
|
|
|
100
107
|
def payi_aws_bedrock_url(payi_base_url: Union[str, None] = None) -> str:
|
|
101
108
|
return _resolve_payi_base_url(payi_base_url=payi_base_url) + "/api/v1/proxy/aws.bedrock"
|
|
109
|
+
|
|
110
|
+
# def payi_google_vertex_url(payi_base_url: Union[str, None] = None) -> str:
|
|
111
|
+
# return _resolve_payi_base_url(payi_base_url=payi_base_url) + "/api/v1/proxy/google.vertex"
|
payi/lib/instrument.py
CHANGED
|
@@ -98,10 +98,12 @@ class _Context(TypedDict, total=False):
|
|
|
98
98
|
use_case_name: Optional[str]
|
|
99
99
|
use_case_id: Optional[str]
|
|
100
100
|
use_case_version: Optional[int]
|
|
101
|
+
use_case_step: Optional[str]
|
|
101
102
|
limit_ids: Optional['list[str]']
|
|
102
103
|
user_id: Optional[str]
|
|
103
104
|
request_tags: Optional["list[str]"]
|
|
104
|
-
|
|
105
|
+
price_as_category: Optional[str]
|
|
106
|
+
price_as_resource: Optional[str]
|
|
105
107
|
resource_scope: Optional[str]
|
|
106
108
|
|
|
107
109
|
class _IsStreaming(Enum):
|
|
@@ -166,7 +168,7 @@ class _PayiInstrumentor:
|
|
|
166
168
|
global_config["proxy"] = self._proxy_default
|
|
167
169
|
|
|
168
170
|
# Use default clients if not provided for global ingest instrumentation
|
|
169
|
-
if not self._payi and not self._apayi
|
|
171
|
+
if not self._payi and not self._apayi:
|
|
170
172
|
self._payi = Payi()
|
|
171
173
|
self._apayi = AsyncPayi()
|
|
172
174
|
|
|
@@ -211,10 +213,10 @@ class _PayiInstrumentor:
|
|
|
211
213
|
logging.error(f"Error instrumenting OpenAI: {e}")
|
|
212
214
|
|
|
213
215
|
def _instrument_anthropic(self) -> None:
|
|
214
|
-
from .AnthropicInstrumentor import
|
|
216
|
+
from .AnthropicInstrumentor import AnthropicInstrumentor
|
|
215
217
|
|
|
216
218
|
try:
|
|
217
|
-
|
|
219
|
+
AnthropicInstrumentor.instrument(self)
|
|
218
220
|
|
|
219
221
|
except Exception as e:
|
|
220
222
|
logging.error(f"Error instrumenting Anthropic: {e}")
|
|
@@ -391,10 +393,12 @@ class _PayiInstrumentor:
|
|
|
391
393
|
experience_id: Optional[str] = None,
|
|
392
394
|
use_case_name: Optional[str]= None,
|
|
393
395
|
use_case_id: Optional[str]= None,
|
|
394
|
-
use_case_version: Optional[int]= None,
|
|
396
|
+
use_case_version: Optional[int]= None,
|
|
397
|
+
use_case_step: Optional[str]= None,
|
|
395
398
|
user_id: Optional[str]= None,
|
|
396
399
|
request_tags: Optional["list[str]"] = None,
|
|
397
|
-
|
|
400
|
+
price_as_category: Optional[str] = None,
|
|
401
|
+
price_as_resource: Optional[str] = None,
|
|
398
402
|
resource_scope: Optional[str] = None,
|
|
399
403
|
) -> None:
|
|
400
404
|
|
|
@@ -441,6 +445,7 @@ class _PayiInstrumentor:
|
|
|
441
445
|
context["use_case_name"] = None
|
|
442
446
|
context["use_case_id"] = None
|
|
443
447
|
context["use_case_version"] = None
|
|
448
|
+
context["use_case_step"] = None
|
|
444
449
|
else:
|
|
445
450
|
if use_case_name == parent_use_case_name:
|
|
446
451
|
# Same use case name, use previous ID unless new one specified
|
|
@@ -474,10 +479,14 @@ class _PayiInstrumentor:
|
|
|
474
479
|
else:
|
|
475
480
|
context["user_id"] = user_id
|
|
476
481
|
|
|
482
|
+
if use_case_step and (context["use_case_name"] or context["use_case_id"]):
|
|
483
|
+
context["use_case_step"] = use_case_step
|
|
477
484
|
if request_tags:
|
|
478
485
|
context["request_tags"] = request_tags
|
|
479
|
-
if
|
|
480
|
-
context["
|
|
486
|
+
if price_as_category:
|
|
487
|
+
context["price_as_category"] = price_as_category
|
|
488
|
+
if price_as_resource:
|
|
489
|
+
context["price_as_resource"] = price_as_resource
|
|
481
490
|
if resource_scope:
|
|
482
491
|
context["resource_scope"] = resource_scope
|
|
483
492
|
|
|
@@ -497,14 +506,14 @@ class _PayiInstrumentor:
|
|
|
497
506
|
) -> Any:
|
|
498
507
|
with self:
|
|
499
508
|
self._init_current_context(
|
|
500
|
-
proxy,
|
|
501
|
-
limit_ids,
|
|
502
|
-
experience_name,
|
|
503
|
-
experience_id,
|
|
504
|
-
use_case_name,
|
|
505
|
-
use_case_id,
|
|
506
|
-
use_case_version,
|
|
507
|
-
user_id)
|
|
509
|
+
proxy=proxy,
|
|
510
|
+
limit_ids=limit_ids,
|
|
511
|
+
experience_name=experience_name,
|
|
512
|
+
experience_id=experience_id,
|
|
513
|
+
use_case_name=use_case_name,
|
|
514
|
+
use_case_id=use_case_id,
|
|
515
|
+
use_case_version=use_case_version,
|
|
516
|
+
user_id=user_id)
|
|
508
517
|
return await func(*args, **kwargs)
|
|
509
518
|
|
|
510
519
|
def _call_func(
|
|
@@ -523,14 +532,14 @@ class _PayiInstrumentor:
|
|
|
523
532
|
) -> Any:
|
|
524
533
|
with self:
|
|
525
534
|
self._init_current_context(
|
|
526
|
-
proxy,
|
|
527
|
-
limit_ids,
|
|
528
|
-
experience_name,
|
|
529
|
-
experience_id,
|
|
530
|
-
use_case_name,
|
|
531
|
-
use_case_id,
|
|
532
|
-
use_case_version,
|
|
533
|
-
user_id)
|
|
535
|
+
proxy=proxy,
|
|
536
|
+
limit_ids=limit_ids,
|
|
537
|
+
experience_name=experience_name,
|
|
538
|
+
experience_id=experience_id,
|
|
539
|
+
use_case_name=use_case_name,
|
|
540
|
+
use_case_id=use_case_id,
|
|
541
|
+
use_case_version=use_case_version,
|
|
542
|
+
user_id=user_id)
|
|
534
543
|
return func(*args, **kwargs)
|
|
535
544
|
|
|
536
545
|
def __enter__(self) -> Any:
|
|
@@ -558,13 +567,18 @@ class _PayiInstrumentor:
|
|
|
558
567
|
args: Sequence[Any],
|
|
559
568
|
kwargs: 'dict[str, Any]',
|
|
560
569
|
) -> None:
|
|
570
|
+
|
|
561
571
|
limit_ids = ingest_extra_headers.pop(PayiHeaderNames.limit_ids, None)
|
|
562
572
|
request_tags = ingest_extra_headers.pop(PayiHeaderNames.request_tags, None)
|
|
573
|
+
|
|
563
574
|
experience_name = ingest_extra_headers.pop(PayiHeaderNames.experience_name, None)
|
|
564
575
|
experience_id = ingest_extra_headers.pop(PayiHeaderNames.experience_id, None)
|
|
576
|
+
|
|
565
577
|
use_case_name = ingest_extra_headers.pop(PayiHeaderNames.use_case_name, None)
|
|
566
578
|
use_case_id = ingest_extra_headers.pop(PayiHeaderNames.use_case_id, None)
|
|
567
579
|
use_case_version = ingest_extra_headers.pop(PayiHeaderNames.use_case_version, None)
|
|
580
|
+
use_case_step = ingest_extra_headers.pop(PayiHeaderNames.use_case_step, None)
|
|
581
|
+
|
|
568
582
|
user_id = ingest_extra_headers.pop(PayiHeaderNames.user_id, None)
|
|
569
583
|
|
|
570
584
|
if limit_ids:
|
|
@@ -581,6 +595,8 @@ class _PayiInstrumentor:
|
|
|
581
595
|
request._ingest["use_case_id"] = use_case_id
|
|
582
596
|
if use_case_version:
|
|
583
597
|
request._ingest["use_case_version"] = int(use_case_version)
|
|
598
|
+
if use_case_step:
|
|
599
|
+
request._ingest["use_case_step"] = use_case_step
|
|
584
600
|
if user_id:
|
|
585
601
|
request._ingest["user_id"] = user_id
|
|
586
602
|
|
|
@@ -628,7 +644,9 @@ class _PayiInstrumentor:
|
|
|
628
644
|
return await wrapped(*args, **kwargs)
|
|
629
645
|
|
|
630
646
|
# after _udpate_headers, all metadata to add to ingest is in extra_headers, keyed by the xproxy-xxx header name
|
|
631
|
-
extra_headers = kwargs.get("extra_headers"
|
|
647
|
+
extra_headers: Optional[dict[str, str]] = kwargs.get("extra_headers")
|
|
648
|
+
if extra_headers is None:
|
|
649
|
+
extra_headers = {}
|
|
632
650
|
self._update_extra_headers(context, extra_headers)
|
|
633
651
|
|
|
634
652
|
if context.get("proxy", self._proxy_default):
|
|
@@ -729,7 +747,9 @@ class _PayiInstrumentor:
|
|
|
729
747
|
return wrapped(*args, **kwargs)
|
|
730
748
|
|
|
731
749
|
# after _udpate_headers, all metadata to add to ingest is in extra_headers, keyed by the xproxy-xxx header name
|
|
732
|
-
extra_headers = kwargs.get("extra_headers"
|
|
750
|
+
extra_headers: Optional[dict[str, str]] = kwargs.get("extra_headers")
|
|
751
|
+
if extra_headers is None:
|
|
752
|
+
extra_headers = {}
|
|
733
753
|
self._update_extra_headers(context, extra_headers)
|
|
734
754
|
|
|
735
755
|
if context.get("proxy", self._proxy_default):
|
|
@@ -836,14 +856,20 @@ class _PayiInstrumentor:
|
|
|
836
856
|
extra_headers: "dict[str, str]",
|
|
837
857
|
) -> None:
|
|
838
858
|
context_limit_ids: Optional[list[str]] = context.get("limit_ids")
|
|
859
|
+
|
|
839
860
|
context_experience_name: Optional[str] = context.get("experience_name")
|
|
840
861
|
context_experience_id: Optional[str] = context.get("experience_id")
|
|
862
|
+
|
|
841
863
|
context_use_case_name: Optional[str] = context.get("use_case_name")
|
|
842
864
|
context_use_case_id: Optional[str] = context.get("use_case_id")
|
|
843
865
|
context_use_case_version: Optional[int] = context.get("use_case_version")
|
|
866
|
+
context_use_case_step: Optional[str] = context.get("use_case_step")
|
|
867
|
+
|
|
844
868
|
context_user_id: Optional[str] = context.get("user_id")
|
|
845
869
|
context_request_tags: Optional[list[str]] = context.get("request_tags")
|
|
846
|
-
|
|
870
|
+
|
|
871
|
+
context_price_as_category: Optional[str] = context.get("price_as_category")
|
|
872
|
+
context_price_as_resource: Optional[str] = context.get("price_as_resource")
|
|
847
873
|
context_resource_scope: Optional[str] = context.get("resource_scope")
|
|
848
874
|
|
|
849
875
|
# headers_limit_ids = extra_headers.get(PayiHeaderNames.limit_ids, None)
|
|
@@ -879,6 +905,7 @@ class _PayiInstrumentor:
|
|
|
879
905
|
extra_headers.pop(PayiHeaderNames.use_case_name, None)
|
|
880
906
|
extra_headers.pop(PayiHeaderNames.use_case_id, None)
|
|
881
907
|
extra_headers.pop(PayiHeaderNames.use_case_version, None)
|
|
908
|
+
extra_headers.pop(PayiHeaderNames.use_case_step, None)
|
|
882
909
|
else:
|
|
883
910
|
# leave the value in extra_headers
|
|
884
911
|
...
|
|
@@ -888,6 +915,8 @@ class _PayiInstrumentor:
|
|
|
888
915
|
extra_headers[PayiHeaderNames.use_case_id] = context_use_case_id
|
|
889
916
|
if context_use_case_version is not None:
|
|
890
917
|
extra_headers[PayiHeaderNames.use_case_version] = str(context_use_case_version)
|
|
918
|
+
if context_use_case_step is not None:
|
|
919
|
+
extra_headers[PayiHeaderNames.use_case_step] = str(context_use_case_step)
|
|
891
920
|
|
|
892
921
|
if PayiHeaderNames.experience_name in extra_headers:
|
|
893
922
|
headers_experience_name = extra_headers.get(PayiHeaderNames.experience_name, None)
|
|
@@ -906,8 +935,11 @@ class _PayiInstrumentor:
|
|
|
906
935
|
if PayiHeaderNames.request_tags not in extra_headers and context_request_tags:
|
|
907
936
|
extra_headers[PayiHeaderNames.request_tags] = ",".join(context_request_tags)
|
|
908
937
|
|
|
909
|
-
if PayiHeaderNames.
|
|
910
|
-
extra_headers[PayiHeaderNames.
|
|
938
|
+
if PayiHeaderNames.price_as_category not in extra_headers and context_price_as_category:
|
|
939
|
+
extra_headers[PayiHeaderNames.price_as_category] = context_price_as_category
|
|
940
|
+
|
|
941
|
+
if PayiHeaderNames.price_as_resource not in extra_headers and context_price_as_resource:
|
|
942
|
+
extra_headers[PayiHeaderNames.price_as_resource] = context_price_as_resource
|
|
911
943
|
|
|
912
944
|
if PayiHeaderNames.resource_scope not in extra_headers and context_resource_scope:
|
|
913
945
|
extra_headers[PayiHeaderNames.resource_scope] = context_resource_scope
|
|
@@ -1276,27 +1308,35 @@ def track_context(
|
|
|
1276
1308
|
use_case_name: Optional[str] = None,
|
|
1277
1309
|
use_case_id: Optional[str] = None,
|
|
1278
1310
|
use_case_version: Optional[int] = None,
|
|
1311
|
+
use_case_step: Optional[str] = None,
|
|
1279
1312
|
user_id: Optional[str] = None,
|
|
1280
1313
|
request_tags: Optional["list[str]"] = None,
|
|
1281
|
-
|
|
1314
|
+
price_as_category: Optional[str] = None,
|
|
1315
|
+
price_as_resource: Optional[str] = None,
|
|
1282
1316
|
resource_scope: Optional[str] = None,
|
|
1283
1317
|
proxy: Optional[bool] = None,
|
|
1284
1318
|
) -> _TrackContext:
|
|
1285
1319
|
# Create a new context for tracking
|
|
1286
1320
|
context: _Context = {}
|
|
1321
|
+
|
|
1322
|
+
context["proxy"] = proxy
|
|
1323
|
+
|
|
1287
1324
|
context["limit_ids"] = limit_ids
|
|
1325
|
+
|
|
1288
1326
|
context["use_case_name"] = use_case_name
|
|
1289
1327
|
context["use_case_id"] = use_case_id
|
|
1290
1328
|
context["use_case_version"] = use_case_version
|
|
1329
|
+
context["use_case_step"] = use_case_step
|
|
1330
|
+
|
|
1291
1331
|
context["user_id"] = user_id
|
|
1292
1332
|
context["request_tags"] = request_tags
|
|
1293
|
-
|
|
1333
|
+
|
|
1334
|
+
context["price_as_category"] = price_as_category
|
|
1335
|
+
context["price_as_resource"] = price_as_resource
|
|
1294
1336
|
context["resource_scope"] = resource_scope
|
|
1295
|
-
context["proxy"] = proxy
|
|
1296
1337
|
|
|
1297
1338
|
return _TrackContext(context)
|
|
1298
1339
|
|
|
1299
|
-
|
|
1300
1340
|
@deprecated("@ingest() is deprecated. Use @track() instead")
|
|
1301
1341
|
def ingest(
|
|
1302
1342
|
limit_ids: Optional["list[str]"] = None,
|
|
@@ -11,7 +11,7 @@ payi/_resource.py,sha256=j2jIkTr8OIC8sU6-05nxSaCyj4MaFlbZrwlyg4_xJos,1088
|
|
|
11
11
|
payi/_response.py,sha256=rh9oJAvCKcPwQFm4iqH_iVrmK8bNx--YP_A2a4kN1OU,28776
|
|
12
12
|
payi/_streaming.py,sha256=Z_wIyo206T6Jqh2rolFg2VXZgX24PahLmpURp0-NssU,10092
|
|
13
13
|
payi/_types.py,sha256=2mbMK86K3W1aMTW7sOGQ-VND6-A2IuXKm8p4sYFztBU,6141
|
|
14
|
-
payi/_version.py,sha256=
|
|
14
|
+
payi/_version.py,sha256=6fhQGgaF_1ZJjjotA3epewXPCe3l-cUfYOAggXnDR6I,165
|
|
15
15
|
payi/pagination.py,sha256=k2356QGPOUSjRF2vHpwLBdF6P-2vnQzFfRIJQAHGQ7A,1258
|
|
16
16
|
payi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
payi/_utils/__init__.py,sha256=PNZ_QJuzZEgyYXqkO1HVhGkj5IU9bglVUcw7H-Knjzw,2062
|
|
@@ -25,13 +25,13 @@ payi/_utils/_transform.py,sha256=n7kskEWz6o__aoNvhFoGVyDoalNe6mJwp-g7BWkdj88,156
|
|
|
25
25
|
payi/_utils/_typing.py,sha256=D0DbbNu8GnYQTSICnTSHDGsYXj8TcAKyhejb0XcnjtY,4602
|
|
26
26
|
payi/_utils/_utils.py,sha256=ts4CiiuNpFiGB6YMdkQRh2SZvYvsl7mAF-JWHCcLDf4,12312
|
|
27
27
|
payi/lib/.keep,sha256=wuNrz-5SXo3jJaJOJgz4vFHM41YH_g20F5cRQo0vLes,224
|
|
28
|
-
payi/lib/AnthropicInstrumentor.py,sha256=
|
|
28
|
+
payi/lib/AnthropicInstrumentor.py,sha256=o_20JNhvgRJIsGHfR0EKtWH8yLIBkafj4jKyzMDdFeI,7643
|
|
29
29
|
payi/lib/BedrockInstrumentor.py,sha256=4IfOwq_MSGlvlSMxAocVu0G-Ctoir6nSL9KtpGfga8I,13969
|
|
30
|
-
payi/lib/OpenAIInstrumentor.py,sha256=
|
|
30
|
+
payi/lib/OpenAIInstrumentor.py,sha256=e93o253yGO-L2qiLg69BO8mc9Q2_NAcvwRFDv9qSSm8,17404
|
|
31
31
|
payi/lib/Stopwatch.py,sha256=7OJlxvr2Jyb6Zr1LYCYKczRB7rDVKkIR7gc4YoleNdE,764
|
|
32
32
|
payi/lib/VertexInstrumentor.py,sha256=R0s3aEW7haj4aC5t1lMeA9siOgYvxlKQShLJ-B5iiNM,11642
|
|
33
|
-
payi/lib/helpers.py,sha256=
|
|
34
|
-
payi/lib/instrument.py,sha256=
|
|
33
|
+
payi/lib/helpers.py,sha256=K1KAfWrpPT1UUGNxspLe1lHzQjP3XV5Pkh9IU4pKMok,4624
|
|
34
|
+
payi/lib/instrument.py,sha256=nUUEnyDJPNMgVvT1gRgSVX1T9D8IXvBG8UzUcmfM9ws,55743
|
|
35
35
|
payi/resources/__init__.py,sha256=1rtrPLWbNt8oJGOp6nwPumKLJ-ftez0B6qwLFyfcoP4,2972
|
|
36
36
|
payi/resources/ingest.py,sha256=8HNHEyfgIyJNqCh0rOhO9msoc61-8IyifJ6AbxjCrDg,22612
|
|
37
37
|
payi/resources/categories/__init__.py,sha256=w5gMiPdBSzJA_qfoVtFBElaoe8wGf_O63R7R1Spr6Gk,1093
|
|
@@ -141,7 +141,7 @@ payi/types/use_cases/definitions/kpi_retrieve_response.py,sha256=uQXliSvS3k-yDYw
|
|
|
141
141
|
payi/types/use_cases/definitions/kpi_update_params.py,sha256=jbawdWAdMnsTWVH0qfQGb8W7_TXe3lq4zjSRu44d8p8,373
|
|
142
142
|
payi/types/use_cases/definitions/kpi_update_response.py,sha256=zLyEoT0S8d7XHsnXZYT8tM7yDw0Aze0Mk-_Z6QeMtc8,459
|
|
143
143
|
payi/types/use_cases/definitions/limit_config_create_params.py,sha256=pzQza_16N3z8cFNEKr6gPbFvuGFrwNuGxAYb--Kbo2M,449
|
|
144
|
-
payi-0.1.
|
|
145
|
-
payi-0.1.
|
|
146
|
-
payi-0.1.
|
|
147
|
-
payi-0.1.
|
|
144
|
+
payi-0.1.0a74.dist-info/METADATA,sha256=1ladcQXJiKcFCEFdcIFQfesQF86aRXPt0D_Wu4ATUAo,15290
|
|
145
|
+
payi-0.1.0a74.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
146
|
+
payi-0.1.0a74.dist-info/licenses/LICENSE,sha256=CQt03aM-P4a3Yg5qBg3JSLVoQS3smMyvx7tYg_6V7Gk,11334
|
|
147
|
+
payi-0.1.0a74.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|