payi 0.1.0a124__py3-none-any.whl → 0.1.0a126__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/BedrockInstrumentor.py +35 -25
- payi/lib/helpers.py +12 -0
- payi/lib/instrument.py +117 -124
- payi/resources/ingest.py +2 -2
- {payi-0.1.0a124.dist-info → payi-0.1.0a126.dist-info}/METADATA +1 -1
- {payi-0.1.0a124.dist-info → payi-0.1.0a126.dist-info}/RECORD +9 -9
- {payi-0.1.0a124.dist-info → payi-0.1.0a126.dist-info}/WHEEL +0 -0
- {payi-0.1.0a124.dist-info → payi-0.1.0a126.dist-info}/licenses/LICENSE +0 -0
payi/_version.py
CHANGED
payi/lib/BedrockInstrumentor.py
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import json
|
|
3
|
-
from typing import Any, Optional, Sequence
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Optional, Sequence
|
|
4
4
|
from functools import wraps
|
|
5
5
|
from typing_extensions import override
|
|
6
6
|
|
|
7
7
|
from wrapt import ObjectProxy, wrap_function_wrapper # type: ignore
|
|
8
|
-
from tokenizers import Tokenizer # type: ignore
|
|
9
8
|
|
|
10
|
-
from payi.lib.helpers import PayiCategories, PayiHeaderNames, payi_aws_bedrock_url
|
|
9
|
+
from payi.lib.helpers import PayiCategories, PayiHeaderNames, PayiPropertyNames, payi_aws_bedrock_url
|
|
11
10
|
from payi.types.ingest_units_params import Units
|
|
12
11
|
from payi.types.pay_i_common_models_api_router_header_info_param import PayICommonModelsAPIRouterHeaderInfoParam
|
|
13
12
|
|
|
@@ -21,9 +20,10 @@ from .instrument import (
|
|
|
21
20
|
)
|
|
22
21
|
from .version_helper import get_version_helper
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from tokenizers import Tokenizer # type: ignore
|
|
25
|
+
else:
|
|
26
|
+
Tokenizer = None
|
|
27
27
|
|
|
28
28
|
GUARDRAIL_SEMANTIC_FAILURE_DESCRIPTION = "Bedrock Guardrails intervened"
|
|
29
29
|
|
|
@@ -118,9 +118,8 @@ def _redirect_to_payi(request: Any, event_name: str, **_: 'dict[str, Any]') -> N
|
|
|
118
118
|
for key, value in extra_headers.items():
|
|
119
119
|
request.headers[key] = value
|
|
120
120
|
|
|
121
|
-
|
|
122
121
|
class InvokeResponseWrapper(ObjectProxy): # type: ignore
|
|
123
|
-
_cohere_embed_english_v3_tokenizer: Optional[Tokenizer] = None
|
|
122
|
+
_cohere_embed_english_v3_tokenizer: Optional['Tokenizer'] = None
|
|
124
123
|
|
|
125
124
|
def __init__(
|
|
126
125
|
self,
|
|
@@ -189,15 +188,26 @@ class InvokeResponseWrapper(ObjectProxy): # type: ignore
|
|
|
189
188
|
if texts and len(texts) > 0:
|
|
190
189
|
text = " ".join(texts)
|
|
191
190
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
self._cohere_embed_english_v3_tokenizer
|
|
191
|
+
try:
|
|
192
|
+
from tokenizers import Tokenizer # type: ignore
|
|
193
|
+
|
|
194
|
+
if self._cohere_embed_english_v3_tokenizer is None: # type: ignore
|
|
195
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
196
|
+
tokenizer_path = os.path.join(current_dir, "data", "cohere_embed_english_v3.json")
|
|
197
|
+
self._cohere_embed_english_v3_tokenizer = Tokenizer.from_file(tokenizer_path) # type: ignore
|
|
198
|
+
|
|
199
|
+
if self._cohere_embed_english_v3_tokenizer is not None and isinstance(self._cohere_embed_english_v3_tokenizer, Tokenizer): # type: ignore
|
|
200
|
+
tokens: list = self._cohere_embed_english_v3_tokenizer.encode(text, add_special_tokens=False).tokens # type: ignore
|
|
196
201
|
|
|
197
|
-
|
|
202
|
+
if tokens and isinstance(tokens, list):
|
|
203
|
+
units["text"] = Units(input=len(tokens), output=0) # type: ignore
|
|
198
204
|
|
|
199
|
-
|
|
200
|
-
|
|
205
|
+
except ImportError:
|
|
206
|
+
self._request._instrumentor._logger.warning("tokenizers module not found, caller must install the tokenizers module. Cannot record text tokens for Cohere embed english v3")
|
|
207
|
+
pass
|
|
208
|
+
except Exception as e:
|
|
209
|
+
self._request._instrumentor._logger.warning(f"Error processing Cohere embed english v3 response: {e}")
|
|
210
|
+
pass
|
|
201
211
|
|
|
202
212
|
if self._log_prompt_and_response:
|
|
203
213
|
ingest["provider_response_json"] = data.decode('utf-8') # type: ignore
|
|
@@ -388,11 +398,11 @@ class _BedrockInvokeProviderRequest(_BedrockProviderRequest):
|
|
|
388
398
|
|
|
389
399
|
guardrail_id = kwargs.get("guardrailIdentifier", "")
|
|
390
400
|
if guardrail_id:
|
|
391
|
-
self.add_internal_request_property(
|
|
401
|
+
self.add_internal_request_property(PayiPropertyNames.aws_bedrock_guardrail_id, guardrail_id)
|
|
392
402
|
|
|
393
403
|
guardrail_version = kwargs.get("guardrailVersion", "")
|
|
394
404
|
if guardrail_version:
|
|
395
|
-
self.add_internal_request_property(
|
|
405
|
+
self.add_internal_request_property(PayiPropertyNames.aws_bedrock_guardrail_version, guardrail_version)
|
|
396
406
|
|
|
397
407
|
if guardrail_id and guardrail_version and BedrockInstrumentor._guardrail_trace:
|
|
398
408
|
trace = kwargs.get("trace", None)
|
|
@@ -488,9 +498,9 @@ class _BedrockInvokeProviderRequest(_BedrockProviderRequest):
|
|
|
488
498
|
def process_stop_action(self, action: str) -> None:
|
|
489
499
|
# record both as a semantic failure and guardrail action so it is discoverable through both properties
|
|
490
500
|
if action == "INTERVENED":
|
|
491
|
-
self.add_internal_request_property(
|
|
492
|
-
self.add_internal_request_property(
|
|
493
|
-
self.add_internal_request_property(
|
|
501
|
+
self.add_internal_request_property(PayiPropertyNames.failure, action)
|
|
502
|
+
self.add_internal_request_property(PayiPropertyNames.failure_description, GUARDRAIL_SEMANTIC_FAILURE_DESCRIPTION)
|
|
503
|
+
self.add_internal_request_property(PayiPropertyNames.aws_bedrock_guardrail_action, action)
|
|
494
504
|
|
|
495
505
|
@override
|
|
496
506
|
def remove_inline_data(self, prompt: 'dict[str, Any]') -> bool:# noqa: ARG002
|
|
@@ -519,11 +529,11 @@ class _BedrockConverseProviderRequest(_BedrockProviderRequest):
|
|
|
519
529
|
if guardrail_config:
|
|
520
530
|
guardrailIdentifier = guardrail_config.get("guardrailIdentifier", "")
|
|
521
531
|
if guardrailIdentifier:
|
|
522
|
-
self.add_internal_request_property(
|
|
532
|
+
self.add_internal_request_property(PayiPropertyNames.aws_bedrock_guardrail_id, guardrailIdentifier)
|
|
523
533
|
|
|
524
534
|
guardrailVersion = guardrail_config.get("guardrailVersion", "")
|
|
525
535
|
if guardrailVersion:
|
|
526
|
-
self.add_internal_request_property(
|
|
536
|
+
self.add_internal_request_property(PayiPropertyNames.aws_bedrock_guardrail_version, guardrailVersion)
|
|
527
537
|
|
|
528
538
|
if guardrailIdentifier and guardrailVersion and BedrockInstrumentor._guardrail_trace:
|
|
529
539
|
trace = guardrail_config.get("trace", None)
|
|
@@ -597,9 +607,9 @@ class _BedrockConverseProviderRequest(_BedrockProviderRequest):
|
|
|
597
607
|
def process_stop_reason(self, reason: str) -> None:
|
|
598
608
|
if reason == "guardrail_intervened":
|
|
599
609
|
# record both as a semantic failure and guardrail action so it is discoverable through both properties
|
|
600
|
-
self.add_internal_request_property(
|
|
601
|
-
self.add_internal_request_property(
|
|
602
|
-
self.add_internal_request_property(
|
|
610
|
+
self.add_internal_request_property(PayiPropertyNames.failure, reason)
|
|
611
|
+
self.add_internal_request_property(PayiPropertyNames.failure_description, GUARDRAIL_SEMANTIC_FAILURE_DESCRIPTION)
|
|
612
|
+
self.add_internal_request_property(PayiPropertyNames.aws_bedrock_guardrail_action, reason)
|
|
603
613
|
|
|
604
614
|
def bedrock_converse_process_streaming_for_function_call(request: _ProviderRequest, chunk: 'dict[str, Any]') -> None:
|
|
605
615
|
contentBlockStart = chunk.get("contentBlockStart", {})
|
payi/lib/helpers.py
CHANGED
|
@@ -25,6 +25,18 @@ class PayiCategories:
|
|
|
25
25
|
aws_bedrock:str = "system.aws.bedrock"
|
|
26
26
|
google_vertex:str = "system.google.vertex"
|
|
27
27
|
|
|
28
|
+
class PayiPropertyNames:
|
|
29
|
+
failure:str = "system.failure"
|
|
30
|
+
failure_description:str = "system.failure.description"
|
|
31
|
+
|
|
32
|
+
account_name:str = "system.account_name"
|
|
33
|
+
use_case_step:str = "system.use_case_step"
|
|
34
|
+
user_id:str = "system.user_id"
|
|
35
|
+
|
|
36
|
+
aws_bedrock_guardrail_id:str = "system.aws.bedrock.guardrail.id"
|
|
37
|
+
aws_bedrock_guardrail_version:str = "system.aws.bedrock.guardrail.version"
|
|
38
|
+
aws_bedrock_guardrail_action:str = "system.aws.bedrock.guardrail.action"
|
|
39
|
+
|
|
28
40
|
def create_limit_header_from_ids(*, limit_ids: List[str]) -> Dict[str, str]:
|
|
29
41
|
if not isinstance(limit_ids, list): # type: ignore
|
|
30
42
|
raise TypeError("limit_ids must be a list")
|
payi/lib/instrument.py
CHANGED
|
@@ -2,13 +2,14 @@ import os
|
|
|
2
2
|
import json
|
|
3
3
|
import time
|
|
4
4
|
import uuid
|
|
5
|
+
import atexit
|
|
5
6
|
import asyncio
|
|
6
7
|
import inspect
|
|
7
8
|
import logging
|
|
8
9
|
import traceback
|
|
9
10
|
from abc import abstractmethod
|
|
10
11
|
from enum import Enum
|
|
11
|
-
from typing import Any, Set, Union,
|
|
12
|
+
from typing import Any, Set, Union, Optional, Sequence, TypedDict
|
|
12
13
|
from datetime import datetime, timezone
|
|
13
14
|
from dataclasses import dataclass
|
|
14
15
|
|
|
@@ -17,7 +18,7 @@ from wrapt import ObjectProxy # type: ignore
|
|
|
17
18
|
|
|
18
19
|
from payi import Payi, AsyncPayi, APIStatusError, APIConnectionError, __version__ as _payi_version
|
|
19
20
|
from payi.types import IngestUnitsParams
|
|
20
|
-
from payi.lib.helpers import PayiHeaderNames
|
|
21
|
+
from payi.lib.helpers import PayiHeaderNames, PayiPropertyNames
|
|
21
22
|
from payi.types.shared import XproxyResult
|
|
22
23
|
from payi.types.ingest_response import IngestResponse
|
|
23
24
|
from payi.types.ingest_units_params import Units, ProviderResponseFunctionCall
|
|
@@ -117,10 +118,10 @@ class _ProviderRequest:
|
|
|
117
118
|
except Exception as _ex:
|
|
118
119
|
pass
|
|
119
120
|
|
|
120
|
-
self.add_internal_request_property(
|
|
121
|
+
self.add_internal_request_property(PayiPropertyNames.failure, exception_str)
|
|
121
122
|
if fields:
|
|
122
123
|
failure_description = ",".join(fields)
|
|
123
|
-
self.add_internal_request_property(
|
|
124
|
+
self.add_internal_request_property(PayiPropertyNames.failure_description, failure_description)
|
|
124
125
|
|
|
125
126
|
if "http_status_code" not in self._ingest:
|
|
126
127
|
# use a non existent http status code so when presented to the user, the origin is clear
|
|
@@ -148,6 +149,9 @@ class _ProviderRequest:
|
|
|
148
149
|
class PayiInstrumentAwsBedrockConfig(TypedDict, total=False):
|
|
149
150
|
guardrail_trace: bool
|
|
150
151
|
|
|
152
|
+
class PayiInstrumentOfflineInstrumentationConfig(TypedDict, total=False):
|
|
153
|
+
file_name: str
|
|
154
|
+
|
|
151
155
|
class PayiInstrumentConfig(TypedDict, total=False):
|
|
152
156
|
proxy: bool
|
|
153
157
|
global_instrumentation: bool
|
|
@@ -163,6 +167,7 @@ class PayiInstrumentConfig(TypedDict, total=False):
|
|
|
163
167
|
request_tags: Optional["list[str]"]
|
|
164
168
|
request_properties: Optional["dict[str, str]"]
|
|
165
169
|
aws_config: Optional[PayiInstrumentAwsBedrockConfig]
|
|
170
|
+
offline_instrumentation: Optional[PayiInstrumentOfflineInstrumentationConfig]
|
|
166
171
|
|
|
167
172
|
class PayiContext(TypedDict, total=False):
|
|
168
173
|
use_case_name: Optional[str]
|
|
@@ -190,7 +195,6 @@ class _Context(TypedDict, total=False):
|
|
|
190
195
|
limit_ids: Optional['list[str]']
|
|
191
196
|
user_id: Optional[str]
|
|
192
197
|
account_name: Optional[str]
|
|
193
|
-
request_tags: Optional["list[str]"]
|
|
194
198
|
request_properties: Optional["dict[str, str]"]
|
|
195
199
|
price_as_category: Optional[str]
|
|
196
200
|
price_as_resource: Optional[str]
|
|
@@ -236,9 +240,6 @@ class _PayiInstrumentor:
|
|
|
236
240
|
instruments: Union[Set[str], None] = None,
|
|
237
241
|
log_prompt_and_response: bool = True,
|
|
238
242
|
logger: Optional[logging.Logger] = None,
|
|
239
|
-
prompt_and_response_logger: Optional[
|
|
240
|
-
Callable[[str, "dict[str, str]"], None]
|
|
241
|
-
] = None, # (request id, dict of data to store) -> None
|
|
242
243
|
global_config: PayiInstrumentConfig = {},
|
|
243
244
|
caller_filename: str = ""
|
|
244
245
|
):
|
|
@@ -257,7 +258,6 @@ class _PayiInstrumentor:
|
|
|
257
258
|
|
|
258
259
|
self._context_stack: list[_Context] = [] # Stack of context dictionaries
|
|
259
260
|
self._log_prompt_and_response: bool = log_prompt_and_response
|
|
260
|
-
self._prompt_and_response_logger: Optional[Callable[[str, dict[str, str]], None]] = prompt_and_response_logger
|
|
261
261
|
|
|
262
262
|
self._blocked_limits: set[str] = set()
|
|
263
263
|
self._exceeded_limits: set[str] = set()
|
|
@@ -275,6 +275,17 @@ class _PayiInstrumentor:
|
|
|
275
275
|
|
|
276
276
|
self._last_result: Optional[Union[XproxyResult, XproxyError]] = None
|
|
277
277
|
|
|
278
|
+
self._offline_instrumentation = global_config.pop("offline_instrumentation", None)
|
|
279
|
+
self._offline_ingest_packets: list[IngestUnitsParams] = []
|
|
280
|
+
self._offline_instrumentation_file_name: Optional[str] = None
|
|
281
|
+
|
|
282
|
+
if self._offline_instrumentation is not None:
|
|
283
|
+
timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
|
284
|
+
self._offline_instrumentation_file_name = self._offline_instrumentation.get("file_name", f"payi_instrumentation_{timestamp}.json")
|
|
285
|
+
|
|
286
|
+
# Register exit handler to write packets when process exits
|
|
287
|
+
atexit.register(lambda: self._write_offline_ingest_packets())
|
|
288
|
+
|
|
278
289
|
global_instrumentation = global_config.pop("global_instrumentation", True)
|
|
279
290
|
|
|
280
291
|
if instruments is None or "*" in instruments:
|
|
@@ -287,9 +298,7 @@ class _PayiInstrumentor:
|
|
|
287
298
|
global_config["proxy"] = self._proxy_default
|
|
288
299
|
|
|
289
300
|
# Use default clients if not provided for global ingest instrumentation
|
|
290
|
-
|
|
291
|
-
self._payi = Payi()
|
|
292
|
-
self._apayi = AsyncPayi()
|
|
301
|
+
self._ensure_payi_clients()
|
|
293
302
|
|
|
294
303
|
if "use_case_name" not in global_config and caller_filename:
|
|
295
304
|
description = f"Default use case for {caller_filename}.py"
|
|
@@ -298,6 +307,9 @@ class _PayiInstrumentor:
|
|
|
298
307
|
self._payi.use_cases.definitions.create(name=caller_filename, description=description)
|
|
299
308
|
elif self._apayi:
|
|
300
309
|
self._call_async_use_case_definition_create(use_case_name=caller_filename, use_case_description=description)
|
|
310
|
+
else:
|
|
311
|
+
# in the case of _local_instrumentation is not None
|
|
312
|
+
pass
|
|
301
313
|
global_config["use_case_name"] = caller_filename
|
|
302
314
|
except Exception as e:
|
|
303
315
|
self._logger.error(f"Error creating default use case definition based on file name {caller_filename}: {e}")
|
|
@@ -315,6 +327,14 @@ class _PayiInstrumentor:
|
|
|
315
327
|
|
|
316
328
|
self._init_current_context(**context)
|
|
317
329
|
|
|
330
|
+
def _ensure_payi_clients(self) -> None:
|
|
331
|
+
if self._offline_instrumentation is not None:
|
|
332
|
+
return
|
|
333
|
+
|
|
334
|
+
if not self._payi and not self._apayi:
|
|
335
|
+
self._payi = Payi()
|
|
336
|
+
self._apayi = AsyncPayi()
|
|
337
|
+
|
|
318
338
|
def _instrument_all(self, global_config: PayiInstrumentConfig) -> None:
|
|
319
339
|
self._instrument_openai()
|
|
320
340
|
self._instrument_anthropic()
|
|
@@ -378,6 +398,30 @@ class _PayiInstrumentor:
|
|
|
378
398
|
except Exception as e:
|
|
379
399
|
self._logger.error(f"Error instrumenting Google GenAi: {e}")
|
|
380
400
|
|
|
401
|
+
def _write_offline_ingest_packets(self) -> None:
|
|
402
|
+
if not self._offline_instrumentation_file_name or not self._offline_ingest_packets:
|
|
403
|
+
return
|
|
404
|
+
|
|
405
|
+
try:
|
|
406
|
+
# Convert datetime objects to ISO strings for JSON serialization
|
|
407
|
+
serializable_packets: list[IngestUnitsParams] = []
|
|
408
|
+
for packet in self._offline_ingest_packets:
|
|
409
|
+
serializable_packet = packet.copy()
|
|
410
|
+
|
|
411
|
+
# Convert datetime fields to ISO format strings
|
|
412
|
+
if 'event_timestamp' in serializable_packet and isinstance(serializable_packet['event_timestamp'], datetime):
|
|
413
|
+
serializable_packet['event_timestamp'] = serializable_packet['event_timestamp'].isoformat()
|
|
414
|
+
|
|
415
|
+
serializable_packets.append(serializable_packet)
|
|
416
|
+
|
|
417
|
+
with open(self._offline_instrumentation_file_name, 'w', encoding='utf-8') as f:
|
|
418
|
+
json.dump(serializable_packets, f)
|
|
419
|
+
|
|
420
|
+
self._logger.debug(f"Written {len(self._offline_ingest_packets)} ingest packets to {self._offline_instrumentation_file_name}")
|
|
421
|
+
|
|
422
|
+
except Exception as e:
|
|
423
|
+
self._logger.error(f"Error writing offline ingest packets to {self._offline_instrumentation_file_name}: {e}")
|
|
424
|
+
|
|
381
425
|
@staticmethod
|
|
382
426
|
def _create_logged_ingest_units(
|
|
383
427
|
ingest_units: IngestUnitsParams,
|
|
@@ -397,7 +441,6 @@ class _PayiInstrumentor:
|
|
|
397
441
|
def _process_ingest_units(
|
|
398
442
|
self,
|
|
399
443
|
request: _ProviderRequest,
|
|
400
|
-
log_data: 'dict[str, str]',
|
|
401
444
|
extra_headers: 'dict[str, str]') -> None:
|
|
402
445
|
ingest_units = request._ingest
|
|
403
446
|
|
|
@@ -408,6 +451,9 @@ class _PayiInstrumentor:
|
|
|
408
451
|
# convert the function call builder to a list of function calls
|
|
409
452
|
ingest_units["provider_response_function_calls"] = list(request._function_call_builder.values())
|
|
410
453
|
|
|
454
|
+
if "provider_response_id" not in ingest_units or not ingest_units["provider_response_id"]:
|
|
455
|
+
ingest_units["provider_response_id"] = f"payi_{uuid.uuid4()}"
|
|
456
|
+
|
|
411
457
|
if 'resource' not in ingest_units or ingest_units['resource'] == '':
|
|
412
458
|
ingest_units['resource'] = "system.unknown_model"
|
|
413
459
|
|
|
@@ -435,19 +481,6 @@ class _PayiInstrumentor:
|
|
|
435
481
|
if not units or all(unit.get("input", 0) == 0 and unit.get("output", 0) == 0 for unit in units.values()):
|
|
436
482
|
self._logger.info('ingesting with no token counts')
|
|
437
483
|
|
|
438
|
-
if self._log_prompt_and_response and self._prompt_and_response_logger:
|
|
439
|
-
response_json = ingest_units.pop("provider_response_json", None)
|
|
440
|
-
request_json = ingest_units.pop("provider_request_json", None)
|
|
441
|
-
stack_trace = ingest_units.get("properties", {}).pop("system.stack_trace", None) # type: ignore
|
|
442
|
-
|
|
443
|
-
if response_json is not None:
|
|
444
|
-
# response_json is a list of strings, convert a single json string
|
|
445
|
-
log_data["provider_response_json"] = json.dumps(response_json)
|
|
446
|
-
if request_json is not None:
|
|
447
|
-
log_data["provider_request_json"] = request_json
|
|
448
|
-
if stack_trace is not None:
|
|
449
|
-
log_data["stack_trace"] = stack_trace
|
|
450
|
-
|
|
451
484
|
def _process_ingest_units_response(self, ingest_response: IngestResponse) -> None:
|
|
452
485
|
if ingest_response.xproxy_result.limits:
|
|
453
486
|
for limit_id, state in ingest_response.xproxy_result.limits.items():
|
|
@@ -490,11 +523,8 @@ class _PayiInstrumentor:
|
|
|
490
523
|
|
|
491
524
|
self._logger.debug(f"_aingest_units")
|
|
492
525
|
|
|
493
|
-
# return early if there are no units to ingest and on a successul ingest request
|
|
494
|
-
log_data: 'dict[str,str]' = {}
|
|
495
526
|
extra_headers: 'dict[str, str]' = {}
|
|
496
|
-
|
|
497
|
-
self._process_ingest_units(request, log_data=log_data, extra_headers=extra_headers)
|
|
527
|
+
self._process_ingest_units(request, extra_headers=extra_headers)
|
|
498
528
|
|
|
499
529
|
try:
|
|
500
530
|
if self._logger.isEnabledFor(logging.DEBUG):
|
|
@@ -504,6 +534,18 @@ class _PayiInstrumentor:
|
|
|
504
534
|
ingest_response = await self._apayi.ingest.units(**ingest_units, extra_headers=extra_headers)
|
|
505
535
|
elif self._payi:
|
|
506
536
|
ingest_response = self._payi.ingest.units(**ingest_units, extra_headers=extra_headers)
|
|
537
|
+
elif self._offline_instrumentation is not None:
|
|
538
|
+
self._offline_ingest_packets.append(ingest_units.copy())
|
|
539
|
+
|
|
540
|
+
# simulate a successful ingest for local instrumentation
|
|
541
|
+
now=datetime.now(timezone.utc)
|
|
542
|
+
ingest_response = IngestResponse(
|
|
543
|
+
event_timestamp=now,
|
|
544
|
+
ingest_timestamp=now,
|
|
545
|
+
request_id="local_instrumentation",
|
|
546
|
+
xproxy_result=XproxyResult(request_id="local_instrumentation"))
|
|
547
|
+
pass
|
|
548
|
+
|
|
507
549
|
else:
|
|
508
550
|
self._logger.error("No payi instance to ingest units")
|
|
509
551
|
return XproxyError(code="configuration_error", message="No Payi or AsyncPayi instance configured for ingesting units")
|
|
@@ -513,10 +555,6 @@ class _PayiInstrumentor:
|
|
|
513
555
|
if ingest_response:
|
|
514
556
|
self._process_ingest_units_response(ingest_response)
|
|
515
557
|
|
|
516
|
-
if ingest_response and self._log_prompt_and_response and self._prompt_and_response_logger:
|
|
517
|
-
request_id = ingest_response.xproxy_result.request_id
|
|
518
|
-
self._prompt_and_response_logger(request_id, log_data) # type: ignore
|
|
519
|
-
|
|
520
558
|
return ingest_response.xproxy_result
|
|
521
559
|
|
|
522
560
|
except APIConnectionError as api_ex:
|
|
@@ -609,10 +647,8 @@ class _PayiInstrumentor:
|
|
|
609
647
|
|
|
610
648
|
self._logger.debug(f"_ingest_units")
|
|
611
649
|
|
|
612
|
-
# return early if there are no units to ingest and on a successul ingest request
|
|
613
|
-
log_data: 'dict[str,str]' = {}
|
|
614
650
|
extra_headers: 'dict[str, str]' = {}
|
|
615
|
-
self._process_ingest_units(request,
|
|
651
|
+
self._process_ingest_units(request, extra_headers=extra_headers)
|
|
616
652
|
|
|
617
653
|
try:
|
|
618
654
|
if self._payi:
|
|
@@ -624,16 +660,18 @@ class _PayiInstrumentor:
|
|
|
624
660
|
|
|
625
661
|
self._process_ingest_units_response(ingest_response)
|
|
626
662
|
|
|
627
|
-
if self._log_prompt_and_response and self._prompt_and_response_logger:
|
|
628
|
-
request_id = ingest_response.xproxy_result.request_id
|
|
629
|
-
self._prompt_and_response_logger(request_id, log_data) # type: ignore
|
|
630
|
-
|
|
631
663
|
return ingest_response.xproxy_result
|
|
632
664
|
elif self._apayi:
|
|
633
665
|
# task runs async. aingest_units will invoke the callback and post process
|
|
634
666
|
sync_response = self._call_aingest_sync(request)
|
|
635
667
|
self._logger.debug(f"_ingest_units: apayi success ({sync_response})")
|
|
636
668
|
return sync_response
|
|
669
|
+
elif self._offline_instrumentation is not None:
|
|
670
|
+
self._offline_ingest_packets.append(ingest_units.copy())
|
|
671
|
+
|
|
672
|
+
# simulate a successful ingest for local instrumentation
|
|
673
|
+
return XproxyResult(request_id="local_instrumentation")
|
|
674
|
+
|
|
637
675
|
else:
|
|
638
676
|
self._logger.error("No payi instance to ingest units")
|
|
639
677
|
return XproxyError(code="configuration_error", message="No Payi or AsyncPayi instance configured for ingesting units")
|
|
@@ -661,6 +699,31 @@ class _PayiInstrumentor:
|
|
|
661
699
|
|
|
662
700
|
return {}
|
|
663
701
|
|
|
702
|
+
@staticmethod
|
|
703
|
+
def _valid_str_or_none(value: Optional[str], default: Optional[str] = None) -> Optional[str]:
|
|
704
|
+
if value is None:
|
|
705
|
+
return default
|
|
706
|
+
elif len(value) == 0:
|
|
707
|
+
# an empty string explicitly blocks the default value
|
|
708
|
+
return None
|
|
709
|
+
else:
|
|
710
|
+
return value
|
|
711
|
+
|
|
712
|
+
@staticmethod
|
|
713
|
+
def _valid_properties_or_none(value: Optional["dict[str, str]"], default: Optional["dict[str, str]"] = None) -> Optional["dict[str, str]"]:
|
|
714
|
+
if value is None:
|
|
715
|
+
return default.copy() if default else None
|
|
716
|
+
elif len(value) == 0:
|
|
717
|
+
# an empty dictionary explicitly blocks the default value
|
|
718
|
+
return None
|
|
719
|
+
elif default:
|
|
720
|
+
# merge dictionaries, child overrides parent keys
|
|
721
|
+
merged = default.copy()
|
|
722
|
+
merged.update(value)
|
|
723
|
+
return merged
|
|
724
|
+
else:
|
|
725
|
+
return value.copy()
|
|
726
|
+
|
|
664
727
|
def _init_current_context(
|
|
665
728
|
self,
|
|
666
729
|
proxy: Optional[bool] = None,
|
|
@@ -671,7 +734,6 @@ class _PayiInstrumentor:
|
|
|
671
734
|
use_case_step: Optional[str]= None,
|
|
672
735
|
user_id: Optional[str]= None,
|
|
673
736
|
account_name: Optional[str]= None,
|
|
674
|
-
request_tags: Optional["list[str]"] = None,
|
|
675
737
|
request_properties: Optional["dict[str, str]"] = None,
|
|
676
738
|
use_case_properties: Optional["dict[str, str]"] = None,
|
|
677
739
|
price_as_category: Optional[str] = None,
|
|
@@ -689,7 +751,6 @@ class _PayiInstrumentor:
|
|
|
689
751
|
parent_use_case_name = parent_context.get("use_case_name", None)
|
|
690
752
|
parent_use_case_id = parent_context.get("use_case_id", None)
|
|
691
753
|
parent_use_case_version = parent_context.get("use_case_version", None)
|
|
692
|
-
parent_use_case_step = parent_context.get("use_case_step", None)
|
|
693
754
|
|
|
694
755
|
assign_use_case_values = False
|
|
695
756
|
|
|
@@ -721,26 +782,12 @@ class _PayiInstrumentor:
|
|
|
721
782
|
assign_use_case_values = True
|
|
722
783
|
|
|
723
784
|
if assign_use_case_values:
|
|
724
|
-
context["
|
|
725
|
-
context["
|
|
726
|
-
context["use_case_step"] = use_case_step
|
|
785
|
+
context["use_case_version"] = use_case_version if use_case_version is not None else parent_use_case_version
|
|
786
|
+
context["use_case_id"] = self._valid_str_or_none(use_case_id, parent_use_case_id)
|
|
787
|
+
context["use_case_step"] = self._valid_str_or_none(use_case_step, None)
|
|
727
788
|
|
|
728
789
|
parent_use_case_properties = parent_context.get("use_case_properties", None)
|
|
729
|
-
|
|
730
|
-
if not use_case_properties:
|
|
731
|
-
# an empty dictionary explicitly blocks inheriting from the parent state
|
|
732
|
-
context["use_case_properties"] = None
|
|
733
|
-
else:
|
|
734
|
-
if parent_use_case_properties:
|
|
735
|
-
# merge dictionaries, child overrides parent keys
|
|
736
|
-
merged = parent_use_case_properties.copy()
|
|
737
|
-
merged.update(use_case_properties)
|
|
738
|
-
context["use_case_properties"] = merged
|
|
739
|
-
else:
|
|
740
|
-
context["use_case_properties"] = use_case_properties.copy()
|
|
741
|
-
elif parent_use_case_properties:
|
|
742
|
-
# use the parent use_case_properties if it exists
|
|
743
|
-
context["use_case_properties"] = parent_use_case_properties.copy()
|
|
790
|
+
context["use_case_properties"] = self._valid_properties_or_none(use_case_properties, parent_use_case_properties)
|
|
744
791
|
|
|
745
792
|
parent_limit_ids = parent_context.get("limit_ids", None)
|
|
746
793
|
if limit_ids is None:
|
|
@@ -754,56 +801,13 @@ class _PayiInstrumentor:
|
|
|
754
801
|
context["limit_ids"] = list(set(limit_ids) | set(parent_limit_ids)) if parent_limit_ids else limit_ids.copy()
|
|
755
802
|
|
|
756
803
|
parent_user_id = parent_context.get("user_id", None)
|
|
757
|
-
|
|
758
|
-
# use the parent user_id if it exists
|
|
759
|
-
context["user_id"] = parent_user_id
|
|
760
|
-
elif len(user_id) == 0:
|
|
761
|
-
# caller passing an empty string explicitly blocks inheriting from the parent state
|
|
762
|
-
context["user_id"] = None
|
|
763
|
-
else:
|
|
764
|
-
context["user_id"] = user_id
|
|
804
|
+
context["user_id"] = self._valid_str_or_none(user_id, parent_user_id)
|
|
765
805
|
|
|
766
806
|
parent_account_name = parent_context.get("account_name", None)
|
|
767
|
-
|
|
768
|
-
# use the parent account_name if it exists
|
|
769
|
-
context["account_name"] = parent_account_name
|
|
770
|
-
elif len(account_name) == 0:
|
|
771
|
-
# caller passing an empty string explicitly blocks inheriting from the parent state
|
|
772
|
-
context["account_name"] = None
|
|
773
|
-
else:
|
|
774
|
-
context["account_name"] = account_name
|
|
775
|
-
|
|
776
|
-
parent_request_tags = parent_context.get("request_tags", None)
|
|
777
|
-
if request_tags is not None:
|
|
778
|
-
if len(request_tags) == 0:
|
|
779
|
-
# caller passing an empty list explicitly blocks inheriting from the parent state
|
|
780
|
-
context["request_tags"] = None
|
|
781
|
-
else:
|
|
782
|
-
if parent_request_tags:
|
|
783
|
-
# union of new and parent lists if the parent context contains request tags
|
|
784
|
-
context["request_tags"] = list(set(request_tags) | set(parent_request_tags))
|
|
785
|
-
else:
|
|
786
|
-
context["request_tags"] = request_tags.copy()
|
|
787
|
-
elif parent_request_tags:
|
|
788
|
-
# use the parent request_tags if it exists
|
|
789
|
-
context["request_tags"] = parent_request_tags.copy()
|
|
807
|
+
context["account_name"] = self._valid_str_or_none(account_name, parent_account_name)
|
|
790
808
|
|
|
791
809
|
parent_request_properties = parent_context.get("request_properties", None)
|
|
792
|
-
|
|
793
|
-
if not request_properties:
|
|
794
|
-
# an empty dictionary explicitly blocks inheriting from the parent state
|
|
795
|
-
context["request_properties"] = None
|
|
796
|
-
else:
|
|
797
|
-
if parent_request_properties:
|
|
798
|
-
# merge dictionaries, child overrides parent keys
|
|
799
|
-
merged = parent_request_properties.copy()
|
|
800
|
-
merged.update(request_properties)
|
|
801
|
-
context["request_properties"] = merged
|
|
802
|
-
else:
|
|
803
|
-
context["request_properties"] = request_properties.copy()
|
|
804
|
-
elif parent_request_properties:
|
|
805
|
-
# use the parent request_properties if it exists
|
|
806
|
-
context["request_properties"] = parent_request_properties.copy()
|
|
810
|
+
context["request_properties"] = self._valid_properties_or_none(request_properties, parent_request_properties)
|
|
807
811
|
|
|
808
812
|
if price_as_category:
|
|
809
813
|
context["price_as_category"] = price_as_category
|
|
@@ -822,7 +826,6 @@ class _PayiInstrumentor:
|
|
|
822
826
|
use_case_version: Optional[int],
|
|
823
827
|
user_id: Optional[str],
|
|
824
828
|
account_name: Optional[str],
|
|
825
|
-
request_tags: Optional["list[str]"] = None,
|
|
826
829
|
request_properties: Optional["dict[str, str]"] = None,
|
|
827
830
|
use_case_properties: Optional["dict[str, str]"] = None,
|
|
828
831
|
*args: Any,
|
|
@@ -837,7 +840,6 @@ class _PayiInstrumentor:
|
|
|
837
840
|
use_case_version=use_case_version,
|
|
838
841
|
user_id=user_id,
|
|
839
842
|
account_name=account_name,
|
|
840
|
-
request_tags=request_tags,
|
|
841
843
|
request_properties=request_properties,
|
|
842
844
|
use_case_properties=use_case_properties
|
|
843
845
|
)
|
|
@@ -853,7 +855,6 @@ class _PayiInstrumentor:
|
|
|
853
855
|
use_case_version: Optional[int],
|
|
854
856
|
user_id: Optional[str],
|
|
855
857
|
account_name: Optional[str],
|
|
856
|
-
request_tags: Optional["list[str]"] = None,
|
|
857
858
|
request_properties: Optional["dict[str, str]"] = None,
|
|
858
859
|
use_case_properties: Optional["dict[str, str]"] = None,
|
|
859
860
|
*args: Any,
|
|
@@ -868,7 +869,6 @@ class _PayiInstrumentor:
|
|
|
868
869
|
use_case_version=use_case_version,
|
|
869
870
|
user_id=user_id,
|
|
870
871
|
account_name=account_name,
|
|
871
|
-
request_tags=request_tags,
|
|
872
872
|
request_properties=request_properties,
|
|
873
873
|
use_case_properties=use_case_properties)
|
|
874
874
|
return func(*args, **kwargs)
|
|
@@ -901,7 +901,8 @@ class _PayiInstrumentor:
|
|
|
901
901
|
) -> None:
|
|
902
902
|
|
|
903
903
|
limit_ids = ingest_extra_headers.pop(PayiHeaderNames.limit_ids, None)
|
|
904
|
-
|
|
904
|
+
# pop and ignore the request tags header since it is no longer processed
|
|
905
|
+
ingest_extra_headers.pop(PayiHeaderNames.request_tags, None)
|
|
905
906
|
|
|
906
907
|
use_case_name = ingest_extra_headers.pop(PayiHeaderNames.use_case_name, None)
|
|
907
908
|
use_case_id = ingest_extra_headers.pop(PayiHeaderNames.use_case_id, None)
|
|
@@ -913,8 +914,6 @@ class _PayiInstrumentor:
|
|
|
913
914
|
|
|
914
915
|
if limit_ids:
|
|
915
916
|
request._ingest["limit_ids"] = limit_ids.split(",")
|
|
916
|
-
if request_tags:
|
|
917
|
-
request._ingest["request_tags"] = request_tags.split(",")
|
|
918
917
|
if use_case_name:
|
|
919
918
|
request._ingest["use_case_name"] = use_case_name
|
|
920
919
|
if use_case_id:
|
|
@@ -1259,7 +1258,6 @@ class _PayiInstrumentor:
|
|
|
1259
1258
|
|
|
1260
1259
|
context_user_id: Optional[str] = context.get("user_id")
|
|
1261
1260
|
context_account_name: Optional[str] = context.get("account_name")
|
|
1262
|
-
context_request_tags: Optional[list[str]] = context.get("request_tags")
|
|
1263
1261
|
|
|
1264
1262
|
context_price_as_category: Optional[str] = context.get("price_as_category")
|
|
1265
1263
|
context_price_as_resource: Optional[str] = context.get("price_as_resource")
|
|
@@ -1320,10 +1318,7 @@ class _PayiInstrumentor:
|
|
|
1320
1318
|
if context_use_case_version is not None:
|
|
1321
1319
|
extra_headers[PayiHeaderNames.use_case_version] = str(context_use_case_version)
|
|
1322
1320
|
if context_use_case_step is not None:
|
|
1323
|
-
extra_headers[PayiHeaderNames.use_case_step] =
|
|
1324
|
-
|
|
1325
|
-
if PayiHeaderNames.request_tags not in extra_headers and context_request_tags:
|
|
1326
|
-
extra_headers[PayiHeaderNames.request_tags] = ",".join(context_request_tags)
|
|
1321
|
+
extra_headers[PayiHeaderNames.use_case_step] = context_use_case_step
|
|
1327
1322
|
|
|
1328
1323
|
if PayiHeaderNames.price_as_category not in extra_headers and context_price_as_category:
|
|
1329
1324
|
extra_headers[PayiHeaderNames.price_as_category] = context_price_as_category
|
|
@@ -1730,7 +1725,6 @@ def payi_instrument(
|
|
|
1730
1725
|
payi: Optional[Union[Payi, AsyncPayi, 'list[Union[Payi, AsyncPayi]]']] = None,
|
|
1731
1726
|
instruments: Optional[Set[str]] = None,
|
|
1732
1727
|
log_prompt_and_response: bool = True,
|
|
1733
|
-
prompt_and_response_logger: Optional[Callable[[str, "dict[str, str]"], None]] = None,
|
|
1734
1728
|
config: Optional[PayiInstrumentConfig] = None,
|
|
1735
1729
|
logger: Optional[logging.Logger] = None,
|
|
1736
1730
|
) -> None:
|
|
@@ -1763,7 +1757,6 @@ def payi_instrument(
|
|
|
1763
1757
|
instruments=instruments,
|
|
1764
1758
|
log_prompt_and_response=log_prompt_and_response,
|
|
1765
1759
|
logger=logger,
|
|
1766
|
-
prompt_and_response_logger=prompt_and_response_logger,
|
|
1767
1760
|
global_config=config if config else PayiInstrumentConfig(),
|
|
1768
1761
|
caller_filename=caller_filename
|
|
1769
1762
|
)
|
|
@@ -1781,6 +1774,7 @@ def track(
|
|
|
1781
1774
|
use_case_properties: Optional["dict[str, str]"] = None,
|
|
1782
1775
|
proxy: Optional[bool] = None,
|
|
1783
1776
|
) -> Any:
|
|
1777
|
+
_ = request_tags
|
|
1784
1778
|
|
|
1785
1779
|
def _track(func: Any) -> Any:
|
|
1786
1780
|
import asyncio
|
|
@@ -1801,7 +1795,6 @@ def track(
|
|
|
1801
1795
|
use_case_version,
|
|
1802
1796
|
user_id,
|
|
1803
1797
|
account_name,
|
|
1804
|
-
request_tags,
|
|
1805
1798
|
request_properties,
|
|
1806
1799
|
use_case_properties,
|
|
1807
1800
|
*args,
|
|
@@ -1825,7 +1818,6 @@ def track(
|
|
|
1825
1818
|
use_case_version,
|
|
1826
1819
|
user_id,
|
|
1827
1820
|
account_name,
|
|
1828
|
-
request_tags,
|
|
1829
1821
|
request_properties,
|
|
1830
1822
|
use_case_properties,
|
|
1831
1823
|
*args,
|
|
@@ -1865,7 +1857,6 @@ def track_context(
|
|
|
1865
1857
|
|
|
1866
1858
|
context["user_id"] = user_id
|
|
1867
1859
|
context["account_name"] = account_name
|
|
1868
|
-
context["request_tags"] = request_tags
|
|
1869
1860
|
|
|
1870
1861
|
context["price_as_category"] = price_as_category
|
|
1871
1862
|
context["price_as_resource"] = price_as_resource
|
|
@@ -1874,6 +1865,8 @@ def track_context(
|
|
|
1874
1865
|
context["request_properties"] = request_properties
|
|
1875
1866
|
context["use_case_properties"] = use_case_properties
|
|
1876
1867
|
|
|
1868
|
+
_ = request_tags
|
|
1869
|
+
|
|
1877
1870
|
return _InternalTrackContext(context)
|
|
1878
1871
|
|
|
1879
1872
|
def get_context() -> PayiContext:
|
payi/resources/ingest.py
CHANGED
|
@@ -210,7 +210,7 @@ class IngestResource(SyncAPIResource):
|
|
|
210
210
|
"xProxy-UseCase-Step": use_case_step,
|
|
211
211
|
"xProxy-UseCase-Version": use_case_version_str
|
|
212
212
|
if is_given(use_case_version)
|
|
213
|
-
else
|
|
213
|
+
else not_given,
|
|
214
214
|
"xProxy-User-ID": user_id,
|
|
215
215
|
"xProxy-Resource-Scope": resource_scope,
|
|
216
216
|
"xProxy-Account-Name": account_name,
|
|
@@ -431,7 +431,7 @@ class AsyncIngestResource(AsyncAPIResource):
|
|
|
431
431
|
"xProxy-UseCase-Step": use_case_step,
|
|
432
432
|
"xProxy-UseCase-Version": use_case_version_str
|
|
433
433
|
if is_given(use_case_version)
|
|
434
|
-
else
|
|
434
|
+
else not_given,
|
|
435
435
|
"xProxy-User-ID": user_id,
|
|
436
436
|
"xProxy-Resource-Scope": resource_scope,
|
|
437
437
|
}
|
|
@@ -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=d6xrZDG6rG6opphTN7UVYdEOis3977LrQQgpNtklXZE,7234
|
|
14
|
-
payi/_version.py,sha256=
|
|
14
|
+
payi/_version.py,sha256=Q_d5ojHOSTeTtbTlwPmPpab5qD4yxOTyShC1FSrNwdk,166
|
|
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=7fch0GT9zpNnErbciSpUNa-SjTxxjY6kxHxKMOM4AGs,2305
|
|
@@ -28,18 +28,18 @@ payi/_utils/_typing.py,sha256=N_5PPuFNsaygbtA_npZd98SVN1LQQvFTKL6bkWPBZGU,4786
|
|
|
28
28
|
payi/_utils/_utils.py,sha256=0dDqauUbVZEXV0NVl7Bwu904Wwo5eyFCZpQThhFNhyA,12253
|
|
29
29
|
payi/lib/.keep,sha256=wuNrz-5SXo3jJaJOJgz4vFHM41YH_g20F5cRQo0vLes,224
|
|
30
30
|
payi/lib/AnthropicInstrumentor.py,sha256=SI6nzU-eVufHbxV5gxgrZDhx3TewRVnsvtwDuwEG6WU,16484
|
|
31
|
-
payi/lib/BedrockInstrumentor.py,sha256
|
|
31
|
+
payi/lib/BedrockInstrumentor.py,sha256=-dF3mk2nsCOrYxeV75eBORxYEJ7Nd1nIJWsy4-2LEHk,27324
|
|
32
32
|
payi/lib/GoogleGenAiInstrumentor.py,sha256=LHiEZ7G5IhCcDlpVzQlXW9Ok96MHLeq7emEhFzPBTm0,8836
|
|
33
33
|
payi/lib/OpenAIInstrumentor.py,sha256=_ULwIli11XP1yZK_pMGXuaSmHZ5pozuEt_v5DfhNuGw,22914
|
|
34
34
|
payi/lib/Stopwatch.py,sha256=7OJlxvr2Jyb6Zr1LYCYKczRB7rDVKkIR7gc4YoleNdE,764
|
|
35
35
|
payi/lib/VertexInstrumentor.py,sha256=OWuMPiW4LdLhj6DSAAy5qZiosVo8DSAuFWGxYpEucoE,7431
|
|
36
36
|
payi/lib/VertexRequest.py,sha256=42F7xCRYY6h3EMUZD1x4-_cwyAcVhnzT9M5zl4KwtE0,11801
|
|
37
|
-
payi/lib/helpers.py,sha256=
|
|
38
|
-
payi/lib/instrument.py,sha256=
|
|
37
|
+
payi/lib/helpers.py,sha256=6c0RFMS0AYVIxU6q8ak1CDwMTwldIN7N2O2XkxTO7ag,4931
|
|
38
|
+
payi/lib/instrument.py,sha256=eaDtiBx3cuCOB4Pxd1svEOEk6MykB_Dn3JaCJKl8Z6w,76473
|
|
39
39
|
payi/lib/version_helper.py,sha256=v0lC3kuaXn6PBDolE3mkmwJiA8Ot3z4RkVR7wlBuZCs,540
|
|
40
40
|
payi/lib/data/cohere_embed_english_v3.json,sha256=YEWwjml3_i16cdsOx_7UKe6xpVFnxTEhP8T1n54R6gY,718306
|
|
41
41
|
payi/resources/__init__.py,sha256=B2bn1ZfCf6TbHlzZvy5TpFPtALnFcBRPYVKQH3S5qfQ,2457
|
|
42
|
-
payi/resources/ingest.py,sha256=
|
|
42
|
+
payi/resources/ingest.py,sha256=Z8ZWZQW-4v-oGpHLZWRVHDMyyChchh-Hl-lJsn9CDZs,21294
|
|
43
43
|
payi/resources/categories/__init__.py,sha256=WeotN_d-0Ri8ohsrNPbve7RyViD9_N0NA9DrV3WYg3w,1701
|
|
44
44
|
payi/resources/categories/categories.py,sha256=H3Ld1gbb_L39HHHc65-MW7Ocn4hIw0O-jnOLtQVhtlo,20557
|
|
45
45
|
payi/resources/categories/fixed_cost_resources.py,sha256=D0FCR20LDwSFc8eS5kU82j4v1ZhRDiNfU_3XQsMWFY8,7830
|
|
@@ -142,7 +142,7 @@ payi/types/use_cases/definitions/kpi_retrieve_response.py,sha256=uQXliSvS3k-yDYw
|
|
|
142
142
|
payi/types/use_cases/definitions/kpi_update_params.py,sha256=jbawdWAdMnsTWVH0qfQGb8W7_TXe3lq4zjSRu44d8p8,373
|
|
143
143
|
payi/types/use_cases/definitions/kpi_update_response.py,sha256=zLyEoT0S8d7XHsnXZYT8tM7yDw0Aze0Mk-_Z6QeMtc8,459
|
|
144
144
|
payi/types/use_cases/definitions/limit_config_create_params.py,sha256=sodtLT84tBmuO_0d-h0CZWCh4vWojJMtUbMjBmEN3IE,492
|
|
145
|
-
payi-0.1.
|
|
146
|
-
payi-0.1.
|
|
147
|
-
payi-0.1.
|
|
148
|
-
payi-0.1.
|
|
145
|
+
payi-0.1.0a126.dist-info/METADATA,sha256=HMMB7v-Q7WLRb5x3j2T4MUUB-dI5WtH6Ne0_J1w0ukQ,16324
|
|
146
|
+
payi-0.1.0a126.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
147
|
+
payi-0.1.0a126.dist-info/licenses/LICENSE,sha256=CQt03aM-P4a3Yg5qBg3JSLVoQS3smMyvx7tYg_6V7Gk,11334
|
|
148
|
+
payi-0.1.0a126.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|