payi 0.1.0a50__py3-none-any.whl → 0.1.0a52__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 CHANGED
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "payi"
4
- __version__ = "0.1.0-alpha.50" # x-release-please-version
4
+ __version__ = "0.1.0-alpha.52" # x-release-please-version
payi/lib/helpers.py CHANGED
@@ -1,4 +1,3 @@
1
- from enum import Enum
2
1
  from typing import Dict, List, Union
3
2
 
4
3
  PAYI_BASE_URL = "https://api.pay-i.com"
@@ -11,12 +10,13 @@ class PayiHeaderNames:
11
10
  user_id:str = "xProxy-User-ID"
12
11
  route_as_resource:str = "xProxy-RouteAs-Resource"
13
12
  provider_base_uri = "xProxy-Provider-BaseUri"
13
+ resource_scope:str = "xProxy-Resource-Scope"
14
14
 
15
- class PayiCategories(Enum):
16
- anthropic = "system.anthropic"
17
- openai = "system.openai"
18
- azure_openai = "system.azureopenai"
19
- aws_bedrock = "system.aws.bedrock"
15
+ class PayiCategories:
16
+ anthropic:str = "system.anthropic"
17
+ openai:str = "system.openai"
18
+ azure_openai:str = "system.azureopenai"
19
+ aws_bedrock:str = "system.aws.bedrock"
20
20
 
21
21
  def create_limit_header_from_ids(limit_ids: List[str]) -> Dict[str, str]:
22
22
  if not isinstance(limit_ids, list): # type: ignore
payi/lib/instrument.py CHANGED
@@ -41,7 +41,7 @@ class PayiInstrumentor:
41
41
  self,
42
42
  payi: Optional[Payi],
43
43
  apayi: Optional[AsyncPayi],
44
- instruments: Union[Set[PayiCategories], None] = None,
44
+ instruments: Union[Set[str], None] = None,
45
45
  log_prompt_and_response: bool = True,
46
46
  prompt_and_response_logger: Optional[
47
47
  Callable[[str, "dict[str, str]"], None]
@@ -56,7 +56,7 @@ class PayiInstrumentor:
56
56
  self._blocked_limits: set[str] = set()
57
57
  self._exceeded_limits: set[str] = set()
58
58
 
59
- if instruments is None:
59
+ if instruments is None or "*" in instruments:
60
60
  self._instrument_all()
61
61
  else:
62
62
  self._instrument_specific(instruments)
@@ -66,7 +66,7 @@ class PayiInstrumentor:
66
66
  self._instrument_anthropic()
67
67
  self._instrument_aws_bedrock()
68
68
 
69
- def _instrument_specific(self, instruments: Set[PayiCategories]) -> None:
69
+ def _instrument_specific(self, instruments: Set[str]) -> None:
70
70
  if PayiCategories.openai in instruments or PayiCategories.azure_openai in instruments:
71
71
  self._instrument_openai()
72
72
  if PayiCategories.anthropic in instruments:
@@ -375,14 +375,18 @@ class PayiInstrumentor:
375
375
  if len(ingest_extra_headers) > 0:
376
376
  ingest["provider_request_headers"] = [PayICommonModelsAPIRouterHeaderInfoParam(name=k, value=v) for k, v in ingest_extra_headers.items()]
377
377
 
378
- provider_prompt = {}
378
+ provider_prompt: "dict[str, Any]" = {}
379
379
  for k, v in kwargs.items():
380
380
  if k == "messages":
381
381
  provider_prompt[k] = [m.model_dump() if hasattr(m, "model_dump") else m for m in v]
382
382
  elif k in ["extra_headers", "extra_query"]:
383
383
  pass
384
384
  else:
385
- provider_prompt[k] = v
385
+ try:
386
+ json.dumps(v)
387
+ provider_prompt[k] = v
388
+ except (TypeError, ValueError):
389
+ pass
386
390
 
387
391
  if self._log_prompt_and_response:
388
392
  ingest["provider_request_json"] = json.dumps(provider_prompt)
@@ -420,18 +424,28 @@ class PayiInstrumentor:
420
424
  ingest: IngestUnitsParams = {"category": category, "units": {}} # type: ignore
421
425
  ingest["resource"] = kwargs.get("model", "")
422
426
 
423
- if category == "system.openai" and instance and hasattr(instance, "_client"):
427
+ if category == PayiCategories.openai and instance and hasattr(instance, "_client"):
424
428
  from .OpenAIInstrumentor import OpenAiInstrumentor # noqa: I001
425
429
 
426
430
  if OpenAiInstrumentor.is_azure(instance):
427
- resource = extra_headers.pop(PayiHeaderNames.route_as_resource, None)
428
- if not resource:
431
+ route_as_resource = extra_headers.pop(PayiHeaderNames.route_as_resource, None)
432
+ resource_scope = extra_headers.pop(PayiHeaderNames.resource_scope, None)
433
+
434
+ if not route_as_resource:
429
435
  logging.error("Azure OpenAI route as resource not found, not ingesting")
430
436
  return await wrapped(*args, **kwargs)
431
437
 
432
- category = "system.azureopenai"
438
+ if resource_scope:
439
+ if not(resource_scope in ["global", "datazone"] or resource_scope.startswith("region")):
440
+ logging.error("Azure OpenAI invalid resource scope, not ingesting")
441
+ return wrapped(*args, **kwargs)
442
+
443
+ ingest["resource_scope"] = resource_scope
444
+
445
+ category = PayiCategories.azure_openai
446
+
433
447
  ingest["category"] = category
434
- ingest["resource"] = resource
448
+ ingest["resource"] = route_as_resource
435
449
 
436
450
  current_frame = inspect.currentframe()
437
451
  # f_back excludes the current frame, strip() cleans up whitespace and newlines
@@ -511,7 +525,7 @@ class PayiInstrumentor:
511
525
  ) -> Any:
512
526
  context = self.get_context()
513
527
 
514
- is_bedrock:bool = category == "system.aws.bedrock"
528
+ is_bedrock:bool = category == PayiCategories.aws_bedrock
515
529
 
516
530
  if not context:
517
531
  if is_bedrock:
@@ -539,17 +553,28 @@ class PayiInstrumentor:
539
553
  else:
540
554
  ingest["resource"] = kwargs.get("model", "")
541
555
 
542
- if category == "system.openai" and instance and hasattr(instance, "_client"):
543
- from .OpenAIInstrumentor import OpenAiInstrumentor
556
+ if category == PayiCategories.openai and instance and hasattr(instance, "_client"):
557
+ from .OpenAIInstrumentor import OpenAiInstrumentor # noqa: I001
558
+
544
559
  if OpenAiInstrumentor.is_azure(instance):
545
- resource = extra_headers.pop(PayiHeaderNames.route_as_resource, None)
546
- if not resource:
560
+ route_as_resource:str = extra_headers.pop(PayiHeaderNames.route_as_resource, None)
561
+ resource_scope:str = extra_headers.pop(PayiHeaderNames.resource_scope, None)
562
+
563
+ if not route_as_resource:
547
564
  logging.error("Azure OpenAI route as resource not found, not ingesting")
548
565
  return wrapped(*args, **kwargs)
549
566
 
550
- category = "system.azureopenai"
567
+ if resource_scope:
568
+ if not(resource_scope in ["global", "datazone"] or resource_scope.startswith("region")):
569
+ logging.error("Azure OpenAI invalid resource scope, not ingesting")
570
+ return wrapped(*args, **kwargs)
571
+
572
+ ingest["resource_scope"] = resource_scope
573
+
574
+ category = PayiCategories.azure_openai
575
+
551
576
  ingest["category"] = category
552
- ingest["resource"] = resource
577
+ ingest["resource"] = route_as_resource
553
578
 
554
579
  current_frame = inspect.currentframe()
555
580
  # f_back excludes the current frame, strip() cleans up whitespace and newlines
@@ -864,7 +889,7 @@ _instrumentor: Optional[PayiInstrumentor] = None
864
889
 
865
890
  def payi_instrument(
866
891
  payi: Optional[Union[Payi, AsyncPayi, 'list[Union[Payi, AsyncPayi]]']] = None,
867
- instruments: Optional[Set[PayiCategories]] = None,
892
+ instruments: Optional[Set[str]] = None,
868
893
  log_prompt_and_response: bool = True,
869
894
  prompt_and_response_logger: Optional[Callable[[str, "dict[str, str]"], None]] = None,
870
895
  ) -> None:
payi/resources/ingest.py CHANGED
@@ -101,11 +101,12 @@ class IngestResource(SyncAPIResource):
101
101
  provider_response_json: Union[str, List[str], None] | NotGiven = NOT_GIVEN,
102
102
  provider_uri: Optional[str] | NotGiven = NOT_GIVEN,
103
103
  time_to_first_token_ms: Optional[int] | NotGiven = NOT_GIVEN,
104
- limit_ids: Union[list[str], None] | NotGiven = NOT_GIVEN,
105
- request_tags: Union[list[str], None] | NotGiven = NOT_GIVEN,
106
- experience_id: Union[str, None] | NotGiven = NOT_GIVEN,
107
- experience_name: Union[str, None] | NotGiven = NOT_GIVEN,
108
- user_id: Union[str, None] | NotGiven = NOT_GIVEN,
104
+ limit_ids: Optional[list[str]] | NotGiven = NOT_GIVEN,
105
+ request_tags: Optional[list[str]] | NotGiven = NOT_GIVEN,
106
+ experience_id: Optional[str] | NotGiven = NOT_GIVEN,
107
+ experience_name: Optional[str] | NotGiven = NOT_GIVEN,
108
+ user_id: Optional[str] | NotGiven = NOT_GIVEN,
109
+ resource_scope: Optional[str] | NotGiven = NOT_GIVEN,
109
110
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
110
111
  # The extra values given here take precedence over values defined on the client or passed to this method.
111
112
  extra_headers: Headers | None = None,
@@ -136,6 +137,8 @@ class IngestResource(SyncAPIResource):
136
137
  experience_id (str, optional): The experience instance id
137
138
 
138
139
  user_id (str, optional): The user id
140
+
141
+ resource_scope(str, optional): The scope of the resource
139
142
 
140
143
  extra_headers (Dict[str, str], optional): Additional headers for the request. Defaults to None.
141
144
 
@@ -176,17 +179,17 @@ class IngestResource(SyncAPIResource):
176
179
  user_id = NOT_GIVEN
177
180
 
178
181
  extra_headers = {
179
- **strip_not_given(
180
- {
181
- "xProxy-Limit-IDs": valid_ids_str,
182
- "xProxy-Request-Tags": valid_tags_str,
183
- "xProxy-Experience-Id": experience_id,
184
- "xProxy-Experience-Name": experience_name,
185
- "xProxy-User-ID": user_id,
186
- }
187
- ),
182
+ **{key: value for key, value in strip_not_given({
183
+ "xProxy-Limit-IDs": valid_ids_str,
184
+ "xProxy-Request-Tags": valid_tags_str,
185
+ "xProxy-Experience-Name": experience_name,
186
+ "xProxy-Experience-Id": experience_id,
187
+ "xProxy-User-ID": user_id,
188
+ "xProxy-Resource-Scope": resource_scope,
189
+ }).items() if value is not None}, # Ensure no 'None' values are included
188
190
  **(extra_headers or {}),
189
191
  }
192
+
190
193
  return self._post(
191
194
  "/api/v1/ingest",
192
195
  body=maybe_transform(
@@ -286,11 +289,12 @@ class AsyncIngestResource(AsyncAPIResource):
286
289
  provider_response_json: Union[str, List[str], None] | NotGiven = NOT_GIVEN,
287
290
  provider_uri: Optional[str] | NotGiven = NOT_GIVEN,
288
291
  time_to_first_token_ms: Optional[int] | NotGiven = NOT_GIVEN,
289
- limit_ids: Union[list[str], None] | NotGiven = NOT_GIVEN,
290
- request_tags: Union[list[str], None] | NotGiven = NOT_GIVEN,
291
- experience_name: Union[str, None] | NotGiven = NOT_GIVEN,
292
- experience_id: Union[str, None] | NotGiven = NOT_GIVEN,
293
- user_id: Union[str, None] | NotGiven = NOT_GIVEN,
292
+ limit_ids: Optional[list[str]] | NotGiven = NOT_GIVEN,
293
+ request_tags: Optional[list[str]] | NotGiven = NOT_GIVEN,
294
+ experience_name: Optional[str] | NotGiven = NOT_GIVEN,
295
+ experience_id: Optional[str] | NotGiven = NOT_GIVEN,
296
+ user_id: Optional[str] | NotGiven = NOT_GIVEN,
297
+ resource_scope: Union[str, None] | NotGiven = NOT_GIVEN,
294
298
  # The extra values given here take precedence over values defined on the client or passed to this method.
295
299
  extra_headers: Headers | None = None,
296
300
  extra_query: Query | None = None,
@@ -320,6 +324,8 @@ class AsyncIngestResource(AsyncAPIResource):
320
324
  experience_id (str, optional): The experience instance id
321
325
 
322
326
  user_id (str, optional): The user id
327
+
328
+ resource_scope (str, optional): The scope of the resource
323
329
 
324
330
  extra_headers (Dict[str, str], optional): Additional headers for the request. Defaults to None.
325
331
 
@@ -360,15 +366,14 @@ class AsyncIngestResource(AsyncAPIResource):
360
366
  user_id = NOT_GIVEN
361
367
 
362
368
  extra_headers = {
363
- **strip_not_given(
364
- {
365
- "xProxy-Limit-IDs": valid_ids_str,
366
- "xProxy-Request-Tags": valid_tags_str,
367
- "xProxy-Experience-Name": experience_name,
368
- "xProxy-Experience-Id": experience_id,
369
- "xProxy-User-ID": user_id,
370
- }
371
- ),
369
+ **{key: value for key, value in strip_not_given({
370
+ "xProxy-Limit-IDs": valid_ids_str,
371
+ "xProxy-Request-Tags": valid_tags_str,
372
+ "xProxy-Experience-Name": experience_name,
373
+ "xProxy-Experience-Id": experience_id,
374
+ "xProxy-User-ID": user_id,
375
+ "xProxy-Resource-Scope": resource_scope,
376
+ }).items() if value is not None}, # Ensure no 'None' values are included
372
377
  **(extra_headers or {}),
373
378
  }
374
379
  return await self._post(
@@ -25,8 +25,6 @@ class IngestEventParam(TypedDict, total=False):
25
25
 
26
26
  units: Required[Dict[str, Units]]
27
27
 
28
- csat_rating: Optional[int]
29
-
30
28
  end_to_end_latency_ms: Optional[int]
31
29
 
32
30
  event_timestamp: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
@@ -51,6 +51,8 @@ class IngestUnitsParams(TypedDict, total=False):
51
51
 
52
52
  experience_id: Annotated[Union[str, None], PropertyInfo(alias="xProxy-Experience-Id")]
53
53
 
54
+ resource_scope: Annotated[Union[str, None], PropertyInfo(alias="xProxy-Resource-Scope")]
55
+
54
56
  user_id: Annotated[Union[str, None], PropertyInfo(alias="xProxy-User-ID")]
55
57
 
56
58
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: payi
3
- Version: 0.1.0a50
3
+ Version: 0.1.0a52
4
4
  Summary: The official Python library for the payi API
5
5
  Project-URL: Homepage, https://github.com/Pay-i/pay-i-python
6
6
  Project-URL: Repository, https://github.com/Pay-i/pay-i-python
@@ -11,7 +11,7 @@ payi/_resource.py,sha256=j2jIkTr8OIC8sU6-05nxSaCyj4MaFlbZrwlyg4_xJos,1088
11
11
  payi/_response.py,sha256=CfrNS_3wbL8o9dRyRVfZQ5E1GUlA4CUIUEK8olmfGqE,28777
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=eV5t7glu1rddfBj2KaJZbWBaWyb8PZ31PrzKJnhd1mc,165
14
+ payi/_version.py,sha256=8EiC_xRCoylkMdtygYL1cGog4vO86O8lPQot0lXlxNU,165
15
15
  payi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  payi/_utils/__init__.py,sha256=PNZ_QJuzZEgyYXqkO1HVhGkj5IU9bglVUcw7H-Knjzw,2062
17
17
  payi/_utils/_logs.py,sha256=fmnf5D9TOgkgZKfgYmSa3PiUc3SZgkchn6CzJUeo0SQ,768
@@ -27,11 +27,11 @@ payi/lib/AnthropicInstrumentor.py,sha256=h-yebG7r7cSRVM_utva55Gc4BVcoW6WGrQrDg55
27
27
  payi/lib/BedrockInstrumentor.py,sha256=4WSZLzLHMv-5U1OFr0ZErESNHTyPHn0kHATUw4HTDkQ,10072
28
28
  payi/lib/OpenAIInstrumentor.py,sha256=ZUu-Byhz7AXhvxjOMdX8tB2JOpM5sCj0KnyRB49lQg0,6881
29
29
  payi/lib/Stopwatch.py,sha256=7OJlxvr2Jyb6Zr1LYCYKczRB7rDVKkIR7gc4YoleNdE,764
30
- payi/lib/helpers.py,sha256=fcT6gAHUP77YaLmgw9HWdIyTDJPI72weUsUVDGW0CbE,2929
31
- payi/lib/instrument.py,sha256=oJdF1ocd-wbQgNF9MIZWAaGDInzbu4TRy9946GVRuvI,36302
30
+ payi/lib/helpers.py,sha256=ghW4v_ZmCfy4ImGJr1PFTPfzHYwCCtdtyq9UqKwxpGc,2967
31
+ payi/lib/instrument.py,sha256=Fk-Vh9NEhfp6UNaTAkkEgL5Kiq7nFPDwUT-EuzCMF5Y,37443
32
32
  payi/resources/__init__.py,sha256=isHGXSl9kOrZDduKrX3UenTwrdTpuKJVBjw6NYSBV20,3592
33
33
  payi/resources/billing_models.py,sha256=5w3RfGXtGlyq5vbTw6hQrx1UlzRBtlq8ArcFlf5e3TY,20152
34
- payi/resources/ingest.py,sha256=Ti-wnHj_A0_h3LxybPIahmxfsBTPG60ndnyCJZRJybo,18698
34
+ payi/resources/ingest.py,sha256=RFfN1hwUngFgHJNcMaqZ1C6Xw1Qdve81dtUgjJSOb_A,19159
35
35
  payi/resources/price_modifiers.py,sha256=t-k2F_zf2FhoxiqDHAPBPvhSgTjewlJqh50y58FNMuw,13475
36
36
  payi/resources/categories/__init__.py,sha256=w5gMiPdBSzJA_qfoVtFBElaoe8wGf_O63R7R1Spr6Gk,1093
37
37
  payi/resources/categories/categories.py,sha256=FohmajDcadMXzhG3Z1HKGkbSImO7rhzQ0olZXHz8z48,16074
@@ -66,9 +66,9 @@ payi/types/cost_details.py,sha256=w9p79opEG3kcsjkRRP7niaMcUswdfB4Y7HCkVTcQ1zQ,30
66
66
  payi/types/default_response.py,sha256=o617LpRsCIZHCZxAc5nVI2JQ3HPGZo4gCDvSDkxkIJ8,270
67
67
  payi/types/experience_instance_response.py,sha256=N07MH6hjs1ISHLVpR2FG-u4awsZ_GGi97UNMXAWV1yA,296
68
68
  payi/types/ingest_bulk_params.py,sha256=d76YwiXaNeltLS3w86ZxLzTKGa7ymGLJDSelaMQGf8Y,382
69
- payi/types/ingest_event_param.py,sha256=IoOQuEEafJtWmXWsBbRCMbt16PXQR_nscnEEIRsEC1s,1539
69
+ payi/types/ingest_event_param.py,sha256=1-pr5wMiWXAGDqBmQHKdpHJy0Fk9vOQl7XTGLtcjtdI,1507
70
70
  payi/types/ingest_response.py,sha256=KZfsgUhC942QkkjDFMqjJwCRoO2vkXv-Sx3X_xjijfg,1449
71
- payi/types/ingest_units_params.py,sha256=bPEo-bTlTrboi24gAlxw7jTBeB1ZoLI59ZgcuwDq_bg,1790
71
+ payi/types/ingest_units_params.py,sha256=QrfkSW-tFDKpn8cPbbyAOhM17W1prC-aJeXMFeGiqJI,1884
72
72
  payi/types/limit_create_params.py,sha256=Av8oMCxlKH7VB2MtYN5-25rAjqDDTPHjsXIQ2xubmck,549
73
73
  payi/types/limit_history_response.py,sha256=sCx2qKBiHU9X2KrYWV8NZiarYMGurof5GF4QobR2-EU,787
74
74
  payi/types/limit_list_params.py,sha256=iWM67oL53y2IZ7D3Gyy8mdYv-B7vF-rbmRFn7SBUnJk,364
@@ -112,7 +112,7 @@ payi/types/requests/request_result.py,sha256=phYQiqhwNaR9igP-Fhs34Y-__dlT7L4wq-r
112
112
  payi/types/shared/__init__.py,sha256=-xz5dxK5LBjLnsi2LpLq5btaGDFp-mSjJ0y2qKy0Yus,264
113
113
  payi/types/shared/evaluation_response.py,sha256=ejEToMA57PUu1SldEtJ5z9r4fAO3U0tvdjbsyIoVX1s,214
114
114
  payi/types/shared/pay_i_common_models_budget_management_cost_details_base.py,sha256=XmIzJXy4zAi-mfrDvEXiYjO3qF1EvugGUl-Gijj4TA4,268
115
- payi-0.1.0a50.dist-info/METADATA,sha256=iM3Z4_67ypMAHvmAMATNobzasM07vzfSO1Vj3h9cYLY,12660
116
- payi-0.1.0a50.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
117
- payi-0.1.0a50.dist-info/licenses/LICENSE,sha256=CQt03aM-P4a3Yg5qBg3JSLVoQS3smMyvx7tYg_6V7Gk,11334
118
- payi-0.1.0a50.dist-info/RECORD,,
115
+ payi-0.1.0a52.dist-info/METADATA,sha256=uBhSl9Hp-zULHZsstIS7MVDPGcLbrVTE_0Zd3ZFzxvA,12660
116
+ payi-0.1.0a52.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
117
+ payi-0.1.0a52.dist-info/licenses/LICENSE,sha256=CQt03aM-P4a3Yg5qBg3JSLVoQS3smMyvx7tYg_6V7Gk,11334
118
+ payi-0.1.0a52.dist-info/RECORD,,